<commit_before>/*mat contains routines for executing operations on matrices. Opersions are
split into easy to use methods which might be somewhat wasteful with memory
consumption and execution time and slightly less easy to use methods which
require explictly managing LU decomposition.

Pretty much everything only works on square matrices because that's all I've
needed so far.
*/
package mat

import (
	"math"
)

// Matrix represents a matrix of float64 values.
type Matrix struct {
	Vals []float64
	Width, Height int
}

// LUFactors contains data fields neccessary for a number of matrix operations.
// Exporting this type allows calling routines to better manage their memory
// consumption and to prevent recomputing the same decomposition many times.
type LUFactors struct {
	lu Matrix
	pivot []int
	d float64
}

// NewMatrix32 creates a matrix with the specified values and dimensions.
func NewMatrix(vals []float64, width, height int) *Matrix {
	m := &Matrix{}
	m.Init(vals, width, height)
	return m
}

// Init initializes a matrix with the specified values and dimensions.
func (m *Matrix) Init(vals []float64, width, height int) {
	if width <= 0 {
		panic("width must be positive.")
	} else if height <= 0 {
		panic("height must be positive.")
	} else if width * height != len(vals) {
		panic("height * width must equal len(vals).")
	}

	m.Vals = vals
	m.Width, m.Height = width, height
}

// Mult multiplies two matrices together.
func (m1 *Matrix) Mult(m2 *Matrix) *Matrix {
	h, w := m1.Height, m2.Width
	out := NewMatrix(make([]float64, h*w), w, h)
	return m1.MultAt(m2, out)
}

// Mult multiplies to matrices together and writes the result to the 
// specified matrix.
func (m1 *Matrix) MultAt(m2, out *Matrix) *Matrix {
	if m1.Width != m2.Height {
		panic("Multiplication of incompatible matrix sizes.")
	}

	for i := range out.Vals { out.Vals[i] = 0 }
	for i := 0; i < m1.Height; i++ {
		off := i*m1.Width
		for j := 0; j < m2.Width; j++ {
			outIdx := off + j
			for k := 0; k < m1.Width; k++ {
				m1Idx := off + k
				m2Idx := k*m2.Width + j
				out.Vals[outIdx] += m1.Vals[m1Idx] * m2.Vals[m2Idx]
			}
		}
	}

	return out
}

// TODO: test.
func MultVec(m *Matrix, v, out []float64) {
	if m.Height != len(out) || m.Width != len(v) {
		panic("Shape error.")
	}

	for i := range out { out[i] = 0 }
	offset := 0
	for j := 0; j < m.Height; j++ {
		for i := 0; i < m.Width; i++ {
			out[j] += m.Vals[offset + i] * v[i]
		}
		offset += m.Width
	}
}

// TODO: test.
func VecMult(v []float64, m *Matrix, out []float64) {
	if m.Height != len(v) || m.Width != len(out) {
		panic("Shape error.")
	}
	for i := range out { out[i] = 0 }
	offset := 0
	for j := 0; j < m.Height; j++ {
		for i := 0; i < m.Width; i++ {
			out[j] += v[j] * m.Vals[i + offset]
		}
		offset += m.Width
	}
}

func (m *Matrix) Transpose() *Matrix {
	vals := make([]float64, m.Height*m.Width)
	out :=NewMatrix(vals, m.Height, m.Width)
	m.TransposeAt(out)
	return out
}

func (m *Matrix) TransposeAt(out *Matrix) {
	recTranspose(m.Vals, out.Vals, m.Width, m.Height,
		0, 0, m.Width, m.Height, 0, 0)
}

const transposeRecWidth = 16000000
func recTranspose(
	m, out []float64, width, height int,
	mXLow, mYLow, mXWidth, mYWidth int,<commit_msg>Fixed VecMult().<commit_after>/*mat contains routines for executing operations on matrices. Opersions are
split into easy to use methods which might be somewhat wasteful with memory
consumption and execution time and slightly less easy to use methods which
require explictly managing LU decomposition.

Pretty much everything only works on square matrices because that's all I've
needed so far.
*/
package mat

import (
	"math"
)

// Matrix represents a matrix of float64 values.
type Matrix struct {
	Vals []float64
	Width, Height int
}

// LUFactors contains data fields neccessary for a number of matrix operations.
// Exporting this type allows calling routines to better manage their memory
// consumption and to prevent recomputing the same decomposition many times.
type LUFactors struct {
	lu Matrix
	pivot []int
	d float64
}

// NewMatrix32 creates a matrix with the specified values and dimensions.
func NewMatrix(vals []float64, width, height int) *Matrix {
	m := &Matrix{}
	m.Init(vals, width, height)
	return m
}

// Init initializes a matrix with the specified values and dimensions.
func (m *Matrix) Init(vals []float64, width, height int) {
	if width <= 0 {
		panic("width must be positive.")
	} else if height <= 0 {
		panic("height must be positive.")
	} else if width * height != len(vals) {
		panic("height * width must equal len(vals).")
	}

	m.Vals = vals
	m.Width, m.Height = width, height
}

// Mult multiplies two matrices together.
func (m1 *Matrix) Mult(m2 *Matrix) *Matrix {
	h, w := m1.Height, m2.Width
	out := NewMatrix(make([]float64, h*w), w, h)
	return m1.MultAt(m2, out)
}

// Mult multiplies to matrices together and writes the result to the 
// specified matrix.
func (m1 *Matrix) MultAt(m2, out *Matrix) *Matrix {
	if m1.Width != m2.Height {
		panic("Multiplication of incompatible matrix sizes.")
	}

	for i := range out.Vals { out.Vals[i] = 0 }
	for i := 0; i < m1.Height; i++ {
		off := i*m1.Width
		for j := 0; j < m2.Width; j++ {
			outIdx := off + j
			for k := 0; k < m1.Width; k++ {
				m1Idx := off + k
				m2Idx := k*m2.Width + j
				out.Vals[outIdx] += m1.Vals[m1Idx] * m2.Vals[m2Idx]
			}
		}
	}

	return out
}

// TODO: test.
func MultVec(m *Matrix, v, out []float64) {
	if m.Height != len(out) || m.Width != len(v) {
		panic("Shape error.")
	}

	for i := range out { out[i] = 0 }
	offset := 0
	for j := 0; j < m.Height; j++ {
		for i := 0; i < m.Width; i++ {
			out[j] += m.Vals[offset + i] * v[i]
		}
		offset += m.Width
	}
}

// TODO: test.
func VecMult(v []float64, m *Matrix, out []float64) {
	if m.Height != len(v) || m.Width != len(out) {
		panic("Shape error.")
	}
	for i := range out { out[i] = 0 }
	for i := 0; i < m.Width; i++ {
		sum := 0.0
		for j := 0; j < m.Height; j++ {
			sum += v[j] * m.Vals[i + m.Width*j]
		}
		out[i] = sum
	}
}

func (m *Matrix) Transpose() *Matrix {
	vals := make([]float64, m.Height*m.Width)
	out :=NewMatrix(vals, m.Height, m.Width)
	m.TransposeAt(out)
	return out
}

func (m *Matrix) TransposeAt(out *Matrix) {
	recTranspose(m.Vals, out.Vals, m.Width, m.Height,
		0, 0, m.Width, m.Height, 0, 0)
}

const transposeRecWidth = 16000000
func recTranspose(
	m, out []float64, width, height int,
	mXLow, mYLow, mXWidth, mYWidth int,
{'fraction_non_alphanumeric': 0.1422360248447205, 'fraction_numerical': 0.02220496894409938, 'mean_word_length': 3.3667796610169494, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5346769', 'n_tokens_mistral': 2495, 'n_tokens_neox': 2317, 'n_words': 816}