2. Currently available features¶
Numscrypt currently supports:
ns_settings.optim_space setting added, default is False. Setting it to True is DISADVISED, since it will result in slow code.
- ndarray with
- dtype int32, float32 and float64, views using offset and strides
- multi-dimensional indexing
- multi-dimensional slicing
- reshape
- astype
- tolist
- __repr__ and __str__
- transpose
- overloaded operators: * / + - @, mixing of ndarray and scalar expressions
empty, array, copy
hsplit, vsplit
hstack.vstack
zeros, ones, identity
- linalg with
- matrix inversion
3. Systematic code examples: a guided tour of Numscrypt¶
One ready-to-run code example is worth more than ten lengthy descriptions. The autotest and demo suite, that is part of the distribution, is a collection of sourcecode fragments called testlets. These testlets are used for automated regression testing of Numscrypt against NumPy. Since they systematically cover all the library constructs, they are also very effective as a learning tool. The testlets are arranged alphabetically by subject.
import org.transcrypt.autotester
import basics
import module_linalg
#import module_fft
autoTester = org.transcrypt.autotester.AutoTester ()
autoTester.run (basics, 'basics')
autoTester.run (module_linalg, 'module_linalg')
#autoTester.run (module_fft, 'module_fft')
autoTester.done ()
3.1. Basics: creating and using arrays¶
from org.transcrypt.stubs.browser import *
from org.transcrypt.stubs.browser import __main__, __envir__, __pragma__
# Imports for Transcrypt, resolved run time
if __envir__.executor_name == __envir__.transpiler_name:
import numscrypt as num
# Imports for CPython, resolved compile time
__pragma__ ('skip')
import numpy as num
__pragma__ ('noskip')
def run (autoTester):
z = num.zeros ((4, 3, 2), 'int32')
autoTester.check ('Zeros', z.tolist (), '<br>')
o = num.ones ((1, 2, 3))
autoTester.check ('Ones', o.astype ('int32') .tolist ())
i = num.identity (3, 'int32')
autoTester.check ('Identity', i.tolist (), '<br>')
# shape: 2 blocks x 3 rows x 4 columns
a = num.array ([
[
[1, 1, 2, 3],
[4, 5, 6, 7],
[8, 9, 10, 12]
], [
[100, 101, 102, 103],
[104, 105, 106, 107],
[108, 109, 110, 112]
]
])
autoTester.check ('Matrix a', a.tolist (), '<br>')
autoTester.check ('Transpose of a', a.transpose () .tolist (), '<br>')
b = num.array ([
[
[2, 2, 4, 6],
[8, 10, 12, 14],
[16, 18, 20, 24]
], [
[200, 202, 204, 206],
[208, 210, 212, 214],
[216, 218, 220, 224]
]
])
bp = b.transpose ((2, 1, 0))
autoTester.check ('Matrix b', b.tolist (), '<br>')
autoTester.check ('Permutation of b', bp.tolist (), '<br>')
c = num.array ([
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
], 'int32')
autoTester.check ('Shape strides c', tuple (c.shape), tuple (c.strides), '<br>')
autoTester.check ('Matrix c', c.tolist (), '<br>')
ct = c.transpose ()
autoTester.check ('Shape strids ct', tuple (ct.shape), tuple (ct.strides), '<br>')
autoTester.check ('Transpose of c', ct .tolist (), '<br>')
cs0, cs1 = num.hsplit (c, 2)
autoTester.check ('Matrix cs0', cs0.tolist (), '<br>')
autoTester.check ('Matrix cs1', cs1.tolist (), '<br>')
ci = num.hstack ((cs1, cs0))
autoTester.check ('Matrix ci', ci.tolist (), '<br>')
cts0, cts1, cts2 = num.hsplit (ct, 3)
autoTester.check ('Matrix cts0', cts0.tolist (), '<br>')
autoTester.check ('Matrix cts1', cts1.tolist (), '<br>')
autoTester.check ('Matrix cts2', cts2.tolist (), '<br>')
cti = num.hstack ((cts2, cts1, cts0))
autoTester.check ('Matrix ci', cti.tolist (), '<br>')
d = num.array ([
[13, 14],
[15, 16],
[17, 18],
[19, 20]
], 'int32')
autoTester.check ('Matrix d', d.tolist (), '<br>')
dt = d.transpose ()
autoTester.check ('Permutation of d', dt.tolist (), '<br>')
ds0, ds1, ds2, ds3 = num.vsplit (d, 4)
autoTester.check ('Matrix ds0', ds0.tolist (), '<br>')
autoTester.check ('Matrix ds1', ds1.tolist (), '<br>')
autoTester.check ('Matrix ds2', ds2.tolist (), '<br>')
autoTester.check ('Matrix ds3', ds3.tolist (), '<br>')
di = num.vstack ((ds3, ds2, ds1, ds0))
autoTester.check ('Matrix di', di.tolist (), '<br>')
dts0, dts1 = num.vsplit (dt, 2)
autoTester.check ('Matrix dts0', dts0.tolist (), '<br>')
autoTester.check ('Matrix dts1', dts1.tolist (), '<br>')
dti = num.vstack ((dts1, dts0))
autoTester.check ('Matrix dti', dti.tolist (), '<br>')
v0 = num.array (range (10))
v1 = num.array ((1, 2, 3, 1, 2, 3, 1, 2, 3, 1))
__pragma__ ('opov')
a [1, 0, 2] = 177
el = b [1, 2, 3]
bsl0 = b [1, 1 : 3, : ]
bsl1 = b [1 : 2, 1 : 3, :]
bsl2 = b [1, 1, :]
bsl3 = b [1, 1 : 3, 1]
bsl4 = b [ : , 1, 1]
bsl5 = b [1, 1 : 3, :]
bsl6 = b [1, 1 : 3, 1 : 4]
bsl7 = b [1, 2 : 3, 2 : 4]
bpsl0 = bp [1, 1 : 3, : ]
bpsl1 = bp [1 : 2, 1 : 3, :]
bpsl2 = bp [1, 1, :]
bpsl3 = bp [1, 1 : 3, 1]
bpsl4 = bp [ : , 1, 1]
bpsl5 = bp [3, 1 : 3, :]
bpsl6 = bp [2 : 4, 1 : 3, 0 : 1]
bpsl7 = bp [2 : 4, 2 : 3, 1 : 2]
sum = a + b
dif = a - b
prod = a * b
quot = a / b
dot = c @ d
vsum = v0 + v1
vel = vsum [6]
vsum [6] = 70
mul_a3 = a * 3
mul_3a = 3 * a
div_a3 = a / 3.1234567
div_3a = 3.1234567 / a
add_a3 = a + 3
add_3a = 3 + a
sub_a3 = a - 3
sub_3a = 3 - a
neg_a = -a
__pragma__ ('noopov')
autoTester.check ('El a [1, 2, 3] alt', a.tolist (), '<br>')
autoTester.check ('El b [1, 2, 3]', el, '<br>')
autoTester.check ('Sl b0', bsl0.tolist (), '<br>')
autoTester.check ('Sl b1', bsl1.tolist (), '<br>')
autoTester.check ('Sl b2', bsl2.tolist (), '<br>')
autoTester.check ('Sl b3', bsl3.tolist (), '<br>')
autoTester.check ('Sl b4', bsl4.tolist (), '<br>')
autoTester.check ('Sl b5', bsl5.tolist (), '<br>')
autoTester.check ('Sl b6', bsl6.tolist (), '<br>')
autoTester.check ('Sl b7', bsl7.tolist (), '<br>')
autoTester.check ('Sl bp0', bpsl0.tolist (), '<br>')
autoTester.check ('Sl bp1', bpsl1.tolist (), '<br>')
autoTester.check ('Sl bp2', bpsl2.tolist (), '<br>')
autoTester.check ('Sl bp3', bpsl3.tolist (), '<br>')
autoTester.check ('Sl bp4', bpsl4.tolist (), '<br>')
autoTester.check ('Sl bp5', bpsl5.tolist (), '<br>')
autoTester.check ('Sl bp6', bpsl6.tolist (), '<br>')
autoTester.check ('Sl bp7', bpsl7.tolist (), '<br>')
autoTester.check ('Matrix sum', sum.tolist (), '<br>')
autoTester.check ('Matrix difference', dif.tolist (), '<br>')
autoTester.check ('Matrix product', prod.tolist (), '<br>')
autoTester.check ('Matrix quotient', quot.tolist (), '<br>')
autoTester.check ('Matrix dotproduct', dot.tolist (), '<br>')
autoTester.check ('Vector', v0.tolist (), '<br>')
autoTester.check ('Vector', v1.tolist (), '<br>')
autoTester.check ('El sum old', vel, '<br>')
autoTester.check ('Vector sum new', vsum.tolist (), '<br>')
autoTester.check ('mul_a3', mul_a3.tolist (), '<br>')
autoTester.check ('mul_3a', mul_3a.tolist (), '<br>')
autoTester.check ('div_a3', num.round (div_a3, 2).tolist (), '<br>')
autoTester.check ('div_3a', num.round (div_3a, 2).tolist (), '<br>')
autoTester.check ('add_a3', add_a3.tolist (), '<br>')
autoTester.check ('add_3a', add_3a.tolist (), '<br>')
autoTester.check ('sub_a3', sub_a3.tolist (), '<br>')
autoTester.check ('sub_3a', sub_3a.tolist (), '<br>')
autoTester.check ('neg_a', neg_a.tolist (), '<br>')
__pragma__ ('opov')
comp_a = num.array ([
[1 + 2j, 2 - 1j, 3],
[4, 5 + 3j, 7]
], 'complex128')
comp_b = num.array ([
[6, 8 - 1j],
[9 + 3j, 10],
[11, 12 -6j]
], 'complex128')
comp_c = comp_a @ comp_b
__pragma__ ('noopov')
autoTester.check ('comp_a', comp_a.tolist (), '<br>')
autoTester.check ('comp_b', comp_b.tolist (), '<br>')
autoTester.check ('comp_c', comp_c.tolist (), '<br>')
__pragma__ ('opov')
comp_a_square = comp_a [ : , : 2]
comp_b_square = comp_b [1 : , : ]
comp_c_square = comp_a_square * comp_b_square
comp_d_square = comp_a_square / comp_b_square
comp_e_square = comp_a_square + comp_b_square
comp_f_square = comp_a_square - comp_b_square
__pragma__ ('noopov')
autoTester.check ('comp_a_square', comp_a_square.tolist (), '<br>')
autoTester.check ('comp_b_square', comp_b_square.tolist (), '<br>')
autoTester.check ('comp_c_square', comp_c_square.tolist (), '<br>')
autoTester.check ('comp_d_square', num.round (comp_d_square, 2).tolist (), '<br>')
autoTester.check ('comp_e_square', comp_e_square.tolist (), '<br>')
autoTester.check ('comp_f_square', comp_f_square.tolist (), '<br>')
3.2. Linalg: matrix inversion¶
from org.transcrypt.stubs.browser import *
from org.transcrypt.stubs.browser import __main__, __envir__, __pragma__
# Imports for Transcrypt, resolved run time
if __envir__.executor_name == __envir__.transpiler_name:
import numscrypt as num
import numscrypt.linalg as linalg
# Imports for CPython, resolved compile time
__pragma__ ('skip')
import numpy as num
import numpy.linalg as linalg
__pragma__ ('noskip')
def run (autoTester):
# Real
r = num.array ([
[2.12, -2.11, -1.23],
[2.31, 1.14, 3.15],
[1.13, 1.98, 2.81]
])
autoTester.check ('Matrix r', num.round (r, 2) .tolist (), '<br>')
ri = linalg.inv (r)
autoTester.check ('Matrix ri', num.round (ri, 2) .tolist (), '<br>')
__pragma__ ('opov')
rid = r @ ri
__pragma__ ('noopov')
autoTester.check ('r @ ri', [[int (round (elem)) for elem in row] for row in rid.tolist ()], '<br>')
__pragma__ ('opov')
delta = 0.001
autoTester.check ('r * r', num.round (r * r + delta, 3) .tolist (), '<br>')
autoTester.check ('r / r', num.round (r / r + delta, 3) .tolist (), '<br>')
autoTester.check ('r + r', num.round (r + r + delta, 3) .tolist (), '<br>')
autoTester.check ('r - r', num.round (r - r + delta, 3) .tolist (), '<br>')
__pragma__ ('noopov')
# Complex
__pragma__ ('opov')
c = num.array ([
[2.12 - 3.15j, -2.11, -1.23],
[2.31, 1.14, 3.15 + 2.75j],
[1.13, 1.98 - 4.33j, 2.81]
], 'complex128')
__pragma__ ('noopov')
autoTester.check ('Matrix c', num.round (c, 2) .tolist (), '<br>')
ci = linalg.inv (c)
autoTester.check ('Matrix ci', num.round (ci, 2) .tolist (), '<br>')
__pragma__ ('opov')
cid = c @ ci
__pragma__ ('noopov')
autoTester.check ('c @ ci', [['{} + j{}'.format (int (round (elem.real)), int (round (elem.imag))) for elem in row] for row in cid.tolist ()], '<br>')
__pragma__ ('opov')
delta = 0.001 + 0.001j
autoTester.check ('c * c', num.round (c * c + delta , 3) .tolist (), '<br>')
autoTester.check ('c / c', num.round (c / c + delta, 3) .tolist (), '<br>')
autoTester.check ('c + c', num.round (c + c + delta, 3) .tolist (), '<br>')
autoTester.check ('c - c', num.round (c - c + delta, 3) .tolist (), '<br>')
__pragma__ ('noopov')
4. Some more examples: interactive tests¶
4.1. ns_settings.optimize_space¶
For time critical operations like @ and inv, slicing operations are avoided. For @ this happens by copying arrays to ‘natural stride order’. Setting ns_settings.optimize_space to True will avoid this copying to save memory space. In general this is DISADVISED, since it will considerably slow down execution of the @ operator, which is O (n^3).
from org.transcrypt.stubs.browser import *
from org.transcrypt.stubs.browser import __pragma__
import numscrypt as num
import numscrypt.random as num_rand
import numscrypt.linalg as linalg
import random
result = ''
for useComplex in (False, True):
for optim_space in (False, True):
num.ns_settings.optim_space = optim_space
for transpose in (False, True):
if useComplex:
a = num.array ([
[complex (random.random (), random.random ()) for iCol in range (30)]
for iRow in range (30)
], 'complex128')
else:
a = num_rand.rand (30, 30)
timeStartTranspose = __new__ (Date ())
if transpose:
a = a.transpose ()
timeStartInv = __new__ (Date ())
ai = linalg.inv (a)
timeStartMul = __new__ (Date ())
__pragma__ ('opov')
id = a @ ai
__pragma__ ('noopov')
timeStartScalp = __new__ (Date ())
__pragma__ ('opov')
sp = a * a
__pragma__ ('noopov')
timeStartDiv = __new__ (Date ())
__pragma__ ('opov')
sp = a / a
__pragma__ ('noopov')
timeStartAdd = __new__ (Date ())
__pragma__ ('opov')
sp = a + a
__pragma__ ('noopov')
timeStartSub = __new__ (Date ())
__pragma__ ('opov')
sp = a - a
__pragma__ ('noopov')
timeEnd = __new__ (Date ())
result += (
'''
<pre>
Optimized for space instead of time: {}
================================================
{}: a @ ai [0:5, 0:5] =
{}
'''
) .format (
optim_space,
'natural' if a.ns_natural else 'unnatural',
str (num.round (id [0:5, 0:5], 2)) .replace (' ', '\t'),
)
if transpose:
result += (
'''
Transpose took: {} ms'''
).format (
timeStartInv - timeStartTranspose
)
result += (
'''
Inverse took: {} ms
Matrix product (@) took: {} ms
Elementwise product (*) took: {} ms
Division took: {} ms
Addition took: {} ms
Subtraction took: {} ms
</pre>
'''
) .format (
timeStartMul - timeStartInv,
timeStartScalp - timeStartMul,
timeStartDiv - timeStartScalp,
timeStartAdd - timeStartDiv,
timeStartSub - timeStartAdd,
timeEnd - timeStartSub
)
document.getElementById ('result') .innerHTML = result