mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-09 21:11:36 -07:00
Add matrix_type to demo.odin
This commit is contained in:
@@ -2203,6 +2203,212 @@ arbitrary_precision_maths :: proc() {
|
||||
print_bigint("\nLCM of random prime A and random number B (in base 36): ", d, 36)
|
||||
}
|
||||
|
||||
matrix_type :: proc() {
|
||||
fmt.println("\n# matrix type")
|
||||
// A matrix is a mathematical type built into Odin. It is a regular array of numbers,
|
||||
// arranged in rows and columns
|
||||
|
||||
{
|
||||
// The following represents a matrix that has 2 rows and 3 columns
|
||||
m: matrix[2, 3]f32
|
||||
|
||||
m = matrix[2, 3]f32{
|
||||
1, 9, -13,
|
||||
20, 5, -6,
|
||||
}
|
||||
|
||||
// Element types of integers, float, and complex numbers are supported by matrices.
|
||||
// There is no support for booleans, quaternions, or any compound type.
|
||||
|
||||
// Indexing a matrix can be used with the matrix indexing syntax
|
||||
// This mirrors othe type usages: type on the left, usage on the right
|
||||
|
||||
elem := m[1, 2] // row 1, column 2
|
||||
assert(elem == -6)
|
||||
|
||||
|
||||
// Scalars act as if they are scaled identity matrices
|
||||
// and can be assigned to matrices as them
|
||||
b := matrix[2, 2]f32{}
|
||||
f := f32(3)
|
||||
b = f
|
||||
|
||||
fmt.println("b", b)
|
||||
fmt.println("b == f", b == f)
|
||||
|
||||
}
|
||||
|
||||
{ // Matrices support multiplication between matrices
|
||||
a := matrix[2, 3]f32{
|
||||
2, 3, 1,
|
||||
4, 5, 0,
|
||||
}
|
||||
|
||||
b := matrix[3, 2]f32{
|
||||
1, 2,
|
||||
3, 4,
|
||||
5, 6,
|
||||
}
|
||||
|
||||
fmt.println("a", a)
|
||||
fmt.println("b", b)
|
||||
|
||||
c := a * b
|
||||
#assert(type_of(c) == matrix[2, 2]f32)
|
||||
fmt.tprintln("c = a * b", c)
|
||||
}
|
||||
|
||||
{ // Matrices support multiplication between matrices and arrays
|
||||
m := matrix[4, 4]f32{
|
||||
1, 2, 3, 4,
|
||||
5, 5, 4, 2,
|
||||
0, 1, 3, 0,
|
||||
0, 1, 4, 1,
|
||||
}
|
||||
|
||||
v := [4]f32{1, 5, 4, 3}
|
||||
|
||||
// treating 'v' as a column vector
|
||||
fmt.println("m * v", m * v)
|
||||
|
||||
// treating 'v' as a row vector
|
||||
fmt.println("v * m", v * m)
|
||||
|
||||
// Support with non-square matrices
|
||||
s := matrix[2, 4]f32{ // [4][2]f32
|
||||
2, 4, 3, 1,
|
||||
7, 8, 6, 5,
|
||||
}
|
||||
|
||||
w := [2]f32{1, 2}
|
||||
r: [4]f32 = w * s
|
||||
fmt.println("r", r)
|
||||
}
|
||||
|
||||
{ // Component-wise operations
|
||||
// if the element type supports it
|
||||
// Not support for '/', '%', or '%%' operations
|
||||
|
||||
a := matrix[2, 2]i32{
|
||||
1, 2,
|
||||
3, 4,
|
||||
}
|
||||
|
||||
b := matrix[2, 2]i32{
|
||||
-5, 1,
|
||||
9, -7,
|
||||
}
|
||||
|
||||
c0 := a + b
|
||||
c1 := a - b
|
||||
c2 := a & b
|
||||
c3 := a | b
|
||||
c4 := a ~ b
|
||||
c5 := a &~ b
|
||||
|
||||
// component-wise multiplication
|
||||
// since a * b would be a standard matrix multiplication
|
||||
c6 := hadamard_product(a, b)
|
||||
|
||||
|
||||
fmt.println("a + b", c0)
|
||||
fmt.println("a - b", c1)
|
||||
fmt.println("a & b", c2)
|
||||
fmt.println("a | b", c3)
|
||||
fmt.println("a ~ b", c4)
|
||||
fmt.println("a &~ b", c5)
|
||||
fmt.println("hadamard_product(a, b)", c6)
|
||||
}
|
||||
|
||||
{ // Submatrix casting square matrices
|
||||
// Casting a square matrix to another square matrix with same element type
|
||||
// is supported.
|
||||
// If the cast is to a smaller matrix type, the top-left submatrix is taken.
|
||||
// If the cast is to a larger matrix type, the matrix is extended with zeros
|
||||
// everywhere and ones in the diagonal for the unfilled elements of the
|
||||
// extended matrix.
|
||||
|
||||
mat2 :: distinct matrix[2, 2]f32
|
||||
mat4 :: distinct matrix[4, 4]f32
|
||||
|
||||
m2 := mat2{
|
||||
1, 3,
|
||||
2, 4,
|
||||
}
|
||||
|
||||
m4 := mat4(m2)
|
||||
assert(m4[2, 2] == 1)
|
||||
assert(m4[3, 3] == 1)
|
||||
fmt.println("m2", m2)
|
||||
fmt.println("m4", m4)
|
||||
fmt.println("mat2(m4)", mat2(m4))
|
||||
assert(mat2(m4) == m2)
|
||||
}
|
||||
|
||||
{ // Casting non-square matrices
|
||||
// Casting a matrix to another matrix is allowed as long as they share
|
||||
// the same element type and the number of elements (rows*columns).
|
||||
// Matrices in Odin are stored in column-major order, which means
|
||||
// the casts will preserve this element order.
|
||||
|
||||
mat2x4 :: distinct matrix[2, 4]f32
|
||||
mat4x2 :: distinct matrix[4, 2]f32
|
||||
|
||||
x := mat2x4{
|
||||
1, 3, 5, 7,
|
||||
2, 4, 6, 8,
|
||||
}
|
||||
|
||||
y := mat4x2(x)
|
||||
fmt.println("x", x)
|
||||
fmt.println("y", y)
|
||||
}
|
||||
|
||||
// TECHNICAL INFORMATION: the internal representation of a matrix in Odin is stored
|
||||
// in column-major format
|
||||
// e.g. matrix[2, 3]f32 is internally [3][2]f32 (with different a alignment requirement)
|
||||
// Column-major is used in order to utilize SIMD instructions effectively on modern hardware
|
||||
//
|
||||
// Unlike normal arrays, matrices try to maximize alignment to allow for the (SIMD) vectorization
|
||||
// properties whilst keeping zero padding (either between columns or at the end of the type).
|
||||
//
|
||||
// Zero padding is a compromise for use with third-party libraries, instead of optimizing for performance
|
||||
//
|
||||
// Currently, matrices are limited to a maximum of 16 elements (rows*columns), and a minimum of 1 element.
|
||||
// This is because matrices are stored as values (not a reference type), and thus operations on them will
|
||||
// be stored on the stack. Restricting the maximum element count minimizing the possibility of stack overflows.
|
||||
|
||||
// Built-in Procedures (Compiler Level)
|
||||
// transpose(m)
|
||||
// transposes a matrix
|
||||
// outer_product(a, b)
|
||||
// takes two array-like data types and returns the outer product
|
||||
// of the values in a matrix
|
||||
// hadamard_product(a, b)
|
||||
// component-wise multiplication of two matrices of the same type
|
||||
// matrix_flatten(m)
|
||||
// converts the matrix into a flatten array of elements
|
||||
// in column-major order
|
||||
// Example:
|
||||
// m := matrix[2, 2]f32{
|
||||
// x0, x1,
|
||||
// y0, y1,
|
||||
// }
|
||||
// array: [4]f32 = matrix_flatten(m)
|
||||
// assert(array == {x0, y0, x1, y1})
|
||||
// conj(x)
|
||||
// conjugates the elements of a matrix for complex element types only
|
||||
|
||||
// Built-in Procedures (Runtime Level) (all square matrix procedures)
|
||||
// determinant(m)
|
||||
// adjugate(m)
|
||||
// inverse(m)
|
||||
// inverse_transpose(m)
|
||||
// hermitian_adjoint(m)
|
||||
// matrix_trace(m)
|
||||
// matrix_minor(m)
|
||||
}
|
||||
|
||||
main :: proc() {
|
||||
when true {
|
||||
the_basics()
|
||||
@@ -2238,5 +2444,6 @@ main :: proc() {
|
||||
or_else_operator()
|
||||
or_return_operator()
|
||||
arbitrary_precision_maths()
|
||||
matrix_type()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user