Python and Viv · Numerics
Matrix operations
What to notice
np.array([[1.0, 2.0], [3.0, 4.0]])is the literal[[1.0, 2.0], [3.0, 4.0]].np.eye(2) * 2.0has no builtin twin; the Viv side writes the matrix out.A @ Bis the matrix product andA * Bthe elementwise product in both.A.Tistranspose(A);A.shapeisshape(A), which unpacks intorows, cols;A.sizeisnumel(A).A.sum()issum(A). There is noaxis=argument, so row and column sums are loops.A > 1.5gives an array of 1.0 and 0.0 in Viv (booleans in NumPy); both multiply the same way.sqrtapplies to every element of an array, asnp.sqrtdoes. Viv'sroundtakes no digit count, so rounding to 6 decimals isround(C * 1e6) / 1e6.tolist()on the Python side andfmt(...)on the Viv side print a matrix the same way,[[1.0, 2.0], [3.0, 4.0]].
Python matrix_ops.py · 32 lines
Viv matrix_ops.viv · 38 lines
py2viv refuses matrix_ops.py
1 imports
4import numpy as np
2# nothing to import: matrices are part of the language
py2viv refuses this program:
matrix_ops.py:24:14: not numeric Python: np.round with decimals or of an array
print("C =", np.round(C, 6).tolist())
^^^^^^^^^^^^^^
Round numbers one at a time with round(x).
1 construct outside the numeric subset (tools/py2viv/SUBSET.md) 2 build matrices
7A = np.array([[1.0, 2.0], [3.0, 4.0]])
8B = np.eye(2) * 2.0
9v = np.array([1.0, -1.0])
10print("A =", A.tolist())
11print("shape", A.shape, "size", A.size)
5A = [[1.0, 2.0], [3.0, 4.0]]
6B = [[2.0, 0.0], [0.0, 2.0]]
7v = [1.0, -1.0]
8print("A =", fmt(A))
9rows, cols = shape(A)
10print("shape (", rows, ", ", cols, ") size ", numel(A), sep="")
(refused)
3 products
14print("A @ B =", (A @ B).tolist())
15print("A * B =", (A * B).tolist())
16print("A @ v =", (A @ v).tolist())
17print("A^T =", A.T.tolist())
13print("A @ B =", fmt(A @ B))
14print("A * B =", fmt(A * B))
15print("A @ v =", fmt(A @ v))
16print("A^T =", fmt(transpose(A)))
(refused)
4 reductions along an axis
20print("sum", A.sum(), "column sums", A.sum(axis=0).tolist(), "row sums", A.sum(axis=1).tolist())
19col_sums = sum(A, axis=0)
20row_sums = sum(A, axis=1)
21print("sum", fmt(sum(A)), "column sums", fmt(col_sums), "row sums", fmt(row_sums))
(refused)
5 elementwise functions and masks
23C = np.sqrt(A) * (A > 1.5)
24print("C =", np.round(C, 6).tolist())
24C = sqrt(A) * (A > 1.5)
25print("C =", fmt(round(C * 1e6) / 1e6))
(refused)
6 determinant and inverse of a 2 by 2
27det = A[0, 0] * A[1, 1] - A[0, 1] * A[1, 0]
28inv = np.array([[A[1, 1], -A[0, 1]], [-A[1, 0], A[0, 0]]]) / det
29print("det", det, "inverse", inv.tolist())
28det = A[0, 0] * A[1, 1] - A[0, 1] * A[1, 0]
29inv = [[A[1, 1], -A[0, 1]], [-A[1, 0], A[0, 0]]] / det
30print("det", fmt(det), "inverse", fmt(inv))
(refused)
7 checks
32assert np.allclose(A @ inv, np.eye(2))
33test "inverse" {
34 assert_allclose(A @ inv, [[1.0, 0.0], [0.0, 1.0]], 1e-12)
35}
(refused)
What they print
identical — the two programs print the same text.
Dimmed lines are left out of the comparison. Each Viv test block prints one PASS line; the Python checks the same facts with assert, which prints nothing.
$ python3 matrix_ops.py
A = [[1.0, 2.0], [3.0, 4.0]]shape (2, 2) size 4A @ B = [[2.0, 4.0], [6.0, 8.0]]A * B = [[2.0, 0.0], [0.0, 8.0]]A @ v = [-1.0, -1.0]A^T = [[1.0, 3.0], [2.0, 4.0]]sum 10.0 column sums [4.0, 6.0] row sums [3.0, 7.0]C = [[0.0, 1.414214], [1.732051, 2.0]]det -2.0 inverse [[-2.0, 1.0], [1.5, -0.5]]
$ viv run matrix_ops.viv
A = [[1.0, 2.0], [3.0, 4.0]]shape (2, 2) size 4A @ B = [[2.0, 4.0], [6.0, 8.0]]A * B = [[2.0, 0.0], [0.0, 8.0]]A @ v = [-1.0, -1.0]A^T = [[1.0, 3.0], [2.0, 4.0]]sum 10.0 column sums [4.0, 6.0] row sums [3.0, 7.0]C = [[0.0, 1.414214], [1.732051, 2.0]]det -2.0 inverse [[-2.0, 1.0], [1.5, -0.5]]PASS inverse