Matft
Numpy-like library in swift. (Multi-dimensional Array, ndarray, matrix and vector library)
Install / Use
/learn @jjjkkkjjj/MatftREADME
Matft
Matft is Numpy-like library in Swift. Function name and usage is similar to Numpy.
INFO: Support Complex!!
<strike> Note: You can use [Protocol version(beta version)](https://github.com/jjjkkkjjj/Matft/tree/protocol) too. </strike>Feature & Usage
-
Many types
-
Pretty print
-
Indexing
- Positive
- Negative
- Boolean
- Fancy
- Complex
-
Slicing
- Start / To / By
- New Axis
-
View
- Assignment
-
Conversion
- Broadcast
- Transpose
- Reshape
- Astype
-
Univarsal function reduction
-
Mathematic
- Arithmetic
- Statistic
- Linear Algebra
-
Complex
-
Image Conversion
...etc.
See Function List for all functions.
Declaration
MfArray
-
The MfArray such like a numpy.ndarray
let a = MfArray([[[ -8, -7, -6, -5], [ -4, -3, -2, -1]], [[ 0, 1, 2, 3], [ 4, 5, 6, 7]]]) let aa = Matft.arange(start: -8, to: 8, by: 1, shape: [2,2,4]) print(a) print(aa) /* mfarray = [[[ -8, -7, -6, -5], [ -4, -3, -2, -1]], [[ 0, 1, 2, 3], [ 4, 5, 6, 7]]], type=Int, shape=[2, 2, 4] mfarray = [[[ -8, -7, -6, -5], [ -4, -3, -2, -1]], [[ 0, 1, 2, 3], [ 4, 5, 6, 7]]], type=Int, shape=[2, 2, 4] */
MfType
-
You can pass MfType as MfArray's argument
mftype: .Hoge. It is similar todtype.※Note that stored data type will be Float or Double only even if you set MfType.Int. So, if you input big number to MfArray, it may be cause to overflow or strange results in any calculation (+, -, *, /,... etc.). But I believe this is not problem in practical use.
-
MfType's list is below
public enum MfType: Int{ case None // Unsupportted case Bool case UInt8 case UInt16 case UInt32 case UInt64 case UInt case Int8 case Int16 case Int32 case Int64 case Int case Float case Double case Object // Unsupported } -
Also, you can convert MfType easily using
astypelet a = MfArray([[[ -8, -7, -6, -5], [ -4, -3, -2, -1]], [[ 0, 1, 2, 3], [ 4, 5, 6, 7]]]) print(a)//See above. if mftype is not passed, MfArray infer MfType. In this example, it's MfType.Int let a = MfArray([[[ -8, -7, -6, -5], [ -4, -3, -2, -1]], [[ 0, 1, 2, 3], [ 4, 5, 6, 7]]], mftype: .Float) print(a) /* mfarray = [[[ -8.0, -7.0, -6.0, -5.0], [ -4.0, -3.0, -2.0, -1.0]], [[ 0.0, 1.0, 2.0, 3.0], [ 4.0, 5.0, 6.0, 7.0]]], type=Float, shape=[2, 2, 4] */ let aa = MfArray([[[ -8, -7, -6, -5], [ -4, -3, -2, -1]], [[ 0, 1, 2, 3], [ 4, 5, 6, 7]]], mftype: .UInt) print(aa) /* mfarray = [[[ 4294967288, 4294967289, 4294967290, 4294967291], [ 4294967292, 4294967293, 4294967294, 4294967295]], [[ 0, 1, 2, 3], [ 4, 5, 6, 7]]], type=UInt, shape=[2, 2, 4] */ //Above output is same as numpy! /* >>> np.arange(-8, 8, dtype=np.uint32).reshape(2,2,4) array([[[4294967288, 4294967289, 4294967290, 4294967291], [4294967292, 4294967293, 4294967294, 4294967295]], [[ 0, 1, 2, 3], [ 4, 5, 6, 7]]], dtype=uint32) */ print(aa.astype(.Float)) /* mfarray = [[[ -8.0, -7.0, -6.0, -5.0], [ -4.0, -3.0, -2.0, -1.0]], [[ 0.0, 1.0, 2.0, 3.0], [ 4.0, 5.0, 6.0, 7.0]]], type=Float, shape=[2, 2, 4] */
Subscription
MfSlice
- You can access specific data using subscript.
You can set MfSlice (see below's list) to subscript.
-
MfSlice(start: Int? = nil, to: Int? = nil, by: Int = 1) -
Matft.newaxis -
~< //this is prefix, postfix and infix operator. same as python's slice, ":" -
Matft.all // same as python's slice :, matft's 0~< -
Matft.reverse // same as python's slice ::-1, matft's ~<<-1
(Positive) Indexing
-
Normal indexing
let a = Matft.arange(start: 0, to: 27, by: 1, shape: [3,3,3]) print(a) /* mfarray = [[[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8]], [[ 9, 10, 11], [ 12, 13, 14], [ 15, 16, 17]], [[ 18, 19, 20], [ 21, 22, 23], [ 24, 25, 26]]], type=Int, shape=[3, 3, 3] */ print(a[2,1,0]) // 21Caution
MfArray conforms to Collection protocol, so 1D MfArray returns MfArray! Use
itemas workaround instead of subscription such likelet a = Matft.arange(start: 0, to: 27, by: 1, shape: [27]) print(a[0]) /* 0 // a[0] is MfArray!! Nevertheless, The scalar is printed (I don't know why...) */ print(a[0] + 4) /* mfarray = [ 4], type=Int, shape=[1] */ // Workaround print(a.item(index: 0, type: Int.self)) /* 0 */ print(a.item(index: 0, type: Int.self) + 4) /* 4 */Slicing
-
If you replace
:with~<, you can get sliced mfarray. Note that usea[0~<]instead ofa[:]to get all elements along axis.print(a[~<1]) //same as a[:1] for numpy /* mfarray = [[[ 9, 10, 11], [ 12, 13, 14], [ 15, 16, 17]]], type=Int, shape=[1, 3, 3] */ print(a[1~<3]) //same as a[1:3] for numpy /* mfarray = [[[ 9, 10, 11], [ 12, 13, 14], [ 15, 16, 17]], [[ 18, 19, 20], [ 21, 22, 23], [ 24, 25, 26]]], type=Int, shape=[2, 3, 3] */ print(a[~<~<2]) //same as a[::2] for numpy //print(a[~<<2]) //alias /* mfarray = [[[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8]], [[ 18, 19, 20], [ 21, 22, 23], [ 24, 25, 26]]], type=Int, shape=[2, 3, 3] */ print(a[Matft.all, 0]) //same as a[:, 0] for numpy /* mfarray = [[ 0, 1, 2], [ 9, 10, 11], [18, 19, 20]], type=Int, shape=[3, 3] */
Negative Indexing
-
Negative indexing is also available That's implementation was hardest for me...
print(a[~<-1]) /* mfarray = [[[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8]], [[ 9, 10, 11], [ 12, 13, 14], [ 15, 16, 17]]], type=Int, shape=[2, 3, 3] */ print(a[-1~<-3]) /* mfarray = [], type=Int, shape=[0, 3, 3] */ print(a[Matft.reverse]) //print(a[~<~<-1]) //alias //print(a[~<<-1]) //alias /* mfarray = [[[ 18, 19, 20], [ 21, 22, 23], [ 24, 25, 26]], [[ 9, 10, 11], [ 12, 13, 14], [ 15, 16, 17]], [[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8]]], type=Int, shape=[3, 3, 3]*/
Boolean Indexing
-
You can use boolean indexing.
<strike>Caution! I don't check performance, so this boolean indexing may be slow</strike>
Unfortunately, Matft is too slower than numpy...
(numpy is 1ms, Matft is 7ms...)
let img = MfArray([[1, 2, 3], [4, 5, 6], [7, 8, 9]], mftype: .UInt8) img[img > 3] = MfArray([10], mftype: .UInt8) print(img) /* mfarray = [[ 1, 2, 3], [ 10, 10, 10], [ 10, 10, 10]], type=UInt8, shape=[3, 3] */
Fancy Indexing
-
You can use fancy indexing!!!
let a = MfArray([[1, 2], [3, 4], [5, 6]]) a[MfArray([0, 1, 2]), MfArray([0, -1, 0])] = MfArray([999,888,777]) print(a) /* mfarray = [[ 999, 2], [ 3, 888], [ 777, 6]], type=Int, shape=[3, 2] */ a.T[MfArray([0, 1, -1]), MfArray([0, 1, 0])] = MfArray([-999,-888,-777]) print(a) /* mfarray = [[ -999, -777], [ 3, -888], [ 777, 6]], type=Int, shape=[3, 2] */
View
-
Note that returned subscripted mfarray will have
baseproperty (is similar toviewin Numpy). See numpy doc in detail.let a = Matft.arange(start: 0, to: 4*4*2, by: 1, shape: [4,4,2]) let b = a[0~<, 1] b[~<<-1] = MfArray([9999]) // cannot pass Int directly such like 9999 print(a) /* mfarray = [[[ 0, 1], [ 9999, 9999], [ 4, 5], [ 6, 7]], [[ 8, 9], [ 9999, 9999], [ 12, 13], [ 14, 15]], [[ 16, 17], [ 9999, 9999], [ 20, 21], [ 22, 23]], [[ 24, 25], [ 9999, 9999], [ 28, 29], [ 30, 31]]], type=Int, shape=[4, 4, 2] */
Complex
Matft supports Complex!!
But this is beta version. so, any bug may be ocurred.
Please report me by issue
Related Skills
healthcheck
339.3kHost security hardening and risk-tolerance configuration for OpenClaw deployments
imsg
339.3kiMessage/SMS CLI for listing chats, history, and sending messages via Messages.app.
node-connect
339.3kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
xurl
339.3kA CLI tool for making authenticated requests to the X (Twitter) API. Use this skill when you need to post tweets, reply, quote, search, read posts, manage followers, send DMs, upload media, or interact with any X API v2 endpoint.
