You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
809 lines
16 KiB
C
809 lines
16 KiB
C
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include "linalg.h"
|
|
|
|
#define MINCAP 128
|
|
|
|
#define VECTOR4 4
|
|
#define MATRIX 16
|
|
|
|
// Constant: version should be 0, id is the constant id, persistent should be 1
|
|
|
|
static float c_ident_vec[4] = { 0,0,0,1 };
|
|
static float c_ident_mat[16] = {
|
|
1,0,0,0,
|
|
0,1,0,0,
|
|
0,0,1,0,
|
|
0,0,0,1,
|
|
};
|
|
|
|
static float c_ident_quat[4] = {
|
|
0, 0, 0, 1,
|
|
};
|
|
|
|
struct constant {
|
|
float * ptr;
|
|
int size;
|
|
};
|
|
|
|
static struct constant c_constant_table[LINEAR_TYPE_COUNT] = {
|
|
{ c_ident_mat, MATRIX },
|
|
{ c_ident_vec, VECTOR4 },
|
|
{ c_ident_quat, VECTOR4 },
|
|
};
|
|
|
|
struct stackid_ {
|
|
uint32_t version:24;
|
|
uint32_t id:24;
|
|
uint32_t type : LINEAR_TYPE_BITS_NUM; // 0:matrix 1:vector4 2:float 3:quaternion 4:euler
|
|
uint32_t persistent:1; // 0: persisent 1: temp
|
|
};
|
|
|
|
union stackid {
|
|
struct stackid_ s;
|
|
int64_t i;
|
|
};
|
|
|
|
int64_t
|
|
lastack_constant(int cons) {
|
|
if (cons < 0 || cons >= LINEAR_TYPE_COUNT)
|
|
return 0;
|
|
union stackid sid;
|
|
sid.s.version = 0;
|
|
sid.s.id = cons;
|
|
sid.s.persistent = 1;
|
|
sid.s.type = cons;
|
|
|
|
return sid.i;
|
|
}
|
|
|
|
struct lastack {
|
|
int temp_vector_cap;
|
|
int temp_vector_top;
|
|
int temp_matrix_cap;
|
|
int temp_matrix_top;
|
|
int version;
|
|
int stack_cap;
|
|
int stack_top;
|
|
float * temp_vec;
|
|
float * temp_mat;
|
|
struct blob * per_vec;
|
|
struct blob * per_mat;
|
|
struct oldpage *old;
|
|
union stackid *stack;
|
|
size_t oldpage_size;
|
|
};
|
|
|
|
#define TAG_FREE 0
|
|
#define TAG_USED 1
|
|
#define TAG_WILLFREE 2
|
|
|
|
struct slot {
|
|
uint32_t id : 30;
|
|
uint32_t tag : 2;
|
|
};
|
|
|
|
struct oldpage {
|
|
struct oldpage *next;
|
|
void *page;
|
|
};
|
|
|
|
struct blob {
|
|
int size;
|
|
int cap;
|
|
int freeslot; // free slot list
|
|
int freelist; // will free
|
|
char * buffer;
|
|
struct slot *s;
|
|
struct oldpage *old;
|
|
size_t oldpage_size;
|
|
};
|
|
|
|
static inline void
|
|
init_blob_slots(struct blob * B, int slot_beg, int slot_end) {
|
|
int i;
|
|
for (i = slot_beg; i < slot_end; ++i) {
|
|
B->s[i].tag = TAG_FREE;
|
|
B->s[i].id = i + 2;
|
|
}
|
|
|
|
B->s[slot_end - 1].id = 0;
|
|
B->freeslot = slot_beg + 1;
|
|
}
|
|
|
|
static struct blob *
|
|
blob_new(int size, int cap) {
|
|
struct blob * B = malloc(sizeof(*B));
|
|
B->size = size;
|
|
B->cap = cap;
|
|
B->freelist = 0; // empty list
|
|
B->buffer = malloc(size * cap);
|
|
B->s = malloc(cap * sizeof(*B->s));
|
|
init_blob_slots(B, 0, cap);
|
|
B->old = NULL;
|
|
B->oldpage_size = 0;
|
|
return B;
|
|
}
|
|
|
|
static size_t
|
|
blob_size(struct blob *B) {
|
|
return sizeof(*B) + (B->size + sizeof(*B->s)) * B->cap + B->oldpage_size;
|
|
}
|
|
|
|
static void
|
|
free_oldpage(struct oldpage *p) {
|
|
while (p) {
|
|
struct oldpage *next = p->next;
|
|
free(p->page);
|
|
free(p);
|
|
p = next;
|
|
}
|
|
}
|
|
|
|
#define SLOT_INDEX(idx) ((idx)-1)
|
|
#define SLOT_EMPTY(idx) ((idx)==0)
|
|
|
|
static int
|
|
blob_alloc(struct blob *B, int version) {
|
|
if (SLOT_EMPTY(B->freeslot)) {
|
|
struct oldpage * p = malloc(sizeof(*p));
|
|
p->next = B->old;
|
|
p->page = B->buffer;
|
|
B->old = p;
|
|
|
|
int cap = B->cap;
|
|
B->oldpage_size += sizeof(*p) + B->size * cap;
|
|
|
|
B->cap *= 2;
|
|
B->buffer = malloc(B->size * B->cap);
|
|
memcpy(B->buffer, p->page, B->size * cap);
|
|
B->s = realloc(B->s, B->cap * sizeof(*B->s));
|
|
static int alloc_count = 0;
|
|
alloc_count ++;
|
|
init_blob_slots(B, cap, B->cap);
|
|
}
|
|
int ret = SLOT_INDEX(B->freeslot);
|
|
struct slot *s = &B->s[ret];
|
|
B->freeslot = s->id; // next free slot
|
|
s->tag = TAG_USED;
|
|
s->id = version;
|
|
return ret;
|
|
}
|
|
|
|
static void *
|
|
blob_address(struct blob *B, int index, int version) {
|
|
struct slot *s = &B->s[index];
|
|
if (s->tag != TAG_USED || s->id != version)
|
|
return NULL;
|
|
return B->buffer + index * B->size;
|
|
}
|
|
|
|
static void
|
|
blob_dealloc(struct blob *B, int index, int version) {
|
|
struct slot *s = &B->s[index];
|
|
if (s->tag != TAG_USED || s->id != version)
|
|
return;
|
|
s->id = B->freelist;
|
|
s->tag = TAG_WILLFREE;
|
|
B->freelist = index + 1;
|
|
}
|
|
|
|
static void
|
|
blob_flush(struct blob *B) {
|
|
int slot = B->freelist;
|
|
while (slot) {
|
|
struct slot *s = &B->s[SLOT_INDEX(slot)];
|
|
s->tag = TAG_FREE;
|
|
if (SLOT_EMPTY(s->id)) {
|
|
s->id = B->freeslot;
|
|
B->freeslot = B->freelist;
|
|
B->freelist = 0;
|
|
break;
|
|
}
|
|
slot = s->id;
|
|
}
|
|
free_oldpage(B->old);
|
|
B->old = NULL;
|
|
B->oldpage_size = 0;
|
|
}
|
|
|
|
static void
|
|
blob_delete(struct blob *B) {
|
|
if (B) {
|
|
free(B->buffer);
|
|
free(B->s);
|
|
free_oldpage(B->old);
|
|
free(B);
|
|
}
|
|
}
|
|
|
|
static void
|
|
print_list(struct blob *B, const char * h, int list, int tag) {
|
|
printf("%s ", h);
|
|
while (!SLOT_EMPTY(list)) {
|
|
int index = SLOT_INDEX(list);
|
|
struct slot *s = &B->s[index];
|
|
if (s->tag == tag) {
|
|
printf("%d,", SLOT_INDEX(list));
|
|
} else {
|
|
printf("%d [ERROR]", SLOT_INDEX(list));
|
|
break;
|
|
}
|
|
list = s->id;
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
static void
|
|
blob_print(struct blob *B) {
|
|
int i;
|
|
printf("USED: ");
|
|
for (i=0;i<B->cap;i++) {
|
|
if (B->s[i].tag == TAG_USED) {
|
|
printf("%d,", i);
|
|
}
|
|
}
|
|
printf("\n");
|
|
print_list(B, "FREE :", B->freeslot, TAG_FREE);
|
|
print_list(B, "WILLFREE :", B->freelist, TAG_WILLFREE);
|
|
}
|
|
|
|
#if 0
|
|
int
|
|
blob_test_main() {
|
|
struct blob *B = blob_new(4, 10);
|
|
int a = blob_alloc(B,1);
|
|
int b = blob_alloc(B,1);
|
|
int c = blob_alloc(B,1);
|
|
blob_print(B);
|
|
blob_dealloc(B, a, 1);
|
|
blob_print(B);
|
|
blob_flush(B);
|
|
blob_print(B);
|
|
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
struct lastack *
|
|
lastack_new() {
|
|
struct lastack * LS = malloc(sizeof(*LS));
|
|
LS->temp_vector_cap = MINCAP;
|
|
LS->temp_vector_top = 0;
|
|
LS->temp_matrix_cap = MINCAP;
|
|
LS->temp_matrix_top = 0;
|
|
LS->version = 1; // base 1
|
|
LS->stack_cap = MINCAP;
|
|
LS->stack_top = 0;
|
|
LS->temp_vec = malloc(LS->temp_vector_cap * VECTOR4 * sizeof(float));
|
|
LS->temp_mat = malloc(LS->temp_matrix_cap * MATRIX * sizeof(float));
|
|
LS->per_vec = blob_new(VECTOR4 * sizeof(float), MINCAP);
|
|
LS->per_mat = blob_new(MATRIX * sizeof(float), MINCAP);
|
|
LS->old = NULL;
|
|
LS->stack = malloc(LS->stack_cap * sizeof(*LS->stack));
|
|
LS->oldpage_size = 0;
|
|
return LS;
|
|
}
|
|
|
|
size_t
|
|
lastack_size(struct lastack *LS) {
|
|
return sizeof(*LS)
|
|
+ LS->temp_vector_cap * VECTOR4 * sizeof(float)
|
|
+ LS->temp_matrix_cap * MATRIX * sizeof(float)
|
|
+ LS->stack_cap * sizeof(*LS->stack)
|
|
+ blob_size(LS->per_vec)
|
|
+ blob_size(LS->per_mat);
|
|
}
|
|
|
|
void
|
|
lastack_delete(struct lastack *LS) {
|
|
if (LS == NULL)
|
|
return;
|
|
free(LS->temp_vec);
|
|
free(LS->temp_mat);
|
|
blob_delete(LS->per_vec);
|
|
blob_delete(LS->per_mat);
|
|
free(LS->stack);
|
|
free_oldpage(LS->old);
|
|
free(LS);
|
|
}
|
|
|
|
static inline void
|
|
push_id(struct lastack *LS, union stackid id) {
|
|
if (LS->stack_top >= LS->stack_cap) {
|
|
LS->stack = realloc(LS->stack, (LS->stack_cap *= 2) * sizeof(*LS->stack));
|
|
}
|
|
LS->stack[LS->stack_top++] = id;
|
|
}
|
|
|
|
static void *
|
|
new_page(struct lastack *LS, void *page, size_t page_size) {
|
|
struct oldpage * p = malloc(sizeof(*p));
|
|
p->next = LS->old;
|
|
p->page = page;
|
|
LS->old = p;
|
|
LS->oldpage_size += page_size + sizeof(*p);
|
|
return page;
|
|
}
|
|
|
|
int
|
|
lastack_typesize(int type) {
|
|
const int sizes[LINEAR_TYPE_COUNT] = { 16, 4, 4 };
|
|
// assert(LINEAR_TYPE_MAT <= type && type < LINEAR_TYPE_COUNT);
|
|
return sizes[type];
|
|
}
|
|
|
|
const char *
|
|
lastack_typename(int t) {
|
|
static const char * type_names[] = {
|
|
"mat",
|
|
"v4",
|
|
"quat",
|
|
};
|
|
if (t < 0 || t >= sizeof(type_names)/sizeof(type_names[0]))
|
|
return "unknown";
|
|
return type_names[t];
|
|
}
|
|
|
|
|
|
static float *
|
|
check_matrix_pool(struct lastack *LS) {
|
|
if (LS->temp_matrix_top >= LS->temp_matrix_cap) {
|
|
size_t sz = LS->temp_matrix_cap * sizeof(float) * MATRIX;
|
|
void * p = new_page(LS, LS->temp_mat, sz);
|
|
LS->temp_mat = malloc(sz * 2);
|
|
memcpy(LS->temp_mat, p, sz);
|
|
LS->temp_matrix_cap *= 2;
|
|
}
|
|
return LS->temp_mat + LS->temp_matrix_top * MATRIX;
|
|
}
|
|
|
|
void
|
|
lastack_pushmatrix(struct lastack *LS, const float *mat) {
|
|
float * pmat = check_matrix_pool(LS);
|
|
memcpy(pmat, mat, sizeof(float) * MATRIX);
|
|
union stackid sid;
|
|
sid.s.type = LINEAR_TYPE_MAT;
|
|
sid.s.persistent = 0;
|
|
sid.s.version = LS->version;
|
|
sid.s.id = LS->temp_matrix_top;
|
|
push_id(LS, sid);
|
|
++ LS->temp_matrix_top;
|
|
}
|
|
|
|
void
|
|
lastack_pushsrt(struct lastack *LS, const float *s, const float *r, const float *t) {
|
|
#define NOTIDENTITY (~0)
|
|
float * mat = check_matrix_pool(LS);
|
|
uint32_t * mark = (uint32_t *)&mat[3*4];
|
|
// scale
|
|
float *scale = &mat[0];
|
|
if (s == NULL) {
|
|
scale[0] = 1;
|
|
scale[1] = 1;
|
|
scale[2] = 1;
|
|
scale[3] = 0;
|
|
mark[0] = 0;
|
|
} else {
|
|
float sx = s[0];
|
|
float sy = s[1];
|
|
float sz = s[2];
|
|
scale[0] = sx;
|
|
scale[1] = sy;
|
|
scale[2] = sz;
|
|
scale[3] = 0;
|
|
if (sx == 1 && sy == 1 && sz == 1) {
|
|
mark[0] = NOTIDENTITY;
|
|
}
|
|
}
|
|
// rotation
|
|
float *rotation = &mat[4*1];
|
|
if (r == NULL || (r[0] == 0 && r[1] == 0 && r[2] == 0 && r[3] == 1)) {
|
|
rotation[0] = 0;
|
|
rotation[1] = 0;
|
|
rotation[2] = 0;
|
|
rotation[3] = 1;
|
|
mark[1] = 0;
|
|
} else {
|
|
rotation[0] = r[0];
|
|
rotation[1] = r[1];
|
|
rotation[2] = r[2];
|
|
rotation[3] = r[3];
|
|
mark[1] = NOTIDENTITY;
|
|
}
|
|
// translate
|
|
float *translate = &mat[4*2];
|
|
if (t == NULL || (t[0] == 0 && t[1] == 0 && t[2] == 0)) {
|
|
translate[0] = 0;
|
|
translate[1] = 0;
|
|
translate[2] = 0;
|
|
translate[3] = 1;
|
|
mark[2] = 0;
|
|
} else {
|
|
translate[0] = t[0];
|
|
translate[1] = t[1];
|
|
translate[2] = t[2];
|
|
translate[3] = 1;
|
|
mark[2] = NOTIDENTITY;
|
|
}
|
|
// mark identity
|
|
if (mark[0] == 0 && mark[1] == 0 && mark[2] == 0) {
|
|
mark[3] = 0;
|
|
} else {
|
|
mark[3] = NOTIDENTITY;
|
|
}
|
|
union stackid sid;
|
|
sid.s.type = LINEAR_TYPE_MAT;
|
|
sid.s.persistent = 0;
|
|
sid.s.version = LS->version;
|
|
sid.s.id = LS->temp_matrix_top;
|
|
push_id(LS, sid);
|
|
++ LS->temp_matrix_top;
|
|
}
|
|
|
|
void
|
|
lastack_pushobject(struct lastack *LS, const float *v, int type) {
|
|
if (type == LINEAR_TYPE_MAT) {
|
|
lastack_pushmatrix(LS, v);
|
|
return;
|
|
}
|
|
assert(type >= LINEAR_TYPE_VEC4 && type <= LINEAR_TYPE_QUAT);
|
|
const int size = lastack_typesize(type);
|
|
if (LS->temp_vector_top >= LS->temp_vector_cap) {
|
|
size_t sz = LS->temp_vector_cap * sizeof(float) * VECTOR4;
|
|
void * p = new_page(LS, LS->temp_vec, sz);
|
|
LS->temp_vec = malloc(sz * 2);
|
|
memcpy(LS->temp_vec, p, sz);
|
|
LS->temp_vector_cap *= 2;
|
|
}
|
|
memcpy(LS->temp_vec + LS->temp_vector_top * VECTOR4, v, sizeof(float) * size);
|
|
union stackid sid;
|
|
sid.s.type = type;
|
|
sid.s.persistent = 0;
|
|
sid.s.version = LS->version;
|
|
sid.s.id = LS->temp_vector_top;
|
|
push_id(LS, sid);
|
|
++ LS->temp_vector_top;
|
|
}
|
|
|
|
void
|
|
lastack_pushvec4(struct lastack *LS, const float *vec4) {
|
|
lastack_pushobject(LS, vec4, LINEAR_TYPE_VEC4);
|
|
}
|
|
|
|
void
|
|
lastack_pushquat(struct lastack *LS, const float *v) {
|
|
lastack_pushobject(LS, v, LINEAR_TYPE_QUAT);
|
|
}
|
|
|
|
const float *
|
|
lastack_value(struct lastack *LS, int64_t ref, int *type) {
|
|
union stackid sid;
|
|
sid.i = ref;
|
|
int id = sid.s.id;
|
|
int ver = sid.s.version;
|
|
void * address = NULL;
|
|
if (type)
|
|
*type = sid.s.type;
|
|
if (sid.s.persistent) {
|
|
if (sid.s.version == 0) {
|
|
// constant
|
|
int id = sid.s.id;
|
|
if (id < 0 || id >= LINEAR_TYPE_COUNT)
|
|
return NULL;
|
|
struct constant * c = &c_constant_table[id];
|
|
return c->ptr;
|
|
}
|
|
if (lastack_typesize(sid.s.type) == MATRIX) {
|
|
address = blob_address( LS->per_mat , id, ver);
|
|
} else {
|
|
address = blob_address( LS->per_vec , id, ver);
|
|
}
|
|
return address;
|
|
} else {
|
|
if (ver != LS->version) {
|
|
// version expired
|
|
return NULL;
|
|
}
|
|
if (lastack_typesize(sid.s.type) == MATRIX) {
|
|
if (id >= LS->temp_matrix_top) {
|
|
return NULL;
|
|
}
|
|
return LS->temp_mat + id * MATRIX;
|
|
} else {
|
|
if (id >= LS->temp_vector_top) {
|
|
return NULL;
|
|
}
|
|
return LS->temp_vec + id * VECTOR4;
|
|
}
|
|
}
|
|
}
|
|
|
|
int
|
|
lastack_pushref(struct lastack *LS, int64_t ref) {
|
|
union stackid id;
|
|
id.i = ref;
|
|
// check alive
|
|
const void *address = lastack_value(LS, id.i, NULL);
|
|
if (address == NULL)
|
|
return 1;
|
|
push_id(LS, id);
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
lastack_unmark(struct lastack *LS, int64_t markid) {
|
|
union stackid id;
|
|
id.i = markid;
|
|
if (id.s.persistent && id.s.version != 0) {
|
|
if (lastack_typesize(id.s.type) != MATRIX) {
|
|
blob_dealloc(LS->per_vec, id.s.id, id.s.version);
|
|
} else {
|
|
blob_dealloc(LS->per_mat, id.s.id, id.s.version);
|
|
}
|
|
}
|
|
}
|
|
|
|
int
|
|
lastack_isconstant(int64_t markid) {
|
|
union stackid id;
|
|
id.i = markid;
|
|
return (id.s.persistent && id.s.version == 0);
|
|
}
|
|
|
|
int64_t
|
|
lastack_mark(struct lastack *LS, int64_t tempid) {
|
|
if (lastack_isconstant(tempid))
|
|
return tempid;
|
|
int t;
|
|
const float *address = lastack_value(LS, tempid, &t);
|
|
if (address == NULL) {
|
|
//printf("--- mark address = null ---");
|
|
return 0;
|
|
}
|
|
int id;
|
|
union stackid sid;
|
|
sid.s.version = LS->version;
|
|
sid.s.type = t;
|
|
if (lastack_typesize(t) != MATRIX) {
|
|
id = blob_alloc(LS->per_vec, LS->version);
|
|
void * dest = blob_address(LS->per_vec, id, LS->version);
|
|
memcpy(dest, address, sizeof(float) * VECTOR4);
|
|
} else {
|
|
id = blob_alloc(LS->per_mat, LS->version);
|
|
void * dest = blob_address(LS->per_mat, id, LS->version);
|
|
memcpy(dest, address, sizeof(float) * MATRIX);
|
|
}
|
|
sid.s.id = id;
|
|
if (sid.s.id != id) {
|
|
//printf(" --- s.id(%d) != id(%d) --- \n ",sid.s.id,id);
|
|
return 0;
|
|
}
|
|
sid.s.persistent = 1;
|
|
return sid.i;
|
|
}
|
|
|
|
int
|
|
lastack_marked(int64_t id, int *type) {
|
|
union stackid sid;
|
|
sid.i = id;
|
|
if (type) {
|
|
*type = sid.s.type;
|
|
}
|
|
return sid.s.persistent;
|
|
}
|
|
|
|
int
|
|
lastack_sametype(int64_t id1, int64_t id2) {
|
|
union stackid sid1,sid2;
|
|
sid1.i = id1;
|
|
sid2.i = id2;
|
|
return sid1.s.type == sid2.s.type;
|
|
}
|
|
|
|
int64_t
|
|
lastack_pop(struct lastack *LS) {
|
|
if (LS->stack_top <= 0)
|
|
return 0;
|
|
union stackid sid = LS->stack[--LS->stack_top];
|
|
return sid.i;
|
|
}
|
|
|
|
int64_t
|
|
lastack_top(struct lastack *LS) {
|
|
if (LS->stack_top <= 0)
|
|
return 0;
|
|
union stackid sid = LS->stack[LS->stack_top-1];
|
|
return sid.i;
|
|
}
|
|
|
|
int64_t
|
|
lastack_dup(struct lastack *LS, int index) {
|
|
if (LS->stack_top < index || index <= 0)
|
|
return 0;
|
|
union stackid sid = LS->stack[LS->stack_top-index];
|
|
push_id(LS, sid);
|
|
return sid.i;
|
|
}
|
|
|
|
int64_t
|
|
lastack_swap(struct lastack *LS) {
|
|
if (LS->stack_top <= 1)
|
|
return 0;
|
|
union stackid top = LS->stack[LS->stack_top-1];
|
|
union stackid newtop = LS->stack[LS->stack_top-2];
|
|
LS->stack[LS->stack_top-2] = top;
|
|
LS->stack[LS->stack_top-1] = newtop;
|
|
return newtop.i;
|
|
}
|
|
|
|
void
|
|
lastack_reset(struct lastack *LS) {
|
|
union stackid v;
|
|
v.s.version = LS->version + 1;
|
|
if (v.s.version == 0)
|
|
++ v.s.version;
|
|
LS->version = v.s.version;
|
|
LS->stack_top = 0;
|
|
free_oldpage(LS->old);
|
|
LS->old = NULL;
|
|
LS->oldpage_size = 0;
|
|
blob_flush(LS->per_vec);
|
|
blob_flush(LS->per_mat);
|
|
LS->temp_vector_top = 0;
|
|
LS->temp_matrix_top = 0;
|
|
}
|
|
|
|
static void
|
|
print_float(const float *address, int n) {
|
|
int i;
|
|
for (i=0;i<n-1;i++) {
|
|
printf("%.3g ", address[i]);
|
|
}
|
|
printf("%.3g",address[i]);
|
|
}
|
|
|
|
static void
|
|
print_object(const float *address, int id, int type) {
|
|
switch(type) {
|
|
case LINEAR_TYPE_NONE:
|
|
printf("(None");
|
|
break;
|
|
case LINEAR_TYPE_MAT:
|
|
printf("(M%d: ",id);
|
|
print_float(address, 16);
|
|
break;
|
|
case LINEAR_TYPE_VEC4:
|
|
printf("(V%d: ",id);
|
|
print_float(address, 4);
|
|
break;
|
|
case LINEAR_TYPE_QUAT:
|
|
printf("(Q%d: ",id);
|
|
print_float(address, 4);
|
|
break;
|
|
default:
|
|
printf("(Invalid");
|
|
break;
|
|
}
|
|
printf(")");
|
|
}
|
|
|
|
void
|
|
lastack_print(struct lastack *LS) {
|
|
printf("version = %d\n", LS->version);
|
|
printf("stack %d/%d:\n", LS->stack_top, LS->stack_cap);
|
|
int i;
|
|
for (i=0;i<LS->stack_top;i++) {
|
|
union stackid id = LS->stack[i];
|
|
int type;
|
|
const float *address = lastack_value(LS, id.i, &type);
|
|
printf("\t[%d]", i);
|
|
if (id.s.persistent) {
|
|
printf("version = %d ", id.s.version);
|
|
}
|
|
print_object(address, id.s.id, type);
|
|
printf("\n");
|
|
}
|
|
printf("Persistent Vector ");
|
|
blob_print(LS->per_vec);
|
|
printf("Persistent Matrix ");
|
|
blob_print(LS->per_mat);
|
|
}
|
|
|
|
int
|
|
lastack_gettop(struct lastack *LS) {
|
|
return LS->stack_top;
|
|
}
|
|
|
|
void
|
|
lastack_dump(struct lastack *LS, int from) {
|
|
if (from < 0) {
|
|
from = LS->stack_top + from;
|
|
if (from < 0)
|
|
from = 0;
|
|
}
|
|
int i;
|
|
for (i=LS->stack_top-1;i>=from;i--) {
|
|
union stackid id = LS->stack[i];
|
|
int type;
|
|
const float *address = lastack_value(LS, id.i, &type);
|
|
print_object(address, id.s.id, type);
|
|
}
|
|
if (from > 0) {
|
|
for (i=0;i<from;i++) {
|
|
printf(".");
|
|
}
|
|
}
|
|
}
|
|
|
|
int
|
|
lastack_type(struct lastack *LS, int64_t id) {
|
|
union stackid sid;
|
|
sid.i = id;
|
|
return sid.s.type;
|
|
}
|
|
|
|
char *
|
|
lastack_idstring(int64_t id, char tmp[64]) {
|
|
union stackid sid;
|
|
sid.i = id;
|
|
char flags[3] = { 0,0,0 };
|
|
switch(sid.s.type) {
|
|
case LINEAR_TYPE_MAT:
|
|
flags[0] = 'M';
|
|
break;
|
|
case LINEAR_TYPE_VEC4:
|
|
flags[0] = 'V';
|
|
break;
|
|
case LINEAR_TYPE_QUAT:
|
|
flags[0] = 'Q';
|
|
break;
|
|
default:
|
|
flags[0] = '?';
|
|
break;
|
|
}
|
|
if (sid.s.persistent) {
|
|
flags[1] = 'P';
|
|
}
|
|
snprintf(tmp, 64, "id=%d version=%d %s",sid.s.id, sid.s.version, flags);
|
|
return tmp;
|
|
}
|
|
|
|
#if 0
|
|
int
|
|
test_main() {
|
|
struct lastack *LS = lastack_new();
|
|
float v[4] = { 1,2,3,4 };
|
|
float m[16] = {
|
|
1,0,0,0,
|
|
0,1,0,0,
|
|
0,0,1,0,
|
|
0,0,0,1
|
|
};
|
|
lastack_pushvector(LS, v, LINEAR_TYPE_VEC4);
|
|
int64_t c = lastack_mark(LS);
|
|
lastack_pushmatrix(LS, m);
|
|
lastack_pushref(LS, -c);
|
|
lastack_dup(LS);
|
|
lastack_print(LS);
|
|
lastack_reset(LS);
|
|
lastack_pushref(LS, c);
|
|
lastack_dup(LS);
|
|
lastack_dup(LS);
|
|
lastack_dup(LS);
|
|
lastack_dup(LS);
|
|
lastack_dup(LS);
|
|
lastack_dup(LS);
|
|
lastack_print(LS);
|
|
lastack_reset(LS);
|
|
lastack_print(LS);
|
|
lastack_delete(LS);
|
|
return 0;
|
|
}
|
|
|
|
#endif
|