|
@@ -1786,28 +1786,35 @@ range_statements_with_multiple_return_values :: proc() {
|
|
|
data[i] = i32(i*i)
|
|
|
}
|
|
|
|
|
|
- {
|
|
|
+ { // Manual Style
|
|
|
it := make_my_iterator(data)
|
|
|
- for val in my_iterator(&it) {
|
|
|
+ for {
|
|
|
+ val, _, cond := my_iterator(&it)
|
|
|
+ if !cond {
|
|
|
+ break
|
|
|
+ }
|
|
|
fmt.println(val)
|
|
|
}
|
|
|
}
|
|
|
- {
|
|
|
+ { // or_break
|
|
|
it := make_my_iterator(data)
|
|
|
- for val, idx in my_iterator(&it) {
|
|
|
- fmt.println(val, idx)
|
|
|
+ loop: for {
|
|
|
+ val, _ := my_iterator(&it) or_break loop
|
|
|
+ fmt.println(val)
|
|
|
}
|
|
|
}
|
|
|
- {
|
|
|
+ { // first value
|
|
|
it := make_my_iterator(data)
|
|
|
- for {
|
|
|
- val, _, cond := my_iterator(&it)
|
|
|
- if !cond {
|
|
|
- break
|
|
|
- }
|
|
|
+ for val in my_iterator(&it) {
|
|
|
fmt.println(val)
|
|
|
}
|
|
|
}
|
|
|
+ { // first and second value
|
|
|
+ it := make_my_iterator(data)
|
|
|
+ for val, idx in my_iterator(&it) {
|
|
|
+ fmt.println(val, idx)
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
|
|
@@ -2072,7 +2079,7 @@ or_else_operator :: proc() {
|
|
|
// have optional ok semantics
|
|
|
v: union{int, f64}
|
|
|
i: int
|
|
|
- i = v.(int) or_else 123
|
|
|
+ i = v.(int) or_else 123
|
|
|
i = v.? or_else 123 // Type inference magic
|
|
|
assert(i == 123)
|
|
|
|
|
@@ -2178,6 +2185,70 @@ or_return_operator :: proc() {
|
|
|
foo_2()
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+or_break_and_or_continue_operators :: proc() {
|
|
|
+ fmt.println("\n#'or_break' and 'or_continue'")
|
|
|
+ // The concept of 'or_break' and 'or_continue' is very similar to that of 'or_return'.
|
|
|
+ // The difference is that unlike 'or_return', the value does not get returned from
|
|
|
+ // the current procedure but rather discarded if it is 'false' or not 'nil', and then
|
|
|
+ // the specified branch (i.e. break or_continue).
|
|
|
+ // The or branch expression can be labelled if a specific statement needs to be used.
|
|
|
+
|
|
|
+ Error :: enum {
|
|
|
+ None,
|
|
|
+ Something_Bad,
|
|
|
+ Something_Worse,
|
|
|
+ The_Worst,
|
|
|
+ Your_Mum,
|
|
|
+ }
|
|
|
+
|
|
|
+ caller_1 :: proc() -> Error {
|
|
|
+ return .Something_Bad
|
|
|
+ }
|
|
|
+
|
|
|
+ caller_2 :: proc() -> (int, Error) {
|
|
|
+ return 123, .Something_Worse
|
|
|
+ }
|
|
|
+ caller_3 :: proc() -> (int, int, Error) {
|
|
|
+ return 123, 345, .None
|
|
|
+ }
|
|
|
+
|
|
|
+ for { // common approach
|
|
|
+ err := caller_1()
|
|
|
+ if err != nil {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for { // or_break approach
|
|
|
+ caller_1() or_break
|
|
|
+ }
|
|
|
+
|
|
|
+ for { // or_break approach with multiple values
|
|
|
+ n := caller_2() or_break
|
|
|
+ _ = n
|
|
|
+ }
|
|
|
+
|
|
|
+ loop: for { // or_break approach with named label
|
|
|
+ n := caller_2() or_break loop
|
|
|
+ _ = n
|
|
|
+ }
|
|
|
+
|
|
|
+ for { // or_continue
|
|
|
+ x, y := caller_3() or_continue
|
|
|
+ _, _ = x, y
|
|
|
+
|
|
|
+ break
|
|
|
+ }
|
|
|
+
|
|
|
+ continue_loop: for { // or_continue with named label
|
|
|
+ x, y := caller_3() or_continue continue_loop
|
|
|
+ _, _ = x, y
|
|
|
+
|
|
|
+ break
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
arbitrary_precision_mathematics :: proc() {
|
|
|
fmt.println("\n# core:math/big")
|
|
|
|
|
@@ -2258,98 +2329,98 @@ 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)
|
|
|
+ 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,
|
|
|
+ 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,
|
|
|
+ 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
|
|
|
+
|
|
|
+ { // 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
|
|
@@ -2359,9 +2430,9 @@ matrix_type :: proc() {
|
|
|
|
|
|
// component-wise multiplication
|
|
|
// since a * b would be a standard matrix multiplication
|
|
|
- c6 := hadamard_product(a, b)
|
|
|
-
|
|
|
-
|
|
|
+ c6 := hadamard_product(a, b)
|
|
|
+
|
|
|
+
|
|
|
fmt.println("a + b", c0)
|
|
|
fmt.println("a - b", c1)
|
|
|
fmt.println("a & b", c2)
|
|
@@ -2370,23 +2441,23 @@ matrix_type :: proc() {
|
|
|
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.
|
|
|
+ // 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
|
|
|
+ // 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)
|
|
@@ -2394,7 +2465,7 @@ matrix_type :: proc() {
|
|
|
fmt.println("m4", m4)
|
|
|
fmt.println("mat2(m4)", mat2(m4))
|
|
|
assert(mat2(m4) == m2)
|
|
|
-
|
|
|
+
|
|
|
b4 := mat4{
|
|
|
1, 2, 0, 0,
|
|
|
3, 4, 0, 0,
|
|
@@ -2403,43 +2474,43 @@ matrix_type :: proc() {
|
|
|
}
|
|
|
fmt.println("b4", matrix_flatten(b4))
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
{ // Casting non-square matrices
|
|
|
- // Casting a matrix to another matrix is allowed as long as they share
|
|
|
+ // 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,
|
|
|
+ 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) vector instructions effectively on
|
|
|
+ // Column-major is used in order to utilize (SIMD) vector instructions effectively on
|
|
|
// modern hardware, if possible.
|
|
|
//
|
|
|
// 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.
|
|
|
- // Padding between columns was not taken even if that would have allowed each column to be loaded
|
|
|
- // individually into a SIMD register with the correct alignment properties.
|
|
|
- //
|
|
|
+ // Padding between columns was not taken even if that would have allowed each column to be loaded
|
|
|
+ // individually into a SIMD register with the correct alignment properties.
|
|
|
+ //
|
|
|
// 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
|
|
@@ -2454,13 +2525,13 @@ matrix_type :: proc() {
|
|
|
// Example:
|
|
|
// m := matrix[2, 2]f32{
|
|
|
// x0, x1,
|
|
|
- // y0, y1,
|
|
|
+ // 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)
|
|
@@ -2474,8 +2545,8 @@ matrix_type :: proc() {
|
|
|
main :: proc() {
|
|
|
/*
|
|
|
For More Odin Examples - https://github.com/odin-lang/examples
|
|
|
- This repository contains examples of how certain things can be accomplished
|
|
|
- in idiomatic Odin, allowing you learn its semantics, as well as how to use
|
|
|
+ This repository contains examples of how certain things can be accomplished
|
|
|
+ in idiomatic Odin, allowing you learn its semantics, as well as how to use
|
|
|
parts of the core and vendor package collections.
|
|
|
*/
|
|
|
|
|
@@ -2513,7 +2584,8 @@ main :: proc() {
|
|
|
relative_data_types()
|
|
|
or_else_operator()
|
|
|
or_return_operator()
|
|
|
+ or_break_and_or_continue_operators()
|
|
|
arbitrary_precision_mathematics()
|
|
|
matrix_type()
|
|
|
}
|
|
|
-}
|
|
|
+}
|