quat/cmplx nan cmp

This commit is contained in:
kalsprite
2026-08-15 20:08:27 -07:00
parent 36d0b056a2
commit 617293c5f0
2 changed files with 157 additions and 0 deletions

View File

@@ -1019,6 +1019,10 @@ gb_internal bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y)
f64 b = x.value_complex->imag;
f64 c = y.value_complex->real;
f64 d = y.value_complex->imag;
if (isnan(a) || isnan(b) || isnan(c) || isnan(d)) {
return op == Token_NotEq;
}
switch (op) {
case Token_CmpEq: return cmp_f64(a, c) == 0 && cmp_f64(b, d) == 0;
case Token_NotEq: return cmp_f64(a, c) != 0 || cmp_f64(b, d) != 0;
@@ -1026,6 +1030,29 @@ gb_internal bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y)
break;
}
case ExactValue_Quaternion: {
Quaternion256 a = *x.value_quaternion;
Quaternion256 b = *y.value_quaternion;
if (isnan(a.real) || isnan(a.imag) || isnan(a.jmag) || isnan(a.kmag) ||
isnan(b.real) || isnan(b.imag) || isnan(b.jmag) || isnan(b.kmag)) {
return op == Token_NotEq;
}
switch (op) {
case Token_CmpEq:
return cmp_f64(a.real, b.real) == 0 &&
cmp_f64(a.imag, b.imag) == 0 &&
cmp_f64(a.jmag, b.jmag) == 0 &&
cmp_f64(a.kmag, b.kmag) == 0;
case Token_NotEq:
return cmp_f64(a.real, b.real) != 0 ||
cmp_f64(a.imag, b.imag) != 0 ||
cmp_f64(a.jmag, b.jmag) != 0 ||
cmp_f64(a.kmag, b.kmag) != 0;
}
break;
}
case ExactValue_String: {
String a = x.value_string;
String b = y.value_string;

View File

@@ -0,0 +1,130 @@
package test_internal
import "core:testing"
// Each constant case is paired with the same comparison on variables: the folded answer
// has to be the answer the backend produces.
@(test)
compare_constant_quaternions :: proc(t: ^testing.T) {
I :: quaternion128(0+1i+0j+0k)
J :: quaternion128(0+0i+1j+0k)
K :: quaternion128(0+0i+0j+1k)
R :: quaternion128(1+0i+0j+0k)
testing.expect_value(t, R == 1, true)
testing.expect_value(t, 1 == R, true)
testing.expect_value(t, R != 1, false)
testing.expect_value(t, I == J, false)
testing.expect_value(t, J == K, false)
testing.expect_value(t, K == R, false)
testing.expect_value(t, I != J, true)
testing.expect_value(t, I == I, true)
// every lane must take part, not just the real one
A :: quaternion128(2+3i+4j+5k)
testing.expect_value(t, A == quaternion128(2+3i+4j+5k), true)
testing.expect_value(t, A == quaternion128(9+3i+4j+5k), false)
testing.expect_value(t, A == quaternion128(2+9i+4j+5k), false)
testing.expect_value(t, A == quaternion128(2+3i+9j+5k), false)
testing.expect_value(t, A == quaternion128(2+3i+4j+9k), false)
// promotion of the other operand, from integer, float and complex
testing.expect_value(t, R == 1.0, true)
testing.expect_value(t, quaternion128(2+3i+0j+0k) == 2+3i, true)
testing.expect_value(t, quaternion128(2+3i+0j+0k) == 2+4i, false)
testing.expect_value(t, quaternion64(0) == 0, true)
testing.expect_value(t, quaternion256(0) == 0, true)
testing.expect_value(t, quaternion128(0) == quaternion128(-0.0), true)
}
@(test)
compare_variable_quaternions :: proc(t: ^testing.T) {
I := quaternion128(0+1i+0j+0k)
J := quaternion128(0+0i+1j+0k)
K := quaternion128(0+0i+0j+1k)
R := quaternion128(1+0i+0j+0k)
testing.expect_value(t, R == 1, true)
testing.expect_value(t, 1 == R, true)
testing.expect_value(t, R != 1, false)
testing.expect_value(t, I == J, false)
testing.expect_value(t, J == K, false)
testing.expect_value(t, K == R, false)
testing.expect_value(t, I != J, true)
testing.expect_value(t, I == I, true)
A := quaternion128(2+3i+4j+5k)
testing.expect_value(t, A == quaternion128(2+3i+4j+5k), true)
testing.expect_value(t, A == quaternion128(9+3i+4j+5k), false)
testing.expect_value(t, A == quaternion128(2+9i+4j+5k), false)
testing.expect_value(t, A == quaternion128(2+3i+9j+5k), false)
testing.expect_value(t, A == quaternion128(2+3i+4j+9k), false)
testing.expect_value(t, R == 1.0, true)
testing.expect_value(t, quaternion128(2+3i+0j+0k) == 2+3i, true)
testing.expect_value(t, quaternion128(2+3i+0j+0k) == 2+4i, false)
q64 := quaternion64(0)
q256 := quaternion256(0)
testing.expect_value(t, q64 == 0, true)
testing.expect_value(t, q256 == 0, true)
testing.expect_value(t, quaternion128(0) == quaternion128(-0.0), true)
}
@(test)
compare_constant_quaternion_nans :: proc(t: ^testing.T) {
NaN :: f64(0h7ff8_0000_0000_0000)
Q :: quaternion(w=NaN, x=0, y=0, z=0)
L :: quaternion(w=0, x=0, y=0, z=NaN)
testing.expect_value(t, Q == Q, false)
testing.expect_value(t, Q != Q, true)
testing.expect_value(t, L == L, false)
testing.expect_value(t, L != L, true)
testing.expect_value(t, Q == 0, false)
testing.expect_value(t, Q != 0, true)
}
@(test)
compare_variable_quaternion_nans :: proc(t: ^testing.T) {
NaN := f64(0h7ff8_0000_0000_0000)
Q := quaternion(w=NaN, x=0, y=0, z=0)
L := quaternion(w=0, x=0, y=0, z=NaN)
testing.expect_value(t, Q == Q, false)
testing.expect_value(t, Q != Q, true)
testing.expect_value(t, L == L, false)
testing.expect_value(t, L != L, true)
testing.expect_value(t, Q == 0, false)
testing.expect_value(t, Q != 0, true)
}
@(test)
compare_constant_complex_nans :: proc(t: ^testing.T) {
NaN :: f64(0h7ff8_0000_0000_0000)
C :: complex(NaN, 0)
D :: complex(0, NaN)
testing.expect_value(t, C == C, false)
testing.expect_value(t, C != C, true)
testing.expect_value(t, D == D, false)
testing.expect_value(t, D != D, true)
testing.expect_value(t, C == 0, false)
testing.expect_value(t, C != 0, true)
}
@(test)
compare_variable_complex_nans :: proc(t: ^testing.T) {
NaN := f64(0h7ff8_0000_0000_0000)
C := complex(NaN, 0)
D := complex(0, NaN)
testing.expect_value(t, C == C, false)
testing.expect_value(t, C != C, true)
testing.expect_value(t, D == D, false)
testing.expect_value(t, D != D, true)
testing.expect_value(t, C == 0, false)
testing.expect_value(t, C != 0, true)
}