# bend-blas: the CBLAS routines on Array, one def per routine, the # names of CBLAS without the cblas_ prefix. Generated by gen/effs.py: # edit the table there, not this file. # # Conventions. Sizes and flags are U32 (an Array has no shape; ta # and tb are 0 or 1 for a transpose), scalars F32, matrices row-major # with their leading dimension equal to their row width. Every array # operand is consumed (the effect drops it after reading it) and an # answered array is a fresh block of the smallest power-of-two size # holding the result, the tail zero. A routine answers # IO(Result<&1, &1, U32 & String, A>): Fail{(code, message)} when no # BLAS is found (2), an operand is smaller than its sizes claim (2), or # a size passes 2^31 floats (2); a full heap is a fail-stop of the # runtime, not a Fail. Its .try twin answers IO(A) and dies on failure. # # The platform BLAS is opened at runtime (dlopen): Accelerate on macOS; # OpenBLAS, else libcblas beside the system BLAS, on Linux, which must # be installed. On the interpreter the JS twins run: plain loops, # correct and slow, whose failures carry the code only. import Base # C = alpha op(A) op(B) + beta C. A is m x k as stored (k x m when ta = 1), # B is k x n (n x k when tb = 1), C is m x n, all row-major. C is consumed # and the updated copy answered; pass beta = 0 and any m x n block for a # fresh product. 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>): import "./effs/blas_sgemm.c" import "./effs/blas_sgemm.js" 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): IO.try(Array, Blas.sgemm(ta, tb, m, n, k, alpha, a, b, beta, c)) # y = alpha op(A) x + beta y. A is m x n as stored, row-major; ta = 1 # applies A^T, so x has n elements (m when ta) and y has m (n when ta). # y is consumed and the updated copy answered. 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>): import "./effs/blas_sgemv.c" import "./effs/blas_sgemv.js" def Blas.sgemv.try(ta: U32, m: U32, n: U32, alpha: F32, a: Array, x: Array, beta: F32, y: Array) -> IO(Array): IO.try(Array, Blas.sgemv(ta, m, n, alpha, a, x, beta, y)) # A = alpha x y^T + A, the rank-1 update; A is m x n, x has m elements, # y has n. A is consumed and the updated copy answered. def Blas.sger(m: U32, n: U32, alpha: F32, x: Array, y: Array, a: Array) -> IO(Result<&1, &1, U32 & String, Array>): import "./effs/blas_sger.c" import "./effs/blas_sger.js" def Blas.sger.try(m: U32, n: U32, alpha: F32, x: Array, y: Array, a: Array) -> IO(Array): IO.try(Array, Blas.sger(m, n, alpha, x, y, a)) # The dot product of the first n elements of x and y. def Blas.sdot(n: U32, x: Array, y: Array) -> IO(Result<&1, &1, U32 & String, F32>): import "./effs/blas_sdot.c" import "./effs/blas_sdot.js" def Blas.sdot.try(n: U32, x: Array, y: Array) -> IO(F32): IO.try(F32, Blas.sdot(n, x, y)) # The Euclidean norm of the first n elements of x. def Blas.snrm2(n: U32, x: Array) -> IO(Result<&1, &1, U32 & String, F32>): import "./effs/blas_snrm2.c" import "./effs/blas_snrm2.js" def Blas.snrm2.try(n: U32, x: Array) -> IO(F32): IO.try(F32, Blas.snrm2(n, x)) # The sum of the absolute values of the first n elements of x. def Blas.sasum(n: U32, x: Array) -> IO(Result<&1, &1, U32 & String, F32>): import "./effs/blas_sasum.c" import "./effs/blas_sasum.js" def Blas.sasum.try(n: U32, x: Array) -> IO(F32): IO.try(F32, Blas.sasum(n, x)) # The index (from 0) of the element of largest absolute value among the first n of x. def Blas.isamax(n: U32, x: Array) -> IO(Result<&1, &1, U32 & String, U32>): import "./effs/blas_isamax.c" import "./effs/blas_isamax.js" def Blas.isamax.try(n: U32, x: Array) -> IO(U32): IO.try(U32, Blas.isamax(n, x)) # y = alpha x + y over the first n elements; y is consumed and the updated copy answered. def Blas.saxpy(n: U32, alpha: F32, x: Array, y: Array) -> IO(Result<&1, &1, U32 & String, Array>): import "./effs/blas_saxpy.c" import "./effs/blas_saxpy.js" def Blas.saxpy.try(n: U32, alpha: F32, x: Array, y: Array) -> IO(Array): IO.try(Array, Blas.saxpy(n, alpha, x, y)) # x = alpha x over the first n elements; x is consumed and the scaled copy answered. def Blas.sscal(n: U32, alpha: F32, x: Array) -> IO(Result<&1, &1, U32 & String, Array>): import "./effs/blas_sscal.c" import "./effs/blas_sscal.js" def Blas.sscal.try(n: U32, alpha: F32, x: Array) -> IO(Array): IO.try(Array, Blas.sscal(n, alpha, x))