naev 0.11.5
nlua_data.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
10#include <lauxlib.h>
11
12#include "naev.h"
15#include "nlua_data.h"
16
17#include "log.h"
18#include "nluadef.h"
19
20/* Helper functions. */
21static size_t dataL_checkpos( lua_State *L, const LuaData_t *ld, long pos );
22
23/* Data metatable methods. */
24static int dataL_gc( lua_State *L );
25static int dataL_eq( lua_State *L );
26static int dataL_new( lua_State *L );
27static int dataL_get( lua_State *L );
28static int dataL_set( lua_State *L );
29static int dataL_getSize( lua_State *L );
30static int dataL_getString( lua_State *L );
31static int dataL_paste( lua_State *L );
32static int dataL_addWeighted( lua_State *L );
33static int dataL_convolve2d( lua_State *L );
34static const luaL_Reg dataL_methods[] = {
35 { "__gc", dataL_gc },
36 { "__eq", dataL_eq },
37 { "new", dataL_new },
38 { "get", dataL_get },
39 { "set", dataL_set },
40 { "getSize", dataL_getSize },
41 { "getString", dataL_getString },
42 { "paste", dataL_paste },
43 { "addWeighted", dataL_addWeighted },
44 { "convolve2d", dataL_convolve2d },
45 {0,0}
46};
54int nlua_loadData( nlua_env env )
55{
56 nlua_register(env, DATA_METATABLE, dataL_methods, 1);
57 return 0;
58}
59
72LuaData_t* lua_todata( lua_State *L, int ind )
73{
74 return (LuaData_t*) lua_touserdata(L,ind);
75}
83LuaData_t* luaL_checkdata( lua_State *L, int ind )
84{
85 if (lua_isdata(L,ind))
86 return lua_todata(L,ind);
87 luaL_typerror(L, ind, DATA_METATABLE);
88 return NULL;
89}
97LuaData_t* lua_pushdata( lua_State *L, LuaData_t data )
98{
99 LuaData_t *c;
100 c = (LuaData_t*) lua_newuserdata(L, sizeof(LuaData_t));
101 *c = data;
102 luaL_getmetatable(L, DATA_METATABLE);
103 lua_setmetatable(L, -2);
104 return c;
105}
113int lua_isdata( lua_State *L, int ind )
114{
115 int ret;
116
117 if (lua_getmetatable(L,ind)==0)
118 return 0;
119 lua_getfield(L, LUA_REGISTRYINDEX, DATA_METATABLE);
120
121 ret = 0;
122 if (lua_rawequal(L, -1, -2)) /* does it have the correct mt? */
123 ret = 1;
124
125 lua_pop(L, 2); /* remove both metatables */
126 return ret;
127}
128
135static int dataL_gc( lua_State *L )
136{
137 LuaData_t *ld = luaL_checkdata(L,1);
138 free(ld->data);
139 return 0;
140}
141
150static int dataL_eq( lua_State *L )
151{
152 LuaData_t *d1, *d2;
153 d1 = luaL_checkdata(L,1);
154 d2 = luaL_checkdata(L,2);
155 if (d1->size != d2->size) {
156 lua_pushboolean( L, 0 );
157 return 1;
158 }
159 lua_pushboolean( L, (memcmp( d1->data, d2->data, d1->size)==0) );
160 return 1;
161}
162
171static int dataL_new( lua_State *L )
172{
173 LuaData_t ld;
174 size_t size = luaL_checklong(L,1);
175 const char *type = luaL_checkstring(L,2);
176 if (strcmp(type,"number")==0) {
177 ld.type = LUADATA_NUMBER;
178 ld.elem = sizeof(float);
179 }
180 else
181 return NLUA_ERROR(L, _("unknown data type '%s'"), type);
182 ld.size = size*ld.elem;
183 ld.data = calloc( ld.elem, size );
184 lua_pushdata( L, ld );
185 return 1;
186}
187
188static size_t dataL_checkpos( lua_State *L, const LuaData_t *ld, long pos )
189{
190 size_t mpos;
191 if (pos < 0)
192 return NLUA_ERROR(L, _("position argument must be positive!"));
193 mpos = pos * ld->elem;
194 if (mpos >= ld->size)
195 return NLUA_ERROR(L, _("position argument out of bounds: %d of %d elements"), pos, ld->size/ld->elem);
196 return mpos;
197}
198
207static int dataL_get( lua_State *L )
208{
209 LuaData_t *ld = luaL_checkdata(L,1);
210 long pos = luaL_checklong(L,2);
211 size_t mpos = dataL_checkpos( L, ld, pos );
212 char *data = ld->data;
213 switch (ld->type) {
214 case LUADATA_NUMBER:
215 lua_pushnumber(L, *((float*)((void*)&data[mpos])));
216 break;
217 }
218 return 1;
219}
220
229static int dataL_set( lua_State *L )
230{
231 LuaData_t *ld = luaL_checkdata(L,1);
232 long pos = luaL_checklong(L,2);
233 size_t mpos = dataL_checkpos( L, ld, pos );
234 char *data = ld->data;
235 double value;
236 switch (ld->type) {
237 case LUADATA_NUMBER:
238 value = luaL_checknumber(L,3);
239 *((float*)((void*)&data[mpos])) = value;
240 break;
241 }
242 return 0;
243}
244
252static int dataL_getSize( lua_State *L )
253{
254 LuaData_t *ld = luaL_checkdata(L,1);
255 lua_pushnumber(L, ld->size);
256 return 1;
257}
258
266static int dataL_getString( lua_State *L )
267{
268 LuaData_t *ld = luaL_checkdata(L,1);
269 lua_pushlstring(L, ld->data, ld->size);
270 return 1;
271}
272
283static int dataL_paste( lua_State *L )
284{
285 LuaData_t *dest = luaL_checkdata(L,1);
286 LuaData_t *source = luaL_checkdata(L,2);
287 long dx = luaL_checklong(L,3) * dest->elem;
288 long sx = luaL_checklong(L,4) * source->elem;
289 long sw = luaL_checklong(L,5) * source->elem;
290 char *ddata = dest->data;
291 const char *sdata = source->data;
292
293 /* Check fits. */
294 if (dx+sw > (long)dest->size)
295 return NLUA_ERROR(L, _("size mismatch: out of bound access dest: %d of %d elements"), dx+sw, dest->size);
296 else if (sx+sw > (long)source->size)
297 return NLUA_ERROR(L, _("size mismatch: out of bound access of source: %d of %d elements"), sx+sw, source->size);
298
299 /* Copy memory over. */
300 memcpy( &ddata[dx], &sdata[sx], sw );
301
302 /* Return destination. */
303 lua_pushvalue(L,1);
304 return 1;
305}
306
318static int dataL_addWeighted( lua_State *L )
319{
320 LuaData_t *A = luaL_checkdata(L,1);
321 LuaData_t *B = luaL_checkdata(L,2);
322 LuaData_t out;
323 double alpha = luaL_checknumber(L,3);
324 double beta = luaL_optnumber(L,4,1.-alpha);
325 double bias = luaL_optnumber(L,5,0.);
326 int i, n;
327 float *o, *a, *b;
328
329 /* Checks. */
330 if (A->size != B->size)
331 return NLUA_ERROR(L, _("size mismatch: A has %d elements but B has %d elements"), A->size, B->size );
332 if (A->type != LUADATA_NUMBER || B->type != LUADATA_NUMBER)
333 return NLUA_ERROR(L, _("%s is only implemented for number types"), __func__);
334
335 /* Create new data. */
336 out.size = A->size;
337 out.elem = A->elem;
338 out.type = A->type;
339 out.data = malloc( out.size );
340
341 /* Interpolate. */
342 n = out.size / out.elem;
343 a = (float*)A->data;
344 b = (float*)B->data;
345 o = (float*)out.data;
346 for (i=0; i<n; i++)
347 o[i] = a[i]*alpha + b[i]*beta + bias;
348
349 /* Return new data. */
350 lua_pushdata(L,out);
351 return 1;
352}
353
366static int dataL_convolve2d( lua_State *L )
367{
368 LuaData_t *lI = luaL_checkdata(L,1);
369 long iw = luaL_checklong(L,2);
370 long ih = luaL_checklong(L,3);
371 LuaData_t *lK = luaL_checkdata(L,4);
372 long kw = luaL_checklong(L,5);
373 long kh = luaL_checklong(L,6);
374 LuaData_t out;
375 int kw2,kh2, bw,bh, ow,oh;
376 const float *I = (const float*)lI->data;
377 const float *K = (const float*)lK->data;
378 float *B, *O;
379
380 /* Checks. */
381 if (iw*ih*4*lI->elem != lI->size)
382 return NLUA_ERROR(L,_("size mismatch for data: got %dx%dx4x%d, expected %d"), iw, ih, lI->elem, lI->size);
383 if (kw*kh*4*lK->elem != lK->size)
384 return NLUA_ERROR(L,_("size mismatch for data: got %dx%dx4x%d, expected %d"), kw, kh, lK->elem, lK->size);
385 if (lI->type != LUADATA_NUMBER || lK->type != LUADATA_NUMBER)
386 return NLUA_ERROR(L, _("%s is only implemented for number types"), __func__);
387
388 /* Set up. */
389 kw2 = (kw-1)/2;
390 kh2 = (kh-1)/2;
391
392 /* Create new data. */
393 ow = iw+kw2;
394 oh = ih+kw2;
395 out.elem = lI->elem;
396 out.type = lI->type;
397 out.size = ow*oh*4*out.elem;
398 out.data = calloc( out.size, 1 );
399 O = (float*)out.data;
400
401#define POS(U,V,W) (4*((V)*(W)+(U)))
402 /* Create buffer. */
403 bw = ow+2*kw2;
404 bh = oh+2*kh2;
405 B = calloc( bw*bh*4, sizeof(float) );
406 for (int v=0; v<ih; v++)
407 memcpy( &B[ POS(kw2, v+kh2, bw) ],
408 &I[ POS( 0, v, iw) ],
409 4*sizeof(float)*iw );
410
411 /* Convolve. */
412 for (int v=0; v<oh; v++) {
413 for (int u=0; u<ow; u++) {
414 for (int kv=0; kv<kh; kv++) {
415 for (int ku=0; ku<kw; ku++) {
416 int bu = u + ku;
417 int bv = v + kv;
418 for (int p=0; p<4; p++)
419 O[ POS( u, v, ow )+p ] +=
420 B[ POS( bu, bv, bw )+p ]
421 * K[ POS( ku, kv, kw )+p ];
422 }
423 }
424 }
425 }
426#undef POS
427
428 /* Cleanup. */
429 free(B);
430
431 /* Return new data. */
432 lua_pushdata(L,out);
433 lua_pushinteger(L,ow);
434 lua_pushinteger(L,oh);
435 return 3;
436}
Header file with generic functions and naev-specifics.
static int dataL_paste(lua_State *L)
Writes the contents of "source" into "dest".
Definition nlua_data.c:283
static int dataL_addWeighted(lua_State *L)
Returns alpha*A + beta*B + bias.
Definition nlua_data.c:318
static int dataL_eq(lua_State *L)
Compares two datas to see if they are the same.
Definition nlua_data.c:150
LuaData_t * luaL_checkdata(lua_State *L, int ind)
Gets data at index or raises error if there is no data at index.
Definition nlua_data.c:83
static int dataL_get(lua_State *L)
Gets the value of an element.
Definition nlua_data.c:207
static int dataL_convolve2d(lua_State *L)
Does a convolution. You'd rather be writing shaders, right?
Definition nlua_data.c:366
static int dataL_gc(lua_State *L)
Frees a data.
Definition nlua_data.c:135
int lua_isdata(lua_State *L, int ind)
Checks to see if ind is a data.
Definition nlua_data.c:113
LuaData_t * lua_pushdata(lua_State *L, LuaData_t data)
Pushes a data on the stack.
Definition nlua_data.c:97
static const luaL_Reg dataL_methods[]
Definition nlua_data.c:34
static int dataL_new(lua_State *L)
Opens a new data.
Definition nlua_data.c:171
LuaData_t * lua_todata(lua_State *L, int ind)
Lua bindings to interact with datas.
Definition nlua_data.c:72
static int dataL_getSize(lua_State *L)
Gets the number of elements.
Definition nlua_data.c:252
static int dataL_set(lua_State *L)
Sets the value of an element.
Definition nlua_data.c:229
static int dataL_getString(lua_State *L)
Returns the data contents as a string.
Definition nlua_data.c:266
int nlua_loadData(nlua_env env)
Loads the data library.
Definition nlua_data.c:54
static const double c[]
Definition rng.c:264
Wrapper to datas.
Definition nlua_data.h:17
LuaDataType_t type
Definition nlua_data.h:21
void * data
Definition nlua_data.h:20
size_t size
Definition nlua_data.h:18
size_t elem
Definition nlua_data.h:19