[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: question about cdata type identification
- From: Luis Carvalho <lexcarvalho@...>
- Date: Mon, 18 Apr 2011 12:16:18 -0400
<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+%.)","")))'