상세 컨텐츠

본문 제목

What a simply implemented Matrix four arithmetic operations in GoLang!

Go

by 경밤 2020. 5. 1. 00:57

본문

반응형

In this post, We are going to make a matrix and additional arithmetic operations plus, minus. mulitply and scalar mulitply the last.

The chapter of post:

1. Matrix Structure

2. Matrix Functions

3. Implement Four Arithmetic Operations

4. Let's Go

https://github.com/SnowyPainter/Matrix

 

SnowyPainter/Matrix

Contribute to SnowyPainter/Matrix development by creating an account on GitHub.

github.com

First, Let's struct a structure (haha)

Let's create a matrix moudle and make a constructor.

The directory sturcture follow as:

matrix module folder, Matrix execute file, go.mod is just a package versioning file that you can create that 'go mod init <projectname>' and last main.go which would help test our matrix program.

next, matrix/matrix.go

package matrix

//Matrix contains Matrix raw
type Matrix struct {
	raw    [][]float64
	Row    int
	Column int
}

The Matrix structure has 3 properties, raw, Row, Column.

Row and Column are raw's data size. In go, if you want to make a property private then make its name's first charactor to lower case. Likewise the public property must be uppercase.

We made a Matrix struct, then next is make a constructor. add the code snippet under into matrix/matrix.go.

//NewMatrix creats new Matrix structure
func NewMatrix(row int, col int) *Matrix {
	r := make([][]float64, col)
	for i := range r {
		r[i] = make([]float64, row)
	}

	return &Matrix{
		raw:    r,
		Row:    row,
		Column: col,
	}
}

NewMatrix function initialize all arrays and put it on matrix reference variable to return.

 

 

Second, Implement Matrix struct functions

There are many functions we have to implement let's implement every functions step by step. first, we need make every get, set columns and rows functions. Step by Step, Easy get functions fisrt.

//GetColumn returns column of index
func (m *Matrix) GetColumn(index int) (array []float64) {
	array = make([]float64, m.Column)
	for i, r := range m.raw {
		array[i] = r[index]
	}
	return
}

//GetRow returns row of index
func (m *Matrix) GetRow(index int) []float64 {
	return m.raw[index]
}

These functions are get data by index. It's easy. Next is Set functions

//SetColumn set raw
func (m *Matrix) SetColumn(index int, data []float64) {
	for i, r := range m.raw {
		if i < len(data) {
			r[index] = data[i]
			continue
		}
		r[index] = 0
	}
}

//SetRow set raw
func (m *Matrix) SetRow(index int, data []float64) {
	if len(data) == m.Row {
		m.raw[index] = data
		return
	}

	for i := 0; i < m.Row; i++ {
		if i >= len(data) {
			m.raw[index][i] = 0
			continue
		}
		m.raw[index][i] = data[i]
	}
}

Set functions are easy too. just a for expressions.

 

Third, Implement four arithmetic operations

Actually more than four and some additional functions(e.g. transpose) so that are too long and maybe boring.

package matrix

import (
	"errors"
)

//ErrMatrixesNotCoincided error
var ErrMatrixesNotCoincided error = errors.New("Two Matrixes are Not Coincided")

//ErrMatrixesNotBeMultiplicable error
var ErrMatrixesNotBeMultiplicable error = errors.New("Two Matrixes Row and Col not same")

//ElementAddHandler handles custom + or -
type ElementAddHandler func(float64, float64) float64

func checkCoincide(m1 *Matrix, m2 *Matrix) bool {
	if m1.Row != m2.Row || m1.Column != m2.Column {
		return false
	}
	return true
}
func checkMultiplicable(m1 *Matrix, m2 *Matrix) bool {
	if m1.Row != m2.Column {
		return false
	}

	return true
}

//Add sum each matrix
func (m *Matrix) add(matrix *Matrix, handler ElementAddHandler) *Matrix {
	result := NewMatrix(m.Row, m.Column)
	for i := 0; i < m.Column; i++ {
		rowSum := make([]float64, m.Row)
		r1 := m.GetRow(i)
		r2 := matrix.GetRow(i)
		for j := 0; j < m.Row; j++ {
			rowSum[j] = handler(r1[j], r2[j])
		}
		result.SetRow(i, rowSum)
	}
	return result
}

//Plus Add two matrixes '+'
func (m *Matrix) Plus(mat *Matrix) (*Matrix, error) {
	if !checkCoincide(m, mat) {
		return nil, ErrMatrixesNotCoincided
	}

	return m.add(mat, func(a float64, b float64) float64 {
		return a + b
	}), nil
}

//Minus Add two matrixes '-'
func (m *Matrix) Minus(mat *Matrix) (*Matrix, error) {
	if !checkCoincide(m, mat) {
		return nil, ErrMatrixesNotCoincided
	}

	return m.add(mat, func(a float64, b float64) float64 {
		return a - b
	}), nil
}

//ScalarMultiply multiply constant value
func (m *Matrix) ScalarMultiply(c float64) *Matrix {
	result := NewMatrix(m.Row, m.Column)
	for i := 0; i < m.Column; i++ {
		rowSum := make([]float64, m.Row)
		for j, v := range m.GetRow(i) {
			rowSum[j] = v * c
		}
		result.SetRow(i, rowSum)
	}
	return result
}

//Multiply Multiply each matrixes
func (m *Matrix) Multiply(mat *Matrix) (*Matrix, error) {
	if !checkMultiplicable(m, mat) {
		return nil, ErrMatrixesNotBeMultiplicable
	}

	result := NewMatrix(mat.Row, m.Column)

	for i := 0; i < m.Column; i++ {
		tmp := make([]float64, m.Row)
		row := m.GetRow(i)
		for j := 0; j < mat.Row; j++ {
			for k, n := range mat.GetColumn(j) {
				tmp[j] += row[k] * n
			}
		}
		result.SetRow(i, tmp)
	}

	return result, nil
}

//Transpose return transpose matrix
func (m *Matrix) Transpose() (matrix *Matrix) {
	matrix = NewMatrix(m.Column, m.Row)

	for i := 0; i < m.Row; i++ { //transposed matrix's col == original.row
		matrix.SetRow(i, m.GetColumn(i))
	}

	return matrix
}

The code above is whole code of matrix/calculate.go. copy & paste it.

Actually all the functions need not explain. everyone know how to add each matrix, multiply... 

 

Fourth, Test go!

package main

import (
	"fmt"

	"github.com/snowypainter/Matrix/matrix"
)

func main() {
	m := matrix.NewMatrix(2, 3)
	m.SetRow(0, []float64{1, 2})
	m.SetRow(1, []float64{3, 4})
	m.SetRow(2, []float64{5, 6})

	m2 := matrix.NewMatrix(2, 2)
	m2.SetRow(0, []float64{1, 3})
	m2.SetRow(1, []float64{2, 4})

	fmt.Println(m)
	fmt.Println(m.Transpose())

	return
}

Thank you

반응형

관련글 더보기