1 # bend-blas: the CBLAS routines on Array, one def per routine, the 2 # names of CBLAS without the cblas_ prefix. Generated by gen/effs.py: 3 # edit the table there, not this file. 4 # 5 # Conventions. Sizes and flags are U32 (an Array has no shape; ta 6 # and tb are 0 or 1 for a transpose), scalars F32, matrices row-major 7 # with their leading dimension equal to their row width. Every array 8 # operand is consumed (the effect drops it after reading it) and an 9 # answered array is a fresh block of the smallest power-of-two size 10 # holding the result, the tail zero. A routine answers 11 # IO(Result<&1, &1, U32 & String, A>): Fail{(code, message)} when no 12 # BLAS is found (2), an operand is smaller than its sizes claim (2), or 13 # a size passes 2^31 floats (2); a full heap is a fail-stop of the 14 # runtime, not a Fail. Its .try twin answers IO(A) and dies on failure. 15 # 16 # The platform BLAS is opened at runtime (dlopen): Accelerate on macOS; 17 # OpenBLAS, else libcblas beside the system BLAS, on Linux, which must 18 # be installed. On the interpreter the JS twins run: plain loops, 19 # correct and slow, whose failures carry the code only. 20 import Base 21 22 # C = alpha op(A) op(B) + beta C. A is m x k as stored (k x m when ta = 1), 23 # B is k x n (n x k when tb = 1), C is m x n, all row-major. C is consumed 24 # and the updated copy answered; pass beta = 0 and any m x n block for a 25 # fresh product. 26 def Blas.sgemm(ta: U32, tb: U32, m: U32, n: U32, k: U32, alpha: F32, a: Array, b: Array, beta: F32, c: Array) -> IO(Result<&1, &1, U32 & String, Array>): 27 import "./effs/blas_sgemm.c" 28 import "./effs/blas_sgemm.js" 29 30 def Blas.sgemm.try(ta: U32, tb: U32, m: U32, n: U32, k: U32, alpha: F32, a: Array, b: Array, beta: F32, c: Array) -> IO(Array): 31 IO.try(Array, Blas.sgemm(ta, tb, m, n, k, alpha, a, b, beta, c)) 32 33 # y = alpha op(A) x + beta y. A is m x n as stored, row-major; ta = 1 34 # applies A^T, so x has n elements (m when ta) and y has m (n when ta). 35 # y is consumed and the updated copy answered. 36 def Blas.sgemv(ta: U32, m: U32, n: U32, alpha: F32, a: Array, x: Array, beta: F32, y: Array) -> IO(Result<&1, &1, U32 & String, Array>): 37 import "./effs/blas_sgemv.c" 38 import "./effs/blas_sgemv.js" 39 40 def Blas.sgemv.try(ta: U32, m: U32, n: U32, alpha: F32, a: Array, x: Array, beta: F32, y: Array) -> IO(Array): 41 IO.try(Array, Blas.sgemv(ta, m, n, alpha, a, x, beta, y)) 42 43 # A = alpha x y^T + A, the rank-1 update; A is m x n, x has m elements, 44 # y has n. A is consumed and the updated copy answered. 45 def Blas.sger(m: U32, n: U32, alpha: F32, x: Array, y: Array, a: Array) -> IO(Result<&1, &1, U32 & String, Array>): 46 import "./effs/blas_sger.c" 47 import "./effs/blas_sger.js" 48 49 def Blas.sger.try(m: U32, n: U32, alpha: F32, x: Array, y: Array, a: Array) -> IO(Array): 50 IO.try(Array, Blas.sger(m, n, alpha, x, y, a)) 51 52 # The dot product of the first n elements of x and y. 53 def Blas.sdot(n: U32, x: Array, y: Array) -> IO(Result<&1, &1, U32 & String, F32>): 54 import "./effs/blas_sdot.c" 55 import "./effs/blas_sdot.js" 56 57 def Blas.sdot.try(n: U32, x: Array, y: Array) -> IO(F32): 58 IO.try(F32, Blas.sdot(n, x, y)) 59 60 # The Euclidean norm of the first n elements of x. 61 def Blas.snrm2(n: U32, x: Array) -> IO(Result<&1, &1, U32 & String, F32>): 62 import "./effs/blas_snrm2.c" 63 import "./effs/blas_snrm2.js" 64 65 def Blas.snrm2.try(n: U32, x: Array) -> IO(F32): 66 IO.try(F32, Blas.snrm2(n, x)) 67 68 # The sum of the absolute values of the first n elements of x. 69 def Blas.sasum(n: U32, x: Array) -> IO(Result<&1, &1, U32 & String, F32>): 70 import "./effs/blas_sasum.c" 71 import "./effs/blas_sasum.js" 72 73 def Blas.sasum.try(n: U32, x: Array) -> IO(F32): 74 IO.try(F32, Blas.sasum(n, x)) 75 76 # The index (from 0) of the element of largest absolute value among the first n of x. 77 def Blas.isamax(n: U32, x: Array) -> IO(Result<&1, &1, U32 & String, U32>): 78 import "./effs/blas_isamax.c" 79 import "./effs/blas_isamax.js" 80 81 def Blas.isamax.try(n: U32, x: Array) -> IO(U32): 82 IO.try(U32, Blas.isamax(n, x)) 83 84 # y = alpha x + y over the first n elements; y is consumed and the updated copy answered. 85 def Blas.saxpy(n: U32, alpha: F32, x: Array, y: Array) -> IO(Result<&1, &1, U32 & String, Array>): 86 import "./effs/blas_saxpy.c" 87 import "./effs/blas_saxpy.js" 88 89 def Blas.saxpy.try(n: U32, alpha: F32, x: Array, y: Array) -> IO(Array): 90 IO.try(Array, Blas.saxpy(n, alpha, x, y)) 91 92 # x = alpha x over the first n elements; x is consumed and the scaled copy answered. 93 def Blas.sscal(n: U32, alpha: F32, x: Array) -> IO(Result<&1, &1, U32 & String, Array>): 94 import "./effs/blas_sscal.c" 95 import "./effs/blas_sscal.js" 96 97 def Blas.sscal.try(n: U32, alpha: F32, x: Array) -> IO(Array): 98 IO.try(Array, Blas.sscal(n, alpha, x))