예제 #1
0
파일: lunum.c 프로젝트: jzrake/lunum
int luaC_lunum_zeros(lua_State *L)
{
  if (lua_isnumber(L, 1)) {
    const int N = luaL_checkinteger(L, 1);
    const enum ArrayType T = (enum ArrayType) luaL_optinteger(L, 2, ARRAY_TYPE_DOUBLE);
    struct Array A = array_new_zeros(N, T);
    lunum_pusharray1(L, &A);
    return 1;
  }
  else if (lua_istable(L, 1) || lunum_hasmetatable(L, 1, "array")) {

    int Nd;
    int *N = (int*) lunum_checkarray2(L, 1, ARRAY_TYPE_INT, &Nd);
    const enum ArrayType T = (enum ArrayType) luaL_optinteger(L, 2, ARRAY_TYPE_DOUBLE);

    int ntot = 1;
    for (int d=0; d<Nd; ++d) ntot *= N[d];
    struct Array A = array_new_zeros(ntot, T);

    array_resize(&A, N, Nd);
    lunum_pusharray1(L, &A);

    return 1;
  }
  else {
    luaL_error(L, "argument must be either number, table, or array");
    return 0;
  }
}
예제 #2
0
파일: lunum.c 프로젝트: MrBurmark/lunum
static int luaC_lunum_zeros(lua_State *L)
{
  if (lua_isnumber(L, 1)) {
    const lua_Integer N = luaL_checkinteger(L, 1);
    if (N <= 0) { return luaL_error(L, "Invalid size %d", N); }
    const ArrayType T = (ArrayType) luaL_optinteger(L, 2, ARRAY_TYPE_DOUBLE);
    Array A = array_new_zeros(N, T);
    lunum_pusharray1(L, &A);
    return 1;
  }
  else if (lua_istable(L, 1) || lunum_hasmetatable(L, 1, "array")) {

    size_t Nd_t;
    size_t *N = (size_t*) lunum_checkarray2(L, 1, ARRAY_TYPE_SIZE_T, &Nd_t);
    int Nd = (int)Nd_t;
    const ArrayType T = (ArrayType) luaL_optinteger(L, 2, ARRAY_TYPE_DOUBLE);

    size_t ntot = 1;
    for (int d=0; d<Nd; ++d) ntot *= N[d];
    Array A = array_new_zeros(ntot, T);

    array_resize_t(&A, N, Nd);
    lunum_pusharray1(L, &A);

    return 1;
  }
  else {
    return luaL_error(L, "argument must be either number, table, or array");
  }
}
예제 #3
0
파일: lunum.c 프로젝트: jzrake/lunum
void _unary_func(lua_State *L, double(*f)(double), Complex(*g)(Complex), int cast)
{
  if (lua_isnumber(L, 1)) {
    const double x = lua_tonumber(L, 1);
    lua_pushnumber(L, f(x));
  }
  else if (lunum_hasmetatable(L, 1, "complex")) {

    if (g == NULL) {
      luaL_error(L, "complex operation not supported");
    }

    const Complex z = lunum_checkcomplex(L, 1);
    lunum_pushcomplex(L, g(z));
  }
  else if (lunum_hasmetatable(L, 1, "array")) {
    struct Array *A = (struct Array*) lunum_checkarray1(L, 1);

    if (cast == 0) {
      struct Array B = array_new_copy(A, A->dtype);

      switch (B.dtype) {
      case ARRAY_TYPE_BOOL    : EXPR_EVALF(Bool   , B.size, B.data); break;
      case ARRAY_TYPE_CHAR    : EXPR_EVALF(char   , B.size, B.data); break;
      case ARRAY_TYPE_SHORT   : EXPR_EVALF(short  , B.size, B.data); break;
      case ARRAY_TYPE_INT     : EXPR_EVALF(long   , B.size, B.data); break;
      case ARRAY_TYPE_LONG    : EXPR_EVALF(int    , B.size, B.data); break;
      case ARRAY_TYPE_FLOAT   : EXPR_EVALF(float  , B.size, B.data); break;
      case ARRAY_TYPE_DOUBLE  : EXPR_EVALF(double , B.size, B.data); break;
      case ARRAY_TYPE_COMPLEX : EXPR_EVALG(Complex, B.size, B.data); break;
      }

      lunum_pusharray1(L, &B);
    }
    else if (A->dtype <= ARRAY_TYPE_DOUBLE) {
      struct Array B = array_new_copy(A, ARRAY_TYPE_DOUBLE);
      double *b = (double*) B.data;
      for (int i=0; i<B.size; ++i) b[i] = f(b[i]);
      lunum_pusharray1(L, &B);
    }
    else if (A->dtype == ARRAY_TYPE_COMPLEX) {

      if (g == NULL) {
        luaL_error(L, "complex operation not supported");
      }

      struct Array B = array_new_copy(A, ARRAY_TYPE_COMPLEX);
      Complex *b = (Complex*) B.data;
      for (int i=0; i<B.size; ++i) b[i] = g(b[i]);
      lunum_pusharray1(L, &B);
    }
  }
예제 #4
0
파일: lunum.c 프로젝트: MrBurmark/lunum
static int luaC_lunum_fromfile(lua_State *L)
// -----------------------------------------------------------------------------
// Opens the binary file 'fname' for reading, and returns a 1d array from the
// data. The file size must be a multiple of the data type 'T'.
// -----------------------------------------------------------------------------
{
  const char *fname = luaL_checkstring(L, 1);
  const ArrayType T = luaL_optinteger(L, 2, ARRAY_TYPE_DOUBLE);
  const int sizeof_T = array_sizeof(T);

  FILE *input = fopen(fname, "rb");

  if (input == NULL) {
    return luaL_error(L, "no such file %s", fname);
  }
  fseek(input, 0L, SEEK_END); const size_t sz = ftell(input);
  fseek(input, 0L, SEEK_SET);

  if (sz % sizeof_T != 0) {
    return luaL_error(L, "file size must be a multiple of the data type size");
  }
  const size_t N = sz / sizeof_T;
  Array A = array_new_zeros(N, T);

  if (fread(A.data, N, sizeof_T, input) != sizeof_T) {
    fclose(input);
    return luaL_error(L, "Error while reading file %s", fname);
  }
  fclose(input);
  lunum_pusharray1(L, &A);

  return 1;
}
예제 #5
0
파일: lunum.c 프로젝트: MrBurmark/lunum
static int _array_array_binary_op(lua_State *L, ArrayBinaryOperation op)
{
  const Array *A = lunum_checkarray1(L, 1);
  const Array *B = lunum_checkarray1(L, 2);

  /* check size and dimensions */
  if (A->ndims != B->ndims) {
    return luaL_error(L, "arrays have different dimensions");
  }
  for (int d=0; d<A->ndims; ++d) {
    if (A->shape[d] != B->shape[d]) {
      return luaL_error(L, "arrays shapes do not agree");
    }
  }

  const ArrayType T = (A->dtype >= B->dtype) ? A->dtype : B->dtype;

  Array C = array_new_zeros(A->size, T);
  array_resize_t(&C, A->shape, A->ndims);
  lunum_pusharray1(L, &C);

  array_array_binary_op(L, A, B, &C, op);

  return 1;
}
예제 #6
0
파일: lunum.c 프로젝트: MrBurmark/lunum
static int luaC_lunum_slice(lua_State *L)
{

  // The first part of this function extracts a slice of the array 'A' according
  // to the convention start:stop:skip. The result is a contiguous array 'B'
  // having the same number of dimensions as 'A'.
  // ---------------------------------------------------------------------------
  size_t Nd0_t, Nd1_t, Nd2_t, Nd3_t;

  const Array *A = lunum_checkarray1(L, 1); // the array to resize
  size_t *start   = (size_t*) lunum_checkarray2(L, 2, ARRAY_TYPE_SIZE_T, &Nd0_t);
  size_t *stop    = (size_t*) lunum_checkarray2(L, 3, ARRAY_TYPE_SIZE_T, &Nd1_t);
  size_t *skip    = (size_t*) lunum_checkarray2(L, 4, ARRAY_TYPE_SIZE_T, &Nd2_t);
  size_t *squeeze = (size_t*) lunum_checkarray2(L, 5, ARRAY_TYPE_SIZE_T, &Nd3_t);

  int Nd0 = (int)Nd0_t, Nd1 = (int)Nd1_t, Nd2 = (int)Nd2_t, Nd3 = (int)Nd3_t;


  if (Nd0 != A->ndims || Nd1 != A->ndims || Nd2 != A->ndims || Nd3 != A->ndims) {
    return luaL_error(L, "slice has wrong number of dimensions for array");
  }

  for (int d=0; d<A->ndims; ++d) {
    if (start[d] < 0 || stop[d] > A->shape[d]) {
      return luaL_error(L, "slice not within array extent");
    }
  }
  Array B = array_new_from_slice(A, start, stop, skip, Nd0);


  // The rest of this function deals with squeezing out the size-1 dimensions of
  // 'B' which are marked by the 'squeeze' array.
  // ---------------------------------------------------------------------------
  size_t Nd_new = 0;
  for (int d=0; d<Nd0; ++d) Nd_new += !squeeze[d];

  // In case we're left with a 0-dimensional (scalar) slice
  if (Nd_new == 0) {
    _push_value(L, B.dtype, B.data);
    return 1;
  }
  // In case there are any dims to squeeze out
  else if (Nd_new != Nd0) {

    size_t *shape_new = (size_t*) malloc(Nd_new * sizeof(size_t));
    for (int d=0,e=0; d<Nd0; ++d) {
      if (B.shape[d] > 1 || !squeeze[d]) {
	shape_new[e] = B.shape[d];
	++e;
      }
    }
    array_resize_t(&B, shape_new, Nd_new);
    free(shape_new);
  }

  lunum_pusharray1(L, &B);
  return 1;
}
예제 #7
0
파일: lunum.c 프로젝트: jzrake/lunum
int luaC_lunum_range(lua_State *L)
{
  const int N = luaL_checkinteger(L, 1);
  struct Array A = array_new_zeros(N, ARRAY_TYPE_INT);
  lunum_pusharray1(L, &A);
  for (int i=0; i<N; ++i) {
    ((int*)A.data)[i] = i;
  }
  return 1;
}
예제 #8
0
파일: capi.c 프로젝트: MrBurmark/lunum
int test_astable(lua_State *L)
{
  size_t N = 100;
  Array A = array_new_zeros(N, ARRAY_TYPE_DOUBLE);
  lunum_pusharray1(L, &A);

  lunum_astable(L, -1);
  lua_replace(L, -2);

  return 1;
}
예제 #9
0
파일: lunum.c 프로젝트: MrBurmark/lunum
static int luaC_lunum_range(lua_State *L)
{
  const lua_Integer N = luaL_checkinteger(L, 1);
  if (N <= 0) { return luaL_error(L, "Invalid size %d", N); }
  if (N <= INT_MAX) {
    Array A = array_new_zeros(N, ARRAY_TYPE_INT);
    lunum_pusharray1(L, &A);
    for (size_t i=0; i<N; ++i) {
      ((int*)A.data)[i] = i;
    }
  } else {
    Array A = array_new_zeros(N, ARRAY_TYPE_LONG);
    lunum_pusharray1(L, &A);
    for (size_t i=0; i<N; ++i) {
      ((long*)A.data)[i] = i;
    }
  }
  
  return 1;
}
예제 #10
0
파일: lunum.c 프로젝트: MrBurmark/lunum
static int luaC_lunum_transpose(lua_State *L)
{
  const Array *A = lunum_checkarray1(L, 1); // the array to transpose

  /* copy transposed shape and size to B */
  Array B = array_new_zeros(A->size, A->dtype);
  array_resize_t(&B, A->shape, A->ndims);
  array_transpose(A, &B);

  lunum_pusharray1(L, &B);

  return 1;

}
예제 #11
0
파일: lunum.c 프로젝트: MrBurmark/lunum
static int _array_unary_op(lua_State *L, ArrayUnaryOperation op)
{
  Array *A = lunum_checkarray1(L, 1);

  const size_t N = A->size;
  ArrayType T = A->dtype;

  Array B = array_new_zeros(N, T);
  array_resize_t(&B, A->shape, A->ndims);
  lunum_pusharray1(L, &B);

  array_unary_op(L, A, &B, op);

  return 1;
}
예제 #12
0
파일: array_class.c 프로젝트: jzrake/lunum
int luaC_array_astype(lua_State *L)
{
  struct Array *A = lunum_checkarray1(L, 1);
  enum ArrayType T;

  if (lua_type(L, 2) == LUA_TSTRING) {
    T = array_typeflag(lua_tostring(L, 2)[0]);
  }
  else {
    T = (enum ArrayType) luaL_checkinteger(L, 2);
  }

  struct Array B = array_new_copy(A, T);
  lunum_pusharray1(L, &B);
  return 1;
}
예제 #13
0
파일: lunum.c 프로젝트: MrBurmark/lunum
static int luaC_lunum_linear(lua_State *L)
{
  const lua_Number  e1 = luaL_checknumber(L, 1);
  const lua_Number  e2 = luaL_checknumber(L, 2);
  const lua_Integer N  = luaL_checkinteger(L, 3);
  if (N <= 1) { return luaL_error(L, "Invalid size %d", N); }
  const ArrayType T = (ArrayType) luaL_optinteger(L, 4, ARRAY_TYPE_DOUBLE);

  Array A = array_new_zeros(N, T);
  void *a = A.data;
  
  ARRAY_ASSIGN_OP(T, EXPR_ASSIGN_LINEAR);
  
  lunum_pusharray1(L, &A);
  
  return 1;
}
예제 #14
0
파일: lunum.c 프로젝트: jzrake/lunum
int luaC_array__index(lua_State *L)
{
  struct Array *A = lunum_checkarray1(L, 1);

  // Figure out what is the format of the input index. If it's a number or a
  // table of numbers, then pass it along to _get_index. If it's a table of
  // tables or numbers, then assume it's a slice. If it's an array of bools,
  // then use it as a mask.
  // ---------------------------------------------------------------------------

  if (lunum_hasmetatable(L, 2, "array")) {
    struct Array *M = lunum_checkarray1(L, 2);
    if (M->dtype != ARRAY_TYPE_BOOL) {
      luaL_error(L, "index array must be of type bool");
    }
    struct Array B = array_new_from_mask(A, M);
    lunum_pusharray1(L, &B);
    return 1;
  }
  else if (lua_type(L, 2) == LUA_TTABLE || lua_type(L, 2) == LUA_TSTRING) {

    lua_getglobal(L, "lunum");
    lua_getfield(L, -1, "__build_slice");
    lua_remove(L, -2);
    lua_pushvalue(L, 1);
    lua_pushvalue(L, 2);
    lua_call(L, 2, 1);

    return 1;
  }

  const int m = _get_index(L, A);
  _push_value(L, A->dtype, (char*)A->data + array_sizeof(A->dtype)*m);

  return 1;
}
예제 #15
0
파일: lunum.c 프로젝트: MrBurmark/lunum
static int luaC_array__index(lua_State *L)
{
  Array *A = lunum_checkarray1(L, 1);

  // Figure out what is the format of the input index. If it's a number or a
  // table of numbers, then pass it along to _get_index. If it's an array of bools,
  // then use it as a mask.
  // ---------------------------------------------------------------------------

  if (lunum_hasmetatable(L, 2, "array")) {
    Array *M = lunum_checkarray1(L, 2);
    if (M->dtype != ARRAY_TYPE_BOOL) {
      return luaL_error(L, "index array must be of type bool");
    }
    Array B = array_new_from_mask(A, M);
    lunum_pusharray1(L, &B);
    return 1;
  }

  /* try to index into array */
  int success;
  const size_t m = _get_index(L, A, &success);
  if (success) {
    _push_value(L, A->dtype, (char*)A->data + array_sizeof(A->dtype)*m);
    return 1;
  }

  /* check metatable */
  lua_getmetatable(L, 1);
  lua_pushvalue(L, 2);
  if (lua_gettable(L, -2) != LUA_TNIL) {
    return 1;
  }

  return 0;
}
예제 #16
0
파일: lunum.c 프로젝트: jzrake/lunum
int _array_binary_op2(lua_State *L, enum ArrayOperation op)
{
  struct Array *A = lunum_checkarray1(L, 1);
  struct Array *B = lunum_checkarray1(L, 2);


  if (A->ndims != B->ndims) {
    luaL_error(L, "arrays have different dimensions");
  }
  for (int d=0; d<A->ndims; ++d) {
    if (A->shape[d] != B->shape[d]) {
      luaL_error(L, "arrays shapes do not agree");
    }
  }


  const int N = A->size;
  enum ArrayType T = (A->dtype >= B->dtype) ? A->dtype : B->dtype;

  struct Array A_ = (A->dtype == T) ? *A : array_new_copy(A, T);
  struct Array B_ = (B->dtype == T) ? *B : array_new_copy(B, T);

  struct Array C = array_new_zeros(N, T);
  array_resize(&C, A->shape, A->ndims);
  lunum_pusharray1(L, &C);

  array_binary_op(&A_, &B_, &C, op);

  luaL_getmetatable(L, "array");
  lua_setmetatable(L, -2);

  if (A->dtype != T) array_del(&A_);
  if (B->dtype != T) array_del(&B_);

  return 1;
}
예제 #17
0
파일: lunum_capi.c 프로젝트: jzrake/lunum
int lunum_upcast(lua_State *L, int pos, enum ArrayType T, int N)
// -----------------------------------------------------------------------------
// If the object at position 'pos' is already an array of dtype 'T', then push
// nothing and return 0. If the dtype is not 'T', then return 1 and push a copy
// of that array with dtype 'T' onto the stack. If it is a table, then push an
// array of dtype 'T' having the length of the table. If it is a number or
// complex, then push an array of dtype float or complex respectively having
// length 'N'.
// -----------------------------------------------------------------------------
{
  if (array_typename(T) == NULL) {
    luaL_error(L, "invalid array type");
  }

  // Deal with lunum.array
  // ---------------------------------------------------------------------------
  if (lunum_hasmetatable(L, pos, "array")) {

    struct Array *A = lunum_checkarray1(L, pos);

    if (A->dtype == T) {
      return 0;
    }

    else {

      struct Array A_ = array_new_copy(A, T);
      lunum_pusharray1(L, &A_);
      return 1;
    }
  }

  // Deal with Lua table
  // ---------------------------------------------------------------------------
  else if (lua_istable(L, pos)) {

    struct Array A = array_new_zeros(lua_rawlen(L, pos), T);

    for (int i=0; i<A.size; ++i) {

      lua_pushnumber(L, i+1);
      lua_gettable(L, pos);

      void *val = lunum_tovalue(L, T);
      memcpy((char*)A.data + array_sizeof(T)*i, val, array_sizeof(T));
      free(val);

      lua_pop(L, 1);
    }
    lunum_pusharray1(L, &A);

    return 1;
  }

  // Deal with Lua bool
  // ---------------------------------------------------------------------------
  else if (lua_isboolean(L, pos)) {
    const Bool x = lua_toboolean(L, pos);
    struct Array A = array_new_zeros(N, ARRAY_TYPE_BOOL);
    array_assign_from_scalar(&A, &x);
    lunum_pusharray1(L, &A);
    return 1;
  }

  // Deal with Lua numbers
  // ---------------------------------------------------------------------------
  else if (lua_isnumber(L, pos)) {
    const double x = lua_tonumber(L, pos);
    struct Array A = array_new_zeros(N, ARRAY_TYPE_DOUBLE);
    array_assign_from_scalar(&A, &x);
    struct Array B = array_new_copy(&A, T);
    array_del(&A);
    lunum_pusharray1(L, &B);
    return 1;
  }

  // Deal with lunum.complex
  // ---------------------------------------------------------------------------
  else if (lunum_hasmetatable(L, pos, "complex")) {

    const Complex z = *((Complex*) lua_touserdata(L, pos));
    struct Array A = array_new_zeros(N, ARRAY_TYPE_COMPLEX);
    array_assign_from_scalar(&A, &z);
    lunum_pusharray1(L, &A);
    return 1;
  }

  // Throw an error
  // ---------------------------------------------------------------------------
  else {
    luaL_error(L, "cannot cast to array from object of dtype %s\n",
               lua_typename(L, lua_type(L, pos)));
    return 0;
  }
}
예제 #18
0
파일: lunum_capi.c 프로젝트: jzrake/lunum
void lunum_pusharray2(lua_State *L, void *data, enum ArrayType T, int N)
{
  struct Array A = array_new_zeros(N, T);
  memcpy(A.data, data, N*array_sizeof(T));
  lunum_pusharray1(L, &A);
}
예제 #19
0
파일: lunum.c 프로젝트: MrBurmark/lunum
static int _array_number_binary_op(lua_State *L, ArrayBinaryOperation op, Bool array_first)
{
  const Array *A = array_first ? lunum_checkarray1(L, 1) : lunum_checkarray1(L, 2);
  ArrayType T = A->dtype;

  int num_pos = array_first ? 2 : 1;
  union {
    Bool b;
    char c;
    short s;
    int i;
    long l;
    size_t t;
    float f;
    double d;
    Complex z;
    lua_Integer li;
    lua_Number ln;
  } num;

  /* to force integer conversion if possible */
  int isnum;

  if (lua_isboolean(L, num_pos)) {
    num.i = lua_toboolean(L, num_pos);
    /* number can't have a higher type, upgrade to type T */
    switch (T) {
      case ARRAY_TYPE_BOOL    : num.b = (Bool)num.i;    break;
      case ARRAY_TYPE_CHAR    : num.c = (char)num.i;    break;
      case ARRAY_TYPE_SHORT   : num.s = (short)num.i;   break;
      case ARRAY_TYPE_INT     : num.i = (int)num.i;     break;
      case ARRAY_TYPE_LONG    : num.l = (long)num.i;    break;
      case ARRAY_TYPE_SIZE_T  : num.t = (size_t)num.i;  break;
      case ARRAY_TYPE_FLOAT   : num.f = (float)num.i;   break;
      case ARRAY_TYPE_DOUBLE  : num.d = (double)num.i;  break;
      case ARRAY_TYPE_COMPLEX : num.z = (Complex)num.i; break;
    }
  }
  else if (num.li = lua_tointegerx(L, num_pos, &isnum), isnum) {
    /* already assigned above */
    if (T >= ARRAY_TYPE_LONG) {
      /* A has higher type */
    } else {
      /* number has higher type */
      T = ARRAY_TYPE_LONG;
    }
    /* upgrade to type T */
    switch (T) {
      case ARRAY_TYPE_BOOL    : num.b = (Bool)num.li;    break;
      case ARRAY_TYPE_CHAR    : num.c = (char)num.li;    break;
      case ARRAY_TYPE_SHORT   : num.s = (short)num.li;   break;
      case ARRAY_TYPE_INT     : num.i = (int)num.li;     break;
      case ARRAY_TYPE_LONG    : num.l = (long)num.li;    break;
      case ARRAY_TYPE_SIZE_T  : num.t = (size_t)num.li;  break;
      case ARRAY_TYPE_FLOAT   : num.f = (float)num.li;   break;
      case ARRAY_TYPE_DOUBLE  : num.d = (double)num.li;  break;
      case ARRAY_TYPE_COMPLEX : num.z = (Complex)num.li; break;
    }
  }
  else if (num.ln = lua_tonumberx(L, num_pos, &isnum), isnum) {
    /* already assigned above */
    if (T >= ARRAY_TYPE_DOUBLE) {
      /* A has higher type */
    } else {
      /* number has higher type */
      T = ARRAY_TYPE_DOUBLE;
    }
    /* upgrade to type T */
    switch (T) {
      case ARRAY_TYPE_BOOL    : num.b = (Bool)num.ln;    break;
      case ARRAY_TYPE_CHAR    : num.c = (char)num.ln;    break;
      case ARRAY_TYPE_SHORT   : num.s = (short)num.ln;   break;
      case ARRAY_TYPE_INT     : num.i = (int)num.ln;     break;
      case ARRAY_TYPE_LONG    : num.l = (long)num.ln;    break;
      case ARRAY_TYPE_SIZE_T  : num.t = (size_t)num.ln;  break;
      case ARRAY_TYPE_FLOAT   : num.f = (float)num.ln;   break;
      case ARRAY_TYPE_DOUBLE  : num.d = (double)num.ln;  break;
      case ARRAY_TYPE_COMPLEX : num.z = (Complex)num.ln; break;
    }
  }
  else if (lunum_hasmetatable(L, num_pos, "complex")) {
    /* number complex */
    num.z = *((Complex*) lua_touserdata(L, num_pos));
    T = ARRAY_TYPE_COMPLEX;
  } else {
    return luaL_error(L, "Invalid argument in Array binary op");
  }

  Array C = array_new_zeros(A->size, T);
  array_resize_t(&C, A->shape, A->ndims);
  lunum_pusharray1(L, &C);

  array_number_binary_op(L, A, (void *)&num, &C, op, array_first);

  return 1;
}