builtin_fp_cmp_negation.c (1803B)
1 /* Route B — negating a floating comparison folds to the unordered dual. 2 * 3 * Because FP compares are delayed SV_CMPs, `!(a < b)` becomes the NaN-correct 4 * unordered relation rather than a bare bitwise negate: 5 * !(a < b) == UGE (a >= b OR unordered) 6 * !(a <= b) == UGT 7 * !(a > b) == ULE 8 * !(a >= b) == ULT 9 * !(a == b) == UNE (already; C `!=` is unordered) 10 * !islessgreater(a, b) == UEQ 11 * For ordinary operands these behave like the plain (negated) comparison; for 12 * a NaN operand every negated ordered relation is true. */ 13 static double mknan(void) { 14 double z = 0.0; 15 return z / z; 16 } 17 18 int test_main(void) { 19 double nan = mknan(); 20 double a = 1.0, b = 2.0; 21 int rc = 0; 22 23 /* !(a < b) -> UGE */ 24 if (!(a < b) != 0) rc |= 1 << 0; /* 1<2 true -> 0 */ 25 if (!(b < a) != 1) rc |= 1 << 1; /* 2<1 false -> 1 */ 26 if (!(nan < a) != 1) rc |= 1 << 2; /* NaN unordered -> 1 */ 27 28 /* !(a <= b) -> UGT */ 29 if (!(a <= b) != 0) rc |= 1 << 3; 30 if (!(b <= a) != 1) rc |= 1 << 4; 31 if (!(nan <= a) != 1) rc |= 1 << 5; 32 33 /* !(a > b) -> ULE */ 34 if (!(b > a) != 0) rc |= 1 << 6; 35 if (!(a > b) != 1) rc |= 1 << 7; 36 if (!(nan > a) != 1) rc |= 1 << 8; 37 38 /* !(a >= b) -> ULT */ 39 if (!(b >= a) != 0) rc |= 1 << 9; 40 if (!(a >= b) != 1) rc |= 1 << 10; 41 if (!(nan >= a) != 1) rc |= 1 << 11; 42 43 /* !(a == b) -> UNE */ 44 if (!(a == a) != 0) rc |= 1 << 12; 45 if (!(a == b) != 1) rc |= 1 << 13; 46 if (!(nan == a) != 1) rc |= 1 << 14; /* NaN never equal -> !false = 1 */ 47 48 /* !islessgreater -> UEQ (equal OR unordered) */ 49 if (!__builtin_islessgreater(a, a) != 1) rc |= 1 << 15; /* equal -> 1 */ 50 if (!__builtin_islessgreater(a, b) != 0) rc |= 1 << 16; /* distinct -> 0 */ 51 if (!__builtin_islessgreater(nan, a) != 1) rc |= 1 << 17; /* NaN -> 1 */ 52 53 return rc == 0 ? 42 : 0; 54 }