@@ -961,27 +961,34 @@ if using clang (gcc and tcc use similar syntax).
961961 #define VECMATH_INLINE static inline
962962#endif
963963
964+ #define VECMATH_SIZEOF(x) sizeof(x)
965+ #define VECMATH_OFFSETOF(st, m) ((long long unsigned)&(((st *)0)->m))
966+ #define VECMATH_STATIC_ASSERT(condition, message) int VECMATH_STATIC_ASSERT(int VECMATH_STATIC_ASSERT[(condition) ? 1 : -1])
967+
968+ struct vecmath_static_assert_test { char x; };
969+ VECMATH_STATIC_ASSERT(VECMATH_SIZEOF(struct vecmath_static_assert_test) == 1, "vecmath static assert test 1");
970+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(struct vecmath_static_assert_test, x) == 0, "vecmath static assert test 2");
971+
964972#ifdef __cplusplus
965973 namespace vecmath {
966974#endif
967975
968976// types
977+ #if defined( VECMATH_VEC2 ) || defined( VECMATH_VEC3 ) || defined( VECMATH_VEC4 ) || \
978+ defined( VECMATH_MAT22 ) || defined( VECMATH_MAT23 ) || defined( VECMATH_MAT24 ) || \
979+ defined( VECMATH_MAT32 ) || defined( VECMATH_MAT33 ) || defined( VECMATH_MAT34 ) || \
980+ defined( VECMATH_MAT42 ) || defined( VECMATH_MAT43 ) || defined( VECMATH_MAT44 )
981+
982+ #if defined( VECMATH_EXT_VECTOR_TYPE )
983+ #error "VECMATH_EXT_VECTOR_TYPE is incompatible with custom types. If you want to use clang vector extensions with your own types, you need to decorate your types with the necessary attributes."
984+ #endif
985+
986+ #endif
987+
969988#if defined( VECMATH_EXT_VECTOR_TYPE ) && !defined( __cplusplus ) && defined(__clang__) && __clang_major__ >= 3
970- #if !defined( VECMATH_VEC2 )
971989 typedef float vec2_t __attribute__((ext_vector_type(2)));
972- #else
973- typedef VECMATH_VEC2 vec2_t;
974- #endif
975- #if !defined( VECMATH_VEC3 )
976990 typedef float vec3_t __attribute__((ext_vector_type(3)));
977- #else
978- typedef VECMATH_VEC3 vec3_t;
979- #endif
980- #if !defined( VECMATH_VEC3 )
981991 typedef float vec4_t __attribute__((ext_vector_type(4)));
982- #else
983- typedef VECMATH_VEC4 vec4_t;
984- #endif
985992#else
986993 #if !defined( VECMATH_VEC2 )
987994 typedef struct vec2_t { float x, y; } vec2_t ;
@@ -1045,6 +1052,76 @@ if using clang (gcc and tcc use similar syntax).
10451052 typedef VECMATH_MAT44 mat44_t;
10461053#endif
10471054
1055+ /* The _get/_set (accessing by index) functions assume the x/y/z/w members are
1056+ * in that specific order, starts at the start of the struct, and that there's
1057+ * no padding. The following static assertions ensure all of this is true. */
1058+
1059+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(vec2_t, x) == 0, "vecmath vec2_t type member 'x' must be at offset 0");
1060+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(vec2_t, y) == 4, "vecmath vec2_t type member 'y' must be at offset 4");
1061+
1062+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(vec3_t, x) == 0, "vecmath vec3_t type member 'x' must be at offset 0");
1063+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(vec3_t, y) == 4, "vecmath vec3_t type member 'y' must be at offset 4");
1064+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(vec3_t, z) == 8, "vecmath vec3_t type member 'z' must be at offset 8");
1065+
1066+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(vec4_t, x) == 0, "vecmath vec3_t type member 'x' must be at offset 0");
1067+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(vec4_t, y) == 4, "vecmath vec3_t type member 'y' must be at offset 4");
1068+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(vec4_t, z) == 8, "vecmath vec3_t type member 'z' must be at offset 8");
1069+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(vec4_t, w) == 12, "vecmath vec4_t type member 'w' must be at offset 12");
1070+
1071+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(mat22_t, x) == 0, "vecmath mat22_t type member 'x' must be at offset 0");
1072+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(mat22_t, y) == 8, "vecmath mat22_t type member 'y' must be at offset 8");
1073+
1074+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(mat23_t, x) == 0, "vecmath mat23_t type member 'x' must be at offset 0");
1075+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(mat23_t, y) == 12, "vecmath mat23_t type member 'y' must be at offset 12");
1076+
1077+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(mat24_t, x) == 0, "vecmath mat24_t type member 'x' must be at offset 0");
1078+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(mat24_t, y) == 16, "vecmath mat24_t type member 'y' must be at offset 16");
1079+
1080+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(mat32_t, x) == 0, "vecmath mat32_t type member 'x' must be at offset 0");
1081+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(mat32_t, y) == 8, "vecmath mat32_t type member 'y' must be at offset 8");
1082+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(mat32_t, z) == 16, "vecmath mat32_t type member 'z' must be at offset 16");
1083+
1084+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(mat33_t, x) == 0, "vecmath mat33_t type member 'x' must be at offset 0");
1085+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(mat33_t, y) == 12, "vecmath mat33_t type member 'y' must be at offset 12");
1086+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(mat33_t, z) == 24, "vecmath mat33_t type member 'z' must be at offset 24");
1087+
1088+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(mat34_t, x) == 0, "vecmath mat34_t type member 'x' must be at offset 0");
1089+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(mat34_t, y) == 16, "vecmath mat34_t type member 'y' must be at offset 16");
1090+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(mat34_t, z) == 32, "vecmath mat34_t type member 'z' must be at offset 32");
1091+
1092+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(mat42_t, x) == 0, "vecmath mat42_t type member 'x' must be at offset 0");
1093+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(mat42_t, y) == 8, "vecmath mat42_t type member 'y' must be at offset 8");
1094+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(mat42_t, z) == 16, "vecmath mat42_t type member 'z' must be at offset 16");
1095+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(mat42_t, w) == 24, "vecmath mat42_t type member 'w' must be at offset 24");
1096+
1097+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(mat43_t, x) == 0, "vecmath mat43_t type member 'x' must be at offset 0");
1098+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(mat43_t, y) == 12, "vecmath mat43_t type member 'y' must be at offset 12");
1099+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(mat43_t, z) == 24, "vecmath mat43_t type member 'z' must be at offset 24");
1100+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(mat43_t, w) == 36, "vecmath mat43_t type member 'w' must be at offset 36");
1101+
1102+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(mat44_t, x) == 0, "vecmath mat44_t type member 'x' must be at offset 0");
1103+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(mat44_t, y) == 16, "vecmath mat44_t type member 'y' must be at offset 16");
1104+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(mat44_t, z) == 32, "vecmath mat44_t type member 'z' must be at offset 32");
1105+ VECMATH_STATIC_ASSERT(VECMATH_OFFSETOF(mat44_t, w) == 48, "vecmath mat44_t type member 'w' must be at offset 48");
1106+
1107+ /* Further, some tests assume the exact binary representation of the types. If
1108+ * the types had trailing elements after the required ones, like debug tags or
1109+ * whatever, those would be lost when new values are returned. The following
1110+ * static assertions ensure there is no hidden data in the structs which could
1111+ * interfere with tests. */
1112+
1113+ VECMATH_STATIC_ASSERT(VECMATH_SIZEOF(vec2_t) == 8, "vecmath vec2_t type must be 8 bytes big exactly");
1114+ VECMATH_STATIC_ASSERT(VECMATH_SIZEOF(vec3_t) == 12, "vecmath vec3_t type must be 12 bytes big exactly");
1115+ VECMATH_STATIC_ASSERT(VECMATH_SIZEOF(vec4_t) == 16, "vecmath vec4_t type must be 16 bytes big exactly");
1116+ VECMATH_STATIC_ASSERT(VECMATH_SIZEOF(mat22_t) == 16, "vecmath mat22_t type must be 16 bytes big exactly");
1117+ VECMATH_STATIC_ASSERT(VECMATH_SIZEOF(mat23_t) == 24, "vecmath mat23_t type must be 24 bytes big exactly");
1118+ VECMATH_STATIC_ASSERT(VECMATH_SIZEOF(mat24_t) == 32, "vecmath mat24_t type must be 32 bytes big exactly");
1119+ VECMATH_STATIC_ASSERT(VECMATH_SIZEOF(mat32_t) == 24, "vecmath mat32_t type must be 24 bytes big exactly");
1120+ VECMATH_STATIC_ASSERT(VECMATH_SIZEOF(mat33_t) == 36, "vecmath mat33_t type must be 36 bytes big exactly");
1121+ VECMATH_STATIC_ASSERT(VECMATH_SIZEOF(mat34_t) == 48, "vecmath mat34_t type must be 48 bytes big exactly");
1122+ VECMATH_STATIC_ASSERT(VECMATH_SIZEOF(mat42_t) == 32, "vecmath mat42_t type must be 32 bytes big exactly");
1123+ VECMATH_STATIC_ASSERT(VECMATH_SIZEOF(mat43_t) == 48, "vecmath mat43_t type must be 48 bytes big exactly");
1124+ VECMATH_STATIC_ASSERT(VECMATH_SIZEOF(mat44_t) == 64, "vecmath mat44_t type must be 64 bytes big exactly");
10481125
10491126// math defines
10501127
0 commit comments