I'm trying to validate matrix values in nested loop for unit tests. The tests pass on macOS (clang) but fail Ubuntu 18.04 (gcc version 7.3.0).
Here what I'm trying to do (I'm trying to validate the result (m3
) is identity matrix):
mat3 m1 = GLM_MAT3_IDENTITY_INIT;
mat3 m2 = GLM_MAT3_IDENTITY_INIT;
mat3 m3;
int i, j, k;
/* test identity matrix multiplication */
glm_mat3_mul(m1, m2, m3);
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
if (i == j) {
assert_true(glm_eq(m3[i][j], 1.0f));
} else {
assert_true(glm_eq(m3[i][j], 0.0f));
}
}
}
This fails on Ubuntu/gcc but passes on macOS. If I use volatile on i variable then it passes on Ubuntu too:
mat3 m1 = GLM_MAT3_IDENTITY_INIT;
mat3 m2 = GLM_MAT3_IDENTITY_INIT;
mat3 m3;
volatile i;
int j, k;
/* test identity matrix multiplication */
glm_mat3_mul(m1, m2, m3);
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
if (i == j) {
assert_true(glm_eq(m3[i][j], 1.0f));
} else {
assert_true(glm_eq(m3[i][j], 0.0f));
}
}
}
if I print i and j values before if (i == j) {
statement without volatile then it also passes. Maybe i is cached and new value of i is not loaded at next iteration. But this would also be true for mat4 tests, same test works for mat4
Using one condition (true condition or false condition) causes test to pass but using if with else causes test to fail.
I'm using cmocka for testing and run make check
command to run tests.
mat3 and mat4 definitions:
typedef float vec2[2];
typedef CGLM_ALIGN_IF(8) float vec3[3];
typedef int ivec3[3];
typedef CGLM_ALIGN_IF(16) float vec4[4];
#ifdef __AVX__
typedef CGLM_ALIGN_IF(32) vec3 mat3[3];
typedef CGLM_ALIGN_IF(32) vec4 mat4[4];
#else
typedef vec3 mat3[3];
typedef CGLM_ALIGN_IF(16) vec4 mat4[4];
#endif
Should I use volatile here? Or what is wrong with my test codes?
PS: Same test passes for mat4 on Ubuntu, it only fails for mat3
EDIT:
Float values are compared using glm_eq(a, b)
:
CGLM_INLINE
bool
glm_eq(float a, float b) {
return fabsf(a - b) <= FLT_EPSILON;
}