├── amos.c ├── amos.h ├── blas.h ├── cdflib.h ├── complex.c ├── dcdflib.c ├── docs ├── index.html └── style.css ├── examples ├── cheb.lua ├── cholesky.lua ├── denmanbeavers.lua ├── elephant.lua ├── fibo.lua ├── gaussseidel.lua ├── householder.lua ├── invert.lua ├── lm.lua ├── marquadt.lua ├── pascal.lua ├── smarquadt.lua ├── solvef.lua ├── solvef1.lua ├── sweep.lua ├── test.lua └── wishart.lua ├── fft.c ├── ipmpar.c ├── lapack.h ├── lhp ├── complex.lhp ├── factor │ ├── design.lhp │ ├── fold.lhp │ └── partition.lhp ├── fft.lhp ├── fft │ ├── plan.lhp │ └── wisdom.lhp ├── mathx.lhp ├── mathx │ ├── airya.lhp │ ├── airyb.lhp │ ├── besselh.lhp │ ├── besseli.lhp │ ├── besselj.lhp │ ├── besselk.lhp │ ├── bessely.lhp │ ├── beta.lhp │ ├── choose.lhp │ ├── digamma.lhp │ ├── feq.lhp │ ├── lbeta.lhp │ ├── lchoose.lhp │ ├── log1pe.lhp │ └── lse.lhp ├── matrix.lhp ├── matrix │ ├── add.lhp │ ├── apply.lhp │ ├── balance.lhp │ ├── c.lhp │ ├── chol.lhp │ ├── col.lhp │ ├── complex.lhp │ ├── concat.lhp │ ├── conj.lhp │ ├── copy.lhp │ ├── cross.lhp │ ├── diag.lhp │ ├── div.lhp │ ├── dot.lhp │ ├── eig.lhp │ ├── eindex.lhp │ ├── entries.lhp │ ├── eorder.lhp │ ├── fct.lhp │ ├── fft.lhp │ ├── find.lhp │ ├── fold.lhp │ ├── get.lhp │ ├── hemul.lhp │ ├── ifelse.lhp │ ├── imag.lhp │ ├── inv.lhp │ ├── iscomplex.lhp │ ├── linspace.lhp │ ├── load.lhp │ ├── ls.lhp │ ├── lu.lhp │ ├── map.lhp │ ├── max.lhp │ ├── min.lhp │ ├── mmul.lhp │ ├── mul.lhp │ ├── new.lhp │ ├── norm.lhp │ ├── ones.lhp │ ├── pivot.lhp │ ├── pow.lhp │ ├── qr.lhp │ ├── rcond.lhp │ ├── real.lhp │ ├── reshape.lhp │ ├── save.lhp │ ├── section.lhp │ ├── set.lhp │ ├── shape.lhp │ ├── size.lhp │ ├── slice.lhp │ ├── sort.lhp │ ├── spread.lhp │ ├── sum.lhp │ ├── svd.lhp │ ├── swap.lhp │ ├── transpose.lhp │ ├── trmul.lhp │ ├── which.lhp │ └── zeros.lhp ├── numlua.lhp ├── numlua │ ├── buffer.lhp │ ├── opmode.lhp │ ├── seeall.lhp │ └── type.lhp ├── rng.lhp ├── rng │ ├── copy.lhp │ ├── lsample.lhp │ ├── new.lhp │ ├── rbeta.lhp │ ├── rbinom.lhp │ ├── rchisq.lhp │ ├── rdirichlet.lhp │ ├── rexp.lhp │ ├── rf.lhp │ ├── rgamma.lhp │ ├── rmvnorm.lhp │ ├── rnbinom.lhp │ ├── rnorm.lhp │ ├── rpois.lhp │ ├── runif.lhp │ ├── runifint.lhp │ ├── runifx.lhp │ ├── sample.lhp │ └── seed.lhp ├── stat.lhp └── stat │ ├── dbeta.lhp │ ├── dbinom.lhp │ ├── dchisq.lhp │ ├── dexp.lhp │ ├── df.lhp │ ├── dgamma.lhp │ ├── dhyper.lhp │ ├── dnbinom.lhp │ ├── dnorm.lhp │ ├── dpois.lhp │ ├── dt.lhp │ └── factor.lhp ├── lmatrix.c ├── mathx.c ├── matrix.lua ├── msort.c ├── mt.c ├── numlua-0.3-1.rockspec ├── numlua.c ├── numlua.h ├── ranlib.c ├── readme.md ├── rng.c ├── rng.h ├── seeall.lua └── stat.c /amos.h: -------------------------------------------------------------------------------- 1 | int zairy_(double *zr, double *zi, int *id, int *kode, 2 | double *air, double *aii, int *nz, int *ierr); 3 | 4 | int zbiry_(double *zr, double *zi, int *id, 5 | int *kode, double *bir, double *bii, int *ierr); 6 | 7 | int zbesh_(double *zr, double *zi, double *fnu, 8 | int *kode, int *m, int *n, double *cyr, double *cyi, 9 | int *nz, int *ierr); 10 | 11 | int zbesi_(double *zr, double *zi, double *fnu, 12 | int *kode, int *n, double *cyr, double *cyi, int *nz, int *ierr); 13 | 14 | int zbesj_(double *zr, double *zi, double *fnu, 15 | int *kode, int *n, double *cyr, double *cyi, int *nz, int *ierr); 16 | 17 | int zbesk_(double *zr, double *zi, double *fnu, 18 | int *kode, int *n, double *cyr, double *cyi, int *nz, int *ierr); 19 | 20 | int zbesy_(double *zr, double *zi, double *fnu, 21 | int *kode, int *n, double *cyr, double *cyi, int *nz, 22 | double *cwrkr, double *cwrki, int *ierr); 23 | 24 | -------------------------------------------------------------------------------- /blas.h: -------------------------------------------------------------------------------- 1 | /* ============================= Level 1 ============================= */ 2 | 3 | double ddot_(int* N, double* X, int* incX, double* Y, 4 | int* incY); 5 | 6 | void zdotu_(double complex* retval, int* N, double complex* X, int* 7 | incX, double complex* Y, int* incY); 8 | 9 | void zdotc_(double complex* retval, int* N, double complex* X, int* 10 | incX, double complex* Y, int* incY); 11 | 12 | double dnrm2_(int* N, double* X, int* incX); 13 | 14 | double dasum_(int* N, double* X, int* incX); 15 | 16 | double dznrm2_(int* N, double complex* X, int* incX); 17 | 18 | double dzasum_(int* N, double complex* X, int* incX); 19 | 20 | int idamax_(int* N, double* X, int* incX); 21 | 22 | int izamax_(int* N, double complex* X, int* incX); 23 | 24 | int dswap_(int* N, double* X, int* incX, double* Y, int* 25 | incY); 26 | 27 | int dcopy_(int* N, double* X, int* incX, double* Y, int* 28 | incY); 29 | 30 | int daxpy_(int* N, double* alpha, double* X, int* incX, 31 | double* Y, int* incY); 32 | 33 | int zswap_(int* N, double complex* X, int* incX, double complex* Y, 34 | int* incY); 35 | 36 | int zcopy_(int* N, double complex* X, int* incX, double complex* Y, 37 | int* incY); 38 | 39 | int zaxpy_(int* N, double complex* alpha, double complex* X, int* incX, 40 | double complex* Y, int* incY); 41 | 42 | int drotg_(double* a, double* b, double* c, double* s); 43 | 44 | int drot_(int* N, double* X, int* incX, double* Y, int* 45 | incY, double* c, double* s); 46 | 47 | int dscal_(int* N, double* alpha, double* X, int* incX); 48 | 49 | int zscal_(int* N, double complex* alpha, double complex* X, int* incX); 50 | 51 | int zdscal_(int* N, double* alpha, double complex* X, int* incX); 52 | 53 | /* ============================= Level 2 ============================= */ 54 | 55 | int dgemv_(char* trans, int* M, int* N, double* alpha, double* 56 | A, int* lda, double* X, int* incX, double* beta, 57 | double* Y, int* incY, int ltrans); 58 | 59 | int dtrmv_(char* uplo, char *trans, char* diag, int *N, double *A, 60 | int *lda, double *X, int *incX, int luplo, int ltrans, 61 | int ldiag); 62 | 63 | int dtrsv_(char* uplo, char* trans, char* diag, int* N, double* A, 64 | int* lda, double* X, int* incX, int luplo, int ltrans, 65 | int ldiag); 66 | 67 | int zgemv_(char* trans, int* M, int* N, double complex* alpha, 68 | double complex* A, int* lda, double complex* X, int* incX, 69 | double complex* beta, double complex* Y, int* incY, int ltrans); 70 | 71 | int ztrmv_(char* uplo, char *trans, char* diag, int *N, double complex *A, 72 | int *lda, double complex *X, int *incX, int luplo, int ltrans, 73 | int ldiag); 74 | 75 | int ztrsv_(char* uplo, char* trans, char* diag, int* N, double complex* A, 76 | int* lda, double complex* X, int* incX, int luplo, int ltrans, 77 | int ldiag); 78 | 79 | int dsymv_(char* uplo, int* N, double* alpha, double* A, int* 80 | lda, double* X, int* incX, double* beta, double* Y, 81 | int* incY, int luplo); 82 | 83 | int dger_(int* M, int* N, double* alpha, double* X, int* 84 | incX, double* Y, int* incY, double* A, int* lda); 85 | 86 | int dsyr_(char* uplo, int* N, double* alpha, double* X, int* 87 | incX, double* A, int* lda, int luplo); 88 | 89 | int dsyr2_(char* uplo, int* N, double* alpha, double* X, int* 90 | incX, double* Y, int* incY, double* A, int* lda, 91 | int luplo); 92 | 93 | int zhemv_(char* uplo, int* N, double complex* alpha, double complex* A, 94 | int* lda, double complex* X, int* incX, double complex* beta, 95 | double complex* Y, int* incY, int luplo); 96 | 97 | int zgeru_(int* M, int* N, double complex* alpha, double complex* X, 98 | int* incX, double complex* Y, int* incY, double complex* A, 99 | int* lda); 100 | 101 | int zgerc_(int* M, int* N, double complex* alpha, double complex* X, 102 | int* incX, double complex* Y, int* incY, double complex* A, 103 | int* lda); 104 | 105 | int zher_(char* uplo, int* N, double* alpha, double complex* X, 106 | int* incX, double complex* A, int* lda, int luplo); 107 | 108 | int zher2_(char* uplo, int* N, double complex* alpha, double complex* X, 109 | int* incX, double complex* Y, int* incY, double complex* A, 110 | int* lda, int luplo); 111 | 112 | /* ============================= Level 3 ============================= */ 113 | 114 | int dgemm_(char* transA, char* transB, int* M, int* N, int* K, 115 | double* alpha, double* A, int* lda, double* B, 116 | int* ldb, double* beta, double* C, int* ldc, 117 | int ltransa, int ltransb); 118 | 119 | int dsymm_(char* side, char* uplo, int* M, int* N, double* alpha, 120 | double* A, int* lda, double* B, int* ldb, double* 121 | beta, double* C, int* ldc, int lside, int luplo); 122 | 123 | int dsyrk_(char* uplo, char* trans, int* N, int* K, double* alpha, 124 | double* A, int* lda, double* beta, double* C, int* 125 | ldc, int luplo, int ltrans); 126 | 127 | int dsyr2k_(char* uplo, char* trans, int* N, int* K, double* 128 | alpha, double* A, int* lda, double* B, int* ldb, 129 | double* beta, double* C, int* ldc, int luplo, 130 | int ltrans); 131 | 132 | int dtrmm_(char* side, char* uplo, char* trans, char* diag, int* M, 133 | int* N, double* alpha, double* A, int* lda, 134 | double* B, int* ldb, int lside, int luplo, 135 | int ltrans, int ldiag); 136 | 137 | int dtrsm_(char* side, char* uplo, char* trans, char* diag, int* M, 138 | int* N, double* alpha, double* A, int* lda, 139 | double* B, int* ldb, int lside, int luplo, 140 | int ltrans, int ldiag); 141 | 142 | int zgemm_(char* transA, char* transB, int* M, int* N, int* K, 143 | double complex* alpha, double complex* A, int* lda, double complex* 144 | B, int* ldb, double complex* beta, double complex* C, int* ldc, 145 | int ltransa, int ltransb); 146 | 147 | int zsyrk_(char* uplo, char* trans, int* N, int* K, double complex* 148 | alpha, double complex* A, int* lda, double complex* beta, 149 | double complex* C, int* ldc, int luplo, int ltrans); 150 | 151 | int zsyr2k_(char* uplo, char* trans, int* N, int* K, double complex* 152 | alpha, double complex* A, int* lda, double complex* B, int* ldb, 153 | double complex* beta, double complex* C, int* ldc, int luplo, 154 | int ltrans); 155 | 156 | int ztrmm_(char* side, char* uplo, char* trans, char* diag, int* M, 157 | int* N, double complex* alpha, double complex* A, int* lda, 158 | double complex* B, int* ldb, int lside, int luplo, 159 | int ltrans, int ldiag); 160 | 161 | int ztrsm_(char* side, char* uplo, char* trans, char* diag, int* M, 162 | int* N, double complex* alpha, double complex* A, int* lda, 163 | double complex* B, int* ldb, int lside, int luplo, 164 | int ltrans, int ldiag); 165 | 166 | int zhemm_(char* side, char* uplo, int* M, int* N, double complex* 167 | alpha, double complex* A, int* lda, double complex* B, int* ldb, 168 | double complex* beta, double complex* C, int* ldc, int lside, 169 | int luplo); 170 | 171 | int zherk_(char* uplo, char* trans, int* N, int* K, double* alpha, 172 | double complex* A, int* lda, double* beta, double complex* C, 173 | int* ldc, int luplo, int ltrans); 174 | 175 | int zher2k_(char* uplo, char* trans, int* N, int* K, double complex* 176 | alpha, double complex* A, int* lda, double complex* B, int* ldb, 177 | double* beta, double complex* C, int* ldc, int luplo, 178 | int ltrans); 179 | 180 | -------------------------------------------------------------------------------- /cdflib.h: -------------------------------------------------------------------------------- 1 | double algdiv(double*,double*); 2 | double alngam(double*); 3 | double alnrel(double*); 4 | double apser(double*,double*,double*,double*); 5 | double basym(double*,double*,double*,double*); 6 | double bcorr(double*,double*); 7 | double betaln(double*,double*); 8 | double bfrac(double*,double*,double*,double*,double*,double*); 9 | void bgrat(double*,double*,double*,double*,double*,double*,int*i); 10 | double bpser(double*,double*,double*,double*); 11 | void bratio(double*,double*,double*,double*,double*,double*,int*); 12 | double brcmp1(int*,double*,double*,double*,double*); 13 | double brcomp(double*,double*,double*,double*); 14 | double bup(double*,double*,double*,double*,int*,double*); 15 | void cdfbet(int*,double*,double*,double*,double*,double*,double*, 16 | int*,double*); 17 | void cdfbin(int*,double*,double*,double*,double*,double*,double*, 18 | int*,double*); 19 | void cdfchi(int*,double*,double*,double*,double*,int*,double*); 20 | void cdfchn(int*,double*,double*,double*,double*,double*,int*,double*); 21 | void cdff(int*,double*,double*,double*,double*,double*,int*,double*); 22 | void cdffnc(int*,double*,double*,double*,double*,double*,double*, 23 | int*s,double*); 24 | void cdfgam(int*,double*,double*,double*,double*,double*,int*,double*); 25 | void cdfnbn(int*,double*,double*,double*,double*,double*,double*, 26 | int*,double*); 27 | void cdfnor(int*,double*,double*,double*,double*,double*,int*,double*); 28 | void cdfpoi(int*,double*,double*,double*,double*,int*,double*); 29 | void cdft(int*,double*,double*,double*,double*,int*,double*); 30 | void cumbet(double*,double*,double*,double*,double*,double*); 31 | void cumbin(double*,double*,double*,double*,double*,double*); 32 | void cumchi(double*,double*,double*,double*); 33 | void cumchn(double*,double*,double*,double*,double*); 34 | void cumf(double*,double*,double*,double*,double*); 35 | void cumfnc(double*,double*,double*,double*,double*,double*); 36 | void cumgam(double*,double*,double*,double*); 37 | void cumnbn(double*,double*,double*,double*,double*,double*); 38 | void cumnor(double*,double*,double*); 39 | void cumpoi(double*,double*,double*,double*); 40 | void cumt(double*,double*,double*,double*); 41 | double dbetrm(double*,double*); 42 | double devlpl(double [],int*,double*); 43 | double dexpm1(double*); 44 | double dinvnr(double *p,double *q); 45 | void dinvr(int*,double*,double*,unsigned long*,unsigned long*); 46 | void dstinv(double*,double*,double*,double*,double*,double*, 47 | double*); 48 | double dlanor(double*); 49 | double dln1mx(double*); 50 | double dln1px(double*); 51 | double dlnbet(double*,double*); 52 | double dlngam(double*); 53 | double dstrem(double*); 54 | double dt1(double*,double*,double*); 55 | void dzror(int*,double*,double*,double*,double *, 56 | unsigned long*,unsigned long*); 57 | void dstzr(double *zxlo,double *zxhi,double *zabstl,double *zreltl); 58 | double erf1(double*); 59 | double erfc1(int*,double*); 60 | double esum(int*,double*); 61 | double exparg(int*); 62 | double fpser(double*,double*,double*,double*); 63 | double gam1(double*); 64 | void gaminv(double*,double*,double*,double*,double*,int*); 65 | double gamln(double*); 66 | double gamln1(double*); 67 | double Xgamm(double*); 68 | void grat1(double*,double*,double*,double*,double*,double*); 69 | void gratio(double*,double*,double*,double*,int*); 70 | double gsumln(double*,double*); 71 | double psi(double*); 72 | double rcomp(double*,double*); 73 | double rexp(double*); 74 | double rlog(double*); 75 | double rlog1(double*); 76 | double spmpar(int*); 77 | double stvaln(double*); 78 | double fifdint(double); 79 | double fifdmax1(double,double); 80 | double fifdmin1(double,double); 81 | double fifdsign(double,double); 82 | long fifidint(double); 83 | long fifmod(long,long); 84 | void ftnstop(char*); 85 | extern int ipmpar(int*); 86 | 87 | -------------------------------------------------------------------------------- /complex.c: -------------------------------------------------------------------------------- 1 | /* {================================================================= 2 | * 3 | * complex.c 4 | * C99 complex numbers for NumericLua 5 | * Luis Carvalho (lexcarvalho@gmail.com) 6 | * See Copyright Notice in numlua.h 7 | * 8 | * ==================================================================} */ 9 | 10 | #include 11 | #include 12 | #include "numlua.h" 13 | 14 | static int complex_mt_ = 0; 15 | #define COMPLEX_MT ((void *)&complex_mt_) 16 | 17 | 18 | /* {===================================================================== 19 | * API 20 | * ======================================================================} */ 21 | 22 | /* Internal: meant for use on functions that have MT as env */ 23 | 24 | static nl_Complex *tocomplexP (lua_State *L, int narg) { 25 | nl_Complex *p = NULL; 26 | if (lua_type(L, narg) == LUA_TUSERDATA /* userdata? */ 27 | && lua_getmetatable(L, narg)) { /* has metatable? */ 28 | if (lua_rawequal(L, -1, lua_upvalueindex(1))) /* MT == upvalue? */ 29 | p = lua_touserdata(L, narg); 30 | lua_pop(L, 1); /* MT */ 31 | } 32 | return p; 33 | } 34 | 35 | static nl_Complex tocomplex (lua_State *L, int narg, int *iscomplex) { 36 | nl_Complex c, *p = tocomplexP(L, narg); 37 | if (p == NULL) { /* not complex? */ 38 | c = lua_tonumber(L, narg); 39 | if (iscomplex != NULL) *iscomplex = lua_isnumber(L, narg); 40 | } 41 | else { 42 | c = *p; 43 | if (iscomplex != NULL) *iscomplex = 1; 44 | } 45 | return c; 46 | } 47 | 48 | static nl_Complex checkcomplex (lua_State *L, int narg) { 49 | int iscomplex; 50 | nl_Complex c = tocomplex(L, narg, &iscomplex); 51 | if (!iscomplex) nl_typeerror(L, narg, "number or complex"); 52 | return c; 53 | } 54 | 55 | static nl_Complex *newcomplex (lua_State *L) { 56 | nl_Complex *z = (nl_Complex *) lua_newuserdata(L, sizeof(nl_Complex)); 57 | lua_pushvalue(L, lua_upvalueindex(1)); 58 | lua_setmetatable(L, -2); 59 | return z; 60 | } 61 | 62 | static nl_Complex *pushcomplex (lua_State *L, nl_Complex c) { 63 | nl_Complex *z = newcomplex(L); 64 | *z = c; 65 | return z; 66 | } 67 | 68 | 69 | /* API: get MT from registry */ 70 | 71 | NUMLUA_API nl_Complex nl_tocomplex (lua_State *L, int narg, int *iscomplex) { 72 | nl_Complex c, *p = NULL; 73 | *iscomplex = 0; 74 | if (lua_type(L, narg) == LUA_TUSERDATA /* userdata? */ 75 | && lua_getmetatable(L, narg)) { /* has metatable? */ 76 | nl_getmetatable(L, COMPLEX_MT); 77 | if (lua_rawequal(L, -1, -2)) /* right MT? */ 78 | p = lua_touserdata(L, narg); 79 | lua_pop(L, 2); /* MTs */ 80 | } 81 | if (p == NULL) { /* not complex? */ 82 | c = lua_tonumber(L, narg); 83 | *iscomplex = (creal(c) != 0 || lua_isnumber(L, narg)); 84 | } 85 | else { 86 | c = *p; 87 | *iscomplex = 1; 88 | } 89 | return c; 90 | } 91 | 92 | NUMLUA_API nl_Complex nl_checkcomplex (lua_State *L, int narg) { 93 | int iscomplex; 94 | nl_Complex c = nl_tocomplex(L, narg, &iscomplex); 95 | if (!iscomplex) nl_typeerror(L, narg, "number or complex"); 96 | return c; 97 | } 98 | 99 | NUMLUA_API nl_Complex nl_optcomplex (lua_State *L, int narg, nl_Complex def) { 100 | return luaL_opt(L, nl_checkcomplex, narg, def); 101 | } 102 | 103 | NUMLUA_API nl_Complex *nl_newcomplex (lua_State *L) { 104 | nl_Complex *z = (nl_Complex *) lua_newuserdata(L, sizeof(nl_Complex)); 105 | nl_getmetatable(L, COMPLEX_MT); 106 | lua_setmetatable(L, -2); 107 | return z; 108 | } 109 | 110 | NUMLUA_API nl_Complex *nl_pushcomplex (lua_State *L, nl_Complex c) { 111 | nl_Complex *z = nl_newcomplex(L); 112 | *z = c; 113 | return z; 114 | } 115 | 116 | 117 | NUMLUA_API lua_Number clogabs (nl_Complex c) { 118 | lua_Number r = fabs(creal(c)); 119 | lua_Number i = fabs(cimag(c)); 120 | lua_Number t; 121 | if ((r + i) == r) return log(r); 122 | if (i > r) { t = r; r = i; i = t; } 123 | t = i / r; 124 | return log(r) + 0.5 * log1p(t * t); 125 | } 126 | 127 | 128 | 129 | /* {===================================================================== 130 | * Metamethods 131 | * ======================================================================} */ 132 | 133 | /* complex.newindex: there are three possible assignments: 134 | * o c._ = x, in-place copy 135 | * o c.r = x, creal(c) = x 136 | * o c.i = x, cimag(c) = x 137 | */ 138 | static int complex_newindex (lua_State *L) { 139 | nl_Complex *c = (nl_Complex *) lua_touserdata(L, 1); 140 | size_t l; 141 | const char *k = lua_tolstring(L, 2, &l); 142 | int iscomplex; 143 | nl_Complex x = tocomplex(L, 3, &iscomplex); 144 | if (k == NULL) luaL_error(L, "complex index must be a string"); 145 | if (l > 1) luaL_error(L, "invalid index: %s", k); 146 | if (!iscomplex) 147 | luaL_error(L, "number expected for assignment, got %s", 148 | luaL_typename(L, 3)); 149 | switch (k[0]) { 150 | case '_': *c = x; break; /* assign */ 151 | case 'r': *c = creal(x) + cimag(*c) * I; break; /* real assign */ 152 | case 'i': *c = creal(*c) + creal(x) * I; break; /* imag assign */ 153 | default: luaL_error(L, "invalid index: %s", k); 154 | } 155 | return 0; 156 | } 157 | 158 | static int complex_tostring (lua_State *L) { 159 | nl_Complex *c = (nl_Complex *) lua_touserdata(L, 1); 160 | if (!signbit(cimag(*c))) 161 | lua_pushfstring(L, "%f+%fi", creal(*c), cimag(*c)); 162 | else 163 | lua_pushfstring(L, "%f%fi", creal(*c), cimag(*c)); 164 | return 1; 165 | } 166 | 167 | 168 | /* {===================================================================== 169 | * Functions 170 | * ======================================================================} */ 171 | 172 | #define cconj conj 173 | 174 | #define F0(f) \ 175 | static int complex_##f (lua_State *L) { \ 176 | nl_Complex a = checkcomplex(L, 1); \ 177 | lua_pushnumber(L, c##f(a)); \ 178 | return 1;\ 179 | } 180 | 181 | #define F1(f) \ 182 | static int complex_##f (lua_State *L) { \ 183 | if (nl_inplace(L, 2)) { \ 184 | nl_Complex *a = tocomplexP(L, 1); \ 185 | if (a == NULL) nl_typeerror(L, 1, "complex"); \ 186 | *a = c##f(*a); \ 187 | lua_settop(L, 1); \ 188 | } \ 189 | else { \ 190 | nl_Complex a = checkcomplex(L, 1); \ 191 | nl_Complex *c = newcomplex(L); \ 192 | *c = c##f(a); \ 193 | } \ 194 | return 1; \ 195 | } 196 | 197 | #define F2(f) \ 198 | static int complex_##f (lua_State *L) { \ 199 | nl_Complex b = checkcomplex(L, 2); \ 200 | if (nl_inplace(L, 3)) { \ 201 | nl_Complex *a = tocomplexP(L, 1); \ 202 | if (a == NULL) nl_typeerror(L, 1, "complex"); \ 203 | *a = c##f(*a,b); \ 204 | lua_settop(L, 1); \ 205 | } \ 206 | else { \ 207 | nl_Complex a = checkcomplex(L, 1); \ 208 | nl_Complex *c = newcomplex(L); \ 209 | *c = c##f(a,b); \ 210 | } \ 211 | return 1;\ 212 | } 213 | 214 | F1(unm) 215 | F2(add) 216 | F2(sub) 217 | F2(mul) 218 | F2(div) 219 | F2(pow) 220 | 221 | /* Methods */ 222 | F0(abs) 223 | F0(logabs) 224 | F0(arg) 225 | F0(real) 226 | F0(imag) 227 | F1(acos) 228 | F1(acosh) 229 | F1(asin) 230 | F1(asinh) 231 | F1(atan) 232 | F1(atanh) 233 | F1(conj) 234 | F1(cos) 235 | F1(cosh) 236 | F1(exp) 237 | F1(log) 238 | F1(proj) 239 | F1(sin) 240 | F1(sinh) 241 | F1(sqrt) 242 | F1(tan) 243 | F1(tanh) 244 | 245 | 246 | /* {===================================================================== 247 | * Interface 248 | * ======================================================================} */ 249 | 250 | static int complexMT__call (lua_State *L) { 251 | /* complex, or one or two numbers on stack */ 252 | nl_Complex *c; 253 | lua_remove(L, 1); /* class table */ 254 | c = pushcomplex(L, checkcomplex(L, 1)); 255 | if (lua_isnumber(L, 2)) /* set imag? */ 256 | *c = creal(*c) + lua_tonumber(L, 2) * I; 257 | return 1; 258 | } 259 | 260 | static const luaL_Reg complex_func[] = { 261 | {"abs", complex_abs}, 262 | {"logabs", complex_logabs}, 263 | {"arg", complex_arg}, 264 | {"real", complex_real}, 265 | {"imag", complex_imag}, 266 | {"acos", complex_acos}, 267 | {"acosh", complex_acosh}, 268 | {"asin", complex_asin}, 269 | {"asinh", complex_asinh}, 270 | {"atan", complex_atan}, 271 | {"atanh", complex_atanh}, 272 | {"conj", complex_conj}, 273 | {"cos", complex_cos}, 274 | {"cosh", complex_cosh}, 275 | {"exp", complex_exp}, 276 | {"log", complex_log}, 277 | {"proj", complex_proj}, 278 | {"sin", complex_sin}, 279 | {"sinh", complex_sinh}, 280 | {"sqrt", complex_sqrt}, 281 | {"tan", complex_tan}, 282 | {"tanh", complex_tanh}, 283 | {"add", complex_add}, 284 | {"sub", complex_sub}, 285 | {"mul", complex_mul}, 286 | {"div", complex_div}, 287 | {"pow", complex_pow}, 288 | {NULL, NULL} 289 | }; 290 | 291 | static const luaL_Reg complex_mt[] = { 292 | {"__newindex", complex_newindex}, 293 | {"__len", complex_abs}, 294 | {"__tostring", complex_tostring}, 295 | {"__unm", complex_unm}, 296 | {"__add", complex_add}, 297 | {"__sub", complex_sub}, 298 | {"__mul", complex_mul}, 299 | {"__div", complex_div}, 300 | {"__pow", complex_pow}, 301 | {NULL, NULL} 302 | }; 303 | 304 | NUMLUA_API int luaopen_numlua_complex (lua_State *L) { 305 | nl_Complex i = 1 * I; 306 | /* complex metatable */ 307 | lua_newtable(L); 308 | lua_pushliteral(L, COMPLEX_LIBNAME); 309 | lua_setfield(L, -2, "__type"); 310 | lua_pushlightuserdata(L, COMPLEX_MT); 311 | lua_pushvalue(L, -2); 312 | lua_rawset(L, LUA_REGISTRYINDEX); 313 | /* push metamethods */ 314 | lua_pushvalue(L, -1); 315 | nl_register(L, complex_mt, 1); 316 | /* class table */ 317 | lua_newtable(L); 318 | lua_pushvalue(L, -2); /* metatable */ 319 | nl_register(L, complex_func, 1); 320 | pushcomplex(L, i); 321 | /* fix metatable for `i` (no upvalues here) */ 322 | lua_pushvalue(L, -3); /* metatable */ 323 | lua_setmetatable(L, -2); 324 | lua_pushvalue(L, -1); 325 | lua_setfield(L, -3, "i"); 326 | lua_setfield(L, -2, "j"); 327 | /* push class table for __index */ 328 | lua_pushvalue(L, -1); 329 | lua_setfield(L, -3, "__index"); 330 | /* push class metatable */ 331 | lua_createtable(L, 0, 2); 332 | lua_pushvalue(L, -3); /* metatable */ 333 | lua_pushcclosure(L, complexMT__call, 1); 334 | lua_setfield(L, -2, "__call"); 335 | lua_pushvalue(L, -2); /* class */ 336 | lua_setfield(L, -2, "__metatable"); /* protect */ 337 | lua_setmetatable(L, -2); 338 | return 1; 339 | } 340 | 341 | -------------------------------------------------------------------------------- /docs/style.css: -------------------------------------------------------------------------------- 1 | /* Basic style */ 2 | /* $Id: style.css,v 1.4 2008-01-09 17:36:55 carvalho Exp $ */ 3 | 4 | /* ===== Typography and colors ===== */ 5 | 6 | body { 7 | font-size: 11pt; 8 | font-family: 'Lucida Grande', Geneva, Verdana, Arial, Helvetica, sans-serif; 9 | background-color: #567; 10 | color: #222; 11 | text-align: center; 12 | } 13 | 14 | #page { 15 | background-color: #fff; 16 | border: 1px solid #868fa0; 17 | text-align: left; 18 | } 19 | 20 | a, h2 a:hover, h3 a:hover { 21 | color: #900; 22 | text-decoration: none; 23 | } 24 | 25 | a:hover { 26 | color: #000080; 27 | background-color: #f0f0ff; 28 | text-decoration: underline; 29 | } 30 | 31 | a:visited { 32 | color: #000080; 33 | } 34 | 35 | #header { 36 | background-color: #fff; 37 | font-size: 1.4em; 38 | text-align: center; 39 | } 40 | 41 | #headerimg { 42 | background: url("images/splash.jpg") no-repeat bottom center; 43 | } 44 | 45 | #horizbar { 46 | margin-top: 10px; 47 | padding: 2px 0 2px; 48 | background-color: #eee; 49 | /* font-size: 1.05em; */ 50 | text-align: center; 51 | border-top: 1px solid #868fa0; 52 | border-bottom: 1px solid #868fa0; 53 | } 54 | 55 | #horizbar a:hover { 56 | background-color: #e0e0ff; 57 | } 58 | 59 | .content { 60 | line-height: 1.2em; 61 | text-align: justify; 62 | } 63 | 64 | .content .comment { 65 | text-align: center; 66 | } 67 | 68 | #footer { 69 | background-color: #eee; 70 | border-top: 1px solid #868fa0; 71 | } 72 | 73 | small { 74 | font-family: 'Lucida Grande', Geneva, Verdana, Arial, Helvetica, sans-serif; 75 | font-size: 0.9em; 76 | line-height: 1.5em; 77 | } 78 | 79 | h1, h2, h3, h4 { 80 | font-family: 'Lucida Grande', Geneva, Verdana, Arial, Helvetica, sans-serif; 81 | font-weight: bold; 82 | } 83 | 84 | h1 { font-size: 1.5em; } 85 | 86 | .description { 87 | font-size: 1.2em; 88 | text-align: left; 89 | } 90 | 91 | h2 { font-size: 1.25em; } 92 | 93 | h3 { font-size: 1.15em; } 94 | 95 | h4 { font-size: 1.05em; } 96 | 97 | #sidebar 98 | { 99 | background-color: #eee; 100 | } 101 | 102 | #sidebar h2 { 103 | font-family: 'Lucida Grande', Verdana, Sans-Serif; 104 | font-size: 1.1em; 105 | background: #d0d0ff; 106 | } 107 | 108 | h1, h1 a, h1 a:hover, h1 a:visited, .description { 109 | text-decoration: none; 110 | color: #000080; 111 | } 112 | 113 | h2, h2 a, h2 a:visited, 114 | h3, h3 a, h3 a:visited, 115 | h4, h4 a, h4 a:visited { 116 | color: #000080; 117 | } 118 | 119 | h2, h2 a, h2 a:hover, h2 a:visited, 120 | h3, h3 a, h3 a:hover, h3 a:visited, 121 | #sidebar h2, cite { 122 | text-decoration: none; 123 | } 124 | 125 | #sidebar { 126 | font: 1em 'Lucida Grande', Verdana, Arial, Sans-Serif; 127 | } 128 | 129 | small, 130 | #sidebar ul ul li, 131 | #sidebar ul ol li, 132 | .comment, 133 | blockquote, strike { 134 | color: #868fa0; 135 | } 136 | 137 | 138 | /* ===== Structure ===== */ 139 | 140 | body { 141 | margin: 0; 142 | padding: 0; 143 | } 144 | 145 | #page { 146 | margin: 0px auto; 147 | padding: 0; 148 | width: 85%; 149 | } 150 | 151 | #header { 152 | padding: 0; 153 | margin: 0 auto; 154 | width: 100%; 155 | } 156 | 157 | #headerimg { 158 | padding: 0; 159 | margin: 0 auto; 160 | height: 200px; 161 | width: 100%; 162 | } 163 | 164 | #title { 165 | height: 200px; 166 | width: 100%; 167 | } 168 | 169 | .content { 170 | padding: 0 0 20px 0; 171 | margin: 5px 50px 30px 50px; 172 | width: 90%; 173 | } 174 | 175 | .content .comment { 176 | margin: 10px 0; 177 | } 178 | 179 | #footer { 180 | padding: 0; 181 | margin: 0 auto; 182 | width: 100%; 183 | clear: both; 184 | } 185 | 186 | #footer p { 187 | margin: 0; 188 | padding: 20px 0; 189 | text-align: center; 190 | } 191 | 192 | #sidebar 193 | { 194 | padding: 20px 0 5px 0; 195 | margin-left: 605px; 196 | width: 130px; 197 | } 198 | 199 | 200 | /* ===== Headers ===== */ 201 | 202 | h1 { 203 | padding-top: 8px; 204 | margin: 0; 205 | } 206 | 207 | h2 { 208 | margin: 30px 0 0; 209 | } 210 | 211 | #sidebar h2 { 212 | margin: 0; 213 | padding-left: 5px; 214 | } 215 | 216 | h3 { 217 | padding: 0; 218 | margin: 30px 0 0; 219 | } 220 | 221 | #header h3 { 222 | margin: 5px; 223 | } 224 | 225 | h4 { 226 | padding: 0; 227 | margin: 20px 0 -10px; 228 | } 229 | 230 | /* ===== Images ===== */ 231 | 232 | p img { 233 | padding: 0; 234 | max-width: 100%; 235 | } 236 | 237 | #header img { 238 | margin-top: 20px; 239 | } 240 | 241 | img.centered { 242 | display: block; 243 | margin-left: auto; 244 | margin-right: auto; 245 | } 246 | 247 | img.alignright { 248 | padding: 4px; 249 | margin: 0 0 2px 7px; 250 | display: inline; 251 | } 252 | 253 | img.alignleft { 254 | padding: 4px; 255 | margin: 0 7px 2px 0; 256 | display: inline; 257 | } 258 | 259 | .alignright { 260 | float: right; 261 | } 262 | 263 | .alignleft { 264 | float: left 265 | } 266 | 267 | 268 | /* ===== Lists ===== */ 269 | 270 | html>body .content ul { 271 | margin-left: 0px; 272 | padding: 0 0 0 30px; 273 | padding-left: 10px; 274 | text-indent: -10px; 275 | } 276 | 277 | html>body .content li { 278 | margin: 7px 0 8px 10px; 279 | } 280 | 281 | .content ol { 282 | padding: 0 0 0 35px; 283 | margin: 0; 284 | } 285 | 286 | .content ol li { 287 | margin: 0; 288 | padding: 0; 289 | } 290 | 291 | .comment ul, .comment li { 292 | display: inline; 293 | list-style-type: none; 294 | list-style-image: none; 295 | } 296 | 297 | #sidebar ul, #sidebar ul ol { 298 | margin: 0; 299 | padding: 0; 300 | } 301 | 302 | #sidebar ul li { 303 | list-style-type: none; 304 | list-style-image: none; 305 | margin-bottom: 15px; 306 | } 307 | 308 | #sidebar ul p, #sidebar ul select { 309 | margin: 5px 0 8px; 310 | } 311 | 312 | #sidebar ul ul, #sidebar ul ol { 313 | margin: 5px 0 0 10px; 314 | } 315 | 316 | #sidebar ul ul ul, #sidebar ul ol { 317 | margin: 0 0 0 10px; 318 | } 319 | 320 | ol li, #sidebar ul ol li { 321 | list-style: decimal outside; 322 | } 323 | 324 | #sidebar ul ul li, #sidebar ul ol li { 325 | margin: 3px 0 0; 326 | padding: 0; 327 | } 328 | 329 | 330 | /* ===== Tables ===== */ 331 | 332 | table { 333 | border: 1px solid black; 334 | border-collapse: collapse; 335 | margin-left: auto; 336 | margin-right: auto; 337 | } 338 | 339 | th, td { 340 | border: 1px solid black; 341 | padding: 5px; 342 | } 343 | 344 | 345 | /* ===== Misc ===== */ 346 | 347 | acronym, abbr, span.caps 348 | { 349 | font-size: 0.9em; 350 | letter-spacing: .07em; 351 | cursor: help; 352 | } 353 | 354 | acronym, abbr { 355 | border-bottom: 1px dashed #666; 356 | } 357 | 358 | blockquote { 359 | margin: 15px 30px 0 10px; 360 | padding-left: 20px; 361 | } 362 | 363 | blockquote cite { 364 | margin: 5px 0 0; 365 | display: block; 366 | } 367 | 368 | .center { 369 | text-align: center; 370 | } 371 | 372 | a img { 373 | border: none; 374 | } 375 | 376 | code { 377 | font-family: 'Courier New', Courier, Fixed, Monospace; 378 | } 379 | 380 | pre { 381 | margin: 10px 20px 10px 20px; 382 | padding: 5px; 383 | text-align: left; 384 | font-size: 10pt; 385 | font-family: 'Courier New', Courier, Fixed, Monospace; 386 | background-color: #eee; 387 | border: 1px solid #868fa0; 388 | } 389 | 390 | -------------------------------------------------------------------------------- /examples/cheb.lua: -------------------------------------------------------------------------------- 1 | -- Based on "A Primer of Scientific Computing in Lua" 2 | 3 | require "numlua" 4 | 5 | local seq, dot, cos = matrix.seq, matrix.dot, matrix.cos 6 | local zeros, map, set, fft = matrix.zeros, matrix.map, matrix.set, matrix.fft 7 | local real, complex, c = matrix.real, matrix.complex, matrix.c 8 | local setmetatable, opmode, pi = setmetatable, numlua.opmode, math.pi 9 | 10 | local function dct (x) 11 | local n = #x - 1 12 | local f = zeros(2 * n, true) 13 | local fr = f:real() 14 | local g = fr(1, n + 1) 15 | g._ = x 16 | fr(n + 2, 2 * n)._ = x(n, 2, -1) 17 | f = fft(f, false, false, true) -- in-place 18 | return g 19 | end 20 | 21 | function clenshawcurtis (f, n) 22 | local x = cos(pi * seq(0, n) / n) 23 | local w = 0 * x; w(1, n + 1, 2)._ = 2 / (1 - seq(0, n, 2) ^ 2) 24 | local fx = map(x, f) / (2 * n) 25 | local g = dct(fx) -- real(fft(complex(c(fx, fx(n, 2, -1))))) 26 | g(2, n)._ = 2 * g(2, n) 27 | return dot(w, g) 28 | end 29 | 30 | 31 | function new0 (f, n) -- naive 32 | local x = cos(pi * seq(0, n) / n) -- Chebyshev points 33 | local w = 0 * x; w(1, n + 1, 2)._ = 2 / (1 - seq(0, n, 2) ^ 2) -- weights 34 | return setmetatable({f=f, n=n}, { 35 | __call = function (_, a, b) -- integral by linear transform 36 | local a, b = a or -1, b or 1 37 | local s = (b - a) / 2 38 | local fx = map(s * x + (b + a) / 2, f) / (2 * n) 39 | local g = real(fft(complex(c(fx, fx(n, 2, -1))))) -- dct 40 | g(2, n)._ = 2 * g(2, n) 41 | return s * dot(w, g(1, n + 1)) 42 | end 43 | }) 44 | end 45 | 46 | function new (f, n) 47 | local x = cos(pi * seq(0, n) / n) -- Chebyshev points 48 | local w = 0 * x; w(1, n + 1, 2)._ = 2 / (1 - seq(0, n, 2) ^ 2) -- weights 49 | local d = zeros(2 * n, true) -- dct buffer 50 | local dr = d:real() -- real ref 51 | local g, r = dr(1, n + 1), dr(n + 2, 2 * n) -- real halfs 52 | local g1 = g(2, n) -- inner ref 53 | -- object 54 | return setmetatable({f=f, n=n}, { 55 | __call = function (_, a, b) -- integral by linear transform 56 | local op = opmode(true) -- in-place 57 | local a, b = a or -1, b or 1 58 | local s = (b - a) / 2 59 | g = map(s * set(g, x) + (b + a) / 2, f) / (2 * n) 60 | r._ = g(n, 2, -1); d = fft(d) -- dct 61 | g1 = 2 * g1 -- g(2, n)._ = 2 * g(2, n) 62 | opmode(op) -- restore opmode 63 | return s * dot(w, g) 64 | end 65 | }) 66 | end 67 | 68 | -------------------------------------------------------------------------------- /examples/cholesky.lua: -------------------------------------------------------------------------------- 1 | require "numlua" 2 | 3 | local zeros, dot, sqrt = matrix.zeros, matrix.dot, math.sqrt 4 | 5 | -- Cholesky decomposition: given positive-definite matrix A, returns U such 6 | -- that A = U' * U 7 | function cholesky (A) 8 | local n = A:size(1) 9 | assert(A:size"#" == 2 and A:size(2) == n, "square matrix expected") 10 | local U = zeros(n, n) 11 | local C = {} -- columns of U 12 | for i = 1, n do C[i] = U:col(i) end 13 | -- factorization: 14 | -- i = 1 15 | local Ai, Ui = A[1], U[1] 16 | local uii = sqrt(Ai[1]) 17 | Ui[1] = uii 18 | for j = 2, n do Ui[j] = Ai[j] / uii end 19 | -- i > 1 20 | for i = 2, n do 21 | Ai, Ui = A[i], U[i] 22 | local uci = C[i](1, i - 1) -- U(i, 1:(i-1)) 23 | uii = sqrt(Ai[i] - dot(uci, uci)) 24 | Ui[i] = uii 25 | for j = i + 1, n do 26 | local ucj = C[j](1, i - 1) -- U(j, 1:(i-1)) 27 | Ui[j] = (Ai[j] - dot(uci, ucj)) / uii 28 | end 29 | end 30 | return U 31 | end 32 | 33 | -- test: cholesky(pascal(n)) 34 | function pascal (n) 35 | local A = zeros(n, n) 36 | A[1]._, A:col(1)._ = 1, 1 -- base 37 | for i = 2, n do 38 | for j = 2, n do 39 | A[i][j] = A[i - 1][j] + A[i][j - 1] 40 | end 41 | end 42 | return A 43 | end 44 | 45 | -------------------------------------------------------------------------------- /examples/denmanbeavers.lua: -------------------------------------------------------------------------------- 1 | require "numlua" 2 | 3 | -- Square-root of a matrix A by Denman-Beavers algorithm: 4 | local TOL, MAXITERS, inf = mathx.eps, 1000, mathx.inf 5 | local inv, norm, abs = matrix.inv, matrix.norm, math.abs 6 | function dbsqrtm (A, tol, maxiters) 7 | local opmode = numlua.opmode(true) -- set in-place operations 8 | local tol, maxiters = tol or TOL, maxiters or MAXITERS 9 | local iY, iZ = matrix.new(A:shape()), matrix.new(A:shape()) -- buffers 10 | local s, n = inf, 1 -- norm(Y), #iterations 11 | local Y, Z = A:copy(), matrix.eye(#A) -- Y_0, Z_0 = A, I 12 | while true do 13 | -- Y_{k+1} = 1/2 * (Y_k + inv(Z_k)) 14 | -- Z_{k+1} = 1/2 * (Z_k + inv(Y_k)) 15 | iY._, iZ._ = Y, Z 16 | Y, Z = (Y + inv(iZ)) / 2, (Z + inv(iY)) / 2 17 | -- check termination 18 | local f = norm(Y) 19 | if abs(f - s) <= tol or n > maxiters then break end 20 | s, n = f, n + 1 21 | end 22 | numlua.opmode(opmode) -- restore previous mode 23 | return Y, Z, s 24 | end 25 | 26 | -------------------------------------------------------------------------------- /examples/elephant.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Implementation for: 3 | "Drawing an elephant with four complex parameters" 4 | Jurgen Mayer, Khaled Khairy, and Jonathon Howard, 5 | Am. J. Phys. 78, 648 (2010), doi:10.1119/1.3254017 6 | --]] 7 | 8 | require "numlua" 9 | 10 | local zeros, c, linspace = matrix.zeros, matrix.c, matrix.linspace 11 | local sin, cos, set = matrix.sin, matrix.cos, matrix.set 12 | local j, creal, cimag = complex.j, complex.real, complex.imag 13 | 14 | -- expand series on `t` with coefficients `A` and `B` 15 | local function fourier0 (t, A, B) -- naive: many temp objects 16 | local f = zeros(#t) 17 | for k = 1, #A do 18 | f = f + A[k] * cos((k - 1) * t) + B[k] * sin((k - 1) * t) 19 | end 20 | return f 21 | end 22 | 23 | local function fourier (t, A, B) 24 | local op = numlua.opmode(true) -- in-place 25 | local f, w = zeros(#t), zeros(#t) -- `w` is workspace 26 | for k = 1, #A do 27 | f = f + A[k] * cos((k - 1) * set(w, t)) 28 | f = f + B[k] * sin((k - 1) * set(w, t)) 29 | end 30 | numlua.opmode(op) -- restore opmode 31 | return f 32 | end 33 | 34 | function elephant (p, nsamples) -- `p` are shape parameters 35 | local Ax = c(0, 0, 0, creal(p[3]), 0, creal(p[4])) 36 | local Bx = c(0, creal(p[1]), creal(p[2]), 0, 0, 0) 37 | local Ay = c(0, cimag(p[4]), 0, 0, 0, 0) 38 | local By = c(0, cimag(p[1]), cimag(p[2]), cimag(p[3]), 0, 0) 39 | -- generate curve 40 | local t = linspace(0, 2 * math.pi, nsamples or 100) 41 | local x, y = fourier(t, Ax, Bx), fourier(t, Ay, By) 42 | return y, -x -- reflect and rotate 43 | end 44 | 45 | -- parameters from Table I in above reference (no "wiggling"): 46 | local param = c(50 - 30*j, 18 + 8*j, 12 - 10*j, -14 - 60*j) 47 | local x, y = elephant(param) 48 | for i = 1, #x do print(x[i], y[i]) end 49 | 50 | -------------------------------------------------------------------------------- /examples/fibo.lua: -------------------------------------------------------------------------------- 1 | require "numlua" 2 | 3 | local zeros, set = matrix.zeros, matrix.set 4 | local eig, mul, dot = matrix.eig, matrix.mul, matrix.dot 5 | 6 | -- if F[n] is the n-th Fibonacci number, 7 | -- {{F[n-1], F[n]}, {F[n], F[n+1]}} = {{0, 1}, {1, 1}} ^ n 8 | local s, V = eig(matrix{{0, 1}, {1, 1}}, 'r', true) 9 | local v = mul(V[1], V[2]) -- element-wise 10 | local w = zeros(2) -- workspace 11 | function fib (n) 12 | return dot(v, set(w, s) ^ n) -- V * diag(s ^ n) * t(V) 13 | end 14 | 15 | for i = 1, 100 do print(i, fib(i)) end 16 | 17 | -------------------------------------------------------------------------------- /examples/gaussseidel.lua: -------------------------------------------------------------------------------- 1 | require "numlua" 2 | 3 | -- Gauss-Seidel linear solver for A * x = b, where A is a square matrix 4 | local zeros, swap = matrix.zeros, matrix.swap 5 | function gaussseidel (A, b, x0, tol) 6 | local tol = tol or 1e-6 7 | local n = A:size(1) 8 | assert(A:size"#" == 2 and A:size(2) == n, "square matrix expected") 9 | assert(b:size"#" == 1 and b:size(1) == n, "consistent vector expected") 10 | local S = zeros(n, n) 11 | S.U = A -- S has upper triangle of A 12 | S:mul(-1, true) -- S = -S (inplace) 13 | S:trmul(A, "l", true) -- S = A.L^(-1) * S 14 | local u = b:copy():trmul(A, "l", true) -- u = A.L^(-1) * b 15 | local x = x0:copy() 16 | local xc = zeros(n) -- current solution 17 | repeat 18 | xc._ = u 19 | xc:mmul(S, x) -- xc = xc + S * x 20 | swap(x, xc) 21 | xc:add(x, -1, true) -- xc = xc - x (inplace) 22 | until xc:norm() < tol 23 | return x 24 | end 25 | 26 | -------------------------------------------------------------------------------- /examples/householder.lua: -------------------------------------------------------------------------------- 1 | require "numlua" 2 | 3 | -- Householder reflections: 4 | -- householder returns a function that multiplies an orthonormal symmetric 5 | -- matrix P by its argument, where P = I - u * u' / c, c = 1/2 * u' * u 6 | local dot, size, add = matrix.dot, matrix.size, matrix.add 7 | function householder (u) 8 | assert(size(u, "#") == 1, "vector expected") 9 | local n = size(u) 10 | local c = 0.5 * dot(u, u) 11 | return function (x) 12 | assert(size(x, "#") == 1, "vector expected") 13 | assert(size(x) == n, "inconsistent dimension") 14 | return add(x, u, -dot(u, x) / c) 15 | end 16 | end 17 | 18 | -- test: reflect1(x) returns -copysign(norm(x), x[1]) * e_1 19 | local zeros, copysign = matrix.zeros, mathx.copysign 20 | function reflect1 (x) 21 | local e1 = zeros(size(x)) 22 | e1[1] = 1 23 | return householder(add(x, e1, copysign(norm(x), x[1])))(x) 24 | end 25 | 26 | -------------------------------------------------------------------------------- /examples/invert.lua: -------------------------------------------------------------------------------- 1 | -- inverting a matrix 2 | -- 3 | -- adapted from p. 124 of Redwine: 4 | -- "Updating to Fortran 90" 5 | -- to show array sections in numlua 6 | 7 | require "numlua" 8 | 9 | -- a is nxn matrix 10 | local swap, eye = matrix.swap, matrix.eye 11 | local function invert (a) 12 | assert(a:size"#" == 2 and a:size(1) == a:size(2), 13 | "square matrix expected") 14 | local n = #a 15 | 16 | local a = a:concat(eye(n, a:iscomplex()), true) -- colcat 17 | 18 | for j = 1, n do 19 | -- find pivot and check its size 20 | local _, i = a:section{{j,n},{j,j}}:norm"m" -- argmax(abs(a[[j:n,j]])) 21 | i = i + j - 1 22 | 23 | -- if necessary apply row interchange 24 | if i ~= j then swap(a[i], a[j]) end 25 | 26 | --a[j]._ = a[j] / a[j][j] 27 | a[j]:div(a[j][j], false, true) -- in-place 28 | 29 | -- loop over each row of matrix 30 | for i = 1, n do 31 | if i ~= j then 32 | --a[i]._ = a[i] - a[j] * a[i][j] 33 | a[i]:add(a[j], -a[i][j], true) -- inplace 34 | end 35 | end 36 | end 37 | 38 | return a:section{{}, {n+1, 2*n}}:copy() 39 | end 40 | 41 | -- main 42 | 43 | local iscomplex = true 44 | local n = 5 45 | a = matrix.zeros(n, n, iscomplex) 46 | a:apply(function (i, j) return i + j * (0.5 - math.random()) end) 47 | 48 | print"a matrix" 49 | a:list() 50 | 51 | print"solution by matrix" 52 | a:inv():list() 53 | 54 | print"present solution" 55 | invert(a):list() 56 | 57 | -------------------------------------------------------------------------------- /examples/lm.lua: -------------------------------------------------------------------------------- 1 | -- Linear models 2 | 3 | require "numlua" 4 | 5 | local zeros, eye, copy = matrix.zeros, matrix.eye, matrix.copy 6 | local ones, concat, shape = matrix.ones, matrix.concat, matrix.shape 7 | local mul, mmul, trmul = matrix.mul, matrix.mmul, matrix.trmul 8 | local diag, sqrt, norm = matrix.diag, matrix.sqrt, matrix.norm 9 | local linspace, sum, qr = matrix.linspace, matrix.sum, matrix.qr 10 | local min, max, abs = math.min, math.max, math.abs 11 | local eps, pt, pf = mathx.eps, stat.pt, stat.pf 12 | local type = numlua.type 13 | 14 | local function fmt (x, nd) 15 | local nd = nd or 4 -- #digits 16 | return string.format("%." .. nd .. "f", x) 17 | end 18 | local function label (n) 19 | n = n - 1 20 | return n == 0 and "(Intercept)" or ("X" .. n) 21 | end 22 | local function printtable (t, ns) 23 | local ns = ns or 1 -- # spaces 24 | local ml = 0 25 | for _, r in ipairs(t) do 26 | for i, v in ipairs(r) do 27 | local s = type(v) == "string" and v or fmt(v) 28 | r[i] = s; s = #s 29 | if ml < s then ml = s end 30 | end 31 | end 32 | for _, r in ipairs(t) do 33 | for i, v in ipairs(r) do 34 | r[i] = (" "):rep(ns + ml - #v) .. v 35 | end 36 | print(table.concat(r)) 37 | end 38 | end 39 | 40 | local function summary (m) 41 | local coef, pvt, rank = m.coef, m.pivot, m.rank 42 | local res, fit = m.residuals, m.fitted 43 | local sigma = sqrt(diag(m.covmatrix)) 44 | -- statistics 45 | local n = #res 46 | local df = n - rank 47 | local dd = rank - 1 -- df0 - df (with intercept) 48 | local mss = norm(fit - sum(fit) / #fit) ^ 2 49 | local rss = norm(res) ^ 2 50 | -- report 51 | local order = linspace(1, #pvt):pivot(pvt) 52 | print("Coefficients:") 53 | local t = {} 54 | -- header 55 | t[1] = {"Predictor", "Estimate", "Std. Error", "t value", "Pr(>|t|)"} 56 | -- coefficients 57 | for i = 1, #pvt do 58 | local oi = order[i] 59 | if oi <= rank then 60 | local bi = coef[oi] 61 | local si = sigma[oi] 62 | local ti = bi / si 63 | local pi = 2 * pt(-abs(ti), df) -- p-value 64 | t[#t + 1] = {label(i), fmt(bi), fmt(si), fmt(ti), fmt(pi, 5)} 65 | end 66 | end 67 | printtable(t); print() 68 | -- regression 69 | local se = rss / df 70 | print("Residual standard error: " .. fmt(math.sqrt(se)) 71 | .. " on " .. df .. " degrees of freedom") 72 | local r2 = mss / (mss + rss) 73 | local adjr2 = 1 - (1 - r2) * (n - 1) / df 74 | print("Multiple R-squared: " .. fmt(r2) 75 | .. ", Adjusted R-squared: " .. fmt(adjr2)) 76 | local f = mss / dd / se 77 | local pv = 1 - pf(f, dd, df) 78 | print("F-statistics: " .. fmt(f) .. " on " .. dd .. " and " .. df 79 | .. " DFs, p-value: " .. fmt(pv, 5)) 80 | end 81 | 82 | 83 | -- find rank from right triangular matrix, output from _,r,_=qr(a,true) 84 | local function getrank (r, tol) 85 | local n = min(shape(r)) 86 | local c = r[n][n] ^ 2 87 | while c < tol and n > 1 do 88 | n = n - 1 89 | local rn = r[n] 90 | c = max(c + rn[n + 1] ^ 2, rn[n] ^ 2) 91 | end 92 | return n 93 | end 94 | 95 | 96 | local mt = {__index = {summary = summary}} 97 | function lm (y, ...) 98 | -- read variables and build design matrix 99 | assert(type(y) == "matrix" and y:size"#" == 1, 100 | "vector expected for response variable") 101 | local m = #y 102 | local t = {ones(m)} 103 | for i = 1, select("#", ...) do 104 | local x = select(i, ...) 105 | assert(type(x) == "matrix" and x:size"#" == 1, 106 | "vector expected for predictor") 107 | assert(#x == m, "inconsistent dimension for predictor") 108 | t[#t + 1] = x 109 | end 110 | local n = #t 111 | t[n + 1] = true 112 | local X = concat(unpack(t)) 113 | local tol = max(m, n) * eps 114 | -- fit model 115 | local q, r, p = qr(X, true) 116 | local rank = getrank(r, tol) 117 | local qt = q{{}, {1, rank}} 118 | local rt = r{{1, rank}, {1, rank}} 119 | local yt = mmul(zeros(rank), qt, y, 't') -- bt = Q'(1:rank,:) * b 120 | local z = trmul(yt, rt, 'u', true) -- rt * z = bt 121 | local fit = qt * trmul(copy(z), rt, 'u') -- fitted values: qt * rt * z 122 | local res = y - fit -- residuals 123 | local xtxi = trmul(eye(rank), rt, 'u', true, 't') 124 | trmul(xtxi, rt, 'u', true) -- xtxi = (r' * r)^(-1) 125 | mul(xtxi, norm(res) ^ 2 / (m - rank), true) -- xtxi = xtxi * sigmahat^2 126 | return setmetatable({coef = z, pivot = p, rank = rank, 127 | residuals = res, fitted = fit, covmatrix = xtxi}, mt) 128 | end 129 | 130 | -------------------------------------------------------------------------------- /examples/marquadt.lua: -------------------------------------------------------------------------------- 1 | -- Levenberg-Marquadt 2 | 3 | -- solve (A + mu * I) * h = -g for h 4 | function solveh (A, mu, g, h) 5 | A:diag():add(mu, true) -- A = A + mu * I 6 | chol(A, true) -- in-place 7 | h._ = g; h:mul(-1, true) -- h = -g 8 | trmul(h, A, "l", true) -- h = inv(A) * h 9 | trmul(h, A, "l", true, "t") -- h = inv(A)' * h 10 | end 11 | 12 | -- f : R^n -> R^m 13 | local TAU, EPS1, EPS2, KMAX = 1e-3, 1e-4, 1e-8, 100 14 | function marquadt (n, m, ff, Jf, x0, tau, tolg, tolx, maxeval) 15 | local tau, eps1, eps2, kmax = TAU, EPS1, EPS2, KMAX 16 | local x, J, f = new(n), new(m, n), new(m) -- arg, Jacobian, function 17 | local xnew, C = new(n), new(n, n) -- caches 18 | local h = new(n) -- step 19 | -- initialize 20 | local k, nu = 0, 2 21 | x:set(x0); J:apply(Jf(x)); f:apply(ff(x)) 22 | local A = zeros(n, n):hemul(J, true) -- A = J' * J 23 | local g = zeros(n):mmul(J, f, "t") -- g = J' * f 24 | local F = dot(f, f) -- objective 25 | local found = g:norm"inf" <= eps1 26 | local mu = tau * A:diag():norm"inf" 27 | -- iterate 28 | while not found and k < kmax do 29 | k = k + 1 30 | solveh(set(C, A), mu, g, h) -- solve (A + mu * I) * h = -g for h 31 | if h:norm() <= eps2 * (eps2 + x:norm()) then 32 | found = true 33 | else 34 | xnew:set(x):add(h, true) -- xnew = x + h 35 | f:apply(ff(xnew)) 36 | local Fnew = dot(f, f) 37 | local rho = (F - Fnew) / (mu * dot(h, h) - dot(h, g)) -- gain ratio 38 | if rho > 0 then -- step acceptable? 39 | x:set(xnew); J:apply(Jf(xnew)) 40 | A:set(0):hemul(J, true) -- A = J' * J 41 | g:set(0):mmul(J, f, "t") -- g = J' * f 42 | F = Fnew 43 | found = g:norm"inf" <= eps1 44 | mu = mu * max(1 / 3, 1 - (2 * rho - 1) ^ 3) 45 | vu = 2 46 | else 47 | mu = mu * vu 48 | vu = vu * 2 49 | end 50 | end 51 | end 52 | return x 53 | end 54 | 55 | -- Example 1.1 56 | local t = {...} 57 | local y = {...} 58 | local exp = math.exp 59 | 60 | local f = function (x) 61 | local x1, x2, x3, x4 = x[1], x[2], x[3], x[4] 62 | return function (i) -- each f_i(x) 63 | local ti = t[i] 64 | return y[i] - x3 * exp(x1 * ti) - x4 * exp(x2 * ti) 65 | end 66 | end 67 | 68 | local J = function (x) -- Jacobian 69 | local x1, x2, x3, x4 = x[1], x[2], x[3], x[4] 70 | local df = { 71 | [1] = function (i) local ti = t[i] return -x3 * ti * exp(x1 * ti) end, 72 | [2] = function (i) local ti = t[i] return -x4 * ti * exp(x2 * ti) end, 73 | [3] = function (i) return -exp(x1 * ti) end, 74 | [4] = function (i) return -exp(x2 * ti) end 75 | } 76 | return function (i, j) return df[j](i) end -- each df_i(x)/dx_j 77 | end 78 | 79 | -------------------------------------------------------------------------------- /examples/pascal.lua: -------------------------------------------------------------------------------- 1 | require "numlua" 2 | 3 | -- Pascal matrix of order `n` 4 | local zeros, set = matrix.zeros, matrix.set 5 | function pascal (n) 6 | local p = zeros(n, n) 7 | set(p[1], 1) 8 | set(p:col(1), 1) 9 | for i = 2, n do 10 | for j = 2, n do 11 | p[i][j] = p[i - 1][j] + p[i][j - 1] 12 | end 13 | end 14 | return p 15 | end 16 | 17 | -------------------------------------------------------------------------------- /examples/smarquadt.lua: -------------------------------------------------------------------------------- 1 | 2 | -- Broyden's rank one update 3 | local function broyden (B, dx, df) 4 | local u = mmul(df, B, dx, "n", "n", -1) -- u = df - B * dx 5 | return mmul(B, u, dx, "n", "t", dot(dx, dx)) -- B = B + u * dx' / u' * u 6 | end 7 | 8 | -------------------------------------------------------------------------------- /examples/solvef.lua: -------------------------------------------------------------------------------- 1 | -- a version of linear system solver 2 | -- modified from "Fortran 90/95 explained" 3 | -- by Metcalf and Reid (p. 131-132) 4 | -- to show array sections 5 | 6 | require "numlua" 7 | 8 | -- a is nxn matrix, b is a vector 9 | -- the solution is returned in b 10 | local swap = matrix.swap 11 | function solve (a, b) 12 | local n = #b 13 | assert(a:size"#" == 2 and a:size(1) == a:size(2), "a must be square") 14 | assert(#a == n, "a and b sizes must be equal") 15 | 16 | for j = 1, n do -- update elements in column j 17 | for i = 1, j - 1 do 18 | a{{i+1,n}, {j,j}}._ = a{{i+1,n}, {j,j}} - a{{i+1,n}, {i,i}} * a[i][j] 19 | --a{{i+1,n}, {j,j}}:add(a{{i+1,n}, {i,i}}, -a[i][j], true) -- in-place 20 | end 21 | 22 | if j < n then 23 | -- find pivot and check its size 24 | local _, i = a{{j,n},{j,j}}:norm"m" -- argmax(abs(a[[j:n, j]])) 25 | i = i + j - 1 26 | 27 | -- if necessary apply row interchange 28 | if i ~= j then 29 | swap(a[i], a[j]) 30 | b[j], b[i] = b[i], b[j] 31 | end 32 | 33 | a{{j+1,n},{j,j}}._ = a{{j+1,n},{j,j}} / a[j][j] 34 | --a{{j+1,n},{j,j}}:div(a[j][j], false, true) -- in-place 35 | end 36 | end 37 | 38 | -- forward substitution 39 | for i = 1, n - 1 do 40 | b{{i+1,n}}._ = b{{i+1,n}} - a{{i+1,n},{i,i}} * b[i] 41 | --b{{i+1,n}}:add(a{{i+1,n},{i,i}}, -b[i], true) -- in-place 42 | end 43 | 44 | -- back substitution 45 | for j = n, 2, -1 do 46 | b[j] = b[j] / a[j][j] 47 | b{{1,j-1}}._ = b{{1,j-1}} - a{{1,j-1},{j,j}} * b[j] 48 | --b{{1,j-1}}:add(a{{1,j-1},{j,j}}, -b[j], true) -- in-place 49 | end 50 | b[1] = b[1] / a[1][1] -- last case 51 | 52 | return b 53 | end 54 | 55 | -- main 56 | --[ 57 | local iscomplex = true 58 | local n = 200 59 | a = matrix.zeros(n, n, iscomplex) 60 | a:apply(function (i,j) return i + j * (0.5 - rng.runif()) end) 61 | 62 | b = matrix.zeros(n, iscomplex) 63 | b:apply(function (i) return i * rng.runif() end) 64 | --]] 65 | --[[ 66 | a = matrix{{2,1,-1},{-3,-1,2},{-2,1,2}} 67 | b = matrix{8, -11, -3} 68 | --]] 69 | 70 | --[[ 71 | print"a matrix" 72 | list(a) 73 | print"b vector" 74 | list(b) 75 | --]] 76 | 77 | print"solution by matrix" 78 | matrix.list(a:inv() * b) 79 | 80 | print"present solution" 81 | matrix.list(solve(a:copy(), b:copy())) 82 | 83 | -------------------------------------------------------------------------------- /examples/solvef1.lua: -------------------------------------------------------------------------------- 1 | -- a version of linear system solver 2 | -- modified from "Fortran 90/95 explained" 3 | -- by Metcalf and Reid (p. 131-132) 4 | -- to show array sections 5 | 6 | require "numlua" 7 | 8 | -- a is nxn matrix, b is a vector 9 | -- the solution is returned in b 10 | local swap, column, norm = matrix.swap, matrix.col, matrix.norm 11 | local slice, add, div = matrix.slice, matrix.add, matrix.div 12 | function solve (a, b) 13 | local n = #b 14 | assert(a:size"#" == 2 and a:size(1) == a:size(2), "a must be square") 15 | assert(#a == n, "a and b sizes must be equal") 16 | 17 | local col = {} -- store columns 18 | for j = 1, n do -- update elements in column j 19 | local cj = column(a, j) 20 | for i = 1, j - 1 do 21 | -- a{{i+1,n}, {j,j}}._ = a{{i+1,n}, {j,j}} - a{{i+1,n}, {i,i}} * a[i][j] 22 | local ci = col[i] 23 | add(slice(cj, i + 1, n), slice(ci, i + 1, n), -cj[i], true) -- in-place 24 | end 25 | col[j] = cj 26 | 27 | if j < n then 28 | -- find pivot and check its size 29 | local _, i = norm(slice(cj, j, n), "m") -- argmax(abs(cj:slice(j,n))) 30 | i = i + j - 1 31 | 32 | -- if necessary apply row interchange 33 | if i ~= j then 34 | swap(a[i], a[j]) 35 | b[j], b[i] = b[i], b[j] 36 | end 37 | 38 | -- a{{j+1,n},{j,j}}._ = a{{j+1,n},{j,j}} / a[j][j] 39 | div(slice(cj, j + 1, n), cj[j], false, true) -- in-place 40 | end 41 | end 42 | 43 | -- forward substitution 44 | for i = 1, n - 1 do 45 | -- b{{i+1,n}}._ = b{{i+1,n}} - a{{i+1,n},{i,i}} * b[i] 46 | add(slice(b, i + 1, n), slice(col[i], i + 1, n), -b[i], true) -- in-place 47 | end 48 | 49 | -- back substitution 50 | for j = n, 2, -1 do 51 | local cj = col[j] 52 | b[j] = b[j] / cj[j] 53 | -- b{{1,j-1}}._ = b{{1,j-1}} - a{{1,j-1},{j,j}} * b[j] 54 | add(slice(b, 1, j - 1), slice(cj, 1, j - 1), -b[j], true) -- in-place 55 | end 56 | b[1] = b[1] / col[1][1] -- last case 57 | 58 | return b 59 | end 60 | 61 | -- main 62 | --[ 63 | local iscomplex = true 64 | local n = 200 65 | a = matrix.zeros(n, n, iscomplex) 66 | a:apply(function (i,j) return i + j * (0.5 - rng.runif()) end) 67 | 68 | b = matrix.zeros(n, iscomplex) 69 | b:apply(function (i) return i * rng.runif() end) 70 | --]] 71 | --[[ 72 | a = matrix{{2,1,-1},{-3,-1,2},{-2,1,2}} 73 | b = matrix{8, -11, -3} 74 | --]] 75 | 76 | --[[ 77 | print"a matrix" 78 | list(a) 79 | print"b vector" 80 | list(b) 81 | --]] 82 | 83 | print"solution by matrix" 84 | matrix.list(a:inv() * b) 85 | 86 | print"present solution" 87 | matrix.list(solve(a:copy(), b:copy())) 88 | 89 | -------------------------------------------------------------------------------- /examples/sweep.lua: -------------------------------------------------------------------------------- 1 | -- sweep operator from cols i to j (defaults to i): 2 | -- when solving y = X * b using least-squares, 3 | -- 4 | -- [ X' * X | X' * y ] SWEEP [ (X' * X) ^ (-1) | b^ ] 5 | -- [-----------------] --------> [-----------------------] 6 | -- [ y' * X | y' * y ] X' * X [ -b^' | RSS ] 7 | 8 | require "numlua" 9 | 10 | local function sweepaux (a, k) -- single column sweep 11 | local ck = a:col(k) 12 | local b = ck:copy() 13 | local ak, d = a[k], b[k] 14 | ak:div(d, false, true) -- a[k] = a[k] / b[k], in-place 15 | for i = 1, #a do 16 | if i ~= k then 17 | a[i]:add(ak, -b[i], true) -- a[i] = a[i] - b[i] * a[k], in-place 18 | end 19 | end 20 | ck._ = b:div(-d, false, true) -- ck = b, b = -b / d in-place 21 | ck[k] = 1 / d 22 | return a 23 | end 24 | 25 | function sweep (a, i, j) 26 | for k = i, (j or i) do sweepaux(a, k) end 27 | return a 28 | end 29 | 30 | -- example from [...] 31 | local concat, ones, c = matrix.concat, matrix.ones, matrix.c 32 | local seq, t = matrix.seq, matrix.transpose 33 | local inv, norm = matrix.inv, matrix.norm 34 | local X = concat(ones(3), seq(1, 3), ones(3), true) 35 | .. concat(ones(3), seq(1, 3), -ones(3), true) 36 | local y = matrix.c(1, 3, 3, 2, 2, 1) 37 | local xtx, xty = t(X) * X, t(X) * y 38 | local a = concat(xtx, xty, true) .. c(xty, norm(y) ^ 2) 39 | print("inv(X' * X):") 40 | print(matrix.pretty(inv(xtx))) 41 | print("LS solution:", matrix.pretty(X % y)) 42 | print("RSS:", norm(y - X * (X % y)) ^ 2) 43 | print("Sweep:") 44 | print(matrix.pretty(sweep(a, 1, 3))) 45 | 46 | -------------------------------------------------------------------------------- /examples/test.lua: -------------------------------------------------------------------------------- 1 | require "numlua.seeall" 2 | 3 | a = matrix{{1,2,3},{4,5,6},{7,8,0}} 4 | b = matrix{7, 13, -8} 5 | 6 | -- solve equation using LU 7 | -- a:pivot(p) = l * u or, since a:pivot(p) = eye(#a):pivot(p) * a, 8 | -- a = t(eye(#a):pivot(p)) * l * u 9 | function lslu (a, b) 10 | local l, u, p = lu(a) 11 | local x = b:pivot(p) -- x = eye(#a):pivot(p) * b 12 | x:trmul(l, 'l', true) -- x = inv(l) * x 13 | x:trmul(u, 'u', true) -- x = inv(u) * x 14 | return x 15 | end 16 | 17 | print("LS by LU") 18 | list(lslu(a,b)) 19 | 20 | -- solve equation using QR 21 | -- q,r,p = qr(a,true) -- a = q * r * t(p) 22 | function lsqr (a, b) 23 | local q,r = qr(a) 24 | local x = zeros(#b):mmul(a, b, 't') -- x = t(a) * b 25 | x:trmul(r, 'u', true, 't') -- x = t(inv(r)) * x 26 | x:trmul(r, 'u', true) -- x = inv(r) * x 27 | return x 28 | end 29 | 30 | print("LS by QR") 31 | list(lsqr(a,b)) 32 | 33 | --[[ 34 | -- iterative refinement 35 | h = b - a * x 36 | e = zeros(#b):mmul(a, h, 't') -- e = t(a) * r 37 | e:trmul(r, 'u', true, 't') -- e = t(inv(r)) * e 38 | e:trmul(r, 'u', true) -- e = inv(r) * e 39 | x:add(e, 1, true) -- in-place 40 | list(x) 41 | --]] 42 | 43 | -- solve equation using LS 44 | print("LS by LS [QR]") 45 | list(ls(a, b)) -- using QR 46 | 47 | print("LS by LS [SVD]") 48 | list(ls(a, b, true)) -- using SVD 49 | 50 | -------------------------------------------------------------------------------- /examples/wishart.lua: -------------------------------------------------------------------------------- 1 | -- Sample from a Wishart distribution 2 | require "numlua" 3 | 4 | local zeros, chol = matrix.zeros, matrix.chol 5 | local add, trmul, hemul = matrix.add, matrix.trmul, matrix.hemul 6 | local rnorm = rng.rnorm 7 | 8 | function mvnorm (mu, S) 9 | local L = assert(chol(S, "L")) -- Cholesky factor: S = L * L^T 10 | return function (dest) 11 | local dest = dest or zeros(#mu) 12 | local s = rnorm(0, 1, dest) -- s ~ N(0, I_n) 13 | s = trmul(s, L) -- s = L * s, s ~ N(0, S) 14 | s = add(s, mu, true) -- s = s + mu, s ~ N(mu, S) 15 | return s 16 | end 17 | end 18 | 19 | function wishart (S, n) 20 | local m = #S 21 | local L = assert(chol(S, "L")) -- Cholesky factor: S = L * L^T 22 | local c = zeros(m) -- cache 23 | return function () 24 | local w = zeros(m, m) 25 | for i = 1, n - 1 do 26 | c = trmul(rnorm(0, 1, c), L) -- c ~ N(0, S) 27 | w = hemul(w, c, false, "L") -- w = w + c * c^T 28 | end 29 | return hemul(w, trmul(rnorm(0, 1, c), L)) -- n-th run: full hemul 30 | end 31 | end 32 | 33 | -------------------------------------------------------------------------------- /fft.c: -------------------------------------------------------------------------------- 1 | /* {================================================================= 2 | * 3 | * fft.c 4 | * Fast Fourier transforms from FFTW for NumericLua 5 | * Luis Carvalho (lexcarvalho@gmail.com) 6 | * See Copyright Notice in numlua.h 7 | * 8 | * ==================================================================} */ 9 | 10 | #include 11 | #include 12 | #include "numlua.h" 13 | 14 | #define PLAN_LIBNAME "plan" 15 | 16 | typedef struct { 17 | fftw_plan plan; 18 | nl_Matrix *cache; 19 | int inverse; /* inverse transform? */ 20 | lua_Number scale; /* for inversion */ 21 | } nl_Plan; 22 | 23 | 24 | /* Guidelines: do not cross domains: real-real, complex-complex; operations 25 | * are in-place */ 26 | 27 | /* {===================================================================== 28 | * Plans 29 | * ======================================================================} */ 30 | 31 | fftw_plan nl_createplan (lua_State *L, 32 | nl_Matrix *m, int inverse, unsigned flags, lua_Number *scale) { 33 | fftw_plan plan; 34 | int i; 35 | nl_Buffer *dim = nl_getbuffer(L, m->ndims); 36 | for (i = 0; i < m->ndims; i++) /* reverse dims */ 37 | dim->data.bint[i] = m->dim[m->ndims - 1 - i]; 38 | *scale = 1.0 / m->size; 39 | if (m->iscomplex) { /* fft plan? */ 40 | /* in-place, howmany == 1, dist ignored, nembed == n */ 41 | plan = fftw_plan_many_dft(m->ndims, (const int *) dim->data.bint, 1, 42 | (fftw_complex *) m->data, NULL, m->stride, 0, 43 | (fftw_complex *) m->data, NULL, m->stride, 0, 44 | inverse ? FFTW_BACKWARD : FFTW_FORWARD, flags); 45 | } 46 | else { /* fct plan? */ 47 | nl_Buffer *kind = nl_getbuffer(L, m->ndims); 48 | if (inverse) { 49 | for (i = 0; i < m->ndims; i++) { 50 | kind->data.bint[i] = FFTW_REDFT01; 51 | *scale *= 0.5; 52 | } 53 | } 54 | else { 55 | for (i = 0; i < m->ndims; i++) 56 | kind->data.bint[i] = FFTW_REDFT10; 57 | } 58 | /* in-place, howmany == 1, dist ignored, nembed == n */ 59 | plan = fftw_plan_many_r2r(m->ndims, (const int *) dim->data.bint, 1, 60 | m->data, NULL, m->stride, 0, 61 | m->data, NULL, m->stride, 0, 62 | (const fftw_r2r_kind *) kind->data.bint, flags); 63 | nl_freebuffer(kind); 64 | } 65 | nl_freebuffer(dim); 66 | return plan; 67 | } 68 | 69 | static int fft_plan (lua_State *L) { 70 | nl_Matrix *m = nl_checkmatrix(L, 1); 71 | int inverse = lua_toboolean(L, 2); 72 | unsigned flags = (unsigned) luaL_optinteger(L, 3, FFTW_MEASURE); 73 | nl_Plan *p = (nl_Plan *) lua_newuserdata(L, sizeof(nl_Plan)); 74 | p->cache = m; 75 | p->inverse = inverse; 76 | p->plan = nl_createplan(L, m, inverse, flags, &p->scale); 77 | if (p->plan == NULL) { 78 | lua_pushnil(L); 79 | lua_pushliteral(L, "cannot create plan"); 80 | return 2; 81 | } 82 | lua_pushvalue(L, lua_upvalueindex(1)); /* metatable */ 83 | lua_pushlightuserdata(L, (void *) p); 84 | lua_pushvalue(L, 1); /* cache (matrix) */ 85 | lua_rawset(L, -3); /* mt[light(p)] = cache */ 86 | lua_setmetatable(L, -2); /* mt(p) = upvalue */ 87 | return 1; 88 | } 89 | 90 | 91 | /* get cache */ 92 | static int fft_plan__len (lua_State *L) { 93 | lua_pushlightuserdata(L, lua_touserdata(L, 1)); 94 | lua_rawget(L, lua_upvalueindex(1)); /* mt[light(plan)] = cache */ 95 | return 1; 96 | } 97 | 98 | /* execute plan */ 99 | static int fft_plan__call (lua_State *L) { 100 | nl_Plan *p = (nl_Plan *) lua_touserdata(L, 1); 101 | fftw_execute(p->plan); 102 | if (p->inverse) { 103 | if (p->cache->iscomplex) /* fft? */ 104 | ZDSCAL(&p->cache->size, &p->scale, (nl_Complex *) p->cache->data, 105 | &p->cache->stride); 106 | else 107 | DSCAL(&p->cache->size, &p->scale, p->cache->data, &p->cache->stride); 108 | } 109 | return 0; 110 | } 111 | 112 | static int fft_plan__gc (lua_State *L) { 113 | nl_Plan *p = (nl_Plan *) lua_touserdata(L, 1); 114 | fftw_destroy_plan(p->plan); 115 | lua_pushvalue(L, lua_upvalueindex(1)); 116 | lua_pushlightuserdata(L, (void *) p); 117 | lua_pushnil(L); 118 | lua_rawset(L, -3); /* mt[light(plan)] = nil, free ref to cache */ 119 | return 0; 120 | } 121 | 122 | static int fft_plan__tostring (lua_State *L) { 123 | lua_pushfstring(L, PLAN_LIBNAME ": %p", lua_touserdata(L, 1)); 124 | return 1; 125 | } 126 | 127 | 128 | /* {===================================================================== 129 | * Wisdom 130 | * ======================================================================} */ 131 | 132 | static void write_char (char c, void *v) { 133 | luaL_Buffer *b = (luaL_Buffer *) v; 134 | luaL_addchar(b, c); 135 | } 136 | 137 | static int fft_wisdom (lua_State *L) { 138 | if (lua_isnoneornil(L, 1)) { /* return wisdom? */ 139 | luaL_Buffer b; 140 | luaL_buffinit(L, &b); 141 | fftw_export_wisdom(write_char, (void *)&b); 142 | luaL_pushresult(&b); 143 | return 1; 144 | } 145 | if (lua_toboolean(L, 1)) /* forget wisdom? */ 146 | fftw_forget_wisdom(); 147 | else /* get wisdom */ 148 | fftw_import_wisdom_from_string(luaL_checkstring(L, 1)); 149 | return 0; 150 | } 151 | 152 | /* {===================================================================== 153 | * Interface 154 | * ======================================================================} */ 155 | 156 | 157 | static const luaL_Reg fft_func[] = { 158 | {"wisdom", fft_wisdom}, 159 | {NULL, NULL} 160 | }; 161 | 162 | static const luaL_Reg plan_mt[] = { 163 | {"__len", fft_plan__len}, 164 | {"__call", fft_plan__call}, 165 | {"__gc", fft_plan__gc}, 166 | {"__tostring", fft_plan__tostring}, 167 | {NULL, NULL} 168 | }; 169 | 170 | NUMLUA_API int luaopen_numlua_fft (lua_State *L) { 171 | fftw_import_system_wisdom(); 172 | /* plan */ 173 | lua_newtable(L); /* metatable */ 174 | lua_pushvalue(L, -1); 175 | nl_register(L, plan_mt, 1); 176 | lua_pushliteral(L, PLAN_LIBNAME); 177 | lua_setfield(L, -2, "__type"); 178 | /* fft */ 179 | luaL_newlib(L, fft_func); 180 | lua_pushvalue(L, -2); /* plan metatable */ 181 | lua_pushcclosure(L, fft_plan, 1); 182 | lua_setfield(L, -2, "plan"); /* fft.plan */ 183 | lua_newtable(L); /* planner flags */ 184 | lua_pushinteger(L, FFTW_ESTIMATE); 185 | lua_setfield(L, -2, "estimate"); 186 | lua_pushinteger(L, FFTW_MEASURE); 187 | lua_setfield(L, -2, "measure"); 188 | lua_pushinteger(L, FFTW_PATIENT); 189 | lua_setfield(L, -2, "patient"); 190 | lua_pushinteger(L, FFTW_EXHAUSTIVE); 191 | lua_setfield(L, -2, "exhaustive"); 192 | lua_pushinteger(L, FFTW_WISDOM_ONLY); 193 | lua_setfield(L, -2, "wisdomonly"); 194 | lua_setfield(L, -2, "flag"); /* fft.flag */ 195 | return 1; 196 | } 197 | 198 | -------------------------------------------------------------------------------- /ipmpar.c: -------------------------------------------------------------------------------- 1 | /* 2 | ----------------------------------------------------------------------- 3 | 4 | IPMPAR PROVIDES THE INTEGER MACHINE CONSTANTS FOR THE COMPUTER 5 | THAT IS USED. IT IS ASSUMED THAT THE ARGUMENT I IS AN INTEGER 6 | HAVING ONE OF THE VALUES 1-10. IPMPAR(I) HAS THE VALUE ... 7 | 8 | INTEGERS. 9 | 10 | ASSUME INTEGERS ARE REPRESENTED IN THE N-DIGIT, BASE-A FORM 11 | 12 | SIGN ( X(N-1)*A**(N-1) + ... + X(1)*A + X(0) ) 13 | 14 | WHERE 0 .LE. X(I) .LT. A FOR I=0,...,N-1. 15 | 16 | IPMPAR(1) = A, THE BASE. 17 | 18 | IPMPAR(2) = N, THE NUMBER OF BASE-A DIGITS. 19 | 20 | IPMPAR(3) = A**N - 1, THE LARGEST MAGNITUDE. 21 | 22 | FLOATING-POINT NUMBERS. 23 | 24 | IT IS ASSUMED THAT THE SINGLE AND DOUBLE PRECISION FLOATING 25 | POINT ARITHMETICS HAVE THE SAME BASE, SAY B, AND THAT THE 26 | NONZERO NUMBERS ARE REPRESENTED IN THE FORM 27 | 28 | SIGN (B**E) * (X(1)/B + ... + X(M)/B**M) 29 | 30 | WHERE X(I) = 0,1,...,B-1 FOR I=1,...,M, 31 | X(1) .GE. 1, AND EMIN .LE. E .LE. EMAX. 32 | 33 | IPMPAR(4) = B, THE BASE. 34 | 35 | SINGLE-PRECISION 36 | 37 | IPMPAR(5) = M, THE NUMBER OF BASE-B DIGITS. 38 | 39 | IPMPAR(6) = EMIN, THE SMALLEST EXPONENT E. 40 | 41 | IPMPAR(7) = EMAX, THE LARGEST EXPONENT E. 42 | 43 | DOUBLE-PRECISION 44 | 45 | IPMPAR(8) = M, THE NUMBER OF BASE-B DIGITS. 46 | 47 | IPMPAR(9) = EMIN, THE SMALLEST EXPONENT E. 48 | 49 | IPMPAR(10) = EMAX, THE LARGEST EXPONENT E. 50 | 51 | ----------------------------------------------------------------------- 52 | 53 | TO DEFINE THIS FUNCTION FOR THE COMPUTER BEING USED REMOVE 54 | THE COMMENT DELIMITORS FROM THE DEFINITIONS DIRECTLY BELOW THE NAME 55 | OF THE MACHINE 56 | 57 | ----------------------------------------------------------------------- 58 | 59 | IPMPAR IS AN ADAPTATION OF THE FUNCTION I1MACH, WRITTEN BY 60 | P.A. FOX, A.D. HALL, AND N.L. SCHRYER (BELL LABORATORIES). 61 | IPMPAR WAS FORMED BY A.H. MORRIS (NSWC). THE CONSTANTS ARE 62 | FROM BELL LABORATORIES, NSWC, AND OTHER SOURCES. 63 | 64 | ----------------------------------------------------------------------- 65 | .. Scalar Arguments .. 66 | */ 67 | int ipmpar(int *i) 68 | { 69 | static int imach[11]; 70 | static int ipmpar; 71 | /* MACHINE CONSTANTS FOR AMDAHL MACHINES. */ 72 | /* 73 | imach[1] = 2; 74 | imach[2] = 31; 75 | imach[3] = 2147483647; 76 | imach[4] = 16; 77 | imach[5] = 6; 78 | imach[6] = -64; 79 | imach[7] = 63; 80 | imach[8] = 14; 81 | imach[9] = -64; 82 | imach[10] = 63; 83 | */ 84 | /* MACHINE CONSTANTS FOR THE AT&T 3B SERIES, AT&T 85 | PC 7300, AND AT&T 6300. */ 86 | /* 87 | imach[1] = 2; 88 | imach[2] = 31; 89 | imach[3] = 2147483647; 90 | imach[4] = 2; 91 | imach[5] = 24; 92 | imach[6] = -125; 93 | imach[7] = 128; 94 | imach[8] = 53; 95 | imach[9] = -1021; 96 | imach[10] = 1024; 97 | */ 98 | /* MACHINE CONSTANTS FOR THE BURROUGHS 1700 SYSTEM. */ 99 | /* 100 | imach[1] = 2; 101 | imach[2] = 33; 102 | imach[3] = 8589934591; 103 | imach[4] = 2; 104 | imach[5] = 24; 105 | imach[6] = -256; 106 | imach[7] = 255; 107 | imach[8] = 60; 108 | imach[9] = -256; 109 | imach[10] = 255; 110 | */ 111 | /* MACHINE CONSTANTS FOR THE BURROUGHS 5700 SYSTEM. */ 112 | /* 113 | imach[1] = 2; 114 | imach[2] = 39; 115 | imach[3] = 549755813887; 116 | imach[4] = 8; 117 | imach[5] = 13; 118 | imach[6] = -50; 119 | imach[7] = 76; 120 | imach[8] = 26; 121 | imach[9] = -50; 122 | imach[10] = 76; 123 | */ 124 | /* MACHINE CONSTANTS FOR THE BURROUGHS 6700/7700 SYSTEMS. */ 125 | /* 126 | imach[1] = 2; 127 | imach[2] = 39; 128 | imach[3] = 549755813887; 129 | imach[4] = 8; 130 | imach[5] = 13; 131 | imach[6] = -50; 132 | imach[7] = 76; 133 | imach[8] = 26; 134 | imach[9] = -32754; 135 | imach[10] = 32780; 136 | */ 137 | /* MACHINE CONSTANTS FOR THE CDC 6000/7000 SERIES 138 | 60 BIT ARITHMETIC, AND THE CDC CYBER 995 64 BIT 139 | ARITHMETIC (NOS OPERATING SYSTEM). */ 140 | /* 141 | imach[1] = 2; 142 | imach[2] = 48; 143 | imach[3] = 281474976710655; 144 | imach[4] = 2; 145 | imach[5] = 48; 146 | imach[6] = -974; 147 | imach[7] = 1070; 148 | imach[8] = 95; 149 | imach[9] = -926; 150 | imach[10] = 1070; 151 | */ 152 | /* MACHINE CONSTANTS FOR THE CDC CYBER 995 64 BIT 153 | ARITHMETIC (NOS/VE OPERATING SYSTEM). */ 154 | /* 155 | imach[1] = 2; 156 | imach[2] = 63; 157 | imach[3] = 9223372036854775807; 158 | imach[4] = 2; 159 | imach[5] = 48; 160 | imach[6] = -4096; 161 | imach[7] = 4095; 162 | imach[8] = 96; 163 | imach[9] = -4096; 164 | imach[10] = 4095; 165 | */ 166 | /* MACHINE CONSTANTS FOR THE CRAY 1, XMP, 2, AND 3. */ 167 | /* 168 | imach[1] = 2; 169 | imach[2] = 63; 170 | imach[3] = 9223372036854775807; 171 | imach[4] = 2; 172 | imach[5] = 47; 173 | imach[6] = -8189; 174 | imach[7] = 8190; 175 | imach[8] = 94; 176 | imach[9] = -8099; 177 | imach[10] = 8190; 178 | */ 179 | /* MACHINE CONSTANTS FOR THE DATA GENERAL ECLIPSE S/200. */ 180 | /* 181 | imach[1] = 2; 182 | imach[2] = 15; 183 | imach[3] = 32767; 184 | imach[4] = 16; 185 | imach[5] = 6; 186 | imach[6] = -64; 187 | imach[7] = 63; 188 | imach[8] = 14; 189 | imach[9] = -64; 190 | imach[10] = 63; 191 | */ 192 | /* MACHINE CONSTANTS FOR THE HARRIS 220. */ 193 | /* 194 | imach[1] = 2; 195 | imach[2] = 23; 196 | imach[3] = 8388607; 197 | imach[4] = 2; 198 | imach[5] = 23; 199 | imach[6] = -127; 200 | imach[7] = 127; 201 | imach[8] = 38; 202 | imach[9] = -127; 203 | imach[10] = 127; 204 | */ 205 | /* MACHINE CONSTANTS FOR THE HONEYWELL 600/6000 206 | AND DPS 8/70 SERIES. */ 207 | /* 208 | imach[1] = 2; 209 | imach[2] = 35; 210 | imach[3] = 34359738367; 211 | imach[4] = 2; 212 | imach[5] = 27; 213 | imach[6] = -127; 214 | imach[7] = 127; 215 | imach[8] = 63; 216 | imach[9] = -127; 217 | imach[10] = 127; 218 | */ 219 | /* MACHINE CONSTANTS FOR THE HP 2100 220 | 3 WORD DOUBLE PRECISION OPTION WITH FTN4 */ 221 | /* 222 | imach[1] = 2; 223 | imach[2] = 15; 224 | imach[3] = 32767; 225 | imach[4] = 2; 226 | imach[5] = 23; 227 | imach[6] = -128; 228 | imach[7] = 127; 229 | imach[8] = 39; 230 | imach[9] = -128; 231 | imach[10] = 127; 232 | */ 233 | /* MACHINE CONSTANTS FOR THE HP 2100 234 | 4 WORD DOUBLE PRECISION OPTION WITH FTN4 */ 235 | /* 236 | imach[1] = 2; 237 | imach[2] = 15; 238 | imach[3] = 32767; 239 | imach[4] = 2; 240 | imach[5] = 23; 241 | imach[6] = -128; 242 | imach[7] = 127; 243 | imach[8] = 55; 244 | imach[9] = -128; 245 | imach[10] = 127; 246 | */ 247 | /* MACHINE CONSTANTS FOR THE HP 9000. */ 248 | /* 249 | imach[1] = 2; 250 | imach[2] = 31; 251 | imach[3] = 2147483647; 252 | imach[4] = 2; 253 | imach[5] = 24; 254 | imach[6] = -126; 255 | imach[7] = 128; 256 | imach[8] = 53; 257 | imach[9] = -1021; 258 | imach[10] = 1024; 259 | */ 260 | /* MACHINE CONSTANTS FOR THE IBM 360/370 SERIES, 261 | THE ICL 2900, THE ITEL AS/6, THE XEROX SIGMA 262 | 5/7/9 AND THE SEL SYSTEMS 85/86. */ 263 | /* 264 | imach[1] = 2; 265 | imach[2] = 31; 266 | imach[3] = 2147483647; 267 | imach[4] = 16; 268 | imach[5] = 6; 269 | imach[6] = -64; 270 | imach[7] = 63; 271 | imach[8] = 14; 272 | imach[9] = -64; 273 | imach[10] = 63; 274 | */ 275 | /* MACHINE CONSTANTS FOR THE IBM PC. */ 276 | /* 277 | imach[1] = 2; 278 | imach[2] = 31; 279 | imach[3] = 2147483647; 280 | imach[4] = 2; 281 | imach[5] = 24; 282 | imach[6] = -125; 283 | imach[7] = 128; 284 | imach[8] = 53; 285 | imach[9] = -1021; 286 | imach[10] = 1024; 287 | */ 288 | /* MACHINE CONSTANTS FOR THE MACINTOSH II - ABSOFT 289 | MACFORTRAN II. */ 290 | /* 291 | imach[1] = 2; 292 | imach[2] = 31; 293 | imach[3] = 2147483647; 294 | imach[4] = 2; 295 | imach[5] = 24; 296 | imach[6] = -125; 297 | imach[7] = 128; 298 | imach[8] = 53; 299 | imach[9] = -1021; 300 | imach[10] = 1024; 301 | */ 302 | /* MACHINE CONSTANTS FOR THE MICROVAX - VMS FORTRAN. */ 303 | /* 304 | imach[1] = 2; 305 | imach[2] = 31; 306 | imach[3] = 2147483647; 307 | imach[4] = 2; 308 | imach[5] = 24; 309 | imach[6] = -127; 310 | imach[7] = 127; 311 | imach[8] = 56; 312 | imach[9] = -127; 313 | imach[10] = 127; 314 | */ 315 | /* MACHINE CONSTANTS FOR THE PDP-10 (KA PROCESSOR). */ 316 | /* 317 | imach[1] = 2; 318 | imach[2] = 35; 319 | imach[3] = 34359738367; 320 | imach[4] = 2; 321 | imach[5] = 27; 322 | imach[6] = -128; 323 | imach[7] = 127; 324 | imach[8] = 54; 325 | imach[9] = -101; 326 | imach[10] = 127; 327 | */ 328 | /* MACHINE CONSTANTS FOR THE PDP-10 (KI PROCESSOR). */ 329 | /* 330 | imach[1] = 2; 331 | imach[2] = 35; 332 | imach[3] = 34359738367; 333 | imach[4] = 2; 334 | imach[5] = 27; 335 | imach[6] = -128; 336 | imach[7] = 127; 337 | imach[8] = 62; 338 | imach[9] = -128; 339 | imach[10] = 127; 340 | */ 341 | /* MACHINE CONSTANTS FOR THE PDP-11 FORTRAN SUPPORTING 342 | 32-BIT INTEGER ARITHMETIC. */ 343 | /* 344 | imach[1] = 2; 345 | imach[2] = 31; 346 | imach[3] = 2147483647; 347 | imach[4] = 2; 348 | imach[5] = 24; 349 | imach[6] = -127; 350 | imach[7] = 127; 351 | imach[8] = 56; 352 | imach[9] = -127; 353 | imach[10] = 127; 354 | */ 355 | /* MACHINE CONSTANTS FOR THE SEQUENT BALANCE 8000. */ 356 | /* 357 | imach[1] = 2; 358 | imach[2] = 31; 359 | imach[3] = 2147483647; 360 | imach[4] = 2; 361 | imach[5] = 24; 362 | imach[6] = -125; 363 | imach[7] = 128; 364 | imach[8] = 53; 365 | imach[9] = -1021; 366 | imach[10] = 1024; 367 | */ 368 | /* MACHINE CONSTANTS FOR THE SILICON GRAPHICS IRIS-4D 369 | SERIES (MIPS R3000 PROCESSOR). */ 370 | /* 371 | imach[1] = 2; 372 | imach[2] = 31; 373 | imach[3] = 2147483647; 374 | imach[4] = 2; 375 | imach[5] = 24; 376 | imach[6] = -125; 377 | imach[7] = 128; 378 | imach[8] = 53; 379 | imach[9] = -1021; 380 | imach[10] = 1024; 381 | */ 382 | /* MACHINE CONSTANTS FOR IEEE ARITHMETIC MACHINES, SUCH AS THE AT&T 383 | 3B SERIES, MOTOROLA 68000 BASED MACHINES (E.G. SUN 3 AND AT&T 384 | PC 7300), AND 8087 BASED MICROS (E.G. IBM PC AND AT&T 6300). */ 385 | 386 | imach[1] = 2; 387 | imach[2] = 31; 388 | imach[3] = 2147483647; 389 | imach[4] = 2; 390 | imach[5] = 24; 391 | imach[6] = -125; 392 | imach[7] = 128; 393 | imach[8] = 53; 394 | imach[9] = -1021; 395 | imach[10] = 1024; 396 | 397 | /* MACHINE CONSTANTS FOR THE UNIVAC 1100 SERIES. */ 398 | /* 399 | imach[1] = 2; 400 | imach[2] = 35; 401 | imach[3] = 34359738367; 402 | imach[4] = 2; 403 | imach[5] = 27; 404 | imach[6] = -128; 405 | imach[7] = 127; 406 | imach[8] = 60; 407 | imach[9] = -1024; 408 | imach[10] = 1023; 409 | */ 410 | /* MACHINE CONSTANTS FOR THE VAX 11/780. */ 411 | /* 412 | imach[1] = 2; 413 | imach[2] = 31; 414 | imach[3] = 2147483647; 415 | imach[4] = 2; 416 | imach[5] = 24; 417 | imach[6] = -127; 418 | imach[7] = 127; 419 | imach[8] = 56; 420 | imach[9] = -127; 421 | imach[10] = 127; 422 | */ 423 | ipmpar = imach[*i]; 424 | return ipmpar; 425 | } 426 | -------------------------------------------------------------------------------- /lhp/complex.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | complex 4 | ======= 5 | 6 | The `complex` module implements complex numbers according to the C99 standard. 7 | To create a complex number `a + b * i`, simply issue `complex(a, b)` or 8 | `a + b * complex.i`, or even simply `a + b * i` when using `numlua.seeall`. 9 | You can set the real and imaginary parts of complex `z` with `z.r = x` and 10 | `z.i = x` respectively. Since complex numbers are userdata, regular assignment 11 | is a reference assignment (`z = c` makes `z` a reference to `c`); to actually 12 | assign values, use `z._ = c`. 13 | 14 | Similarly to the `math` library, all mathematical functions for C99 complex 15 | numbers are available; please check your man pages for more details about the 16 | following functions: 17 | 18 | abs arg acos acosh asin asinh 19 | atan atanh conj cos cosh exp 20 | imag log logabs proj real sin 21 | sinh sqrt tan tanh 22 | 23 | In particular, to recover the real and imaginary parts of complex `z`, use 24 | `z:real()` and `z:imag()` respectively. In addition to these methods, `add`, 25 | `sub`, `mul`, `div`, and `pow` implement arithmetical methods and metamethods, 26 | that is, `a + b` is equivalent to `complex.add(a, b)` and so on. The "length" 27 | of `z`, `#z`, is `complex.abs(z)`. 28 | 29 | All methods accept an optional last argument -- whose default value is given 30 | by `numlua.opmode` -- that codes for _in-place_ applications. For instance, 31 | 32 | > c = complex(2, -1) 33 | > print(c:exp(), c) 34 | 3.9923240484413-6.217676312368i 2-1i 35 | > print(c:exp(true), c) -- in-place 36 | 3.9923240484413-6.217676312368i 3.9923240484413-6.217676312368i 37 | 38 | and while `c = complex.exp(z * i) * a + b; print(c)` creates (and discards) 39 | four temporary complex numbers, 40 | 41 | op = numlua.opmode(true) -- in-place by default now 42 | c = complex(0, 1); c = complex.exp(c * z) * a + b 43 | numlua.opmode(op) -- restore previous mode 44 | 45 | creates no temporary userdata as all operations are in-place. Note that 46 | operand order is important even when the operation is commutative: if 47 | `numlua.opmode()` is **true**, `a + b` is equivalent to 48 | `complex.add(a, b, true)` where the result is stored at `a`, while `b + a`, or 49 | `complex.add(b, a, true)`, stores at `b`. 50 | ]=] 51 | -------------------------------------------------------------------------------- /lhp/factor/design.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | factor.design(f, [ref]) 4 | ----------------------- 5 | 6 | Retuns design matrix for factor `f`. If `ref` is zero (default value) then no 7 | contrasts are assumed; otherwise, return a "sum to zero" contrast matrix with 8 | `ref` as reference level. 9 | 10 | Example: 11 | 12 | > f = stat.factor{"a", "c", "a", "a", "b", "c"} 13 | > print(f:design():pretty()) 14 | 1 0 0 15 | 0 1 0 16 | 1 0 0 17 | 1 0 0 18 | 0 0 1 19 | 0 1 0 20 | > print(f:design(2):pretty()) 21 | 1 1 0 22 | -1 1 -1 23 | 1 1 0 24 | 1 1 0 25 | 0 1 1 26 | -1 1 -1 27 | 28 | ]=] 29 | -------------------------------------------------------------------------------- /lhp/factor/fold.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | factor.fold(f, m, func [, init]) 4 | -------------------------------- 5 | 6 | Folds the entries in matrix `m` according to the levels in factor `f` and 7 | fold function `func`, that is, for each key level `l`, returns a vector `v` 8 | such that `v[l] = func(m[i1], func(m[i2], func(..., func(m[in], init)...)))` 9 | where `i1, ..., in` satisfy `f(i1) = ... = f(in) = l`. The default value for 10 | `init` is zero. 11 | 12 | Example: 13 | 14 | > f = stat.factor{"a", "c", "a", "a", "b", "c"} 15 | > add2 = function(x, y) return x + y end 16 | > x = matrix.linspace(1, (#f):sum()) 17 | > for l, v in f:fold(x, add2):entries() do print(l, v) end 18 | 1 8 19 | 2 8 20 | 3 5 21 | 22 | 23 | __See also__: `stat.factor`, `factor.partition` 24 | ]=] 25 | -------------------------------------------------------------------------------- /lhp/factor/partition.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | factor.partition(f, m) 4 | ---------------------- 5 | 6 | Partitions the matrix `m` according to the levels in `f` by returning a table 7 | `t` such that `t[l]` is a vector containing the entries `i1, ..., in` in `m` 8 | such that `f(i1) = ... = f(in) = l`. 9 | 10 | Example: 11 | 12 | > f = stat.factor{"a", "c", "a", "a", "b", "c"} 13 | > x = matrix.linspace(1, (#f):sum()) 14 | > vprint = function(v) return table.concat(v:totable(), ", ") end 15 | > for l, v in ipairs(f:partition(x)) do print(l, vprint(v)) end 16 | 1 1, 3, 4 17 | 2 2, 6 18 | 3 5 19 | 20 | 21 | __See also__: `stat.factor`, `factor.fold` 22 | ]=] 23 | -------------------------------------------------------------------------------- /lhp/fft.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | fft 4 | === 5 | 6 | The `fft` module implements fast Fourier transforms. The simple interface to 7 | FFTs comprehends just `matrix.fft` and `matrix.fct` which operate directly on 8 | a matrix. If, however, you intend to execute the same transform many times it 9 | might be more efficient to use a _plan_, so check `fft.plan`. If more control 10 | on how plans are executed is needed, there is also an interface to the 11 | _wisdom_ of FFTW in `fft.wisdom`. 12 | 13 | Example: 14 | 15 | > a = matrix({{1, 2, 3}, {0, -1, -4}}, true) 16 | > b = matrix(a:shape(1, true)) 17 | > p = fft.plan(b, false, fft.flag["measure"]) -- direct transform 18 | > ip = fft.plan(b, true, fft.flag["measure"]) -- inverse transform 19 | > b._ = a 20 | > p(); print(b:pretty()) -- execute direct 21 | 1+0i 1-1.7320508075689i 1+1.7320508075689i 22 | 11+0i -4+3.4641016151378i -4-3.4641016151378i 23 | > ip(); print(b:pretty()) -- execute inverse 24 | 1+0i 2+0i 3+0i 25 | 0+0i -1+0i -4+0i 26 | ]=] 27 | -------------------------------------------------------------------------------- /lhp/fft/plan.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | fft.plan(m [ [, inverse], flag]) 4 | -------------------------------- 5 | 6 | Returns a FFTW plan that uses matrix `m` as a buffer to apply discrete 7 | transforms _in-place_ in `m`. If `m` is complex, a fast Fourier transform 8 | is executed, otherwise, if `m` is real, a discrete cosine transform is 9 | performed. If `inverse` is **true**, _normalized_ inverse transforms are 10 | computed. 11 | 12 | Parameter `flag` specifies a planner flag. Possible values are available in 13 | table `fft.flag`. The default flag is `fft.flag["measure"]`, `FFTW_MEASURE`. 14 | Note that only `"estimate"` (`FFTW_ESTIMATE`) and `"wisdomonly"` 15 | (`FFTW_WISDOM_ONLY`) do _not_ overwrite buffer `m`; for all other flags, `m` 16 | has to be initialized _after_ the plan is created. 17 | 18 | If `plan = fft.plan(m, ...)`, `#plan` returns `m` and `plan()` executes the 19 | plan. 20 | 21 | __See also__: `matrix.fft`, `matrix.fct` 22 | ]=] 23 | -------------------------------------------------------------------------------- /lhp/fft/wisdom.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | fft.wisdom([wisdom]) 4 | -------------------- 5 | 6 | Provides an interface for FFTW wisdoms. If `wisdom` is **nil**, returns the 7 | currently accumulated wisdom; if `wisdom` is **true**, forgets accumulated 8 | wisdom; if `wisdom` is a string, imports wisdom from it. 9 | ]=] 10 | -------------------------------------------------------------------------------- /lhp/mathx.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | mathx 4 | ===== 5 | 6 | This module contains C99 math functions, Bessel functions (from Netlib's AMOS 7 | library), and other utilitary functions. C99 math functions are listed below: 8 | 9 | * `isfinite`, `isinf`, `isnan`, `isnormal`, and `signbit` take one number 10 | argument and return a boolean; 11 | * `acosh`, `asinh`, `atanh`, `cbrt`, `erf`, `erfc`, `exp2`, `expm1`, 12 | `lgamma`, `log1p`, `log2`, `logb`, `nearbyint`, `rint`, `round`, 13 | `tgamma`, and `trunc` take one number argument and return a number; 14 | * `copysign`, `fdim`, `fmax`, `fmin`, `hypot`, `nextafter`, and `remainder` 15 | take two arguments and return a number; 16 | * `fpclassify` takes a number and returns a string; 17 | * `fma` takes three numbers and returns a number; 18 | * `scalbn` takes a number and an "integer" and returns a number 19 | 20 | Please refer to the man pages for details about each of these functions. 21 | ]=] 22 | -------------------------------------------------------------------------------- /lhp/mathx/airya.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | mathx.airya (z, deriv, scaling) 4 | ------------------------------- 5 | 6 | Returns the complex Airy function _Ai(z)_ or its derivative if `deriv` is 7 | **true**, and a completion `status`. If `scaling` is **true**, returns 8 | _Ai(z) * exp(zeta)_ where _zeta = 2 / 3 * z * sqrt(z)_ to remove the 9 | exponential decay in _-pi / 3 < arg(z) < pi / 3_ and the exponential growth 10 | in _pi / 3 < abs(arg(z)) < pi_. 11 | 12 | If `status` is **true**, the return is normal, that is, the computation 13 | completed without errors, underflows, or overflows; otherwise, `status` is 14 | an error message. If no computation is performed, **nil** is returned. 15 | 16 | __See also__: `mathx.airyb` 17 | ]=] 18 | -------------------------------------------------------------------------------- /lhp/mathx/airyb.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | mathx.airyb (z, deriv, scaling) 4 | ------------------------------- 5 | 6 | Returns the complex Airy function _Bi(z)_ or its derivative if `deriv` is 7 | **true**, and a completion `status`. If `scaling` is **true**, returns 8 | _Bi(z) * exp(-abs(real(zeta)))_ where _zeta = 2 / 3 * z * sqrt(z)_, to 9 | remove the exponential behavior in both the left and right half planes. 10 | 11 | If `status` is **true**, the return is normal, that is, the computation 12 | completed without errors, underflows, or overflows; otherwise, `status` is 13 | an error message. If no computation is performed, **nil** is returned. 14 | 15 | __See also__: `mathx.airya` 16 | ]=] 17 | -------------------------------------------------------------------------------- /lhp/mathx/besselh.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | mathx.besselh(nu, z, secondkind, scaling [, n]) 4 | ----------------------------------------------- 5 | 6 | Returns a `n` member sequence of complex Hankel (Bessel) functions 7 | _CY(j) = H(m, nu + j - 1, z)_ where _m = 2_ if `secondkind` is **true** or 8 | _m = 1_ otherwise, with nonnegative orders _nu + j - 1_ for _j = 1, ..., 9 | n_ and complex _z ~= 0_ in the cut plane _-pi < arg(z) < pi_. The size of 10 | the sequence `n` defaults to 1. A completion `status` is also returned. 11 | 12 | If `scaling` is **true**, returns _CY(j) * exp(-mm * z * I)_, where 13 | _mm = 3 - 2 * m_ and _I_ is the imaginary unit. The scaling removes the 14 | exponential behavior in both the upper and lower half planes. 15 | 16 | If `status` is **true**, the return is normal, that is, the computation 17 | completed without errors, underflows, or overflows; otherwise, `status` is 18 | an error message. If no computation is performed, **nil** is returned. 19 | 20 | __See also__: `mathx.besseli`, `mathx.besselj`, `mathx.besselk`, 21 | `mathx.bessely`. 22 | ]=] 23 | -------------------------------------------------------------------------------- /lhp/mathx/besseli.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | mathx.besseli(nu, z, scaling [, n]) 4 | ----------------------------------- 5 | 6 | Returns a `n` member sequence of complex modified Bessel functions of first 7 | kind _CY(j) = I(nu + j - 1, z)_ with nonnegative orders _nu + j - 1_ 8 | for _j = 1, ..., n_ and complex `z` in the cut plane _-pi < arg(z) < pi_. 9 | The size of the sequence `n` defaults to 1. A completion `status` is also 10 | returned. 11 | 12 | If `scaling` is **true**, returns _CY(j) * exp(-abs(real(z)))_ to remove 13 | the exponential growth in both the left and right half planes. 14 | 15 | If `status` is **true**, the return is normal, that is, the computation 16 | completed without errors, underflows, or overflows; otherwise, `status` is 17 | an error message. If no computation is performed, **nil** is returned. 18 | 19 | __See also__: `mathx.besselh`, `mathx.besselj`, `mathx.besselk`, 20 | `mathx.bessely`. 21 | ]=] 22 | -------------------------------------------------------------------------------- /lhp/mathx/besselj.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | mathx.besselj(nu, z, scaling [, n]) 4 | ----------------------------------- 5 | 6 | Returns a `n` member sequence of complex Bessel functions of first 7 | kind _CY(j) = J(nu + j - 1, z)_ with nonnegative orders _nu + j - 1_ 8 | for _j = 1, ..., n_ and complex `z` in the cut plane _-pi < arg(z) < pi_. 9 | The size of the sequence `n` defaults to 1. A completion `status` is also 10 | returned. 11 | 12 | If `scaling` is **true**, returns _CY(j) * exp(-abs(imag(z)))_ to remove 13 | the exponential growth in both the lower and upper half planes. 14 | 15 | If `status` is **true**, the return is normal, that is, the computation 16 | completed without errors, underflows, or overflows; otherwise, `status` is 17 | an error message. If no computation is performed, **nil** is returned. 18 | 19 | __See also__: `mathx.besselh`, `mathx.besseli`, `mathx.besselk`, 20 | `mathx.bessely`. 21 | ]=] 22 | -------------------------------------------------------------------------------- /lhp/mathx/besselk.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | mathx.besselk(nu, z, scaling [, n]) 4 | ----------------------------------- 5 | 6 | Returns a `n` member sequence of complex modified Bessel functions of 7 | second kind _CY(j) = K(nu + j - 1, z)_ with nonnegative orders _nu + j - 1_ 8 | for _j = 1, ..., n_ and complex `z ~= 0` in the cut plane 9 | _-pi < arg(z) < pi_. The size of the sequence `n` defaults to 1. 10 | A completion `status` is also returned. 11 | 12 | If `scaling` is **true**, returns _CY(j) * exp(z)_ to remove 13 | the exponential behavior in both the left and right half planes. 14 | 15 | If `status` is **true**, the return is normal, that is, the computation 16 | completed without errors, underflows, or overflows; otherwise, `status` is 17 | an error message. If no computation is performed, **nil** is returned. 18 | 19 | __See also__: `mathx.besselh`, `mathx.besseli`, `mathx.besselj`, 20 | `mathx.bessely`. 21 | ]=] 22 | -------------------------------------------------------------------------------- /lhp/mathx/bessely.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | mathx.bessely(nu, z, scaling [, n]) 4 | ----------------------------------- 5 | 6 | Returns a `n` member sequence of complex Bessel functions of 7 | second kind _CY(j) = Y(nu + j - 1, z)_ with nonnegative orders _nu + j - 1_ 8 | for _j = 1, ..., n_ and complex `z` in the cut plane 9 | _-pi < arg(z) < pi_. The size of the sequence `n` defaults to 1. 10 | A completion `status` is also returned. 11 | 12 | If `scaling` is **true**, returns _CY(j) * exp(-abs(imag(z)))_ to remove 13 | the exponential growth in both the lower and upper half planes. 14 | 15 | If `status` is **true**, the return is normal, that is, the computation 16 | completed without errors, underflows, or overflows; otherwise, `status` is 17 | an error message. If no computation is performed, **nil** is returned. 18 | 19 | __See also__: `mathx.besselh`, `mathx.besseli`, `mathx.besselj`, 20 | `mathx.besselk`. 21 | ]=] 22 | -------------------------------------------------------------------------------- /lhp/mathx/beta.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | mathx.beta(x, y) 4 | mathx.lbeta(x, y) 5 | ----------------- 6 | 7 | Computes the beta function `B` with arguments `x` and `y` and its logarithm 8 | (`beta` and `lbeta` respectively.) The beta function is defined by 9 | `B(x, y) = integral_0^1 t^(x - 1) (1 - t)^(y - 1) dt`, or, equivalently, by 10 | `B(x, y) = G(x) * G(y) / G(x + y)` where `G` is the gamma function. 11 | 12 | __See also__: `mathx.gamma`, `mathx.lgamma` 13 | ]=] 14 | -------------------------------------------------------------------------------- /lhp/mathx/choose.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | mathx.choose(n, k) 4 | mathx.lchoose(n, k) 5 | ------------------- 6 | 7 | Compute binomial coefficients and their logarithms (`choose` and `lchoose` 8 | respectively`.) 9 | ]=] 10 | -------------------------------------------------------------------------------- /lhp/mathx/digamma.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | mathx.digamma(x) 4 | ---------------- 5 | 6 | Computes the digamma function, the logarithmic derivative of the gamma 7 | function, at `x`. 8 | 9 | __See also__: `mathx.gamma` 10 | ]=] 11 | -------------------------------------------------------------------------------- /lhp/mathx/feq.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | mathx.feq(x1, x2 [, epsilon]) 4 | ----------------------------- 5 | 6 | Approximate equal up to precision `epsilon`, based on Knuth's suggestion 7 | in: Knuth, D. E. (1998), "The Art of Computer Programming. Vol. 2: 8 | Seminumerical Algorithms", Section 4.2.2. 9 | 10 | Note that if `x1 ~== x2` when `feq(x1, x2)` is **true**, then similarly 11 | 12 | * `x1 ~< x2` when `not feq(x1, x2) and x1 < x2` 13 | * `x1 ~> x2` when `not feq(x1, x2) and x1 > x2` 14 | * `x1 ~<= x2` when `feq(x1, x2) or x1 < x2` 15 | * `x1 ~>= x2` when `feq(x1, x2) or x1 > x2` 16 | ]=] 17 | -------------------------------------------------------------------------------- /lhp/mathx/lbeta.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | mathx.beta(x, y) 4 | mathx.lbeta(x, y) 5 | ----------------- 6 | 7 | Computes the beta function `B` with arguments `x` and `y` and its logarithm 8 | (`beta` and `lbeta` respectively.) The beta function is defined by 9 | `B(x, y) = integral_0^1 t^(x - 1) (1 - t)^(y - 1) dt`, or, equivalently, by 10 | `B(x, y) = G(x) * G(y) / G(x + y)` where `G` is the gamma function. 11 | 12 | __See also__: `mathx.gamma`, `mathx.lgamma` 13 | ]=] 14 | -------------------------------------------------------------------------------- /lhp/mathx/lchoose.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | mathx.choose(n, k) 4 | mathx.lchoose(n, k) 5 | ------------------- 6 | 7 | Compute binomial coefficients and their logarithms (`choose` and `lchoose` 8 | respectively`.) 9 | ]=] 10 | -------------------------------------------------------------------------------- /lhp/mathx/log1pe.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | mathx.log1pe(x) 4 | --------------- 5 | 6 | Computes `log(1 + exp(x))` by avoiding calls to `log` and `exp` when `abs(x) < 7 | eps`. 8 | ]=] 9 | -------------------------------------------------------------------------------- /lhp/mathx/lse.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | mathx.lse(x1, x2) 4 | ----------------- 5 | 6 | Computes the "soft max" of `x1` and `x2`, the log sum of exps 7 | `log(exp(x1) + exp(x2))`. 8 | ]=] 9 | -------------------------------------------------------------------------------- /lhp/matrix.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix 4 | ====== 5 | 6 | The `matrix` module implements multidimensional matrices. New `matrix` objects 7 | are created by specifying dimensions with `matrix.new` (uninitialized), 8 | `matrix.zeros` or `matrix.ones` (filled with zeros or ones), or by directly 9 | specifying entries in a table and using `matrix` (or `matrix.fromtable`.) 10 | Matrices can be real or complex, which can be set in the last argument of 11 | these functions. To retrieve the dimensions of a matrix use `matrix.shape` or 12 | `matrix.size`; in particular, `m:size"#"` returns the number of dimensions of 13 | a matrix `m`. 14 | 15 | To access and set entries in a matrix `m` with `n` dimensions you can simply 16 | use `m[i1]...[in]`; for example, to set the entry at row `i` and column `j` of 17 | a two-dimensional matrix you can use `m[i][j] = x`. Alternatively, you can use 18 | `matrix.get` and `matrix.set`. These two functions can also be used to 19 | produce a _reference_ to a submatrix and to assign whole submatrices; as an 20 | example, `m:set(a)` assigns `a` to `m`, either element-wise if `a` is a 21 | conformable matrix or by filling `m` with `a` if `a` is a number or complex. 22 | You can also use `matrix.copy` to copy a matrix. More general matrix 23 | references can be created with `matrix.section` or `matrix.slice`. 24 | 25 | Entries in a matrix can be set more systematically using functional 26 | facilities: `matrix.apply` sets entries based on a function that takes indices 27 | as arguments while `matrix.map` takes a function on entries. Both functions 28 | operate _in-place_ and in _element-order_, that is, in column-major order 29 | (first indices vary faster.) Element-order is also respected when iterating on 30 | a matrix with `matrix.entries`. 31 | 32 | Logical methods -- `matrix.find`, `matrix.ifelse`, and `matrix.which` -- are 33 | helpful for filtering matrix entries. These functions always take a 34 | _condition_ argument, which can be: a boolean function on each entry; or, if a 35 | number `x`, the boolean function `function (e) return e == x end`; or, if a 36 | conformable matrix `x`, `function (e) return e == ex end` where `ex` is the 37 | entry in `x` at the same element-order index of `e`, and so, a boolean 38 | function for element-wise comparison. The condition argument defaults to 39 | `function (e) return e ~= 0 end`. 40 | 41 | Common mathematical operations can be carried using `matrix.map` but for 42 | convenience `matrix` provides the following functions: 43 | 44 | abs acos acosh asin asinh atan 45 | atanh cos cosh exp log sin 46 | sinh sqrt tan tanh 47 | 48 | All these functions take an optional second argument -- whose default value is 49 | given by `numlua.opmode` -- that specifies if the operation should be 50 | in-place. Thus, calling `m:f()` where `f` is any of the functions above, is 51 | semantically equivalent to `matrix.map(inplace and m or m:copy(), f)`. 52 | 53 | Arithmetical methods `matrix.add`, `matrix.mul`, `matrix.div`, and 54 | `matrix.pow` operate element-wise and accept an optional last argument that 55 | signals in-place application to the first argument. Matrix multiplication is 56 | implemented in three specialized methods: `matrix.mmul` for general matrix 57 | multiplication, `matrix.hemul` for Hermitian matrix multiplication, and 58 | `matrix.trmul` for triangular matrix multiplication. Arithmetical metamethods 59 | are, not surprisingly, based on these methods and should work as expected: 60 | `__add` and `__sub` are based on `matrix.add`, `__mul` is based on 61 | `matrix.mul` (for scalars) and `matrix.mmul`, `__mod` is `matrix.ls` (left 62 | division), and `__div` is based on `matrix.div` or `matrix.ls` for right 63 | division (`a / b` is equivalent to `t(t(b) % t(a))` when `a` and `b` are 64 | conformable matrices, where `t` is `matrix.t`, the transpose operator.) 65 | 66 | Note however, that even though metamethods make the code cleaner and more 67 | intuitive, it is often computationally more efficient to use the basic methods 68 | to avoid creation of temporary matrices. Here is a quick example: 69 | 70 | -- updates invA to inv(A + u * v') according to the 71 | -- Sherman-Morrison formula: inv(A + u * v') = inv(A) 72 | -- - (inv(A) * u * v' * inv(A)) / (1 + v' * inv(A) * u) 73 | function shermanmorrison (invA, u, v) 74 | local x = v * invA -- v' * inv(A) 75 | return invA:copy():mmul(invA * u, x, "n", "n", -1 / (1 + dot(x, u))) 76 | end 77 | 78 | The next function is equivalent, 79 | 80 | function naiveshermanmorrison (invA, u, v) 81 | local x = v * invA -- v' * inv(A) 82 | return invA - invA * u * x / (1 + dot(x, u)) 83 | end 84 | 85 | but creates two extra temporary matrices: one from `t = (invA * u) * x` and 86 | other from `t / (1 + dot(x,u))`. 87 | 88 | While favoring in-place operations can help avoid temporary object creation, 89 | the adoption of `numlua.opmode` can make notation lighter and less functional. 90 | It should be used with care, however, since operations being applied to the 91 | first argument of the methods break operation commutativity; for instance, 92 | while both `matrix.add(a, b)` and `matrix.add(b, a)` return a new matrix `c = 93 | a + b`, `matrix.add(a, b, true)` stores -- or better, applies -- the result in 94 | `a` and `matrix.add(b, a, true)` stores the result in `b`. Another example: 95 | 96 | function sweep (a, k) 97 | local ck = a:col(k) 98 | local b = ck:copy() 99 | local ak, d = a[k], b[k] 100 | ak:div(d, false, true) -- a[k] = a[k] / b[k], in-place 101 | for i = 1, #a do 102 | if i ~= k then 103 | a[i]:add(ak, -b[i], true) -- a[i] = a[i] - b[i] * a[k], in-place 104 | end 105 | end 106 | ck._ = b:div(-d, false, true) -- ck = b, b = -b / d in-place 107 | ck[k] = 1 / d 108 | return a 109 | end 110 | 111 | and now using in-place operations by default and metamethods: 112 | 113 | numlua.opmode(true) -- in-place 114 | function sweep (a, k) 115 | local ck = a:col(k) 116 | local b = ck:copy() 117 | local ak, d = a[k], b[k] 118 | ak = ak / d 119 | for i = 1, #a do 120 | if i ~= k then 121 | a[i]:add(ak, -b[i]) -- a[i] = a[i] - ak * b[i] 122 | end 123 | end 124 | ck._ = b / (-d) -- equivalent to ck:set(b / (-d)) 125 | ck[k] = 1 / d 126 | return a 127 | end 128 | 129 | Finally, matrices can be serialized (in HDF5 format) using `matrix.save` and 130 | retrieved using `matrix.load`. 131 | ]=] 132 | -------------------------------------------------------------------------------- /lhp/matrix/add.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.add(a, b [, s [, inplace]]) 4 | ---------------------------------- 5 | 6 | Adds `s * b` to `a`, where `s` defaults to 1. If `b` is a number `s` is 7 | ignored and sets `a[i] = a[i] + real(b)` if `a` is real, or 8 | `a[i] = a[i] + b` if `a` is complex; otherwise, sets 9 | `a[i] = a[i] + b[i] * s` if `b` is a conformable matrix. 10 | In particular, `matrix.add(a, b, -1)` subtracts `b` from `a`. 11 | 12 | If `inplace` is **true**, `a` is updated _in-place_. 13 | ]=] 14 | -------------------------------------------------------------------------------- /lhp/matrix/apply.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.apply(m, f [, eorder]) 4 | ----------------------------- 5 | 6 | Applies a function `f` to each entry in `m` _in-place_, that is, sets 7 | `m[i1,...,in] = f(i1, ..., in, m[i1, ..., in])` where `i1, ..., in` are 8 | indices in `m` (`m` has dimension `n`). If `eorder` is **true**, `f` takes 9 | indices in element-order. If `f` does not return a numeric value, `m` is 10 | not changed for the called index. 11 | 12 | Examples: 13 | 14 | local h = function (i, j) return 1 / (i + j - 1) end 15 | function hilbert (n) 16 | return matrix.new(n, n):apply(h) 17 | end 18 | 19 | local circ = function (v, n) 20 | return function (i, j) return v[(j - i) % n + 1] end 21 | end 22 | function circulant (v) 23 | local n = #v 24 | return matrix.new(n, n):apply(circ(v, n)) 25 | end 26 | ]=] 27 | -------------------------------------------------------------------------------- /lhp/matrix/balance.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.balance (A [, what]) 4 | --------------------------- 5 | 6 | Balances a matrix `A` as a way to reduce its 1-norm and thus improve the 7 | accuracy of the computed eigenvalues and eigenvectors. The operations involve, 8 | first, _permuting_ `A` by a similarity transformation to isolate eigenvalues 9 | in the first 1 to `l` and last `h` to `#A` elements of the diagonal, and then 10 | _scaling_ by a diagonal similarity transformation to rows and columns `l + 1` 11 | to `h - 1` to make them as close in norm as possible. Parameter `what` 12 | controls which operations are performed to balance `A`: 13 | 14 | * `what == "n"` or `what == "N"`: nothing is done (no balancing); 15 | * `what == "p"` or `what == "P"`: permute only; 16 | * `what == "s"` or `what == "S"`: scale only; 17 | * `what == "b"` or `what == "B"`: both permute and scale, the default option 18 | 19 | __See also__: `matrix.eig` 20 | ]=] 21 | -------------------------------------------------------------------------------- /lhp/matrix/c.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.c(v1, ..., vn) 4 | --------------------- 5 | 6 | Concatenates vectors or numbers `v1`, `...`, `vn` into a new vector. 7 | ]=] 8 | -------------------------------------------------------------------------------- /lhp/matrix/chol.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.chol(A [, what [, inplace]]) 4 | ----------------------------------- 5 | 6 | Computes the Cholesky factorization of symmetric positive-definite matrix `A`. 7 | Parameter `what` defines the computation: 8 | 9 | * If `what == "l"` or `what == "L"`, the default value, references only the 10 | lower triangle of `A` and returns a lower triangular matrix `L` such that 11 | `A = L * L^H`; 12 | * If `what == "u"` or `what == "U"`, references only the upper triangle of 13 | `A` and returns an upper triangular matrix `U` such that `A = U^H * U`. 14 | 15 | If an internal error occurs, returns **nil** and an error message; if `A` is 16 | not positive-definite, returns **false** and a warning message. If `inplace` 17 | is **true**, overwrites `A` with its Cholesky factor. 18 | 19 | Examples: 20 | 21 | function matrix.isposdef (m) 22 | local c, msg = chol(m) 23 | if c == nil then error(msg) end 24 | return not c == false 25 | end 26 | 27 | -- generates multivariable normal deviates (also check rng.rmvnorm) 28 | function mvnorm (mu, S) 29 | local L = assert(chol(S, "L")) -- Cholesky factor: S = L * L^T 30 | return function (dest) 31 | local dest = dest or zeros(#mu) 32 | local s = rnorm(0, 1, dest) -- s ~ N(0, I_n) 33 | s = trmul(s, L) -- s = L * s, s ~ N(0, S) 34 | s = add(s, mu, true) -- s = s + mu, s ~ N(mu, S) 35 | return s 36 | end 37 | end 38 | 39 | __See also__: `matrix.hemul`, `matrix.trmul` 40 | ]=] 41 | -------------------------------------------------------------------------------- /lhp/matrix/col.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.col(m, i) 4 | ---------------- 5 | 6 | Returns a _reference_ to the `i`-th column of the two-dimensional matrix `m`. 7 | ]=] 8 | -------------------------------------------------------------------------------- /lhp/matrix/complex.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.complex(a [, b]) 4 | ----------------------- 5 | 6 | Returns a _complex_ matrix `m` such that `real(m) = real(a)` and 7 | `imag(m) = imag(b)`. The default value for `b` is `a`, so, in particular, 8 | `complex(a)` returns a copy of `a` if `a` is complex. An error is raised if 9 | `a` and `b` are not conformable. 10 | 11 | __See also__: `matrix.real`, `matrix.imag` 12 | ]=] 13 | -------------------------------------------------------------------------------- /lhp/matrix/concat.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.concat(m1, ..., mn [, colcat]) 4 | ------------------------------------- 5 | 6 | Concatenates conformable matrices `m1`, `...`, `mn` _row-wise_. If `colcat` is 7 | **true**, concatenates _column-wise_. 8 | ]=] 9 | -------------------------------------------------------------------------------- /lhp/matrix/conj.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.conj(a [, inplace]) 4 | -------------------------- 5 | 6 | Sets each element in `a` to its conjugate in-place if `inplace` is 7 | **true**, or returns the conjugate of `a`. If `a` is not complex, does 8 | nothing. 9 | ]=] 10 | -------------------------------------------------------------------------------- /lhp/matrix/copy.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.copy(m [, x]) 4 | -------------------- 5 | 6 | Returns a copy of `m` and optionally sets its content to `x`, a number. 7 | `matrix.copy` is semantically equivalent to 8 | 9 | function matrix.copy (m, x) 10 | local c = matrix.new(matrix.shape(m, 1, true)) -- frame 11 | return set(c, x or m) 12 | end 13 | 14 | __See also__: `matrix.set` 15 | ]=] 16 | -------------------------------------------------------------------------------- /lhp/matrix/cross.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.cross(a, b [, inplace]) 4 | ------------------------------ 5 | 6 | Computes the cross product of ternary vectors `a` and `b` in-place in `a` if 7 | `inplace` is **true**. 8 | ]=] 9 | -------------------------------------------------------------------------------- /lhp/matrix/diag.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.diag(m [, shift]) 4 | ------------------------ 5 | 6 | If `m` is a vector, returns a square matrix such that the `shift` diagonal of 7 | the matrix is `m`; otherwise, if `m` is two-dimensional, returns a reference 8 | to the `shift` diagonal of `m`. If `shift` is zero (the default value), the 9 | main diagonal is referenced; if `shift > 0`, the `shift` diagonal above the 10 | main diagonal is referenced, and if `shift < 0`, the `shift` diagonal below 11 | the main diagonal is referenced. 12 | 13 | Example: 14 | 15 | function trace (m) 16 | local r, c = m:shape() 17 | assert(m:size"#" == 2 and r == c, "square matrix expected") 18 | return m:diag():sum() 19 | end 20 | ]=] 21 | -------------------------------------------------------------------------------- /lhp/matrix/div.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.div(a, b [, right [, inplace]]) 4 | -------------------------------------- 5 | 6 | Performs _element-wise_ division of `a` and `b`. If `b` is a number, sets 7 | `a[i] = a[i] / real(b)` if `a` is real, or `a[i] = a[i] / b` if `a` is 8 | complex; otherwise, sets `a[i] = a[i] / b[i]` if `b` is a conformable 9 | matrix. 10 | 11 | If `right` is **true**, `a` is divided in the right, that is, `a = b / a`. 12 | If `inplace` is **true**, `a` is updated _in-place_. 13 | ]=] 14 | -------------------------------------------------------------------------------- /lhp/matrix/dot.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.dot(a, b [, trans]) 4 | -------------------------- 5 | 6 | Computes the dot product of conformable matrices `a` and `b`, `a^H b` as 7 | the sum of their element-wise product. If `trans` is **true**, the 8 | conjugate of `a` is _not_ used (and so `a^T b` is actually computed.) 9 | ]=] 10 | -------------------------------------------------------------------------------- /lhp/matrix/eig.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.eig(A [, what [, hermitian]]) 4 | ------------------------------------ 5 | 6 | Computes the eigenvalues of `A`, and optionally the eigenvectors according 7 | to parameter `what`: 8 | 9 | * `what == "n"` or `what == "N"`: do not compute the eigenvectors of `A`, 10 | just return the eigenvalues of `A` (in a vector); 11 | * `what == "l"` or `what == "L"`: returns the eigenvalues (in a vector) and 12 | the left eigenvectors of `A` (in a matrix); 13 | * `what == "r"` or `what == "R"`: the default option, returns the 14 | eigenvalues (in a vector) and the right eigenvectors of `A` (in a 15 | matrix); 16 | * `what == "a"` or `what == "A"`: returns the eigenvalues and both left and 17 | right eigenvectors of `A`. 18 | 19 | Note that the right eigenvectors of `A` are the left eigenvalues of `A^H` and 20 | vice-versa. If `hermitian` is **true**, `A` is assumed to be Hermitian and 21 | only its upper triangle is accessed. 22 | 23 | When computing the eigenvalues -- and optionally eigenvectors -- of `A`, the 24 | matrix is _balanced_ to improve accuracy; see `matrix.balance` for a 25 | description of the operations. There is currently no way of preventing 26 | balancing. 27 | 28 | Examples: 29 | 30 | -- condition number 31 | function cond (m) 32 | local x = zeros(#m, #m):hemul(m) -- x = m * t(m) 33 | local e = eig(x, "n", true) -- sqrt(e) are singular values of m 34 | return math.sqrt(math.abs(max(e) / min(e))) 35 | end 36 | 37 | -- if F[n] is the n-th Fibonacci number, 38 | -- {{F[n-1], F[n]}, {F[n], F[n+1]}} = {{0, 1}, {1, 1}} ^ n 39 | local s, V = eig(matrix{{0, 1}, {1, 1}}, "r", true) 40 | local v = V[1] * V[2] -- element-wise multiplication 41 | local w = zeros(2) -- workspace 42 | function fib (n) 43 | w._ = s; w:pow(n, true) -- w = s ^ n, in-place 44 | return dot(v, w) -- V * diag(s ^ n) * t(V) 45 | end 46 | 47 | __See also__: `matrix.balance`, `matrix.svd` 48 | ]=] 49 | -------------------------------------------------------------------------------- /lhp/matrix/eindex.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.eindex(m, eopos) 4 | ----------------------- 5 | 6 | Returns the dimensional indexes in `m` that correspond to element-order 7 | index `eopos`. 8 | 9 | Example: 10 | 11 | function list (m) 12 | for i, e in m:entries(true) do 13 | local t = {m:eindex(i)} 14 | t[#t + 1] = e 15 | print(unpack(t)) 16 | end 17 | end 18 | 19 | __See also__: `matrix.eorder`, `matrix.entries` 20 | ]=] 21 | -------------------------------------------------------------------------------- /lhp/matrix/entries.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.entries(m [, eorder]) 4 | ---------------------------- 5 | 6 | Returns an iterator over the entries of `m` so that the following construction 7 | iterates over the entries of `m`: 8 | 9 | for i1, i2, ..., in, e in m:entries() do 10 | -- body 11 | end 12 | 13 | Here `n = m:size"#"` is the number of dimensions of `m` and 14 | `e = m[i1][i2]...[in]` takes the value of each entry in `m`. 15 | 16 | This construction is semantically equivalent to 17 | 18 | for i = 1, m:size"*" do 19 | local i1, i2, ..., in = m:eindex(i) 20 | local e = m:get(i1, i2, ..., in) 21 | -- body 22 | end 23 | 24 | __See also__: `matrix.eindex` 25 | ]=] 26 | -------------------------------------------------------------------------------- /lhp/matrix/eorder.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.eorder(m, i1, i2, ..., in) 4 | --------------------------------- 5 | 6 | Returns the element-order index in `m` that corresponds to the dimensional 7 | indexes `i1`, `i2`, ..., `in`, where `n` is the dimensionality of `m`. 8 | 9 | __See also__: `matrix.eindex` 10 | ]=] 11 | -------------------------------------------------------------------------------- /lhp/matrix/fct.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.fct(m [, inverse [, wisdomonly [, inplace]]]) 4 | ---------------------------------------------------- 5 | 6 | Computes the discrete cosine transform of _real_ matrix `m`. 7 | If `inverse` is **true**, computes the _normalized_ inverse DCT. `wisdomonly` 8 | is a FFTW-specific parameter: if **true**, a plan to compute the transform is 9 | only created if wisdom is available for the given problem, that is, a 10 | `FFTW_WISDOM_ONLY` flag is passed when building the plan. The default flag is 11 | `FFTW_ESTIMATE`. If `inplace` is **true**, `m` is updated _in-place_. 12 | 13 | __See also__: `matrix.fft`, `fft.plan` 14 | ]=] 15 | -------------------------------------------------------------------------------- /lhp/matrix/fft.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.fft(m [, inverse [, wisdomonly [, inplace]]]) 4 | ---------------------------------------------------- 5 | 6 | Computes the fast Fourier transform of _complex_ matrix `m`. 7 | If `inverse` is **true**, computes the _normalized_ inverse FFT. `wisdomonly` 8 | is a FFTW-specific parameter: if **true**, a plan to compute the transform is 9 | only created if wisdom is available for the given problem, that is, a 10 | `FFTW_WISDOM_ONLY` flag is passed when building the plan. The default flag is 11 | `FFTW_ESTIMATE`. If `inplace` is **true**, `m` is updated _in-place_. 12 | 13 | __See also__: `matrix.fct`, `fft.plan` 14 | ]=] 15 | -------------------------------------------------------------------------------- /lhp/matrix/find.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.find(m [, cond [, reverse]]) 4 | ----------------------------------- 5 | 6 | Returns the first element-order index in `m` whose respective entry 7 | satisfies `cond`. If `reverse` is **true**, returns the first occurrence in 8 | `m` that does _not_ satisfy `cond`. If no entry in `m` satisfies `cond`, 9 | **nil** is returned. Note that matrix `m` is traversed only up to the first 10 | successful entry. 11 | 12 | Examples: 13 | 14 | function any (m, cond) 15 | return matrix.find(m, cond) ~= nil 16 | end 17 | 18 | function all (m, cond) 19 | return matrix.find(m, cond, true) == nil 20 | end 21 | ]=] 22 | -------------------------------------------------------------------------------- /lhp/matrix/fold.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.fold(m, f [, init]) 4 | -------------------------- 5 | 6 | Computes the _left_ fold of function `f` over the entries in `m` in 7 | element-order, that is, returns 8 | 9 | f(...f(f(init, m[1]), m[2])..., m[n]) 10 | 11 | __See also__: `matrix.sum` 12 | ]=] 13 | -------------------------------------------------------------------------------- /lhp/matrix/get.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.get(m, i1 [, i2 [... [, in]]]) 4 | matrix.get(m, eoindex) 5 | ---------------------- 6 | 7 | Returns a submatrix of `m`. There are two ways of specifying the submatrix: 8 | 9 | * Using the indexes `i1`, ..., `in`, where `n` is `m:size"#"`, the number 10 | of dimensions in `m`: returns the submatrix `m[i1]...[in]`. In 11 | particular, `get(m, i1, ..., in)` returns the entry `m(i1, ..., in)`, 12 | and `m[i]` returns the `i`-th "row" of `m`. 13 | Indices that are greater than their dimension or negative are circularly 14 | remapped to the correct range: if `i` is the index for dimension `d`, `i` 15 | is mapped to `(i - 1) % d + 1` if `i > 0` and `(i + 1) % n + n` if `i < 16 | 0`. Null indices are not allowed. 17 | * Providing an _element-order_ vector `eoindex`; in this case, returns the 18 | respective entries in `m`, that is, returns `v` such that 19 | `v[i] = m[eoindex[i]]` for `i=1, ..., #eoindex`. 20 | 21 | __See also__: `matrix.set` 22 | ]=] 23 | -------------------------------------------------------------------------------- /lhp/matrix/hemul.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.hemul (C, A, [, inner, [, what [, alpha]]]) 4 | -------------------------------------------------- 5 | 6 | Given a Hermitian matrix `C`, performs the Hermitian update `C = C + alpha * 7 | A^H * A` if `inner` is **true**, or `C = C + alpha * A * A^H` otherwise. The 8 | default value for `alpha` is 1. 9 | 10 | Parameter `what` specifies how `C` is to be updated; if `what == "l"` or 11 | `what == "L"`, only the lower triangle of `C` is updated; if `what == "u"` or 12 | `what == "U"`, only the upper triangle of `C` is updated; if `what == "f"` or 13 | `what == "F"`, the lower triangle of `C` is updated by the multiplication and 14 | reflected to the strict upper triangle. The default value for `what` is "F". 15 | 16 | Example: 17 | 18 | -- generates Wishart deviates 19 | function wishart (S, n) 20 | local m = #S 21 | local L = assert(chol(S, "L")) -- Cholesky factor: S = L * L^T 22 | local c = zeros(m) -- cache 23 | return function () 24 | local w = zeros(m, m) 25 | for i = 1, n - 1 do 26 | c = trmul(rnorm(0, 1, c), L) -- c ~ N(0, S) 27 | w = hemul(w, c, false, "L") -- w = w + c * c^T 28 | end 29 | return hemul(w, trmul(rnorm(0, 1, c), L)) -- n-th run: full hemul 30 | end 31 | end 32 | ]=] 33 | -------------------------------------------------------------------------------- /lhp/matrix/ifelse.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.ifelse(m, cond, x [, y]) 4 | ------------------------------- 5 | 6 | Sets the entries in `m` that satisfy `cond` to `x` and, if `y` is specified, 7 | the entries in `m` that do not satisfy `cond` to `y`. Parameters `x` and `y` 8 | can be numbers or conformable matrices to `m`. 9 | 10 | Examples: 11 | 12 | -- note that matrix.which(m, cond, "#") is preferred 13 | function count (m, cond) 14 | return matrix.sum(matrix.ifelse(m:copy(), cond, 1, 0)) 15 | end 16 | 17 | -- mask has ones for true and zeros for false 18 | function merge (x, y, mask) 19 | return matrix.ifelse(mask:copy(), 1, x, y) 20 | end 21 | 22 | local lt = function (x, y) return x < y and 1 or 0 end 23 | function min (x, y) 24 | return ifelse(matrix.map(x:copy(), y, lt), 1, x, y) 25 | end 26 | function max (x, y) 27 | return ifelse(matrix.map(x:copy(), y, lt), 0, x, y) 28 | end 29 | 30 | __See also__: `matrix.which` 31 | ]=] 32 | -------------------------------------------------------------------------------- /lhp/matrix/imag.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.imag(a) 4 | -------------- 5 | 6 | Returns a _real_ matrix that references the _imaginary_ part of `a` if `a` is 7 | complex or returns `matrix.zeros(a:shape())` if `a` is real. 8 | 9 | __See also__: `matrix.real`, `matrix.complex` 10 | ]=] 11 | -------------------------------------------------------------------------------- /lhp/matrix/inv.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.inv(A [, what [, inplace [, norcond]]]) 4 | ---------------------------------------------- 5 | 6 | Returns the inverse of square matrix `A` and an estimate of the reciprocal of 7 | its condition number, according to parameter `what`: 8 | 9 | * `what == "d"` or `what == "D"`, assumes that `A` is a diagonal matrix; 10 | * `what == "l"` or `what == "L"`, assumes that `A` is a lower triangular 11 | matrix, if `what == "u"` or `what == "U"`, assumes `A` is an upper 12 | triangular matrix; 13 | * `what == "p"` or `what == "P"`, assumes that `A` is a Hermitian 14 | positive-definite matrix; 15 | * `what == "g"` or `what == "G"`, the default value, assumes that `A` is a 16 | general matrix. 17 | 18 | If `inplace` is **true** and `what` codes for `A` as being Hermitian 19 | positive-definite or general, `A` is overwritten with either a Cholesky 20 | or LU decomposition respectively. 21 | 22 | If `norcond` is **true**, the reciprocal of the condition number is not 23 | estimated. 24 | 25 | Example: 26 | 27 | -- Square-root of a matrix A by Denman-Beavers algorithm 28 | function dbsqrtm (A, tol, maxiters) 29 | local opmode = numlua.opmode(true) -- set in-place operations 30 | local iY, iZ = zeros(A:shape()), zeros(A:shape()) -- buffers 31 | local s, n = inf, 1 -- norm(Y), #iterations 32 | local Y, Z = copy(A), eye(#A) -- initialize 33 | while true do 34 | iY._, iZ._ = Y, Z 35 | Y, Z = (Y + inv(iZ)) / 2, (Z + inv(iY)) / 2 -- in-place 36 | -- check termination: 37 | local f = norm(Y) 38 | if abs(f - s) <= tol or n > maxiters then break end 39 | s, n = f, n + 1 40 | end 41 | numlua.opmode(opmode) -- restore previous mode 42 | return Y, Z, s 43 | end 44 | 45 | __See also__: `matrix.rcond` 46 | ]=] 47 | -------------------------------------------------------------------------------- /lhp/matrix/iscomplex.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.iscomplex(m) 4 | ------------------- 5 | 6 | Returns **true** if `m` is complex and **false** otherwise. 7 | ]=] 8 | -------------------------------------------------------------------------------- /lhp/matrix/linspace.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.linspace(a, b [, n]) 4 | --------------------------- 5 | 6 | Returns a vector `v` of length `n` -- taken to be `int(|b - a| + 1)` if not 7 | specified -- such that `v[i] = (i - 1) * s` where `s` is `(b - a) / (n - 1)`, 8 | and so `v[1] = a` and `v[n] = b`. 9 | 10 | Examples: 11 | 12 | v = linspace(1, n) -- v = 1:n 13 | 14 | function arith (a, r, n) 15 | return linspace(a, r * (n - 1) + a, n) 16 | end 17 | 18 | function seq (a, b, step) 19 | local n = floor(abs((b - a) / s + 1)) 20 | return linspace(a, b, n) 21 | end 22 | ]=] 23 | -------------------------------------------------------------------------------- /lhp/matrix/load.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.load(filename) 4 | ------------------------ 5 | 6 | Loads a matrix from HDF5 file `filename` and returns the loaded matrix. 7 | ]=] 8 | -------------------------------------------------------------------------------- /lhp/matrix/ls.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.ls (A, b [, svd [, tol [, inplace]]]) 4 | -------------------------------------------- 5 | 6 | Computes the least-squares solution to the linear system `A * x = b`, that is, 7 | finds `x` that minimizes the 2-norm of `b - A * x`, where `A` is a `m`-by-`n` 8 | matrix. Parameter `b` can be a (`m`-by-`nrhs`) matrix containing many 9 | right-hand side vectors as columns. 10 | 11 | If `svd` is **true**, the solution is found using a singular value 12 | decomposition; otherwise, a QR factorization is applied. The effective rank of 13 | `A` is relative to `tol`, which defaults to `max(m, n) * mathx.eps` (see 14 | Example in `matrix.svd` for details). 15 | 16 | If `inplace` is **true**, the solution is returned in `b` if the system is 17 | not underdetermined, that is, if `A` has at least as many rows as columns. In 18 | this case, `b:slice(1,n)` contains the solutions `x` and the sum of squares 19 | for the `i`-th column of `b:slice(n+1, m)` is the residual sum of squares for 20 | the solution of the `i`-th right-hand side. 21 | 22 | The solution and the effective rank are returned; in addition, if `svd` is 23 | **true**, the singular values of `A` are also returned (as a vector). 24 | 25 | Example: 26 | 27 | -- basic LS linear model fitting 28 | function matrix.lm (a, b, svd) 29 | local m, n = a:shape() 30 | assert(m >= n, "system is underdetermined") 31 | assert(b:size"#" == 1, "single RHS expected") 32 | local x, rank = ls(a, b, svd) 33 | -- report summary statistics 34 | local coef = x:slice(1, n) 35 | local rss = (b - a * coef):norm() ^ 2 36 | local rss0 = (b - b:sum() / m):norm() ^ 2 37 | local df = m - rank 38 | local F = df / (rank - 1) * (rss0 / rss - 1) 39 | local pvalue = 1 - stat.pf(F, rank - 1, df) 40 | return {coef = coef, rss = rss, df = df, F = F, pvalue = pvalue} 41 | end 42 | 43 | __See also__: `matrix.svd`, `matrix.qr` 44 | ]=] 45 | -------------------------------------------------------------------------------- /lhp/matrix/lu.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.lu(A [, inplace]) 4 | ------------------------ 5 | 6 | Computes the LU decomposition of `A`: returns an unit lower triangular matrix 7 | `L`, an upper triangular matrix `U` and a permutation vector `pvt` such that 8 | `A:pivot(pvt) = L * U`, or equivalently, `A = P^T * L * U` where 9 | `P = eye(#A):pivot(pvt)`. If `inplace` is **true**, both `L` and `U` are 10 | returned _in-place_ at `A`, `L` on the strict lower triangle and `U` on the 11 | upper triangle. 12 | 13 | Examples: 14 | 15 | -- compute determinant of m 16 | function det (m) 17 | local c = assert(lu(copy(m), true)) -- in-place on copy 18 | return prod(diag(c)) 19 | end 20 | 21 | -- solve linear system A * x = b 22 | function linsolve (A, b) 23 | local l, u, p = lu(A) 24 | local x = b:pivot(p) -- x = eye(#A):pivot(p) * b 25 | x:trmul(l, 'l', true) -- x = inv(l) * x 26 | x:trmul(u, 'u', true) -- x = inv(u) * x 27 | return x 28 | end 29 | 30 | __See also__: `matrix.pivot` 31 | ]=] 32 | -------------------------------------------------------------------------------- /lhp/matrix/map.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.map(m1, m2, ..., mn, f) 4 | ------------------------------ 5 | 6 | Sets, in element-order, the i-th entry in `m1` _in-place_ to 7 | 8 | m1[i] = f(m1[i], m2[i], ..., mn[i]) 9 | 10 | if the returned value is a number or complex, where `m2`, ..., `mn` are all 11 | conformable to `m1`. 12 | ]=] 13 | -------------------------------------------------------------------------------- /lhp/matrix/max.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.max(m) 4 | ------------- 5 | 6 | Returns the _maximum_ element in `m` and the maximizing element-order index 7 | of `m`. Complex numbers are compared based on their real parts, and their 8 | imaginary parts are only used to break ties. 9 | 10 | __See also__: `matrix.min`, `matrix.sort` 11 | ]=] 12 | -------------------------------------------------------------------------------- /lhp/matrix/min.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.min(m) 4 | ------------- 5 | 6 | Returns the _minimum_ element in `m` and the minimizing element-order index 7 | of `m`. Complex numbers are compared based on their real parts, and their 8 | imaginary parts are only used to break ties. 9 | 10 | __See also__: `matrix.max`, `matrix.sort` 11 | ]=] 12 | -------------------------------------------------------------------------------- /lhp/matrix/mmul.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.mmul (C, A, B [, transA, transB, alpha]) 4 | ----------------------------------------------- 5 | 6 | For conformable matrices `A`, `B`, and `C`, updates `C` with the 7 | multiplication `C = C + alpha * transA(A) * transB(B)`. Parameters `transA` 8 | and `transB` specify possible operations for `A` and `B`: 9 | 10 | * `"n"` or `"N"` does nothing (default); 11 | * `"t"` or `"T"` takes the transpose; 12 | * `"c"` or `"C"` takes the conjugate transpose. 13 | 14 | If `B` is a vector, `transB` is ignored. Moreover, `A` can only be a vector if 15 | `B` is also a vector, in which case the outer product `A * B^H` is computed 16 | regardless of `transA` and `transB`. 17 | ]=] 18 | -------------------------------------------------------------------------------- /lhp/matrix/mul.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.mul(a, b [, inplace]) 4 | ---------------------------- 5 | 6 | Performs _element-wise_ multiplication of `a` and `b`. If `b` is a number, 7 | sets `a[i] = a[i] * real(b)` if `a` is real, or `a[i] = a[i] * b` if `a` is 8 | complex; otherwise, sets `a[i] = a[i] * b[i]` if `b` is a conformable 9 | matrix. 10 | 11 | If `inplace` is **true**, `a` is updated _in-place_. 12 | ]=] 13 | -------------------------------------------------------------------------------- /lhp/matrix/new.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.new(d1, d2, ... [, iscomplex]) 4 | matrix.zeros(d1, d2, ... [, iscomplex]) 5 | matrix.ones(d1, d2, ... [, iscomplex]) 6 | -------------------------------------- 7 | 8 | Returns a matrix with dimensions `d1`, `d2`, and so on. If last argument 9 | `iscomplex` is **true**, the returned matrix is _complex_. The entries are 10 | _arbitrary_ (not initialized) when using `new`, initialized to zero when 11 | using `zeros`, and initialized to one when using `ones`. 12 | ]=] 13 | -------------------------------------------------------------------------------- /lhp/matrix/norm.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.norm(m [, what]) 4 | ----------------------- 5 | 6 | Computes the norm of `m` according to parameter `what`: 7 | 8 | * if `what` is a number `p`, computes the Lp norm 9 | * `what == "m"` or `what == "M"`: computes `max(abs(m))` 10 | * `what == "o"` or `what == "O"`: computes the one norm, that is, 11 | the maximum column sum if `m` is a two-dimensional matrix 12 | * `what == "i"` or `what == "I"`: computes the infinity (sup) norm, that is, 13 | the maximum row sum if `m` is a two-dimensional matrix 14 | * `what == "f"` or `what == "F"`: computes the Frobenius norm 15 | 16 | The default value for `what` is `"F"`. If `what == "m"`, `what == "M"`, 17 | `what == "i"`, or `what == "I"`, also returns the index the maximizes the 18 | norm. 19 | ]=] 20 | -------------------------------------------------------------------------------- /lhp/matrix/ones.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.new(d1, d2, ... [, iscomplex]) 4 | matrix.zeros(d1, d2, ... [, iscomplex]) 5 | matrix.ones(d1, d2, ... [, iscomplex]) 6 | -------------------------------------- 7 | 8 | Returns a matrix with dimensions `d1`, `d2`, and so on. If last argument 9 | `iscomplex` is **true**, the returned matrix is _complex_. The entries are 10 | _arbitrary_ (not initialized) when using `new`, initialized to zero when 11 | using `zeros`, and initialized to one when using `ones`. 12 | ]=] 13 | -------------------------------------------------------------------------------- /lhp/matrix/pivot.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.pivot(m, pvt [, colpivot [, inplace]]) 4 | --------------------------------------------- 5 | 6 | Given pivot vector `pvt`, returns a new matrix `p` with the same rows of 7 | `m` but with rows `i` and `pvt[i]` swapped. Note that, in particular, 8 | `p = P * m`, where `P = eye(#m):pivot(pvt)`, that is, `P` is the 9 | permutation matrix for `pvt`. 10 | 11 | If `colpivot` is **true**, columns are swapped instead of rows, that is, 12 | returns `p = m * P` where `P = eye(#m):pivot(pvt, true)`. 13 | 14 | If `inplace` is **true**, rows/columns are swapped _in-place_. 15 | 16 | Examples: 17 | 18 | function perm (p) -- column permutation 19 | local n = #p 20 | local s = matrix.linspace(1, n):pivot(p) 21 | local P = matrix.zeros(n, n) 22 | for i = 1, n do P[i][s[i]] = 1 end 23 | return P 24 | end 25 | 26 | -- see `matrix.lu` and `matrix.qr` for details: 27 | require "numlua.seeall" 28 | l, u, p = lu(a) 29 | print(pretty(perm(p) * a)) -- = a:pivot(p)) = l * u 30 | q, r, p = qr(a,true) 31 | print(pretty(q * r * t(perm(p)))) -- = (q * r):pivot(p,true) = a 32 | 33 | ]=] 34 | -------------------------------------------------------------------------------- /lhp/matrix/pow.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.pow(a, b [, inplace]) 4 | ---------------------------- 5 | 6 | Performs element-wise power of `a` and `b`. If `b` is a number, sets 7 | `a[i] = a[i] ^ real(b)` if `a` is real, or `a[i] = a[i] ^ b` if `a` is 8 | complex; otherwise, sets `a[i] = a[i] ^ b[i]` if `b` is a conformable 9 | matrix. 10 | 11 | If `inplace` is **true**, `a` is updated _in-place_. 12 | ]=] 13 | -------------------------------------------------------------------------------- /lhp/matrix/qr.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.qr(A [, permute [, inplace]]) 4 | ------------------------------------ 5 | 6 | Computes the QR factorization of matrix `A`, that is, returns an unitary 7 | matrix `Q` and an upper trapezoidal matrix `R` such that `A = Q * R`. 8 | 9 | If `permute` is **true**, computes the QR factorization with column pivoting 10 | by also returning a permutation vector `p` such that 11 | `A = (Q * R):pivot(p, true)`, that is, `P = eye(A:size(2)):pivot(p, true)` 12 | satisfies `A * P^T = Q * R`. 13 | 14 | In `inplace` is **true**, `A` is overwritten with `R`. 15 | 16 | Example: 17 | 18 | -- solve linear system A * x = b 19 | function linsolve (A, b) 20 | local q, r = qr(A) 21 | local x = zeros(#b):mmul(A, b, 't') -- x = t(A) * b 22 | x:trmul(r, 'u', true, 't') -- x = t(inv(r)) * x 23 | x:trmul(r, 'u', true) -- x = inv(r) * x 24 | return x 25 | end 26 | 27 | ]=] 28 | -------------------------------------------------------------------------------- /lhp/matrix/rcond.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.rcond(A [, what [, inplace]]) 4 | ------------------------------------ 5 | 6 | Estimates the reciprocal of the condition number of matrix `A` in 1-norm, 7 | depending on parameter `what`: 8 | 9 | * `what == "d"` or `what == "D"`, assumes that `A` is a diagonal matrix; 10 | * `what == "l"` or `what == "L"`, assumes that `A` is a lower triangular 11 | matrix, if `what == "u"` or `what == "U"`, assumes `A` is an upper 12 | triangular matrix; 13 | * `what == "p"` or `what == "P"`, assumes that `A` is a Hermitian 14 | positive-definite matrix; 15 | * `what == "g"` or `what == "G"`, the default value, assumes that `A` is a 16 | general matrix. 17 | 18 | If `inplace` is **true** and `what` codes for `A` as being Hermitian 19 | positive-definite or general, `A` is overwritten with either a Cholesky 20 | or LU decomposition respectively. 21 | 22 | __See also__: `matrix.svd`, `matrix.inv` 23 | ]=] 24 | -------------------------------------------------------------------------------- /lhp/matrix/real.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.real(a) 4 | -------------- 5 | 6 | Returns a _real_ matrix that references the _real_ part of `a` if `a` is 7 | complex or returns `a` itself if `a` is real. 8 | 9 | __See also__: `matrix.imag`, `matrix.complex` 10 | ]=] 11 | -------------------------------------------------------------------------------- /lhp/matrix/reshape.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.reshape(m, d1, d2, ..., dn) 4 | ---------------------------------- 5 | 6 | Returns a _reference_ to `m` that has dimensions `d1`, `d2`, `...`, `dn`. The 7 | new dimensions need to be consistent, that is, `d1 * d2 * ... * dn == 8 | m:size"*"`. 9 | 10 | __See also__: `matrix.size` 11 | ]=] 12 | -------------------------------------------------------------------------------- /lhp/matrix/save.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.save(m, filename) 4 | ------------------------ 5 | 6 | Saves matrix `m` in HDF5 file `filename`. 7 | ]=] 8 | -------------------------------------------------------------------------------- /lhp/matrix/section.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.section(m, section) 4 | -------------------------- 5 | 6 | Returns a _section_ of matrix `m` according to table `section`. `section` 7 | is taken as a table with integer indices from 1 to `n`, the number of 8 | dimensions of `m`; the `i`-th value of `section` should contain another 9 | table specifying a _slice_ in the form `{first, last, step}`, where `first` 10 | and `step` default to 1 and `last` defaults to `m:size(i)`. The returned 11 | section is a _reference_ to `m`. 12 | 13 | A shortcut for `matrix.section(m, section)` is `m(section)`. 14 | 15 | Example: 16 | 17 | -- assume a and b are real two-dimensional matrices 18 | -- check `matrix.kronecker` for a more efficient version 19 | function kronecker (a, b) 20 | local ra, ca = a:shape() 21 | local rb, cb = b:shape() 22 | local x = matrix.new(ra * rb, ca * cb) 23 | for i = 1, ra do 24 | for j = 1, ca do 25 | x{{(i-1)*rb+1, i*rb}, {(j-1)*cb+1, j*cb}}._ = b * a[i][j] 26 | end 27 | end 28 | return x 29 | end 30 | 31 | 32 | __See also__: `matrix.slice` 33 | ]=] 34 | -------------------------------------------------------------------------------- /lhp/matrix/set.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.set(m, i1 [, i2 [... [, in]]], value) 4 | matrix.set(m, eoindex, value) 5 | matrix.set(m, what, value) 6 | -------------------------- 7 | 8 | Sets a submatrix of `m` to `value`. There are three ways of specifying the 9 | submatrix: 10 | 11 | * Using the indexes `i1`, ..., `in`, where `n` is `m:size"#"`, the number 12 | of dimensions in `m`: operates on the submatrix `m[i1]...[in]`. Similarly 13 | to `matrix.get`, indices can be remapped if out of range and null indices 14 | are forbidden. 15 | * Providing an _element-order_ vector `eoindex`; in this case, 16 | `m[eoindex[i]] = value[i]`, that is, the respective entries in `m` 17 | are set for `i=1, ..., #eoindex`. 18 | * Specifying `what` to `"_"` to assign the whole matrix, `"l"` or `"L"` to 19 | assign only the strict lower triangle of `m`, `"u"` or `"U"` to assign 20 | only the strict upper triangle of `m`, and `"d"` or `"D"` to assign the 21 | diagonal of `m`. 22 | 23 | Parameter `value` can be a number (or complex) or a conformable matrix 24 | according to the submatrix being indexed. 25 | 26 | __See also__: `matrix.get` 27 | ]=] 28 | -------------------------------------------------------------------------------- /lhp/matrix/shape.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.shape(m [, index [, complex]]) 4 | ------------------------------------- 5 | 6 | Returns the dimensions of `m` starting at dimension `index` (defaults to 1) 7 | and if `m` is complex when `complex` is **true**. 8 | 9 | __See also__: `matrix.size` 10 | ]=] 11 | -------------------------------------------------------------------------------- /lhp/matrix/size.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.size(m [, index]) 4 | ------------------------ 5 | 6 | Returns the size of `m`, depending on parameter `index`: 7 | 8 | * if `index` is a number, returns the size of the `index`-th dimension of 9 | `m` 10 | * if `index == "#"`, returns the number of dimensions of `m` 11 | * if `index == "*"`, returns the total number of elements of `m` 12 | 13 | The default value for `index` is 1. 14 | 15 | __See also__: `matrix.shape` 16 | ]=] 17 | -------------------------------------------------------------------------------- /lhp/matrix/slice.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.slice(m [, first] [, last] [, step]) 4 | ------------------------------------------- 5 | 6 | Returns a _section_ of matrix `m` that is a slice in the first dimension of 7 | `m` starting at `first` (defaults to 1), ending at `last` (defaults to 8 | `#m`), and alternating by `step` (defaults to 1) positions. The returned 9 | section is a _reference_ to `m`. 10 | 11 | A shortcut for `matrix.slice(m, first, last, step)` is `m(first, last, step)`. 12 | 13 | __See also__: `matrix.section` 14 | ]=] 15 | -------------------------------------------------------------------------------- /lhp/matrix/sort.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.sort (m [, decreasing [, returnindex]]) 4 | ---------------------------------------------- 5 | 6 | Sorts `m` _in-place_. If `decreasing` is **true**, sorts in decreasing order. 7 | If `returnindex` is **true** returns `index` such that `m[i]` was 8 | `m[index[i]]` before sorting, where `i` is in element-order; otherwise, 9 | returns `m`. 10 | 11 | As in `matrix.min` and `matrix.max`, complex numbers are compared based on 12 | their real parts, and their imaginary parts are only used to break ties. 13 | 14 | Example: 15 | 16 | iv = matrix.sort(v, false, true) -- increasing, return index 17 | x = matrix.new(matrix.shape(v, 1, true)) 18 | x[iv] = v -- restore v 19 | 20 | __See also__: `matrix.min`, `matrix.max` 21 | ]=] 22 | -------------------------------------------------------------------------------- /lhp/matrix/spread.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.spread(m [, dim [, count]]) 4 | ---------------------------------- 5 | 6 | Returns a replicated version of `m` along dimension `d` (defaults to 1) 7 | `count` number of times (defaults to 1). 8 | ]=] 9 | -------------------------------------------------------------------------------- /lhp/matrix/sum.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.sum(m [, alpha [, init]]) 4 | -------------------------------- 5 | 6 | Performs a linear fold on matrix `m` in element-order, that is, computes 7 | 8 | (...((init * alpha + m[1]) * alpha + m[2]) ... ) * alpha + m[n]) 9 | 10 | where `n = m:size"*"`. 11 | 12 | Parameters `alpha` and `init` default to 1 and 0 respectively; in 13 | particular, `matrix.sum(m)` computes the simple sum of the entries in `m`. 14 | It is semantically equivalent to 15 | 16 | matrix.fold(m, function(a, e) return a * alpha + e end, init) 17 | 18 | __See also__: `matrix.fold` 19 | ]=] 20 | -------------------------------------------------------------------------------- /lhp/matrix/svd.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.svd(A [, what]) 4 | ---------------------- 5 | 6 | Computes the singular value decomposition of `m`-by-`n` matrix `A`. The SVD is 7 | specified as `A = U * S * V^H`, where `U` and `V` are unitary matrices whose 8 | first `min(m, n)` columns represent the left and right singular vectors of 9 | `A`, respectively, and `S` is a diagonal matrix whose `min(m, n)` diagonal 10 | entries contain the singular values of `A`. `U`, `V`, and `S` are computed 11 | according to parameter `what`: 12 | 13 | * `what == "n"` or `what == "N"`, returns only the singular values of `A`; 14 | * `what == "l"` or `what == "L"`, the first `min(m, n)` columns of `U` are 15 | stored _in-place_ at `A`; 16 | * `what == "r"` or `what == "R"`, the first `min(m, n)` rows of `V^H` are 17 | stored _in-place_ at `A`; 18 | * `what == "a"` or `what == "A"`, the default value, returns `U`, `S`, and 19 | `V^H`. 20 | 21 | The singular values are returned in descending order. Note that `V^H` is 22 | returned, not `V`. 23 | 24 | If an internal error occurs, returns **nil** and a diagnostic message; if the 25 | algorithm fails to converge, returns **false** and a warning message. 26 | 27 | Examples: 28 | 29 | function cond (m) 30 | local s = assert(svd(m, "n")) -- just singular values 31 | return s[1] / s[#m] -- condition number 32 | end 33 | 34 | local lt = function (x) return function(e) return e < x end end 35 | function matrix.rank (m, tol) -- effective rank according to tol 36 | local s = assert(svd(m, "n")) -- just singular values 37 | local tol = tol or 0 38 | if tol <= 0 then -- set default tolerance? 39 | tol = max(m:shape()) * eps * s[1] 40 | end 41 | local r = s:find(lt(tol)) 42 | if r == nil then -- all > tol? 43 | return #s -- full rank: min(m:shape()) 44 | end 45 | return r - 1 -- last position > tol 46 | end 47 | 48 | For other examples, see `matrix.null`, `matrix.orth`, and `matrix.pinv` in 49 | `matrix.lua`. 50 | 51 | __See also__: `matrix.rcond` 52 | ]=] 53 | -------------------------------------------------------------------------------- /lhp/matrix/swap.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.swap (a, b) 4 | ------------------ 5 | 6 | Swaps the contents of conformable vectors `a` and `b`. 7 | ]=] 8 | -------------------------------------------------------------------------------- /lhp/matrix/transpose.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.transpose (m [, hermitian]) 4 | ------------------------------------ 5 | 6 | Returns the transpose of matrix `m`. If `hermitian` is **true**, returns the 7 | conjugate transpose of `m`. 8 | ]=] 9 | -------------------------------------------------------------------------------- /lhp/matrix/trmul.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.trmul (x, A [, uplo [, invert [, trans [, side]]]]) 4 | ---------------------------------------------------------- 5 | 6 | For conformable two-dimensional matrices `A` and `x`, `A` square, returns the 7 | result of `tri(A) * x` _in-place_ in `x`, where `tri(A)` takes the lower 8 | triangle section of `A` if `uplo == "l"` or `uplo == "L"`, or the upper 9 | triangle section of `A` if `uplo == "u"` or `uplo == "U"`. The default value 10 | for `uplo` is `"L"`. 11 | 12 | If `invert` is **true**, multiplies by the inverse of `A`. 13 | 14 | If `trans == "t"` or `trans == "T"`, returns `tri(A)^T * x`; if `trans == "c"` 15 | or `trans == "C"`, returns `tri(A)^H * x` (conjugate transpose); if 16 | `trans == "n"` or `trans == "N"`, does nothing (default behavior). 17 | 18 | If `side == "l"` or `side == "L"`, `A` is multiplied at the left of `x` 19 | (default); if `side == "r"` or `side == "R"`, `A` is multiplied at the right, 20 | that is, returns `x * tri(A)`. 21 | 22 | For examples, see `matrix.lu` and `matrix.qr`. 23 | ]=] 24 | -------------------------------------------------------------------------------- /lhp/matrix/which.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.which(m [, cond [, what]]) 4 | --------------------------------- 5 | 6 | Returns entries in `m` that satisfy `cond` depending on `what`: 7 | 8 | * `what = "k"`: returns a vector of element-order indices in `m` whose 9 | respective entries satisfy `cond` or **nil** otherwise; 10 | * `what = "v"`: returns a vector containing the entries in `m` that 11 | satisfy `cond` or **nil** otherwise; 12 | * `what = "#"`: returns only the number of entries that safisty `cond`. 13 | 14 | Parameter `what` defaults to `"k"`. 15 | 16 | Examples: 17 | 18 | -- simple alias 19 | function count (m, cond) 20 | return matrix.which(m, cond, "#") 21 | end 22 | 23 | -- mask has ones for true and zeros for false 24 | function pack (m, mask) 25 | return matrix.which(m, mask, "v") 26 | end 27 | function unpack (v, mask, m) 28 | return matrix.set(m, matrix.which(m, mask), v) 29 | end 30 | 31 | __See also__: `matrix.ifelse` 32 | ]=] 33 | -------------------------------------------------------------------------------- /lhp/matrix/zeros.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | matrix.new(d1, d2, ... [, iscomplex]) 4 | matrix.zeros(d1, d2, ... [, iscomplex]) 5 | matrix.ones(d1, d2, ... [, iscomplex]) 6 | -------------------------------------- 7 | 8 | Returns a matrix with dimensions `d1`, `d2`, and so on. If last argument 9 | `iscomplex` is **true**, the returned matrix is _complex_. The entries are 10 | _arbitrary_ (not initialized) when using `new`, initialized to zero when 11 | using `zeros`, and initialized to one when using `ones`. 12 | ]=] 13 | -------------------------------------------------------------------------------- /lhp/numlua.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | Numeric Lua 4 | =========== 5 | 6 | _Numeric Lua_ is a numerical package for the Lua programming language. It 7 | includes support for complex numbers, multidimensional matrices, random number 8 | generation, fast Fourier transforms, and special functions. Most of the 9 | routines are simple wrappers for well known numerical libraries: complex 10 | numbers and part of the extended math modules come from C99; other special 11 | functions, including statistical functions, are adapted from Netlib's SLATEC 12 | and DCDFLIB; random number generation is based on Takuji Nishimura and Makoto 13 | Matsumoto's Mersenne Twister generator as the "engine" (uniform deviates) and 14 | Netlib's RANLIB for the remaining deviates; fast Fourier transforms are 15 | implemented from FFTW; and the matrix package draws most of its numeric 16 | intensive routines from Netlib's ubiquitous BLAS and LAPACK packages. 17 | 18 | Numeric Lua tries to maintain Lua's minimalist approach by providing bare-bone 19 | wrappers to the numerical routines. The user can use the outputs for further 20 | computations and is then fully responsible for the results. Other Lua features 21 | are also available, such as OO simulation through metamethods and functional 22 | facilities. A basic API is provided in order to promote extensibility. Also, 23 | check `numlua.seeall` for a quick way to start using Numeric Lua. 24 | 25 | Numeric Lua is licensed under the same license as Lua -- the MIT license -- 26 | and so can be freely used for academic and commercial purposes. 27 | ]=] 28 | -------------------------------------------------------------------------------- /lhp/numlua/buffer.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | numlua.buffer(opt [, arg]) 4 | -------------------------- 5 | 6 | Operates on Numlua buffer according to `opt`: 7 | 8 | * `"release"`: release all buffers with size at least `arg`; `arg` defaults 9 | to 0. 10 | * `"status"`: returns the total size and number of buffers that are _busy_ 11 | if `arg` is **true** or _free_ otherwise. 12 | ]=] 13 | -------------------------------------------------------------------------------- /lhp/numlua/opmode.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | numlua.opmode ([mode]) 4 | ---------------------- 5 | 6 | Returns and optionally sets the operation mode to in-place. If `mode` is 7 | absent, returns the current operation mode; otherwise, sets the operation 8 | mode to `mode` and returns the old mode. 9 | 10 | Note that metamethods are affected by opmode; for example, if 11 | `numlua.opmode()` is **true**,`-a` updates `a` in-place and the statement 12 | `u = u + c * v` updates _both_ `v` and `u`. 13 | ]=] 14 | -------------------------------------------------------------------------------- /lhp/numlua/seeall.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | numlua.seeall 4 | ------------- 5 | 6 | A `require` call to `numlua.seeall` loads most of the functions in Numlua to 7 | the global table to make it easier to prototype and test code or even just use 8 | Numlua is a flexible computational shell. In particular, `numlua.seeall` does 9 | the following: 10 | 11 | * Loads the `help` module, if installed. 12 | * Sets _all_ methods in Numlua to the global table; a prefix is appended to 13 | a method if it exists in more than one class table or in the global table 14 | to avoid conflicts. The order in which the methods are "registered" and 15 | their prefixes are: `"x"` for `math` (regular lua module) and `mathx`, 16 | `"c"` for `complex`, `"m"` for `matrix`, `"s"` for `stat`, and `"r"` for 17 | `rng`. 18 | * Mathematical functions that are defined on numbers, complex numbers, and 19 | matrices -- `abs`, `exp`, and so on -- are shadowed by functions that call 20 | a particular method based on its argument. For example, `exp(x)` calls 21 | `math.exp(x)` if `x` is a number, `complex.exp(x)` (or `cexp(x)`) if `x` 22 | is complex, and `matrix.exp(x)` (or `mexp(x)`) if `x` is a matrix. 23 | * `type` is overridden with `numlua.type` and `opmode` is `numlua.opmode`. 24 | ]=] 25 | -------------------------------------------------------------------------------- /lhp/numlua/type.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | numlua.type(obj) 4 | ---------------- 5 | 6 | If `obj` is an userdata with metatable `mt` and `mt.__type` is not **nil**, 7 | returns `mt.__type`, otherwise returns the type of `obj` (`type(obj)`). 8 | ]=] 9 | -------------------------------------------------------------------------------- /lhp/rng.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | rng 4 | === 5 | 6 | The `rng` module provides _random number generators_ based on the 7 | Mersenne-Twister generator and netlib's `ranlib`. Objects can be created with 8 | `rng.new`, copied with `rng.copy`, and have their seed set with `rng.seed`. 9 | 10 | The following methods sample deviates from a number of probability 11 | distributions or elements in a matrix object: 12 | 13 | rbeta rchisq rexp rf rgamma rnorm 14 | rmvnorm runif runifx rdirichlet rbinom rnbinom 15 | rpois runifint sample lsample 16 | 17 | Each one of these methods are closed on a `rng` object and each object `r` has 18 | a (uservalue) table containing its methods, that is, methods for which `r` is 19 | an upvalue. To retrieve the method table for `r`, use `#r`. For convenience, a 20 | "class" `rng` object `c` is always created and has its methods stored in the 21 | class table so that `rng.f` is `(#c).f`. 22 | 23 | All random deviate methods accept an optional last parameter `v` that must be 24 | a _real_ matrix that serves as destination: if `v` is provided, `v:size()` 25 | deviates are generated and stored in-place at `v`. 26 | 27 | Examples: 28 | 29 | > n = 5 30 | > for i = 1, n do print(i, rng.rnorm()) end 31 | 1 -0.83608755044204 32 | 2 0.30498104946162 33 | 3 -1.227283848856 34 | 4 -0.91148894025705 35 | 5 0.28245551259444 36 | > r = rng.new() 37 | > v = (#r).rnorm(0, 1, matrix.new(n)) 38 | > for i = 1, n do print(i, v[i]) end 39 | 1 -0.83608755044204 40 | 2 0.30498104946162 41 | 3 -1.227283848856 42 | 4 -0.91148894025705 43 | 5 0.28245551259444 44 | ]=] 45 | -------------------------------------------------------------------------------- /lhp/rng/copy.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | rng.copy() 4 | ---------- 5 | 6 | Returns a copy of rng object `rng`. 7 | ]=] 8 | -------------------------------------------------------------------------------- /lhp/rng/lsample.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | rng.lsample(m [, normalized]) 4 | ----------------------------- 5 | 6 | Returns a sample from 1 to `m:size"*"` with log-weights specified by the 7 | entries in the matrix `m`. If `normalized` is **true**, the entries of `m` are 8 | considered to be normalized, that is, it is assumed that `m:exp():sum() == 1`. 9 | ]=] 10 | -------------------------------------------------------------------------------- /lhp/rng/new.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | rng.new([seed]) 4 | --------------- 5 | 6 | Returns a new rng object `r` with seed `seed`. To obtain a table with 7 | methods that use `r`, call `#r`. 8 | 9 | __See also__: `rng`, `rng.seed` 10 | ]=] 11 | -------------------------------------------------------------------------------- /lhp/rng/rbeta.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | rng.rbeta(a, b [, dest]) 4 | ------------------------ 5 | 6 | Returns random deviates from the beta distribution with shape parameters 7 | `a` (`a > 0`) and `b` (`b > 0`). 8 | 9 | __See also__: `stat.dbeta` 10 | ]=] 11 | -------------------------------------------------------------------------------- /lhp/rng/rbinom.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | rng.rbinom(n, p [, dest]) 4 | ------------------------- 5 | 6 | Returns random deviates from the binomial distribution with size `n` 7 | (`n >= 0`) and probability `p` (`0 <= p <= 1`). 8 | 9 | __See also__: `stat.dbinom` 10 | ]=] 11 | -------------------------------------------------------------------------------- /lhp/rng/rchisq.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | rng.rchisq(df [,xnonc [, dest]]) 4 | -------------------------------- 5 | 6 | Returns random deviates from the chi-square distribution with degrees of 7 | freedom `df` (`df > 0`) and optional non-centrality parameter `xnonc` 8 | (`xnonc >= 0`, defaults to zero). 9 | 10 | __See also__: `stat.dchisq` 11 | ]=] 12 | -------------------------------------------------------------------------------- /lhp/rng/rdirichlet.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | rng.rdirichlet(alpha [, dest]) 4 | ------------------------------ 5 | 6 | Returns random deviates from the Dirichlet distribution with parameter 7 | `alpha`. `alpha` should be a real vector with positive entries. 8 | ]=] 9 | -------------------------------------------------------------------------------- /lhp/rng/rexp.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | rng.rexp([av [, dest]]) 4 | ----------------------- 5 | 6 | Returns random deviates from the exponential distribution with mean `av` 7 | (defaults to one). 8 | 9 | __See also__: `stat.dexp` 10 | ]=] 11 | -------------------------------------------------------------------------------- /lhp/rng/rf.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | rng.rf(dfn, dfd [, xnonc [, dest]]) 4 | ----------------------------------- 5 | 6 | Returns random deviates from the F distribution with degrees of freedom 7 | `dfn` and `dfd` (`dfn > 0` and `dfd > 0`) and optional non-centrality 8 | parameter `xnonc` (`xnonc >= 0`, defaults to zero). 9 | 10 | __See also__: `stat.df` 11 | ]=] 12 | -------------------------------------------------------------------------------- /lhp/rng/rgamma.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | rng.rgamma(a [, s [, dest]]) 4 | ---------------------------- 5 | 6 | Returns random deviates from the gamma distribution with shape `a` and 7 | optional rate `s`. 8 | 9 | __See also__: `stat.dgamma` 10 | ]=] 11 | -------------------------------------------------------------------------------- /lhp/rng/rmvnorm.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | rng.rmvnorm(m, S [, dest]) 4 | -------------------------- 5 | 6 | Returns random deviates from the multivariate normal distribution with mean 7 | `m`, a real vector of size `n`, and "standard deviation" `S` -- either a 8 | square matrix of order `n`, taken as the lower triangular Cholesky 9 | decomposition of the variance-covariance matrix, or a positive real vector 10 | of size `n` representing the square root of the diagonal of the 11 | variance-covariance matrix. 12 | 13 | Returns `S * u + m`, where `u` is sampled from `N(0, I_n)`. 14 | 15 | __See also__: `matrix.chol`, `rng.rnorm` 16 | ]=] 17 | -------------------------------------------------------------------------------- /lhp/rng/rnbinom.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | rng.rnbinom(n, p [, dest]) 4 | -------------------------- 5 | 6 | Returns random deviates from the negative binomial distribution with size `n` 7 | (`n >= 0`) and probability `p` (`0 <= p <= 1`). 8 | 9 | __See also__: `stat.dnbinom` 10 | ]=] 11 | -------------------------------------------------------------------------------- /lhp/rng/rnorm.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | rng.rnorm([m [, sd [, dest]]]) 4 | ------------------------------ 5 | 6 | Returns random deviates from the normal distribution with mean `m` (defaults 7 | to zero) and standard deviation `sd` (`sd > 0`, defaults to one). 8 | 9 | __See also__: `stat.dnorm`, `rng.rmvnorm` 10 | ]=] 11 | -------------------------------------------------------------------------------- /lhp/rng/rpois.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | rng.rpois(l [, dest]) 4 | --------------------- 5 | 6 | Returns random deviates from the Poisson distribution with mean `l >= 0`. 7 | 8 | __See also__: `stat.dpois` 9 | ]=] 10 | -------------------------------------------------------------------------------- /lhp/rng/runif.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | rng.runif([low [, high [, dest]]]) 4 | ---------------------------------- 5 | 6 | Returns random deviates from the uniform distribution between `low` (defaults 7 | to zero) and `high` (defaults to one). 8 | 9 | __See also__: `stat.dunif` 10 | ]=] 11 | -------------------------------------------------------------------------------- /lhp/rng/runifint.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | rng.runifint([low [, high [, dest]]]) 4 | ------------------------------------- 5 | 6 | Returns random deviates from the discrete uniform distribution between 7 | `low` and `high`. 8 | ]=] 9 | -------------------------------------------------------------------------------- /lhp/rng/runifx.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | rng.runifx([low [, high [, dest]]]) 4 | ----------------------------------- 5 | 6 | Returns random deviates from the uniform distribution between `low` (defaults 7 | to zero) and `high` (defaults to one) with 53-bit resolution. 8 | 9 | __See also__: `stat.dunif` 10 | ]=] 11 | -------------------------------------------------------------------------------- /lhp/rng/sample.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | rng.sample(m [, normalized]) 4 | ---------------------------- 5 | 6 | Returns a sample from 1 to `m:size"*"` with weights specified by the entries 7 | in the matrix `m`. If `normalized` is **true**, the entries of `m` are 8 | considered to be normalized, that is, it is assumed that `m:sum() == 1`. 9 | ]=] 10 | -------------------------------------------------------------------------------- /lhp/rng/seed.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | rng.seed([seed]) 4 | ---------------- 5 | 6 | Sets the seed of `rng` to `seed`; `seed` can be a number or a real vector. 7 | ]=] 8 | -------------------------------------------------------------------------------- /lhp/stat.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | stat 4 | ==== 5 | 6 | The `stat` module implements statistical routines: probability mass and 7 | density functions, cumulative distribution functions (cdf) and inverse cdf 8 | (quantile) functions for a number of distributions; and _factors_. 9 | ]=] 10 | -------------------------------------------------------------------------------- /lhp/stat/dbeta.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | stat.dbeta(x, a, b) 4 | stat.pbeta(x, a, b) 5 | stat.qbeta(p, a, b) 6 | ------------------- 7 | 8 | Computes the density (`dbeta`), cumulative distribution function (`pbeta`), and 9 | inverse cdf (`qbeta`) for the *beta* distribution with parameters `a >= 0` and 10 | `b >= 0`. The density is given by `x^(a - 1) * (1 - x)^(b - 1) / B(a, b)` for 11 | `0 <= x <= 1`, where `B(a, b)` is the beta function. 12 | 13 | __See also__: `mathx.beta` 14 | ]=] 15 | -------------------------------------------------------------------------------- /lhp/stat/dbinom.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | stat.dbinom(s, xn, pr) 4 | stat.pbinom(s, xn, pr) 5 | stat.qbinom(p, xn, pr) 6 | ---------------------- 7 | 8 | Computes the probability mass function (`dbinom`), cumulative distribution 9 | function (`pbinom`), and inverse cdf (`qbinom`) for the *binomial* distribution 10 | with size `xn >= 0` and probability of success on each trial `0 <= pr <= 1`. 11 | The density is given by `choose(xn, s) * pr^s * (1 - pr)^(xn - s)` for 12 | `s = 0, ..., xn`, where `choose(xn, s)` is the binomial coefficient. 13 | ]=] 14 | -------------------------------------------------------------------------------- /lhp/stat/dchisq.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | stat.dchisq(x, df [, pnonc]) 4 | stat.pchisq(x, df [, pnonc]) 5 | stat.qchisq(p, df [, pnonc]) 6 | ---------------------------- 7 | 8 | Computes the density (`dchisq`), cumulative distribution function (`pchisq`), 9 | and inverse cdf (`qchisq`) for the *chi-squared* distribution with `df > 0` 10 | degrees of freedom and non-centrality parameter `pnonc`. If `pnonc ~= 0`, `df` 11 | can be zero. 12 | ]=] 13 | -------------------------------------------------------------------------------- /lhp/stat/dexp.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | stat.dexp(x [, r]) 4 | stat.pexp(x [, r]) 5 | stat.qexp(p [, r]) 6 | ------------------ 7 | 8 | Computes the density (`dexp`), cumulative distribution function (`pexp`), 9 | and inverse cdf (`qexp`) for the *exponential* distribution with rate `r`. 10 | The default value for `r` is one. The exponential distribution has density 11 | `r * exp(-r * x)`. 12 | ]=] 13 | -------------------------------------------------------------------------------- /lhp/stat/df.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | stat.df(x, dfn, dfd) 4 | stat.pf(x, dfn, dfd [, pnonc]) 5 | stat.qf(p, dfn, dfd [, pnonc]) 6 | ------------------------------ 7 | 8 | Computes the density (`df`), cumulative distribution function (`pf`), and 9 | inverse cdf (`qf`) for the *F* distribution with `dfn >= 0` and `dfd >= 0` 10 | degrees of freedom in the numerator and denominator, and non-centrality 11 | parameter `pnonc`. 12 | ]=] 13 | -------------------------------------------------------------------------------- /lhp/stat/dgamma.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | stat.dgamma(x, shape [, rate]) 4 | stat.pgamma(x, shape [, rate]) 5 | stat.qgamma(p, shape [, rate]) 6 | ------------------------------- 7 | 8 | Computes the density (`dgamma`), cumulative distribution function (`pgamma`), 9 | and inverse cdf (`qgamma`) for the *gamma* distribution with parameters 10 | `shape >= 0` and `rate >= 0`. The default value for `rate` is one. A gamma 11 | distribution with shape `s` and rate `r` has density `r^s / G(s) * x^(s - 1) * 12 | exp(-r * x)` where `G` is the gamma function, for `x >= 0`. 13 | 14 | __See also__: `mathx.gamma` 15 | ]=] 16 | -------------------------------------------------------------------------------- /lhp/stat/dhyper.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | stat.dhyper(x, r, b, n) 4 | stat.phyper(x, r, b, n) 5 | ----------------------- 6 | 7 | Computes the probability mass function (`dhyper`) and cumulative distribution 8 | function (`phyper`) for the *hypergeometric* distribution with parameters 9 | `r, b >= 0` and `0 <= n <= r + b`. The density is given by 10 | `choose(r, x) * choose(b, n - x) / choose(r + b, n)` for `x = 0, ..., n`. 11 | ]=] 12 | -------------------------------------------------------------------------------- /lhp/stat/dnbinom.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | stat.dnbinom(s, xn, pr) 4 | stat.pnbinom(s, xn, pr) 5 | stat.qnbinom(p, xn, pr) 6 | ---------------------- 7 | 8 | Computes the probability mass function (`dnbinom`), cumulative distribution 9 | function (`pnbinom`), and inverse cdf (`qnbinom`) for the *negative binomial* 10 | distribution with size `xn >= 0` and probability of success on each trial 11 | `0 <= pr <= 1`. The density is given by 12 | `choose(xn + s - 1, s) * pr^xn * (1 - pr)^s` for `s = 0, ..., xn`, where 13 | `choose(xn + s - 1, s)` is the binomial coefficient. 14 | ]=] 15 | -------------------------------------------------------------------------------- /lhp/stat/dnorm.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | stat.dnorm(x [, mean [, sd]]) 4 | stat.pnorm(x [, mean [, sd]]) 5 | stat.qnorm(p [, mean [, sd]]) 6 | ----------------------------- 7 | 8 | Computes the density (`dnorm`), cumulative distribution function (`pnorm`), and 9 | inverse cdf (`qnorm`) for the *normal* distribution with parameters `mean` and 10 | standard deviation `sd >= 0`. The default values for `mean` and `sd` are zero 11 | and one, respectively. 12 | ]=] 13 | -------------------------------------------------------------------------------- /lhp/stat/dpois.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | stat.dpois(s, l) 4 | stat.ppois(s, l) 5 | stat.qpois(p, l) 6 | ------------------- 7 | 8 | Computes the probability mass function (`dpois`), cumulative distribution 9 | function (`ppois`), and inverse cdf (`qpois`) for the *Poisson* distribution 10 | with mean `l >= 0`. The density is given by `l^s * exp(-l) / s!` for 11 | `s = 0, 1, ...`. 12 | ]=] 13 | -------------------------------------------------------------------------------- /lhp/stat/dt.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | stat.dt(x, df) 4 | stat.pt(x, df) 5 | stat.qt(p, df) 6 | -------------- 7 | 8 | Computes the density (`dt`), cumulative distribution function (`pt`), and 9 | inverse cdf (`qt`) for the *Student t* distribution with `df >= 0` degrees of 10 | freedom. 11 | ]=] 12 | -------------------------------------------------------------------------------- /lhp/stat/factor.lhp: -------------------------------------------------------------------------------- 1 | Help [=[ 2 | 3 | stat.factor(t) 4 | -------------- 5 | 6 | Constructs a _factor_ based on table `t`, a *sequence*. A factor is a more 7 | compact representation of `t` where each distinct entry -- a *level* -- is 8 | assigned an integer key, the *key level*. If `f` is a factor built from `t`, 9 | `f[i]` returns `t[i]`, `f(i)` returns the key level of `t[i]`, and `f()` 10 | returns the levels of `f` as a table; in particular, `f[i]` is equivalent to 11 | `f()[f(i)]`. The expression `#f` returns a vector with level counts, that is, 12 | `(#f)[l]` returns the number of entries in `t` with key level `l` and thus 13 | values `f()[l]`; note that `(#f):sum()` is `#t`. 14 | 15 | Example: 16 | 17 | > f = stat.factor{"a", "c", "a", "a", "b", "c"} 18 | > for l, level in ipairs(f()) do print(l, level, (#f)[l]) end 19 | 1 a 3 20 | 2 c 2 21 | 3 b 1 22 | > for i = 1, (#f):sum() do print(i, f[i], f(i)) end 23 | 1 a 1 24 | 2 c 2 25 | 3 a 1 26 | 4 a 1 27 | 5 b 3 28 | 6 c 2 29 | 30 | 31 | __See also__: `factor.fold`, `factor.partition`, `factor.design` 32 | ]=] 33 | -------------------------------------------------------------------------------- /msort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "numlua.h" 4 | 5 | /* Adapted from ssort.f (translated by f2c) in SLATEC: */ 6 | /* ***PURPOSE Sort an array and optionally make the same interchanges in */ 7 | /* an auxiliary array. The array may be sorted in increasing */ 8 | /* or decreasing order. A slightly modified QUICKSORT */ 9 | /* algorithm is used. */ 10 | /* ***LIBRARY SLATEC */ 11 | /* ***CATEGORY N6A2B */ 12 | /* ***TYPE SINGLE PRECISION (SSORT-S, DSORT-D, ISORT-I) */ 13 | /* ***KEYWORDS SINGLETON QUICKSORT, SORT, SORTING */ 14 | /* ***AUTHOR Jones, R. E., (SNLA) */ 15 | /* Wisniewski, J. A., (SNLA) */ 16 | 17 | #define SORTDIM (31) 18 | 19 | /* assume mx is not a section and complex */ 20 | int sort1c (nl_Matrix *mx) { 21 | int i, j, k, l, m, ij; 22 | int il[SORTDIM], iu[SORTDIM]; 23 | int n = mx->size; 24 | int s = mx->stride; 25 | lua_Number r; 26 | nl_Complex t, tt; 27 | nl_Complex *x = (nl_Complex *) mx->data; 28 | 29 | if (n < 1) return 0; 30 | m = 1; 31 | i = 0; 32 | j = (n - 1) * s; 33 | r = .375; 34 | 35 | L20: 36 | if (i == j) goto L60; 37 | if (r <= .5898437) 38 | r += .0390625; 39 | else 40 | r += -.21875; 41 | 42 | L30: 43 | k = i; 44 | /* Select a central element of the array and save it in location T */ 45 | ij = i + ((int) ((j - i) / s * r)) * s; 46 | t = x[ij]; 47 | /* If first element of array is greater than T, interchange with T */ 48 | if (cgt(x[i], t)) { 49 | x[ij] = x[i]; x[i] = t; t = x[ij]; 50 | } 51 | l = j; 52 | /* If last element of array is less than than T, interchange with T */ 53 | if (clt(x[j], t)) { 54 | x[ij] = x[j]; x[j] = t; t = x[ij]; 55 | /* If first element of array is greater than T, interchange with T */ 56 | if (cgt(x[i], t)) { 57 | x[ij] = x[i]; x[i] = t; t = x[ij]; 58 | } 59 | } 60 | 61 | /* Find an element in the second half of the array which is smaller than T */ 62 | L40: 63 | l -= s; 64 | if (cgt(x[l], t)) goto L40; 65 | 66 | /* Find an element in the first half of the array which is greater than T */ 67 | L50: 68 | k += s; 69 | if (clt(x[k], t)) goto L50; 70 | /* Interchange these elements */ 71 | if (k <= l) { 72 | tt = x[l]; x[l] = x[k]; x[k] = tt; 73 | goto L40; 74 | } 75 | /* Save upper and lower subscripts of the array yet to be sorted */ 76 | if (l - i > j - k) { 77 | il[m - 1] = i; 78 | iu[m - 1] = l; 79 | i = k; 80 | ++m; 81 | } 82 | else { 83 | il[m - 1] = k; 84 | iu[m - 1] = j; 85 | j = l; 86 | ++m; 87 | } 88 | goto L70; 89 | 90 | /* Begin again on another portion of the unsorted array */ 91 | L60: 92 | --m; 93 | if (m == 0) return 0; 94 | i = il[m - 1]; 95 | j = iu[m - 1]; 96 | 97 | L70: 98 | if (j - i > 0) goto L30; 99 | if (i == 0) goto L20; 100 | i -= s; 101 | 102 | L80: 103 | i += s; 104 | if (i == j) goto L60; 105 | t = x[i + s]; 106 | if (!cgt(x[i], t)) goto L80; 107 | k = i; 108 | 109 | L90: 110 | x[k + s] = x[k]; 111 | k -= s; 112 | if (clt(t, x[k])) goto L90; 113 | x[k + s] = t; 114 | goto L80; 115 | } 116 | 117 | /* assume mx is not a section and not complex */ 118 | int sort1d (nl_Matrix *mx) { 119 | int i, j, k, l, m, ij; 120 | int il[SORTDIM], iu[SORTDIM]; 121 | int n = mx->size; 122 | int s = mx->stride; 123 | lua_Number r, t, tt; 124 | lua_Number *x = mx->data; 125 | 126 | if (n < 1) return 0; 127 | m = 1; 128 | i = 0; 129 | j = (n - 1) * s; 130 | r = .375; 131 | 132 | L20: 133 | if (i == j) goto L60; 134 | if (r <= .5898437) 135 | r += .0390625; 136 | else 137 | r += -.21875; 138 | 139 | L30: 140 | k = i; 141 | /* Select a central element of the array and save it in location T */ 142 | ij = i + ((int) ((j - i) / s * r)) * s; 143 | t = x[ij]; 144 | /* If first element of array is greater than T, interchange with T */ 145 | if (x[i] > t) { 146 | x[ij] = x[i]; x[i] = t; t = x[ij]; 147 | } 148 | l = j; 149 | /* If last element of array is less than than T, interchange with T */ 150 | if (x[j] < t) { 151 | x[ij] = x[j]; x[j] = t; t = x[ij]; 152 | /* If first element of array is greater than T, interchange with T */ 153 | if (x[i] > t) { 154 | x[ij] = x[i]; x[i] = t; t = x[ij]; 155 | } 156 | } 157 | 158 | /* Find an element in the second half of the array which is smaller than T */ 159 | L40: 160 | l -= s; 161 | if (x[l] > t) goto L40; 162 | 163 | /* Find an element in the first half of the array which is greater than T */ 164 | L50: 165 | k += s; 166 | if (x[k] < t) goto L50; 167 | /* Interchange these elements */ 168 | if (k <= l) { 169 | tt = x[l]; x[l] = x[k]; x[k] = tt; 170 | goto L40; 171 | } 172 | /* Save upper and lower subscripts of the array yet to be sorted */ 173 | if (l - i > j - k) { 174 | il[m - 1] = i; 175 | iu[m - 1] = l; 176 | i = k; 177 | ++m; 178 | } 179 | else { 180 | il[m - 1] = k; 181 | iu[m - 1] = j; 182 | j = l; 183 | ++m; 184 | } 185 | goto L70; 186 | 187 | /* Begin again on another portion of the unsorted array */ 188 | L60: 189 | --m; 190 | if (m == 0) return 0; 191 | i = il[m - 1]; 192 | j = iu[m - 1]; 193 | 194 | L70: 195 | if (j - i > 0) goto L30; 196 | if (i == 0) goto L20; 197 | i -= s; 198 | 199 | L80: 200 | i += s; 201 | if (i == j) goto L60; 202 | t = x[i + s]; 203 | if (x[i] <= t) goto L80; 204 | k = i; 205 | 206 | L90: 207 | x[k + s] = x[k]; 208 | k -= s; 209 | if (t < x[k]) goto L90; 210 | x[k + s] = t; 211 | goto L80; 212 | } 213 | 214 | 215 | 216 | /* x and y are size-consistent, y is simple vector */ 217 | int sort2c (nl_Matrix *mx, nl_Matrix *my) { 218 | int i, j, k, l, m, ij; 219 | int ix, jx, kx, lx, ijx; 220 | int il[SORTDIM], iu[SORTDIM]; 221 | int n = mx->size; 222 | int s = mx->stride; 223 | lua_Number r, ty, tty; 224 | nl_Complex t, tt; 225 | nl_Complex *x = (nl_Complex *) mx->data; 226 | lua_Number *y = my->data; 227 | 228 | if (n < 1) return 0; 229 | m = 1; 230 | i = 0; ix = 0; 231 | j = n - 1; jx = j * s; 232 | r = .375; 233 | 234 | L110: 235 | if (i == j) goto L150; 236 | if (r <= .5898437) 237 | r += .0390625; 238 | else 239 | r += -.21875; 240 | 241 | L120: 242 | k = i; kx = ix; 243 | /* Select a central element of the array and save it in location T */ 244 | ij = i + (int) ((j - i) * r); ijx = ij * s; 245 | t = x[ijx]; 246 | ty = y[ij]; 247 | /* If first element of array is greater than T, interchange with T */ 248 | if (cgt(x[ix], t)) { 249 | x[ijx] = x[ix]; x[ix] = t; t = x[ijx]; 250 | y[ij] = y[i]; y[i] = ty; ty = y[ij]; 251 | } 252 | l = j; lx = jx; 253 | /* If last element of array is less than T, interchange with T */ 254 | if (clt(x[jx], t)) { 255 | x[ijx] = x[jx]; x[jx] = t; t = x[ijx]; 256 | y[ij] = y[j]; y[j] = ty; ty = y[ij]; 257 | /* If first element of array is greater than T, interchange with T */ 258 | if (cgt(x[ix], t)) { 259 | x[ijx] = x[ix]; x[ix] = t; t = x[ijx]; 260 | y[ij] = y[i]; y[i] = ty; ty = y[ij]; 261 | } 262 | } 263 | 264 | /* Find an element in the second half of the array which is smaller than T */ 265 | L130: 266 | --l; lx -= s; 267 | if (cgt(x[lx], t)) goto L130; 268 | 269 | /* Find an element in the first half of the array which is greater than T */ 270 | L140: 271 | ++k; kx += s; 272 | if (clt(x[kx], t)) goto L140; 273 | /* Interchange these elements */ 274 | if (k <= l) { 275 | tt = x[lx]; x[lx] = x[kx]; x[kx] = tt; 276 | tty = y[l]; y[l] = y[k]; y[k] = tty; 277 | goto L130; 278 | } 279 | /* Save upper and lower subscripts of the array yet to be sorted */ 280 | if (l - i > j - k) { 281 | il[m - 1] = i; 282 | iu[m - 1] = l; 283 | i = k; ix = kx; 284 | ++m; 285 | } 286 | else { 287 | il[m - 1] = k; 288 | iu[m - 1] = j; 289 | j = l; jx = lx; 290 | ++m; 291 | } 292 | goto L160; 293 | 294 | /* Begin again on another portion of the unsorted array */ 295 | L150: 296 | --m; 297 | if (m == 0) return 0; 298 | i = il[m - 1]; ix = i * s; 299 | j = iu[m - 1]; jx = j * s; 300 | 301 | L160: 302 | if (j - i > 0) goto L120; 303 | if (i == 0) goto L110; 304 | --i; ix -= s; 305 | 306 | L170: 307 | ++i; ix += s; 308 | if (i == j) goto L150; 309 | t = x[ix + s]; 310 | ty = y[i + 1]; 311 | if (!cgt(x[ix], t)) goto L170; 312 | k = i; kx = ix; 313 | 314 | L180: 315 | x[kx + s] = x[kx]; 316 | y[k + 1] = y[k]; 317 | --k; kx -= s; 318 | if (clt(t, x[kx])) goto L180; 319 | x[kx + s] = t; 320 | y[k + 1] = ty; 321 | goto L170; 322 | } 323 | 324 | 325 | /* x and y are size-consistent, y is simple vector */ 326 | int sort2d (nl_Matrix *mx, nl_Matrix *my) { 327 | int i, j, k, l, m, ij; 328 | int ix, jx, kx, lx, ijx; 329 | int il[SORTDIM], iu[SORTDIM]; 330 | int n = mx->size; 331 | int s = mx->stride; 332 | lua_Number r, t, tt, ty, tty; 333 | lua_Number *x = mx->data; 334 | lua_Number *y = my->data; 335 | 336 | if (n < 1) return 0; 337 | m = 1; 338 | i = 0; ix = 0; 339 | j = n - 1; jx = j * s; 340 | r = .375; 341 | 342 | L110: 343 | if (i == j) goto L150; 344 | if (r <= .5898437) 345 | r += .0390625; 346 | else 347 | r += -.21875; 348 | 349 | L120: 350 | k = i; kx = ix; 351 | /* Select a central element of the array and save it in location T */ 352 | ij = i + (int) ((j - i) * r); ijx = ij * s; 353 | t = x[ijx]; 354 | ty = y[ij]; 355 | /* If first element of array is greater than T, interchange with T */ 356 | if (x[ix] > t) { 357 | x[ijx] = x[ix]; x[ix] = t; t = x[ijx]; 358 | y[ij] = y[i]; y[i] = ty; ty = y[ij]; 359 | } 360 | l = j; lx = jx; 361 | /* If last element of array is less than T, interchange with T */ 362 | if (x[jx] < t) { 363 | x[ijx] = x[jx]; x[jx] = t; t = x[ijx]; 364 | y[ij] = y[j]; y[j] = ty; ty = y[ij]; 365 | /* If first element of array is greater than T, interchange with T */ 366 | if (x[ix] > t) { 367 | x[ijx] = x[ix]; x[ix] = t; t = x[ijx]; 368 | y[ij] = y[i]; y[i] = ty; ty = y[ij]; 369 | } 370 | } 371 | 372 | /* Find an element in the second half of the array which is smaller than T */ 373 | L130: 374 | --l; lx -= s; 375 | if (x[lx] > t) goto L130; 376 | 377 | /* Find an element in the first half of the array which is greater than T */ 378 | L140: 379 | ++k; kx += s; 380 | if (x[kx] < t) goto L140; 381 | /* Interchange these elements */ 382 | if (k <= l) { 383 | tt = x[lx]; x[lx] = x[kx]; x[kx] = tt; 384 | tty = y[l]; y[l] = y[k]; y[k] = tty; 385 | goto L130; 386 | } 387 | /* Save upper and lower subscripts of the array yet to be sorted */ 388 | if (l - i > j - k) { 389 | il[m - 1] = i; 390 | iu[m - 1] = l; 391 | i = k; ix = kx; 392 | ++m; 393 | } 394 | else { 395 | il[m - 1] = k; 396 | iu[m - 1] = j; 397 | j = l; jx = lx; 398 | ++m; 399 | } 400 | goto L160; 401 | 402 | /* Begin again on another portion of the unsorted array */ 403 | L150: 404 | --m; 405 | if (m == 0) return 0; 406 | i = il[m - 1]; ix = i * s; 407 | j = iu[m - 1]; jx = j * s; 408 | 409 | L160: 410 | if (j - i > 0) goto L120; 411 | if (i == 0) goto L110; 412 | --i; ix -= s; 413 | 414 | L170: 415 | ++i; ix += s; 416 | if (i == j) goto L150; 417 | t = x[ix + s]; 418 | ty = y[i + 1]; 419 | if (x[ix] <= t) goto L170; 420 | k = i; kx = ix; 421 | 422 | L180: 423 | x[kx + s] = x[kx]; 424 | y[k + 1] = y[k]; 425 | --k; kx -= s; 426 | if (t < x[kx]) goto L180; 427 | x[kx + s] = t; 428 | y[k + 1] = ty; 429 | goto L170; 430 | } 431 | 432 | -------------------------------------------------------------------------------- /mt.c: -------------------------------------------------------------------------------- 1 | /* {================================================================= 2 | * 3 | * mt.c 4 | * Mersenne Twister random number generator 5 | * Luis Carvalho (lexcarvalho@gmail.com) 6 | * Adapted from mt19937ar.c: state vector is now kept on a dedicated 7 | * struct instead of global var, as implemented by Luiz Henrique 8 | * de Figueiredo on lrandom (at 9 | * http://www.tecgraf.puc-rio.br/~lhf/ftp/lua/lrandom.tar.gz). 10 | * 11 | * Original file can be found at: 12 | * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html 13 | * [ A C-program for MT19937, with initialization improved 2002/1/26. 14 | * Coded by Takuji Nishimura and Makoto Matsumoto. ] 15 | * 16 | * See Copyright Notice at the bottom of this file 17 | * 18 | * ==================================================================} */ 19 | 20 | #include "rng.h" 21 | 22 | /* Period parameters */ 23 | #define N RNG_MAXSTATES 24 | #define M 397 25 | #define MATRIX_A 0x9908b0dfUL /* constant vector a */ 26 | #define UPPER_MASK 0x80000000UL /* most significant w-r bits */ 27 | #define LOWER_MASK 0x7fffffffUL /* least significant r bits */ 28 | 29 | #define mt (o->v) 30 | #define mti (o->i) 31 | 32 | /* initializes mt[N] with a seed */ 33 | void init_genrand(nl_RNG *o, unsigned long s) 34 | { 35 | mt[0]= s & 0xffffffffUL; 36 | for (mti=1; mti> 30)) + mti); 39 | /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ 40 | /* In the previous versions, MSBs of the seed affect */ 41 | /* only MSBs of the array mt[]. */ 42 | /* 2002/01/09 modified by Makoto Matsumoto */ 43 | mt[mti] &= 0xffffffffUL; 44 | /* for >32 bit machines */ 45 | } 46 | } 47 | 48 | /* initialize by an array with array-length */ 49 | /* init_key is the array for initializing keys */ 50 | /* key_length is its length */ 51 | /* slight change for C++, 2004/2/26 */ 52 | void init_by_array(nl_RNG *o, unsigned long init_key[], int key_length) 53 | { 54 | int i, j, k; 55 | init_genrand(o, 19650218UL); 56 | i=1; j=0; 57 | k = (N>key_length ? N : key_length); 58 | for (; k; k--) { 59 | mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL)) 60 | + init_key[j] + j; /* non linear */ 61 | mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ 62 | i++; j++; 63 | if (i>=N) { mt[0] = mt[N-1]; i=1; } 64 | if (j>=key_length) j=0; 65 | } 66 | for (k=N-1; k; k--) { 67 | mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL)) 68 | - i; /* non linear */ 69 | mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ 70 | i++; 71 | if (i>=N) { mt[0] = mt[N-1]; i=1; } 72 | } 73 | 74 | mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ 75 | } 76 | 77 | /* generates a random number on [0,0xffffffff]-interval */ 78 | unsigned long genrand_int32(nl_RNG *o) 79 | { 80 | unsigned long y; 81 | static unsigned long mag01[2]={0x0UL, MATRIX_A}; 82 | /* mag01[x] = x * MATRIX_A for x=0,1 */ 83 | 84 | if (mti >= N) { /* generate N words at one time */ 85 | int kk; 86 | 87 | if (mti == N+1) /* if init_genrand() has not been called, */ 88 | init_genrand(o, 5489UL); /* a default initial seed is used */ 89 | 90 | for (kk=0;kk> 1) ^ mag01[y & 0x1UL]; 93 | } 94 | for (;kk> 1) ^ mag01[y & 0x1UL]; 97 | } 98 | y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); 99 | mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL]; 100 | 101 | mti = 0; 102 | } 103 | 104 | y = mt[mti++]; 105 | 106 | /* Tempering */ 107 | y ^= (y >> 11); 108 | y ^= (y << 7) & 0x9d2c5680UL; 109 | y ^= (y << 15) & 0xefc60000UL; 110 | y ^= (y >> 18); 111 | 112 | return y; 113 | } 114 | 115 | /* generates a random number on [0,0x7fffffff]-interval */ 116 | long genrand_int31(nl_RNG *o) 117 | { 118 | return (long)(genrand_int32(o)>>1); 119 | } 120 | 121 | /* generates a random number on [0,1]-real-interval */ 122 | double genrand_real1(nl_RNG *o) 123 | { 124 | return genrand_int32(o)*(1.0/4294967295.0); 125 | /* divided by 2^32-1 */ 126 | } 127 | 128 | /* generates a random number on [0,1)-real-interval */ 129 | double genrand_real2(nl_RNG *o) 130 | { 131 | return genrand_int32(o)*(1.0/4294967296.0); 132 | /* divided by 2^32 */ 133 | } 134 | 135 | /* generates a random number on (0,1)-real-interval */ 136 | double genrand_real3(nl_RNG *o) 137 | { 138 | return (((double)genrand_int32(o)) + 0.5)*(1.0/4294967296.0); 139 | /* divided by 2^32 */ 140 | } 141 | 142 | /* generates a random number on [0,1) with 53-bit resolution*/ 143 | double genrand_res53(nl_RNG *o) 144 | { 145 | unsigned long a=genrand_int32(o)>>5, b=genrand_int32(o)>>6; 146 | return(a*67108864.0+b)*(1.0/9007199254740992.0); 147 | } 148 | /* These real versions are due to Isaku Wada, 2002/01/09 added */ 149 | 150 | /* {================================================================= 151 | * 152 | * Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, 153 | * All rights reserved. 154 | * 155 | * Redistribution and use in source and binary forms, with or without 156 | * modification, are permitted provided that the following conditions 157 | * are met: 158 | * 159 | * 1. Redistributions of source code must retain the above copyright 160 | * notice, this list of conditions and the following disclaimer. 161 | * 162 | * 2. Redistributions in binary form must reproduce the above copyright 163 | * notice, this list of conditions and the following disclaimer in the 164 | * documentation and/or other materials provided with the distribution. 165 | * 166 | * 3. The names of its contributors may not be used to endorse or promote 167 | * products derived from this software without specific prior written 168 | * permission. 169 | * 170 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 172 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 173 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 174 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 175 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 176 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 177 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 178 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 179 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 180 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 181 | * 182 | * ==================================================================} */ 183 | 184 | 185 | -------------------------------------------------------------------------------- /numlua-0.3-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "NumLua" 2 | version = "0.3-1" 3 | 4 | source = { 5 | url = "https://github.com/downloads/carvalho/numlua/numlua-0.3-1.tar.gz", 6 | md5 = "abc29945daadd1499c7596ebbfb0f88a", 7 | dir = "numlua-0.3" 8 | } 9 | 10 | description = { 11 | summary = "Numerical routines for Lua", 12 | detailed = [[ 13 | Numeric Lua is a numerical package for the Lua programming language. It 14 | includes support for complex numbers, multidimensional matrices, random 15 | number generation, fast Fourier transforms, and special functions. Most of 16 | the routines are simple wrappers for well known numerical libraries: 17 | complex numbers and part of the extended math modules come from C99; other 18 | special functions, including statistical functions, are adapted from 19 | Netlib's SLATEC and DCDFLIB; random number generation is based on Takuji 20 | Nishimura and Makoto Matsumoto's Mersenne Twister generator as the 21 | "engine" (uniform deviates) and Netlib's RANLIB for the remaining 22 | deviates; fast Fourier transforms are implemented from FFTW; and the 23 | matrix package draws most of its numeric intensive routines from Netlib's 24 | ubiquitous BLAS and LAPACK packages. 25 | ]], 26 | homepage = "https://github.com/carvalho/numlua", 27 | license = "MIT" 28 | } 29 | 30 | dependencies = { 31 | "lua >= 5.1" 32 | } 33 | 34 | external_dependencies = { 35 | FFTW3 = { header = "fftw3.h" }, 36 | HDF5 = { header = "hdf5.h" }, 37 | LAPACK = { library = "lapack" }, -- actually, blas and lapack 38 | } 39 | 40 | build = { 41 | type = "builtin", 42 | modules = { 43 | numlua = { 44 | sources = {"numlua.c", "complex.c", "fft.c", 45 | "msort.c", "lmatrix.c", -- matrix 46 | "mt.c", "ranlib.c", "rng.c", -- rng 47 | "dcdflib.c", "ipmpar.c", "stat.c", -- stat 48 | "amos.c", "mathx.c", -- C99 math 49 | }, 50 | -- header files for blas/lapack are already included 51 | incdirs = {"$(FFTW3_INCDIR)", "$(HDF5_INCDIR)"}, 52 | -- assume blas is in same libdir as lapack 53 | libdirs = {"$(FFTW3_LIBDIR)", "$(HDF5_LIBDIR)", "$(LAPACK_LIBDIR)"}, 54 | --libraries = {"hdf5", "fftw3", "lapack", "f77blas", "atlas"}, 55 | libraries = {"hdf5", "fftw3", "lapack", "blas"}, -- f77 blas 56 | }, 57 | ["numlua.matrix"] = "matrix.lua", 58 | ["numlua.seeall"] = "seeall.lua", 59 | }, 60 | platforms = { 61 | mingw32 = { -- assumes that libs are linked with "-l%s" format 62 | modules = { 63 | numlua = { -- needs gfortran for blas and lapack 64 | libraries = {"hdf5", "fftw3", "lapack", "blas", "gfortran"} 65 | } 66 | } 67 | } 68 | } 69 | } 70 | 71 | -- lhp files 72 | local baselhp = { 73 | "lhp/complex.lhp", "lhp/mathx.lhp", "lhp/matrix.lhp", "lhp/rng.lhp", 74 | } 75 | 76 | local liblhp = { 77 | -- factor 78 | "lhp/factor/design.lhp", "lhp/factor/fold.lhp", "lhp/factor/partition.lhp", 79 | -- fft 80 | "lhp/fft/plan.lhp", "lhp/fft/wisdom.lhp", 81 | -- mathx 82 | "lhp/mathx/airya.lhp", "lhp/mathx/airyb.lhp", "lhp/mathx/besselh.lhp", 83 | "lhp/mathx/besseli.lhp", "lhp/mathx/besselj.lhp", "lhp/mathx/besselk.lhp", 84 | "lhp/mathx/bessely.lhp", "lhp/mathx/beta.lhp", "lhp/mathx/choose.lhp", 85 | "lhp/mathx/digamma.lhp", "lhp/mathx/feq.lhp", "lhp/mathx/lbeta.lhp", 86 | "lhp/mathx/lchoose.lhp", "lhp/mathx/log1pe.lhp", "lhp/mathx/lse.lhp", 87 | -- matrix 88 | "lhp/matrix/add.lhp", "lhp/matrix/apply.lhp", "lhp/matrix/balance.lhp", 89 | "lhp/matrix/chol.lhp", "lhp/matrix/c.lhp", "lhp/matrix/col.lhp", 90 | "lhp/matrix/complex.lhp", "lhp/matrix/concat.lhp", "lhp/matrix/conj.lhp", 91 | "lhp/matrix/copy.lhp", "lhp/matrix/cross.lhp", "lhp/matrix/diag.lhp", 92 | "lhp/matrix/div.lhp", "lhp/matrix/dot.lhp", "lhp/matrix/eig.lhp", 93 | "lhp/matrix/eindex.lhp", "lhp/matrix/entries.lhp", "lhp/matrix/eorder.lhp", 94 | "lhp/matrix/fct.lhp", "lhp/matrix/fft.lhp", "lhp/matrix/find.lhp", 95 | "lhp/matrix/fold.lhp", "lhp/matrix/get.lhp", "lhp/matrix/hemul.lhp", 96 | "lhp/matrix/ifelse.lhp", "lhp/matrix/imag.lhp", "lhp/matrix/inv.lhp", 97 | "lhp/matrix/iscomplex.lhp", "lhp/matrix/linspace.lhp", "lhp/matrix/load.lhp", 98 | "lhp/matrix/ls.lhp", "lhp/matrix/lu.lhp", "lhp/matrix/map.lhp", 99 | "lhp/matrix/max.lhp", "lhp/matrix/min.lhp", "lhp/matrix/mmul.lhp", 100 | "lhp/matrix/mul.lhp", "lhp/matrix/new.lhp", "lhp/matrix/norm.lhp", 101 | "lhp/matrix/ones.lhp", "lhp/matrix/pivot.lhp", "lhp/matrix/pow.lhp", 102 | "lhp/matrix/qr.lhp", "lhp/matrix/rcond.lhp", "lhp/matrix/real.lhp", 103 | "lhp/matrix/reshape.lhp", "lhp/matrix/save.lhp", "lhp/matrix/section.lhp", 104 | "lhp/matrix/set.lhp", "lhp/matrix/shape.lhp", "lhp/matrix/size.lhp", 105 | "lhp/matrix/slice.lhp", "lhp/matrix/sort.lhp", "lhp/matrix/spread.lhp", 106 | "lhp/matrix/sum.lhp", "lhp/matrix/svd.lhp", "lhp/matrix/swap.lhp", 107 | "lhp/matrix/transpose.lhp", "lhp/matrix/trmul.lhp", "lhp/matrix/which.lhp", 108 | "lhp/matrix/zeros.lhp", 109 | -- numlua 110 | "lhp/numlua/buffer.lhp", "lhp/numlua/opmode.lhp", "lhp/numlua/type.lhp", 111 | -- rng 112 | "lhp/rng/copy.lhp", "lhp/rng/lsample.lhp", "lhp/rng/new.lhp", 113 | "lhp/rng/rbeta.lhp", "lhp/rng/rbinom.lhp", "lhp/rng/rchisq.lhp", 114 | "lhp/rng/rdirichlet.lhp", "lhp/rng/rexp.lhp", "lhp/rng/rf.lhp", 115 | "lhp/rng/rgamma.lhp", "lhp/rng/rmvnorm.lhp", "lhp/rng/rnbinom.lhp", 116 | "lhp/rng/rnorm.lhp", "lhp/rng/rpois.lhp", "lhp/rng/runifint.lhp", 117 | "lhp/rng/runif.lhp", "lhp/rng/runifx.lhp", "lhp/rng/sample.lhp", 118 | "lhp/rng/seed.lhp", 119 | -- stat 120 | "lhp/stat/dbeta.lhp", "lhp/stat/dbinom.lhp", "lhp/stat/dchisq.lhp", 121 | "lhp/stat/dexp.lhp", "lhp/stat/df.lhp", "lhp/stat/dgamma.lhp", 122 | "lhp/stat/dhyper.lhp", "lhp/stat/dnbinom.lhp", "lhp/stat/dnorm.lhp", 123 | "lhp/stat/dpois.lhp", "lhp/stat/dt.lhp", "lhp/stat/factor.lhp", 124 | } 125 | 126 | local lhp = {} 127 | for i = 1, #baselhp do 128 | local f = baselhp[i] 129 | local t = {f:match("^(lhp)/([%w_]+)%.lhp$")} 130 | lhp[t[1] .. "." .. t[2]] = f 131 | end 132 | for i = 1, #liblhp do 133 | local f = liblhp[i] 134 | local t = {f:match("^(lhp)/(%w+)/([%w_]+)%.lhp$")} 135 | lhp[t[1] .. "." .. t[2] .. "." .. t[3]] = f 136 | end 137 | build.install = {lua = lhp} 138 | 139 | -- vim: set syn=lua : 140 | -------------------------------------------------------------------------------- /numlua.c: -------------------------------------------------------------------------------- 1 | /* {================================================================= 2 | * 3 | * numlua.c 4 | * Numeric Lua (base routines) 5 | * Luis Carvalho (lexcarvalho@gmail.com) 6 | * See Copyright Notice in numlua.h 7 | * 8 | * ==================================================================} */ 9 | 10 | #include 11 | #include 12 | #include "numlua.h" 13 | 14 | 15 | /* {===================================================================== 16 | * API 17 | * ======================================================================} */ 18 | 19 | NUMLUA_API int nl_typeerror (lua_State *L, int narg, const char *tname) { 20 | const char *msg = lua_pushfstring(L, "%s expected, got %s", 21 | tname, luaL_typename(L, narg)); 22 | return luaL_argerror(L, narg, msg); 23 | } 24 | 25 | #if LUA_VERSION_NUM <= 501 26 | /* adapted from Lua 5.2's lauxlib.c */ 27 | NUMLUA_API void nl_require (lua_State *L, const char *modname, 28 | lua_CFunction openf, int glb) { 29 | lua_pushcfunction(L, openf); 30 | lua_pushstring(L, modname); 31 | lua_call(L, 1, 1); /* open module */ 32 | luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); 33 | lua_pushvalue(L, -2); 34 | lua_setfield(L, -2, modname); /* _LOADED[modname] = module */ 35 | lua_pop(L, 1); /* _LOADED table */ 36 | if (glb) { 37 | lua_pushvalue(L, -1); /* module */ 38 | lua_setfield(L, LUA_GLOBALSINDEX, modname); /* _G[modname] = module */ 39 | } 40 | } 41 | #endif 42 | 43 | /* Numeric buffer */ 44 | static int nl_buffer_ = 0; 45 | #define NL_BUFFER ((void *)&nl_buffer_) 46 | static int nl_buffer_mt_ = 0; 47 | #define NL_BUFFER_MT ((void *)&nl_buffer_mt_) 48 | 49 | static nl_Buffer *nbuffer_new (lua_State *L, int size) { 50 | nl_Buffer *nb = (nl_Buffer *) lua_newuserdata(L, sizeof(nl_Buffer) 51 | + size * sizeof(buf_Number)); 52 | nb->size = size; 53 | nb->busy = 0; /* free */ 54 | return nb; 55 | } 56 | 57 | NUMLUA_API nl_Buffer *nl_getbuffer (lua_State *L, int size) { 58 | nl_Buffer *nb = NULL; 59 | int found = 0; 60 | int i, n; 61 | lua_pushlightuserdata(L, NL_BUFFER); 62 | lua_rawget(L, LUA_REGISTRYINDEX); /* buffer table */ 63 | n = (int) lua_rawlen(L, -1); 64 | /* search best nl_Buffer: 65 | * either max size or the first one s.t. b->size >= size */ 66 | for (i = 1; i <= n && !found; i++) { 67 | nl_Buffer *curr_nb; 68 | lua_rawgeti(L, -1, i); 69 | curr_nb = (nl_Buffer *) lua_touserdata(L, -1); 70 | if (!curr_nb->busy) { 71 | if (curr_nb->size >= size) { /* found */ 72 | nb = curr_nb; 73 | found = 1; 74 | } 75 | else if (!nb || curr_nb->size > nb->size) 76 | nb = curr_nb; 77 | } 78 | lua_pop(L, 1); 79 | } 80 | if (!nb || !found) { /* need new buffer? */ 81 | nb = nbuffer_new(L, size); 82 | lua_rawseti(L, -2, n + 1); 83 | } 84 | nb->busy = 1; /* busy */ 85 | lua_pop(L, 1); /* buffer table */ 86 | return nb; 87 | } 88 | 89 | NUMLUA_API void nl_getbuffertable (lua_State *L) { 90 | lua_pushlightuserdata(L, NL_BUFFER); 91 | lua_rawget(L, LUA_REGISTRYINDEX); 92 | } 93 | 94 | NUMLUA_API int nl_releasebuffer (lua_State *L, int thold) { 95 | int i, l, n = 0; 96 | lua_pushlightuserdata(L, NL_BUFFER); 97 | lua_rawget(L, LUA_REGISTRYINDEX); /* buffer table */ 98 | l = lua_rawlen(L, -1); 99 | lua_createtable(L, l, 0); /* store at most l buffers */ 100 | lua_pushlightuserdata(L, NL_BUFFER_MT); 101 | lua_rawget(L, LUA_REGISTRYINDEX); /* weak-valued MT */ 102 | lua_setmetatable(L, -2); /* weak-valued MT */ 103 | for (i = 1; i <= l; i++) { 104 | nl_Buffer *nb; 105 | lua_rawgeti(L, -2, i); 106 | nb = (nl_Buffer *) lua_touserdata(L, -1); 107 | if (nb->busy || nb->size < thold) 108 | lua_rawseti(L, -2, ++n); 109 | else lua_pop(L, 1); 110 | } 111 | lua_pushlightuserdata(L, NL_BUFFER); 112 | lua_insert(L, -2); 113 | lua_rawset(L, LUA_REGISTRYINDEX); /* reg[NL_BUFFER] = new buffer table */ 114 | lua_pop(L, 1); /* old buffer table */ 115 | return l - n; /* #released buffers */ 116 | } 117 | 118 | 119 | /* {===================================================================== 120 | * Interface 121 | * ======================================================================} */ 122 | 123 | static int numlua_buffer (lua_State *L) { 124 | nl_Buffer *nb; 125 | static const char *const opts[] = {"release", "status", NULL}; 126 | int opt = luaL_checkoption(L, 1, "status", opts); 127 | switch (opt) { 128 | case 0: { 129 | lua_pushinteger(L, nl_releasebuffer(L, luaL_optinteger(L, 2, 0))); 130 | return 1; 131 | } 132 | case 1: { 133 | int status = lua_toboolean(L, 2); 134 | int i, l, n, size; 135 | nl_getbuffertable(L); 136 | l = lua_rawlen(L, -1); 137 | n = size = 0; 138 | for (i = 1; i <= l; i++) { 139 | lua_rawgeti(L, -1, i); 140 | nb = (nl_Buffer *) lua_touserdata(L, -1); 141 | if (nb->busy == status) { 142 | n++; 143 | size += nb->size; 144 | } 145 | lua_pop(L, 1); 146 | } 147 | lua_pushinteger(L, size); 148 | lua_pushinteger(L, n); 149 | return 2; 150 | } 151 | } 152 | return 0; /* avoid compiler warnings */ 153 | } 154 | 155 | 156 | static int numlua_type (lua_State *L) { 157 | luaL_checkany(L, 1); 158 | if (lua_type(L, 1) == LUA_TUSERDATA) { 159 | if (lua_getmetatable(L, 1)) { 160 | lua_getfield(L, -1, "__type"); 161 | if (!lua_isnil(L, -1)) return 1; 162 | } 163 | } 164 | lua_pushstring(L, luaL_typename(L, 1)); 165 | return 1; 166 | } 167 | 168 | int nl_opmode = 0; /* in-place? */ 169 | static int numlua_opmode (lua_State *L) { 170 | if (lua_gettop(L) > 0) { /* set mode? */ 171 | lua_pushboolean(L, nl_opmode); 172 | nl_opmode = lua_toboolean(L, 1); 173 | } 174 | else lua_pushboolean(L, nl_opmode); 175 | return 1; 176 | } 177 | 178 | 179 | static const luaL_Reg numlua_func[] = { 180 | {"buffer", numlua_buffer}, 181 | {"type", numlua_type}, 182 | {"opmode", numlua_opmode}, 183 | {NULL, NULL} 184 | }; 185 | 186 | 187 | 188 | 189 | NUMLUA_API int luaopen_numlua_base (lua_State *L) { 190 | /* init buffer table */ 191 | lua_pushlightuserdata(L, NL_BUFFER); 192 | lua_newtable(L); 193 | lua_createtable(L, 0, 1); 194 | lua_pushliteral(L, "v"); 195 | lua_setfield(L, -2, "__mode"); 196 | lua_pushlightuserdata(L, NL_BUFFER_MT); 197 | lua_pushvalue(L, -2); 198 | lua_rawset(L, LUA_REGISTRYINDEX); /* reg[NL_BUFFER_MT] = mt */ 199 | lua_setmetatable(L, -2); 200 | lua_rawset(L, LUA_REGISTRYINDEX); /* reg[NL_BUFFER] = buffer table */ 201 | /* register base lib */ 202 | luaL_newlib(L, numlua_func); 203 | lua_pushliteral(L, NUMLUA_VERSION); 204 | lua_setfield(L, -2, "_VERSION"); 205 | return 1; 206 | } 207 | 208 | static const luaL_Reg numlua_modules[] = { 209 | {NUMLUA_LIBNAME, luaopen_numlua_base}, 210 | {COMPLEX_LIBNAME, luaopen_numlua_complex}, 211 | {FFT_LIBNAME, luaopen_numlua_fft}, 212 | {MATRIX_LIBNAME, luaopen_numlua_lmatrix}, 213 | {RNG_LIBNAME, luaopen_numlua_rng}, 214 | {STAT_LIBNAME, luaopen_numlua_stat}, 215 | {MATHX_LIBNAME, luaopen_numlua_mathx}, 216 | {NULL, NULL} 217 | }; 218 | 219 | NUMLUA_API int luaopen_numlua (lua_State *L) { 220 | const luaL_Reg *mod; 221 | for (mod = numlua_modules; mod->func; mod++) { 222 | nl_require(L, mod->name, mod->func, 1); 223 | lua_pop(L, 1); 224 | } 225 | lua_pushglobaltable(L); 226 | lua_getfield(L, -1, "require"); 227 | lua_pushliteral(L, "numlua.matrix"); 228 | lua_call(L, 1, 0); 229 | return 0; 230 | } 231 | 232 | -------------------------------------------------------------------------------- /numlua.h: -------------------------------------------------------------------------------- 1 | /* {================================================================= 2 | * 3 | * numlua.h 4 | * Numeric Lua 5 | * Luis Carvalho (lexcarvalho@gmail.com) 6 | * See Copyright Notice at the bottom of this file 7 | * 8 | * ==================================================================} */ 9 | 10 | #ifndef numlua_h 11 | #define numlua_h 12 | 13 | #define H5_NO_DEPRECATED_SYMBOLS /* use HDF5 1.8 */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "blas.h" 22 | #include "lapack.h" 23 | 24 | #define NUMLUA_VERSION "NumericLua 0.3" 25 | #define NUMLUA_API extern 26 | 27 | #if LUA_VERSION_NUM <= 501 28 | #define lua_rawlen lua_objlen 29 | #define nl_register(L,l,n) luaL_openlib(L,NULL,l,n) 30 | #define luaL_newlibtable(L,l) \ 31 | lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) 32 | #define luaL_newlib(L,l) (luaL_newlibtable(L,l), nl_register(L,l,0)) 33 | #define lua_setuservalue lua_setfenv 34 | #define lua_getuservalue lua_getfenv 35 | NUMLUA_API void nl_require (lua_State *L, const char *modname, 36 | lua_CFunction openf, int glb); 37 | #define lua_pushglobaltable(L) lua_pushvalue(L, LUA_GLOBALSINDEX) 38 | #else 39 | #define lua_number2int(i,n) ((i)=(int)(n)) 40 | #define nl_register luaL_setfuncs 41 | #define nl_require luaL_requiref 42 | #endif 43 | NUMLUA_API int nl_typeerror (lua_State *L, int narg, const char *tname); 44 | 45 | NUMLUA_API int nl_opmode; 46 | #define nl_inplace(L,n) \ 47 | (lua_isnoneornil(L,(n)) ? nl_opmode : lua_toboolean(L,(n))) 48 | 49 | #define NUMLUA_LIBNAME "numlua" 50 | #define COMPLEX_LIBNAME "complex" 51 | #define MATRIX_LIBNAME "matrix" 52 | #define FFT_LIBNAME "fft" 53 | #define RNG_LIBNAME "rng" 54 | #define STAT_LIBNAME "stat" 55 | #define MATHX_LIBNAME "mathx" 56 | 57 | #define nl_getmetatable(L,mt) (lua_pushlightuserdata(L, (mt)), \ 58 | lua_rawget(L, LUA_REGISTRYINDEX)) 59 | 60 | typedef struct { 61 | int ld; /* leading dimension */ 62 | int step; /* per dimension stride */ 63 | } nl_Section; 64 | 65 | /* nl_Buffer */ 66 | typedef union { 67 | int bint[1]; 68 | lua_Number bnum[1]; 69 | } buf_Number; 70 | 71 | typedef struct { 72 | int size; 73 | int busy; /* status */ 74 | buf_Number data; 75 | } nl_Buffer; 76 | 77 | #define nl_freebuffer(nb) ((nb)->busy = 0) 78 | NUMLUA_API nl_Buffer *nl_getbuffer (lua_State *L, int size); 79 | NUMLUA_API void nl_getbuffertable (lua_State *L); 80 | NUMLUA_API int nl_releasebuffer (lua_State *L, int threshold); 81 | 82 | NUMLUA_API int luaopen_numlua_base (lua_State *L); 83 | NUMLUA_API int luaopen_numlua (lua_State *L); 84 | 85 | 86 | /* complex */ 87 | typedef double complex nl_Complex; 88 | #define CPX(x) ((nl_Complex *) (x)) 89 | 90 | NUMLUA_API lua_Number clogabs (nl_Complex c); 91 | #define cunm(c) (-(c)) 92 | #define cadd(a,b) ((a) + (b)) 93 | #define csub(a,b) ((a) - (b)) 94 | #define cmul(a,b) ((a) * (b)) 95 | #define cdiv(a,b) ((a) / (b)) 96 | #define ceq(a,b) ((a) == (b)) 97 | #define clt(a,b) \ 98 | (creal(a)creal(b) || ((creal(a)==creal(b))&&(cimag(a)>cimag(b)))) 101 | 102 | NUMLUA_API nl_Complex nl_tocomplex (lua_State *L, int narg, int *iscomplex); 103 | NUMLUA_API nl_Complex nl_checkcomplex (lua_State *L, int narg); 104 | NUMLUA_API nl_Complex nl_optcomplex (lua_State *L, int narg, nl_Complex def); 105 | NUMLUA_API nl_Complex *nl_newcomplex (lua_State *L); 106 | NUMLUA_API nl_Complex *nl_pushcomplex (lua_State *L, nl_Complex c); 107 | NUMLUA_API int luaopen_numlua_complex (lua_State *L); 108 | 109 | /* matrix */ 110 | typedef struct { 111 | int iscomplex; 112 | int ndims; 113 | int stride; /* internal for indexing */ 114 | int size; /* overall size (product of dims) */ 115 | nl_Section *section; 116 | lua_Number *data; 117 | int dim[1]; 118 | } nl_Matrix; 119 | 120 | NUMLUA_API nl_Matrix *nl_tomatrix (lua_State *L, int narg); 121 | NUMLUA_API nl_Matrix *nl_checkmatrix (lua_State *L, int narg); 122 | NUMLUA_API nl_Matrix *nl_pushmatrix (lua_State *L, int iscomplex, 123 | int ndims, int *dim, int stride, int size, lua_Number *data); 124 | 125 | NUMLUA_API int nl_msshift (nl_Matrix *m, int eo); 126 | #define nl_mshift(m,i) \ 127 | (((m)->section) ? nl_msshift((m),(i)) : ((i) * (m)->stride)) 128 | 129 | int luaopen_numlua_lmatrix (lua_State *L); 130 | 131 | /* rng */ 132 | NUMLUA_API int luaopen_numlua_rng (lua_State *L); 133 | 134 | /* fft */ 135 | NUMLUA_API int luaopen_numlua_fft (lua_State *L); 136 | 137 | /* stat */ 138 | NUMLUA_API int luaopen_numlua_stat (lua_State *L); 139 | 140 | /* C99 mathx */ 141 | NUMLUA_API lua_Number nl_lse (lua_Number w1, lua_Number w2); 142 | NUMLUA_API int luaopen_numlua_mathx (lua_State *L); 143 | 144 | /* BLAS level 1 */ 145 | #define DSWAP dswap_ 146 | #define ZSWAP zswap_ 147 | #define DCOPY dcopy_ 148 | #define ZCOPY zcopy_ 149 | #define DSCAL dscal_ 150 | #define ZSCAL zscal_ 151 | #define ZDSCAL zdscal_ 152 | #define DAXPY daxpy_ 153 | #define ZAXPY zaxpy_ 154 | #define DDOT ddot_ 155 | #define ZDOTC zdotc_ 156 | #define ZDOTU zdotu_ 157 | #define DNRM2 dnrm2_ 158 | #define DZNRM2 dznrm2_ 159 | #define DASUM dasum_ 160 | #define DZASUM dzasum_ 161 | #define IDAMAX idamax_ 162 | #define IZAMAX izamax_ 163 | /* BLAS level 2 */ 164 | #define DTRMV dtrmv_ 165 | #define DTRSV dtrsv_ 166 | #define ZTRMV ztrmv_ 167 | #define ZTRSV ztrsv_ 168 | #define ZHER zher_ 169 | #define DSYR dsyr_ 170 | #define DGER dger_ 171 | #define ZGERC zgerc_ 172 | #define DGEMV dgemv_ 173 | #define ZGEMV zgemv_ 174 | /* BLAS level 3 */ 175 | #define DTRMM dtrmm_ 176 | #define DTRSM dtrsm_ 177 | #define ZTRMM ztrmm_ 178 | #define ZTRSM ztrsm_ 179 | #define ZHERK zherk_ 180 | #define DSYRK dsyrk_ 181 | #define DGEMM dgemm_ 182 | #define ZGEMM zgemm_ 183 | 184 | /* LAPACK */ 185 | /* chol */ 186 | #define DPOTRF dpotrf_ 187 | #define ZPOTRF zpotrf_ 188 | /* lu */ 189 | #define DGETRF dgetrf_ 190 | #define ZGETRF zgetrf_ 191 | /* inv */ 192 | #define DTRTRI dtrtri_ 193 | #define ZTRTRI ztrtri_ 194 | #define DPOTRI dpotri_ 195 | #define ZPOTRI zpotri_ 196 | #define DGETRI dgetri_ 197 | #define ZGETRI zgetri_ 198 | /* rcond */ 199 | #define DTRCON dtrcon_ 200 | #define ZTRCON ztrcon_ 201 | #define DPOCON dpocon_ 202 | #define ZPOCON zpocon_ 203 | #define DGECON dgecon_ 204 | #define ZGECON zgecon_ 205 | /* svd */ 206 | #define ZGESVD zgesvd_ 207 | #define DGESVD dgesvd_ 208 | /* qr */ 209 | #define ZGEQRF zgeqrf_ 210 | #define DGEQRF dgeqrf_ 211 | #define ZGEQP3 zgeqp3_ 212 | #define DGEQP3 dgeqp3_ 213 | #define ZUNGQR zungqr_ 214 | #define DORGQR dorgqr_ 215 | /* eig */ 216 | #define ZHEEV zheev_ 217 | #define DSYEV dsyev_ 218 | #define ZGEEV zgeev_ 219 | #define DGEEV dgeev_ 220 | /* balance */ 221 | #define ZGEBAL zgebal_ 222 | #define DGEBAL dgebal_ 223 | /* ls */ 224 | #define ZGELSY zgelsy_ 225 | #define DGELSY dgelsy_ 226 | #define ZGELSS zgelss_ 227 | #define DGELSS dgelss_ 228 | 229 | 230 | /* {================================================================= 231 | * 232 | * Copyright (c) 2005 Luis Carvalho 233 | * 234 | * Permission is hereby granted, free of charge, to any person 235 | * obtaining a copy of this software and associated documentation files 236 | * (the "Software"), to deal in the Software without restriction, 237 | * including without limitation the rights to use, copy, modify, 238 | * merge, publish, distribute, sublicense, and/or sell copies of the 239 | * Software, and to permit persons to whom the Software is furnished 240 | * to do so, subject to the following conditions: 241 | * 242 | * The above copyright notice and this permission notice shall be 243 | * included in all copies or substantial portions of the Software. 244 | * 245 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 246 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 247 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 248 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 249 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 250 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 251 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 252 | * SOFTWARE. 253 | * 254 | * ==================================================================} */ 255 | 256 | #endif 257 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | Numeric Lua 2 | =========== 3 | 4 | _Numeric Lua_ is a numerical package for the Lua programming language. It 5 | includes support for complex numbers, multidimensional matrices, random number 6 | generation, fast Fourier transforms, and special functions. Most of the 7 | routines are simple wrappers for well known numerical libraries: complex 8 | numbers and part of the extended math modules come from C99; other special 9 | functions, including statistical functions, are adapted from Netlib's SLATEC 10 | and DCDFLIB; random number generation is based on Takuji Nishimura and Makoto 11 | Matsumoto's Mersenne Twister generator as the "engine" (uniform deviates) and 12 | Netlib's RANLIB for the remaining deviates; fast Fourier transforms are 13 | implemented from FFTW; and the matrix package draws most of its numeric 14 | intensive routines from Netlib's ubiquitous BLAS and LAPACK packages. 15 | 16 | Numeric Lua tries to maintain Lua's minimalist approach by providing bare-bone 17 | wrappers to the numerical routines. The user can use the outputs for further 18 | computations and is then fully responsible for the results. Other Lua features 19 | are also available, such as OO simulation through metamethods and functional 20 | facilities. A basic API is provided in order to promote extensibility. Also, 21 | check `numlua.seeall` for a quick way to start using Numeric Lua. 22 | 23 | Numeric Lua is licensed under the same license as Lua -- the MIT license -- 24 | and so can be freely used for academic and commercial purposes. 25 | 26 | 27 | Documentation 28 | ------------- 29 | 30 | The documentation for Numeric Lua can be found in the distribution in two 31 | formats: _html_ in `docs` and "Lua help pages" (_lhp_). Lua help pages are 32 | viewed in the interpreter and are thus more suitable for quick on-line 33 | reference checks --- similar to man pages --- but they require `luahelp`. 34 | 35 | 36 | Installation 37 | ------------ 38 | 39 | Numeric Lua depends on 40 | [BLAS/LAPACK](http://www.netlib.org/lapack "BLAS/LAPACK"), 41 | [FFTW](http://www.fftw.org "FFTW"), and 42 | [HDF5](http://www.hdfgroup.org/HDF5 "HDF5"). These external dependencies are 43 | more easily and conveniently handled by package managers in Linux (`apt` and 44 | `yum`, for example) or Mac OS X (`fink`, `macports`); in Windows there is more 45 | work to be done, especially if tailored, optimized versions of these libraries 46 | are desired. In any case, Numeric Lua can be installed or built with 47 | [`luarocks`](http://luarocks.org "luarocks"). 48 | 49 | Building Numeric Lua in `luarocks` should be straightforward and mostly 50 | requires specifying include and lib dirs for the dependencies. In 51 | Debian/Ubuntu systems, for example, you would typically just need to issue 52 | 53 | $ sudo apt-get install libblas-dev liblapack-dev libfftw3-dev libhdf5-serial-dev 54 | $ luarocks make numlua-0.3-1.rockspec 55 | 56 | since the dirs happen to be system defaults. Similarly, on Mac OS X using 57 | `fink`, 58 | 59 | $ fink install atlas fftw3 hdf5 60 | $ luarocks HDF5_DIR=/sw FFTW3_DIR=/sw LAPACK=/sw make numlua-0.3-1.rockspec 61 | 62 | Note that ATLAS optimized libraries are being used here, instead of the 63 | vanilla BLAS/LAPACK (a similar package exists in `apt`.) In this case, you 64 | need to change the rockspec to match your libraries. 65 | 66 | 67 | ### Building on Windows ### 68 | 69 | Building on Windows is trickier, so we provide more details. We will be using 70 | [MinGW](http://www.mingw.org "Minimalist GNU for Windows") in the following 71 | steps: 72 | 73 | 1. Install MinGW and utils with `mingw-get install mingw-utils` 74 | 75 | 2. Install the `luarocks` binaries for Windows: 76 | * Download and install with: `install.bat /MW` (use MinGW) 77 | * Change `add_flags(extras, "%s.lib", libraries)` to 78 | `add_flags(extras, "-l%s", libraries)` in `compile_library` at 79 | `c:\LuaRocks\2.0\lua\luarocks\build\builtin.lua` 80 | 81 | 3. Download BLAS/LAPACK (note: _unoptimized_!) from Netlib and build: 82 | * Copy `make.inc.example` to `make.inc`, set `PLAT=`, and remove the `-g` 83 | flags and add `-O2` in `OPTS` 84 | * Now build: `cd install && make`, `cd blas\src && make`, `cd src && make` 85 | (for LAPACK) 86 | * Rename `blas.a` and `lapack.a` to `libblas.a` and `liblapack.a` 87 | 88 | 4. Download `fftw3` and compile it (check instructions in FFTW 89 | documentation.) 90 | 91 | 5. Download the binary distribution of HDF5. 92 | * Patch `include/H5public.h` by adding: 93 | 94 | #undef H5_SIZEOF_SSIZE_T 95 | #define H5_SIZEOF_SSIZE_T H5_SIZEOF_LONG 96 | 97 | * Wrap the dll for MinGW: 98 | 99 | pexports hdf5dll.dll > hdf5dll.def 100 | dlltool -d hdf5dll.def -l libhdf5.a 101 | 102 | * Put `hdf5dll.dll`, `zlib1.dll`, and `szip.dll` in your `PATH` 103 | 104 | 6. Finally, run `luarocks make`: 105 | 106 | luarocks HDF5_INCDIR=\path\to\hdf5\include HDF5_LIBDIR=\path\tohdf5\dll 107 | FFTW3_INCDIR=\path\to\fftw3\include FFTW3_LIBDIR=\path\to\fftw3\lib 108 | LAPACK_LIBDIR=\path\to\lapack\lib make numlua-0.3-1.rockspec 109 | 110 | For example, `\path\to\fftw3` is usually `c:\MinGW\msys\1.0\local`. 111 | 112 | -------------------------------------------------------------------------------- /rng.h: -------------------------------------------------------------------------------- 1 | /* {================================================================= 2 | * 3 | * rng.h 4 | * Random number generator (RNG) library for Lua [header file] 5 | * Luis Carvalho (lexcarvalho@gmail.com) 6 | * See Copyright Notice in numlua.h 7 | * 8 | * ==================================================================} */ 9 | 10 | #ifndef rng_h 11 | #define rng_h 12 | 13 | #include 14 | #include "numlua.h" 15 | 16 | /* Uniform deviates are generated by Mersenne Twister method, 17 | * algorithm mt19937 by Makoto Matsumoto and Takuji Nishimura. 18 | * Check mt.c for details. */ 19 | 20 | /* Struct to hold state vector and current position */ 21 | #define RNG_MAXSTATES (624) /* _N_ in mt19937ar.c */ 22 | typedef struct { 23 | unsigned long v[RNG_MAXSTATES]; /* the array for the state vector */ 24 | int i; /* i==N+1 means v[N] is not initialized */ 25 | } nl_RNG; 26 | 27 | #define RNG_SEED (5489UL) /* default initial seed in mt199937ar.c */ 28 | void init_genrand(nl_RNG *o, unsigned long s); 29 | void init_by_array(nl_RNG *o, unsigned long init_key[], int key_length); 30 | unsigned long genrand_int32(nl_RNG *o); 31 | long genrand_int31(nl_RNG *o); 32 | double genrand_real1(nl_RNG *o); 33 | double genrand_real2(nl_RNG *o); 34 | double genrand_real3(nl_RNG *o); 35 | double genrand_res53(nl_RNG *o); 36 | 37 | /* All other deviates are computed from an adapted ranlib.c from Netlib */ 38 | #define ranf(o) genrand_real3(o) 39 | #define ignlgi(o) genrand_int31(o) 40 | double genbet(nl_RNG *o,double aa,double bb); 41 | double genchi(nl_RNG *o,double df); 42 | double genexp(nl_RNG *o,double av); 43 | double genf(nl_RNG *o,double dfn,double dfd); 44 | double gengam(nl_RNG *o,double a,double r); 45 | void genmul(nl_RNG *o,long n,double *p,long ncat,long *ix); 46 | double gennch(nl_RNG *o,double df,double xnonc); 47 | double gennf(nl_RNG *o,double dfn,double dfd,double xnonc); 48 | double gennor(nl_RNG *o,double av,double sd); 49 | void genprm(nl_RNG *o,long *iarray,int larray); 50 | double genunf(nl_RNG *o,double low,double high); 51 | long ignbin(nl_RNG *o,long n,double pp); 52 | long ignnbn(nl_RNG *o,long n,double p); 53 | long ignpoi(nl_RNG *o,double mu); 54 | long ignuin(nl_RNG *o,long low,long high); 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /seeall.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | -- seeall.lua 3 | -- Easy prototyping in NumericLua 4 | -- Luis Carvalho (lexcarvalho@gmail.com) 5 | -- See Copyright Notice in numlua.h 6 | --]] 7 | 8 | require "numlua" 9 | pcall(require, "help") 10 | 11 | local classes = {"math", "mathx", "complex", "matrix"} 12 | local words = setmetatable({}, {__index = function() return 0 end}) 13 | for _, c in pairs(classes) do 14 | for k in pairs(_G[c]) do 15 | words[k] = words[k] + 1 16 | end 17 | end 18 | 19 | local nltype = numlua.type 20 | local function registermath (name) 21 | _G[name] = function (x, ...) 22 | local xtype = nltype(x) 23 | if xtype == "number" then 24 | local f = math[name] or mathx[name] or complex[name] 25 | return f(x, ...) 26 | elseif xtype == "complex" then 27 | return complex[name](x, ...) 28 | else 29 | return matrix[name](x, ...) 30 | end 31 | end 32 | end 33 | 34 | local register = function (t, prefix) 35 | for k, v in pairs(t) do 36 | if not _G[k] then 37 | _G[k] = v 38 | elseif prefix then 39 | _G[prefix .. k] = v 40 | end 41 | end 42 | end 43 | 44 | -- register common math functions first 45 | for k, v in pairs(words) do 46 | if v > 1 then -- conflict? 47 | registermath(k) -- register common function 48 | end 49 | end 50 | register(math, "x") 51 | register(mathx, "x") 52 | register(complex, "c") 53 | register(matrix, "m") 54 | register(stat, "s") 55 | register(rng, "r") -- conflicts with matrix: new, copy 56 | 57 | type = numlua.type -- override 58 | opmode = numlua.opmode 59 | 60 | -- set matrix __tostring to `pretty`: more convenient for interpreter 61 | getmetatable(matrix(1)).__tostring = matrix.pretty 62 | 63 | --------------------------------------------------------------------------------