Mojo-Numerics-and-Algorithms-group / NuMojo

NuMojo is a library for numerical computing in Mojo 🔥 similar to numpy in Python.
Apache License 2.0
112 stars 15 forks source link

[add] Add `Matrix` type (2D array) #138

Closed forFudan closed 3 days ago

forFudan commented 3 weeks ago

Add Matrix type (2D array) in numojo.core.mat module. It is like numpy.matrix type. It provides:

Because the number of dimensions is known at the compile time, the Matrix type gains advantages in the running speed compared to the NDArray type when the users only want to deal with the matrices manipulation, and it can also be more consistent with numpy.matrix, for example:

TODO: In future, we can also make use of the trait ArrayLike to align the behavior of NDArray type and the Matrix type.

Example slicing:

> from numojo.prelude import *
> from numojo import mat
> var A = mat.fromstring[i32](
>     "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16", (4, 4)
> )
> print(A)
[[1     2       3       4]
 [5     6       7       8]
 [9     10      11      12]
 [13    14      15      16]]
Size: 4x4  DType: int32
> print(A[0:-1:2, 1:4:1])
[[2     3       4]
 [10    11      12]]
Size: 2x3  DType: int32
> print(A[:, 1:-1:2])
[[2]
 [6]
 [10]
 [14]]
Size: 4x1  DType: int32
> print(A[:, 2])
[[3]
 [7]
 [11]
 [15]]
Size: 4x1  DType: int32
> print(A[-1, :])
[[13    14      15      16]]
Size: 1x4  DType: int32
> print(A[:, -2])
[[3]
 [7]
 [11]
 [15]]
Size: 4x1  DType: int32
> print(A[-2])
[[9     10      11      12]]
Size: 1x4  DType: int32

Examples broadcasting:

> from numojo import mat
> a = mat.fromstring("1 2 3", shape=(1, 3))
> print(mat.broadcast_to(a, (3, 3)))
[[1.0   2.0     3.0]
    [1.0   2.0     3.0]
    [1.0   2.0     3.0]]
> a = mat.fromstring("1 2 3", shape=(3, 1))
> print(mat.broadcast_to(a, (3, 3)))
[[1.0   1.0     1.0]
    [2.0   2.0     2.0]
    [3.0   3.0     3.0]]
> a = mat.fromstring("1", shape=(1, 1))
> print(mat.broadcast_to(a, (3, 3)))
[[1.0   1.0     1.0]
    [1.0   1.0     1.0]
    [1.0   1.0     1.0]]
> a = mat.fromstring("1 2", shape=(1, 2))
> print(mat.broadcast_to(a, (1, 2)))
[[1.0   2.0]]
> a = mat.fromstring("1 2 3 4", shape=(2, 2))
> print(mat.broadcast_to(a, (4, 2)))
Unhandled exception caught during execution: Cannot broadcast shape 2x2 to shape 4x2!

Examples calculation:

import numojo as nm
from numojo import mat
from numojo.prelude import *

fn main() raises:
    var A = mat.rand(shape=(4, 4))
    var B = mat.rand(shape=(4, 4))
    var C = mat.rand(shape=(4, 1))
    print(A + B)
    print(A - B)
    print(A * B)
    print(A @ B)
    print(C.T())
    print(mat.solve(A, B))
    print(mat.inv(A))
    print(mat.lstsq(A, C))
    print(A[1,1])
    print(A[2])
    for i in A:
        print(i)
[[0.17900230112507259   0.78688435818322744     0.97536967234506511     1.0442033876322623]
 [1.9172431825477732    1.2727722072283303      0.10725799328507851     1.4144073219568987]
 [0.44410959157723867   0.54457400238097575     0.9616795524855235      1.0969436951643456]
 [1.4245850644921205    0.71448328971403641     1.2057134894337875      1.0812309810840872]]
Size: 4x4  DType: float64
[[0.084073274352448712  0.13041590586321211     -0.5374512999201071     0.3135260458491087]
 [-0.047857390094295571 -0.23393946318283543    -0.038113772355383629   -0.35500693567478425]
 [-0.42871321945404034  -0.4108895278558406     0.41186587233256694     0.76392929477504001]
 [-0.37072750897230833  0.59335463464700899     0.19666769956456576     0.44316509891318107]]
Size: 4x4  DType: float64
[[0.0062433770869322648 0.15054467116282691     0.16562302448617663     0.24801553332922879]
 [0.91838277280981906   0.39130535476465073     0.0025129043700959854   0.46862953700702142]
 [0.0033595761990634029 0.031932659991909827    0.18879851621912264     0.15492437573632972]
 [0.47300093001630156   0.039604162205876509    0.35376670863764542     0.24316628239033203]]
Size: 4x4  DType: float64
[[1.1618336626560359    0.53442070082054172     0.53553012186636917     0.70686537021182994]
 [1.0452938203117723    0.74670068560309133     1.0215157301049123      0.97575914338110725]
 [1.2009688638228961    0.43732719838952505     0.66890650590034695     0.47314074187295319]
 [1.6577181167663226    1.0467327576541341      1.0234135822803136      1.1309537919135062]]
Size: 4x4  DType: float64
[[0.49397668520668309   0.090732894580629803    0.073749075222416957    0.38414214796805357]]
Size: 1x4  DType: float64
[[1.3725149272269348    0.61616917126146553     -0.95375915933913213    0.62127427275303182]
 [-0.49020448862530741  -0.8740285366786662     1.3840126497149174      -0.074267299862233419]
 [0.86080319628318269   -0.92275334539358389    -0.38511942911242053    -0.69494698482804995]
 [-0.14247533465107939  1.2522426057180509      0.48818814720304116     0.69210455195846554]]
Size: 4x4  DType: float64
[[-1.5555558895214847   1.25352509116357        0.37458099698785391     0.057066134017150424]
 [1.7455473386289457    -0.91209994222365609    -1.7436190267047393     1.2076596152560233]
 [-1.7028384482186347   -0.76564654439368218    0.22015670035475846     1.7800075091093974]
 [1.1443678907041122    0.62029175394639735     1.0344243733069187      -1.4010870902423451]]
Size: 4x4  DType: float64
[[-0.60512587258751216]
 [1.1148248881615339]
 [-0.21061955828829815]
 [0.15964316020994287]]
Size: 4x1  DType: float64
0.51941637202274749
[[0.007698186061599179  0.06684223726256755     0.68677271240904525     0.93043649496969283]]
Size: 1x4  DType: float64
[[0.13153778773876065   0.4586501320232198      0.21895918621247895     0.67886471674068549]]
Size: 1x4  DType: float64
[[0.93469289622673879   0.51941637202274749     0.034572110464847441    0.52970019314105721]]
Size: 1x4  DType: float64
[[0.007698186061599179  0.06684223726256755     0.68677271240904525     0.93043649496969283]]
Size: 1x4  DType: float64
[[0.5269287777599061    0.6539189621805227      0.70119059449917664     0.76219803999863411]]
Size: 1x4  DType: float64