Nuod (Numerical Odin) is an Odin package for creating, manipulating, and performing numerical operations on multi-dimensional arrays. It is inspired by the Numpy Python library.
Important
Noud is now in early access. It does pass all the tests; however, the tests are still limited. If you face any bugs, unexpected errors, or issue, please report it in the Issues section.
- A flexible multi-dimensional array type with various manipulation procedures.
- Various mathematical procedures.
- Multi-dimensional fast Fourier transform procedures.
- Basic linear algebra procedures.
- Several matrix factorization techniques.
- Random number methods with various generators.
The package is mostly documented through comments in the source code. However, by utilizing a fork of the official Odin documentation tool, Nuod has a static documentation site set up to help with navigation.
To add Nuod to your project, you may simply make a copy of the "nuod" folder and add it to your project's repository. Aside from the libraries and packages provided by the Odin language, Nuod makes use of only one dependency: OpenBLAS. For MacOS and Linux-based systems, installing the OpenBLAS library may be done globally for ease of use. However, in the case of Windows, copies of the static and dynamic OpenBLAS library files must be included. To facilitate usage, Nuod along with the required OpenBlas files are provided in the release section of this repository.
To install the OpenBlas dependency you may follow:
sudo apt update
sudo apt install libopenblas-dev
sudo dnf check-update
sudo dnf install openblas openblas-devel
sudo pacman -S openblas
sudo zypper refresh
sudo zypper install openblas-devel
brew install openblas
sudo port install OpenBLAS-devel
pkg install openblas
To use Nuod with Windows, you may use the "Nuod_win" release archive in the Releases section. The current release tag is v0.0.1.
package main
import "core:log"
import "core:fmt"
import md "nuod/mdarray"
import ml "nuod/linalg"
import rn "nuod/random"
import "core:math/rand"
main :: proc () {
// create a console logger to view log messages created by the library.
logger:= log.create_console_logger()
context.logger = logger
defer log.destroy_console_logger(logger)
// you can make use of the provided odin-compatible random number generators.
context.random_generator = rn.pcg_random_generator()
rand.reset(64)
// create a random array of type f64 with a dimensions (2, 3, 3)
arr := rn.random_float(f64, shape=[3]int{2, 3, 3})
// get a view slice of the first matrix of dimensions (3, 3)
first_matrix := md.slice_view(3, arr, index=0)
// transpose the first matrix
trans_matrix := md.transpose_copy(first_matrix)
// perform matrix multiplication on the two matrices.
inner_product := ml.matmul(trans_matrix, first_matrix)
fmt.println("Inner product: ")
md.println(inner_product)
// free the created arrays.
md.free_mdarray(arr)
md.free_mdarray(trans_matrix)
md.free_mdarray(inner_product)
}
package main
import "core:log"
import "core:fmt"
import md "nuod/mdarray"
import fft "nuod/fft"
import rn "nuod/random"
import "core:math/rand"
main :: proc () {
// create a console logger to view log messages created by the library.
logger:= log.create_console_logger()
context.logger = logger
defer log.destroy_console_logger(logger)
// you can make use of the provided odin-compatible random number generators.
context.random_generator = rn.pcg_random_generator()
rand.reset(64)
// create a random array of type f64 with a dimensions (2, 64),
// sampled from a normal distribution
arr := rn.normal_sample(
mean=f64(0.0),
stddev=f64(1.0),
shape=[2]int{2, 64}
)
// cast the array to complex type, this will generate an array of
arr_c := md.cast_array(arr, complex128)
// perform the two-dimensional fast Fourier transform.
f_arr := fft.fft2d(arr_c)
// take the inverse of the fft.
arr_c_ := fft.fft2d(f_arr, inverse=true)
// confirm that the arrays before and after the transform are very close!
fmt.assertf(
md.all_close(arr_c, arr_c_),
"The provided arrays aren't close :("
)
// subtract the two arrays to create an error array.
err_a := md.subtract(arr_c, arr_c_)
// perform the absolute operator in place.
md.i_abs(err_a)
// take the sum of all the errors in the absolute error array.
sae := real(md.all_reduce_sum(err_a))
fmt.printfln("Sum of Abs Errors: %v", sae)
// free the created arrays.
md.free_mdarray(arr)
md.free_mdarray(arr_c)
md.free_mdarray(f_arr)
md.free_mdarray(arr_c_)
md.free_mdarray(err_a)
}more examples will soon be provided!
Odin makes testing quite an easy task. Since Nuod has several subpackages you can run the tests by running the following command in your terminal:
odin test tests/ -all-packages
Special thanks to Kalsprite for providing OpenBLAS bindings.