lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


<snip>
> The problem here is that for the arithmetic operators I need to know
> if the operands are real or complex number or real or complex
> matrices. The problem is that if I use the 'type' function I get can
> obtain just 'number' or 'cdata' and I have no means to discriminate
> between, for example, a complex number and a matrix because both are
> cdata.

I might be missing something, but why don't you just store this information in
the matrix struct? I mean, what do you need this information through a 'type'
function?

> I can imagine some workarounds but these solutions are all not
> satisfying and I have the feeling that we lack a primitive FFI
> function to have information about the C type of a cdata object.
> 
> I was thinking that may be a function ffi.ctype could make the affair.
> The function should return a string that identify the C type of the
> object. What do you think of this idea ?
<snip>

If getmetatable returns a string as you mentioned later, then you do need a
workaround; a simple one is to just define a _type field in your __index
table and make all your objects adhere to this convention.

Here's a short module for vectors illustrating my points -- caveat emptor!


local ffi = require "ffi"

-- note the icomplex field in the struct:
ffi.cdef [[
typedef struct { int size, stride, icomplex; double *data; } Vector;
int daxpy_ (int *n, double *alpha, double *x, int *incx, double *y, int *incy);
int zaxpy_ (int *n, double *alpha, double *x, int *incx, double *y, int *incy);
]]
local blas = ffi.load "f77blas"

local datablock = ffi.typeof "double[?]"
local _D = setmetatable({}, {__mode = "k"}) -- cache

local _add
do -- __add (note: in-place operation)
  local alpha = ffi.new("double[2]", 1, 0)
  local iarg = ffi.new("int[3]", 0, 1, 1) -- n, incx, incy
  _add = function (a, b)
    assert(a.size == b.size and a.icomplex == b.icomplex)
    iarg[0], iarg[1], iarg[2] = b.size, b.stride, a.stride
    if b.icomplex == 1 then
      blas.zaxpy_(iarg, alpha, b.data, iarg + 1, a.data, iarg + 2)
    else
      blas.daxpy_(iarg, alpha, b.data, iarg + 1, a.data, iarg + 2)
    end
    return a
  end
end

local it = { -- class: note _type field
  iscomplex = function(m) return m.icomplex == 1 end,
  _type = "vector",
}

local vector
local mt = {
  __add = _add,
  __index = function (m, k)
    if type(k) ~= "string" then
      local x = m.icomplex == 0 and m.data
        or ffi.cast("double complex *", m.data)
      return x[k - 1]
    end
    return it[k]
  end,
  __newindex = function (m, k, v)
    local x = m.icomplex == 0 and m.data
      or ffi.cast("double complex *", m.data)
    x[k - 1] = v
  end,
}
vector = ffi.metatype("Vector", mt)

module(...)

function new (n, iscomplex)
  local data = datablock(iscomplex and 2 * n or n)
  local v = vector()
  v.size = n
  v.stride = 1
  v.icomplex = iscomplex and 1 or 0
  v.data = data
  _D[v] = data
  return v
end


Cheers,
Luis


-- 
Computers are useless. They can only give you answers.
                -- Pablo Picasso

-- 
Luis Carvalho (Kozure)
lua -e 'print((("lexcarvalho@NO.gmail.SPAM.com"):gsub("(%u+%.)","")))'