+#include "../q.h"
+
+typedef struct _mymatrix {
+ float m00,m01,m10,m11;
+ char*id;
+} mymatrix_t;
+
+static void* mymatrix_clone(const void*_m) {
+ if(_m==0)
+ return 0;
+ const mymatrix_t*m1=_m;
+ mymatrix_t*m2 = malloc(sizeof(mymatrix_t));
+ *m2 = *m1;
+ m2->id = strdup(m1->id);
+ return m2;
+}
+static unsigned int mymatrix_hash(const void*_m) {
+ if(!_m)
+ return 0;
+ const mymatrix_t*m = (mymatrix_t*)_m;
+ unsigned int h=0;
+ h = crc32_add_bytes(h, (char*)&m->m00, sizeof(m->m00));
+ h = crc32_add_bytes(h, (char*)&m->m01, sizeof(m->m01));
+ h = crc32_add_bytes(h, (char*)&m->m10, sizeof(m->m10));
+ h = crc32_add_bytes(h, (char*)&m->m11, sizeof(m->m11));
+ h = crc32_add_string(h, m->id);
+ return h;
+}
+static void mymatrix_destroy(void*_m) {
+ mymatrix_t*m = (mymatrix_t*)_m;
+ free(m->id);m->id=0;
+ free(m);
+}
+static char mymatrix_equals(const void*_m1, const void*_m2) {
+ const mymatrix_t*m1=_m1;
+ const mymatrix_t*m2=_m2;
+ if(!m1 || !m2)
+ return m1==m2;
+
+ /* we do a binary comparison of the float32
+ bits here instead of a numerical comparison
+ to prevent the compiler from e.g. removing the
+ (float) cast during optimization, which would break
+ the equivalence between equals() and hash() (as
+ the hash is derived from the float32 values) */
+ return *(U32*)&m1->m00 == *(U32*)&m2->m00 &&
+ *(U32*)&m1->m01 == *(U32*)&m2->m01 &&
+ *(U32*)&m1->m10 == *(U32*)&m2->m10 &&
+ *(U32*)&m1->m11 == *(U32*)&m2->m11 &&
+ !strcmp(m1->id, m2->id);
+}
+type_t mymatrix_type = {
+ dup: mymatrix_clone,
+ hash: mymatrix_hash,
+ free: mymatrix_destroy,
+ equals: mymatrix_equals
+};