naev 0.10.4
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, 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 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, LuaData_t *ld, long pos )
189{
190 size_t mpos;
191 if (pos < 0)
192 NLUA_ERROR(L, _("position argument must be positive!"));
193 mpos = pos * ld->elem;
194 if (mpos >= ld->size)
195 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 switch (ld->type) {
213 case LUADATA_NUMBER:
214 lua_pushnumber(L, *((float*)(&ld->data[mpos])));
215 break;
216 }
217 return 1;
218}
219
228static int dataL_set( lua_State *L )
229{
230 LuaData_t *ld = luaL_checkdata(L,1);
231 long pos = luaL_checklong(L,2);
232 size_t mpos = dataL_checkpos( L, ld, pos );
233 double value;
234 switch (ld->type) {
235 case LUADATA_NUMBER:
236 value = luaL_checknumber(L,3);
237 *((float*)(&ld->data[mpos])) = value;
238 break;
239 }
240 return 0;
241}
242
250static int dataL_getSize( lua_State *L )
251{
252 LuaData_t *ld = luaL_checkdata(L,1);
253 lua_pushnumber(L, ld->size);
254 return 1;
255}
256
264static int dataL_getString( lua_State *L )
265{
266 LuaData_t *ld = luaL_checkdata(L,1);
267 lua_pushlstring(L, ld->data, ld->size);
268 return 1;
269}
270
281static int dataL_paste( lua_State *L )
282{
283 LuaData_t *dest = luaL_checkdata(L,1);
284 LuaData_t *source = luaL_checkdata(L,2);
285 long dx = luaL_checklong(L,3) * dest->elem;
286 long sx = luaL_checklong(L,4) * source->elem;
287 long sw = luaL_checklong(L,5) * source->elem;
288
289 /* Check fits. */
290 if (dx+sw > (long)dest->size)
291 NLUA_ERROR(L, _("size mismatch: out of bound access dest: %d of %d elements"), dx+sw, dest->size);
292 else if (sx+sw > (long)source->size)
293 NLUA_ERROR(L, _("size mismatch: out of bound access of source: %d of %d elements"), sx+sw, source->size);
294
295 /* Copy memory over. */
296 memcpy( &dest->data[dx], &source->data[sx], sw );
297
298 /* Return destination. */
299 lua_pushvalue(L,1);
300 return 1;
301}
302
314static int dataL_addWeighted( lua_State *L )
315{
316 LuaData_t *A = luaL_checkdata(L,1);
317 LuaData_t *B = luaL_checkdata(L,2);
318 LuaData_t out;
319 double alpha = luaL_checknumber(L,3);
320 double beta = luaL_optnumber(L,4,1.-alpha);
321 double bias = luaL_optnumber(L,5,0.);
322 int i, n;
323 float *o, *a, *b;
324
325 /* Checks. */
326 if (A->size != B->size)
327 NLUA_ERROR(L, _("size mismatch: A has %d elements but B has %d elements"), A->size, B->size );
328 if (A->type != LUADATA_NUMBER || B->type != LUADATA_NUMBER)
329 NLUA_ERROR(L, _("%s is only implemented for number types"), __func__);
330
331 /* Create new data. */
332 out.size = A->size;
333 out.elem = A->elem;
334 out.type = A->type;
335 out.data = malloc( out.size );
336
337 /* Interpolate. */
338 n = out.size / out.elem;
339 a = (float*)A->data;
340 b = (float*)B->data;
341 o = (float*)out.data;
342 for (i=0; i<n; i++)
343 o[i] = a[i]*alpha + b[i]*beta + bias;
344
345 /* Return new data. */
346 lua_pushdata(L,out);
347 return 1;
348}
349
362static int dataL_convolve2d( lua_State *L )
363{
364 LuaData_t *lI = luaL_checkdata(L,1);
365 long iw = luaL_checklong(L,2);
366 long ih = luaL_checklong(L,3);
367 LuaData_t *lK = luaL_checkdata(L,4);
368 long kw = luaL_checklong(L,5);
369 long kh = luaL_checklong(L,6);
370 LuaData_t out;
371 int p, u,v, ku,kv, bu,bv;
372 int kw2,kh2, bw,bh, ow,oh;
373 float *I = (float*)lI->data;
374 float *K = (float*)lK->data;
375 float *B, *O;
376
377 /* Checks. */
378 if (iw*ih*4*lI->elem != lI->size)
379 NLUA_ERROR(L,_("size mismatch for data: got %dx%dx4x%d, expected %d"), iw, ih, lI->elem, lI->size);
380 if (kw*kh*4*lK->elem != lK->size)
381 NLUA_ERROR(L,_("size mismatch for data: got %dx%dx4x%d, expected %d"), kw, kh, lK->elem, lK->size);
382 if (lI->type != LUADATA_NUMBER || lK->type != LUADATA_NUMBER)
383 NLUA_ERROR(L, _("%s is only implemented for number types"), __func__);
384
385 /* Set up. */
386 kw2 = (kw-1)/2;
387 kh2 = (kh-1)/2;
388
389 /* Create new data. */
390 ow = iw+kw2;
391 oh = ih+kw2;
392 out.elem = lI->elem;
393 out.type = lI->type;
394 out.size = ow*oh*4*out.elem;
395 out.data = calloc( out.size, 1 );
396 O = (float*)out.data;
397
398#define POS(U,V,W) (4*((V)*(W)+(U)))
399 /* Create buffer. */
400 bw = ow+2*kw2;
401 bh = oh+2*kh2;
402 B = calloc( bw*bh*4, sizeof(float) );
403 for (v=0; v<ih; v++)
404 memcpy( &B[ POS(kw2, v+kh2, bw) ],
405 &I[ POS( 0, v, iw) ],
406 4*sizeof(float)*iw );
407
408 /* Convolve. */
409 for (v=0; v<oh; v++) {
410 for (u=0; u<ow; u++) {
411 for (kv=0; kv<kh; kv++) {
412 for (ku=0; ku<kw; ku++) {
413 bu = u + ku;
414 bv = v + kv;
415 for (p=0; p<4; p++)
416 O[ POS( u, v, ow )+p ] +=
417 B[ POS( bu, bv, bw )+p ]
418 * K[ POS( ku, kv, kw )+p ];
419 }
420 }
421 }
422 }
423#undef POS
424
425 /* Cleanup. */
426 free(B);
427
428 /* Return new data. */
429 lua_pushdata(L,out);
430 lua_pushinteger(L,ow);
431 lua_pushinteger(L,oh);
432 return 3;
433}
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:281
static int dataL_addWeighted(lua_State *L)
Returns alpha*A + beta*B + bias.
Definition: nlua_data.c:314
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:362
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:250
static int dataL_set(lua_State *L)
Sets the value of an element.
Definition: nlua_data.c:228
static int dataL_getString(lua_State *L)
Returns the data contents as a string.
Definition: nlua_data.c:264
int nlua_loadData(nlua_env env)
Loads the data library.
Definition: nlua_data.c:54
static const double c[]
Definition: rng.c:264
static const double a[]
Definition: rng.c:247
static const double b[]
Definition: rng.c:256
Wrapper to datas.
Definition: nlua_data.h:17
char * data
Definition: nlua_data.h:20
LuaDataType_t type
Definition: nlua_data.h:21
size_t size
Definition: nlua_data.h:18
size_t elem
Definition: nlua_data.h:19