Home

Awesome

Matft

SwiftPM compatible CocoaPods compatible Carthage compatible license

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

...etc.

See Function List for all functions.

Declaration

MfArray

MfType

Subscription

MfSlice

You can set MfSlice (see below's list) to subscript.

(Positive) Indexing

Negative Indexing

Boolean Indexing

Fancy Indexing

View

Complex

Matft supports Complex!!

But this is beta version. so, any bug may be ocurred.

Please report me by issue! (Progres

TODO

let real = Matft.arange(start: 0, to: 16, by: 1).reshape([2,2,4])
let imag = Matft.arange(start: 0, to: -16, by: -1).reshape([2,2,4])
let a = MfArray(real: real, imag: imag)
print(a)

/*
mfarray = 
[[[    0 +0j,        1 -1j,        2 -2j,        3 -3j],
[    4 -4j,        5 -5j,        6 -6j,        7 -7j]],

[[    8 -8j,        9 -9j,        10 -10j,        11 -11j],
[    12 -12j,        13 -13j,        14 -14j,        15 -15j]]], type=Int, shape=[2, 2, 4]
*/

print(a+a)
/*
mfarray = 
[[[    0 +0j,        2 -2j,        4 -4j,        6 -6j],
[    8 -8j,        10 -10j,        12 -12j,        14 -14j]],

[[    16 -16j,        18 -18j,        20 -20j,        22 -22j],
[    24 -24j,        26 -26j,        28 -28j,        30 -30j]]], type=Int, shape=[2, 2, 4]
*/

print(Matft.complex.angle(a))
/*
mfarray = 
[[[    -0.0,        -0.7853982,        -0.7853982,        -0.7853982],
[    -0.7853982,        -0.7853982,        -0.7853982,        -0.7853982]],

[[    -0.7853982,        -0.7853982,        -0.7853982,        -0.7853982],
[    -0.7853982,        -0.7853982,        -0.7853982,        -0.7853982]]], type=Float, shape=[2, 2, 4]
*/

print(Matft.complex.conjugate(a))
/*
mfarray = 
[[[    0 +0j,        1 +1j,        2 +2j,        3 +3j],
[    4 +4j,        5 +5j,        6 +6j,        7 +7j]],

[[    8 +8j,        9 +9j,        10 +10j,        11 +11j],
[    12 +12j,        13 +13j,        14 +14j,        15 +15j]]], type=Int, shape=[2, 2, 4]
*/

Image

You can acheive an image processing by Matft! (Beta version) Please refer to the example here.

@IBOutlet weak var originalImageView: UIImageView!
@IBOutlet weak var reverseImageView: UIImageView!
@IBOutlet weak var swapImageView: UIImageView!

func reverse(){
    var image = Matft.image.cgimage2mfarray(self.reverseImageView.image!.cgImage!)

    // reverse
    image = image[Matft.reverse] // same as image[~<<-1]
    self.reverseImageView.image = UIImage(cgImage: Matft.image.mfarray2cgimage(image))
}


func swapchannel(){
    var image = Matft.image.cgimage2mfarray(self.swapImageView.image!.cgImage!)

    // swap channel
    image = image[Matft.all, Matft.all, MfArray([1,0,2,3])] // same as image[0~<, 0~<, MfArray([1,0,2,3])]
    self.swapImageView.image = UIImage(cgImage: Matft.image.mfarray2cgimage(image))
}

For more complex conversion, see OpenCV code.

<img width="513" alt="Screen Shot 2022-07-19 at 21 09 02" src="https://user-images.githubusercontent.com/16914891/179746856-c4e8048d-3e7c-4835-b39c-ddf6af5b5fd7.png">

Function List

Below is Matft's function list. As I mentioned above, almost functions are similar to Numpy. Also, these function use Accelerate framework inside, the perfomance may keep high.

* means method function exists too. Shortly, you can use a.shallowcopy() where a is MfArray.

^ means method function only. Shortly, you can use a.tolist() not Matft.tolist where a is MfArray.

# means support complex operation

MatftNumpy
*#Matft.shallowcopy*numpy.copy
*#Matft.deepcopycopy.deepcopy
Matft.numsnumpy.ones * N
Matft.nums_likenumpy.ones_like * N
Matft.arangenumpy.arange
Matft.eyenumpy.eye
Matft.diagnumpy.diag
Matft.vstacknumpy.vstack
Matft.hstacknumpy.hstack
Matft.concatenatenumpy.concatenate
*Matft.appendnumpy.append
*Matft.insertnumpy.insert
*Matft.takenumpy.take
^MfArray.item^numpy.ndarray.item
MatftNumpy
*#Matft.astype*numpy.astype
*#Matft.transpose*numpy.transpose
*#Matft.expand_dims*numpy.expand_dims
*#Matft.squeeze*numpy.squeeze
*#Matft.broadcast_to*numpy.broadcast_to
*#Matft.to_contiguous*numpy.ascontiguousarray
*#Matft.flatten*numpy.flatten
*#Matft.flip*numpy.flip
*#Matft.clip*numpy.clip
*#Matft.swapaxes*numpy.swapaxes
*#Matft.moveaxis*numpy.moveaxis
*Matft.rollnumpy.roll
*Matft.sort*numpy.sort
*Matft.argsort*numpy.argsort
^MfArray.toArray^numpy.ndarray.tolist
^MfArray.toFlattenArrayn/a
^MfArray.toMLMultiArrayn/a
*Matft.orderedUniquenumpy.unique
MatftNumpy
Matft.file.loadtxtnumpy.loadtxt
Matft.file.genfromtxtnumpy.genfromtxt
Matft.file.savetxtnumpy.savetxt
MatftNumpy
#Matft.add<br />+numpy.add<br />+
#Matft.sub<br />-numpy.sub<br />-
#Matft.div<br />/numpy.div<br />.
#Matft.mul<br />*numpy.multiply<br />*
Matft.inner<br />*+numpy.inner<br />n/a
Matft.cross<br />*^numpy.cross<br />n/a
Matft.matmul<br />*&  numpy.matmul<br />@ 
Matft.dot   numpy.dot  
Matft.equal<br />===numpy.equal<br />==
Matft.not_equal<br />!==numpy.not_equal<br />!=
Matft.less<br /><numpy.less<br /><
Matft.less_equal<br /><=numpy.less_equal<br /><=
Matft.greater<br />>numpy.greater<br />>
Matft.greater_equal<br />>=numpy.greater_equal<br />>=
#Matft.allEqual<br />==numpy.array_equal<br />n/a
#Matft.neg<br />-numpy.negative<br />-
MatftNumpy
*#Matft.ufuncReduce<br />e.g.) Matft.ufuncReduce(a, Matft.add)numpy.add.reduce<br />e.g.) numpy.add.reduce(a)
*#Matft.ufuncAccumulate<br />e.g.) Matft.ufuncAccumulate(a, Matft.add)numpy.add.accumulate<br />e.g.) numpy.add.accumulate(a)
MatftNumpy
#Matft.math.sinnumpy.sin
Matft.math.asinnumpy.asin
Matft.math.sinhnumpy.sinh
Matft.math.asinhnumpy.asinh
#Matft.math.cosnumpy.cos
Matft.math.acosnumpy.acos
Matft.math.coshnumpy.cosh
Matft.math.acoshnumpy.acosh
#Matft.math.tannumpy.tan
Matft.math.atannumpy.atan
Matft.math.tanhnumpy.tanh
Matft.math.atanhnumpy.atanh
Matft.math.sqrtnumpy.sqrt
Matft.math.rsqrtnumpy.rsqrt
#Matft.math.expnumpy.exp
#Matft.math.lognumpy.log
Matft.math.log2numpy.log2
Matft.math.log10numpy.log10
*Matft.math.ceilnumpy.ceil
*Matft.math.floornumpy.floor
*Matft.math.truncnumpy.trunc
*Matft.math.nearestnumpy.nearest
*Matft.math.roundnumpy.round
#Matft.math.absnumpy.abs
Matft.math.reciprocalnumpy.reciprocal
#Matft.math.powernumpy.power
Matft.math.arctan2numpy.arctan2
Matft.math.squarenumpy.square
Matft.math.signnumpy.sign
MatftNumpy
*Matft.stats.mean*numpy.mean
*Matft.stats.max*numpy.max
*Matft.stats.argmax*numpy.argmax
*Matft.stats.min*numpy.min
*Matft.stats.argmin*numpy.argmin
*Matft.stats.sum*numpy.sum
Matft.stats.maximumnumpy.maximum
Matft.stats.minimumnumpy.minimum
*Matft.stats.sumsqrtn/a
*Matft.stats.squaresumn/a
*Matft.stats.cumsum*numpy.cumsum
MatftNumpy
Matft.random.randnumpy.random.rand
Matft.random.randintnumpy.random.randint
MatftNumpy
Matft.linalg.solvenumpy.linalg.solve
Matft.linalg.invnumpy.linalg.inv
Matft.linalg.detnumpy.linalg.det
Matft.linalg.eigennumpy.linalg.eig
Matft.linalg.svdnumpy.linalg.svd
Matft.linalg.pinvnumpy.linalg.pinv
Matft.linalg.polar_leftscipy.linalg.polar
Matft.linalg.polar_rightscipy.linalg.polar
Matft.linalg.normlp_vecscipy.linalg.norm
Matft.linalg.normfro_matscipy.linalg.norm
Matft.linalg.normnuc_matscipy.linalg.norm
MatftNumpy
Matft.complex.anglenumpy.angle
Matft.complex.conjugatenumpy.conj / numpy.conjugate
Matft.complex.absnumpy.abs / numpy.absolute
MatftNumpy
Matft.fft.rfftnumpy.fft.rfft
Matft.fft.irfftnumpy.fft.irfft

Matft supports only natural cubic spline. I'll implement other boundary condition later.

MatftScipy
Matft.interp1d.cubicSplinescipy.interpolation.CubicSpline
MatftNumpy
Matft.image.cgimage2mfarrayN/A
Matft.image.mfarray2cgimageN/A
MatftOpenCV
Matft.image.colorcv2.cvtColor
Matft.image.resizecv2.resize
Matft.image.warpAffinecv2.warpAffine

Performance

I use Accelerate framework, so all of MfArray operation may keep high performance.

let a = Matft.arange(start: 0, to: 10*10*10*10*10*10, by: 1, shape: [10,10,10,10,10,10])
let aneg = Matft.arange(start: 0, to: -10*10*10*10*10*10, by: -1, shape: [10,10,10,10,10,10])
let aT = a.T
let b = a.transpose(axes: [0,3,4,2,1,5])
let c = a.transpose(axes: [1,2,3,4,5,0])
let posb = a > 0
import numpy as np

a = np.arange(10**6).reshape((10,10,10,10,10,10))
aneg = np.arange(0, -10**6, -1).reshape((10,10,10,10,10,10))
aT = a.T
b = a.transpose((0,3,4,2,1,5))
c = a.transpose((1,2,3,4,5,0))
posb = a > 0
MatfttimeNumpytime
let _ = a+aneg596μsa+aneg1.04ms
let _ = b+aT4.46msb+aT4.31ms
let _ = c+aT5.31msc+aT2.92ms
MatfttimeNumpytime
let _ = Matft.math.sin(a)2.14msnp.sin(a)14.7ms
let _ = Matft.math.sin(b)7.02msnp.sin(b)15.8ms
let _ = Matft.math.sign(a)3.09msnp.sign(a)1.37ms
let _ = Matft.math.sign(b)8.33msnp.sign(b)1.42ms
MatfttimeNumpytime
let _ = a > 04.63msa > 0855μs
let _ = a > b17.8msa > b1.83ms
let _ = a === 04.65msa == 0603μs
let _ = a === b19.7msa == b1.78ms
MatfttimeNumpytime
let _ = a[posb]1.21msa[posb]1.29ms

Matft achieved almost same performance as Numpy!!!

※Swift's performance test was conducted in release mode

However, as you can see the above table, Matft's boolean operation is toooooooo slow...(Issue #18)

So, a pull request is very welcome!!

Installation

SwiftPM

Important!!! the below installation is outdated. Please install Matft via swiftPM!!!

Carthage

CocoaPods

Contact

Feel free to ask this project or anything via junnosuke.kado.git@gmail.com