~edwargix/tallyard

2da3af851323848f78ab6f96b1ffb388b5bb2f48 — David Florness 5 years ago 0b145b9
Matrices and RREF
2 files changed, 103 insertions(+), 0 deletions(-)

A linalg.go
A linalg_test.go
A linalg.go => linalg.go +67 -0
@@ 0,0 1,67 @@
package main

import (
	"math/big"
)

type Matrix [][]big.Rat

func (M Matrix) RREF() {
	lead := 0
	rowCount := len(M)
	if rowCount == 0 {
		return
	}
	columnCount := len(M[0])
	zero := big.NewRat(0, 1)

	for r := 0; r < rowCount; r++ {
		if lead >= columnCount {
			return
		}
		i := r
		for M[i][lead].Cmp(zero) == 0 {
			i++
			if rowCount == i {
				i = r
				lead++
				if columnCount == lead {
					return
				}
			}
		}
		M[i], M[r] = M[r], M[i]
		f := &big.Rat{}
		f.Inv(&M[r][lead])
		for j := range M[r] {
			M[r][j].Mul(&M[r][j], f)
		}
		for i = 0; i < rowCount; i++ {
			if i != r {
				f.Set(&M[i][lead])
				for j, e := range M[r] {
					M[i][j].Sub(&M[i][j], new(big.Rat).Mul(&e, f))
				}
			}
		}
		lead++
	}
}

// assumes `M' and `other' are valid matrices
func (M Matrix) Equals(other Matrix) bool {
	if len(M) != len(other) {
		return false
	}
	if len(M) > 0 && len(M[0]) != len(other[0]) {
		return false
	}
	for r := range M {
		for c := range M[r] {
			if M[r][c].Cmp(&other[r][c]) != 0 {
				return false
			}
		}
	}
	return true
}

A linalg_test.go => linalg_test.go +36 -0
@@ 0,0 1,36 @@
package main

import (
	"math/big"
	"testing"
)

func TestRREF(t *testing.T) {
	mat := Matrix{
		{*big.NewRat( 1, 1), *big.NewRat(2, 1), *big.NewRat(-1, 1), *big.NewRat( -4, 1)},
		{*big.NewRat( 2, 1), *big.NewRat(3, 1), *big.NewRat(-1, 1), *big.NewRat(-11, 1)},
		{*big.NewRat(-2, 1), *big.NewRat(0, 1), *big.NewRat(-3, 1), *big.NewRat( 22, 1)},
	}
	mat.RREF()
	result := Matrix{
		{*big.NewRat(1, 1), *big.NewRat(0, 1), *big.NewRat(0, 1), *big.NewRat(-8, 1)},
		{*big.NewRat(0, 1), *big.NewRat(1, 1), *big.NewRat(0, 1), *big.NewRat( 1, 1)},
		{*big.NewRat(0, 1), *big.NewRat(0, 1), *big.NewRat(1, 1), *big.NewRat(-2, 1)},
	}
	if !mat.Equals(result) {
		t.Fail()
	}

	mat = Matrix{
		{*big.NewRat(1, 1), *big.NewRat(3, 1), *big.NewRat(-1, 1)},
		{*big.NewRat(0, 1), *big.NewRat(1, 1),  *big.NewRat(7, 1)},
	}
	mat.RREF()
	result = Matrix{
		{*big.NewRat(1, 1), *big.NewRat(0, 1), *big.NewRat(-22, 1)},
		{*big.NewRat(0, 1), *big.NewRat(1, 1), *big.NewRat(  7, 1)},
	}
	if !mat.Equals(result) {
		t.Fail()
	}
}