summaryrefslogtreecommitdiffstats
path: root/tests/compute/ieee754-mixed-type-nan-comparisons.slang
blob: 28a90df38320ae336f14dfab5ad4d834bab5fe4a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
//TEST:COMPARE_COMPUTE(filecheck-buffer=CHECK): -shaderobj -output-using-type
//TEST:COMPARE_COMPUTE(filecheck-buffer=CHECK): -shaderobj -output-using-type -cuda

// Test IEEE 754 NaN comparison behavior with mixed int/float types
// Tests the type promotion logic across integer and floating-point categories
// Also tests both operand orders since implementation bugs could affect operand handling

static const float fNAN = 0.0f / 0.0f;
static const float fONE = 1.0f;
static const int iONE = 1;
static const int iZERO = 0;
static const uint uONE = 1u;

//TEST_INPUT:ubuffer(data=[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0], stride=4):out,name=outputBuffer
RWStructuredBuffer<uint> outputBuffer;

[numthreads(1, 1, 1)]
void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
{
    uint testIndex = 0;

    // Test int compared with float NaN - all should follow IEEE 754
    // CHECK: 0
    // CHECK: 1
    // CHECK: 0
    // CHECK: 0
    // CHECK: 0
    // CHECK: 0
    outputBuffer[testIndex++] = (iONE == fNAN) ? 1u : 0u;   // int 1 == float NaN -> false
    outputBuffer[testIndex++] = (iONE != fNAN) ? 1u : 0u;   // int 1 != float NaN -> true
    outputBuffer[testIndex++] = (iONE < fNAN) ? 1u : 0u;    // int 1 < float NaN -> false
    outputBuffer[testIndex++] = (iONE > fNAN) ? 1u : 0u;    // int 1 > float NaN -> false
    outputBuffer[testIndex++] = (iONE <= fNAN) ? 1u : 0u;   // int 1 <= float NaN -> false
    outputBuffer[testIndex++] = (iONE >= fNAN) ? 1u : 0u;   // int 1 >= float NaN -> false

    // Test float NaN compared with int - same results but different operand order
    // CHECK: 0
    // CHECK: 1
    // CHECK: 0
    // CHECK: 0
    // CHECK: 0
    // CHECK: 0
    outputBuffer[testIndex++] = (fNAN == iONE) ? 1u : 0u;   // float NaN == int 1 -> false
    outputBuffer[testIndex++] = (fNAN != iONE) ? 1u : 0u;   // float NaN != int 1 -> true
    outputBuffer[testIndex++] = (fNAN < iONE) ? 1u : 0u;    // float NaN < int 1 -> false
    outputBuffer[testIndex++] = (fNAN > iONE) ? 1u : 0u;    // float NaN > int 1 -> false
    outputBuffer[testIndex++] = (fNAN <= iONE) ? 1u : 0u;   // float NaN <= int 1 -> false
    outputBuffer[testIndex++] = (fNAN >= iONE) ? 1u : 0u;   // float NaN >= int 1 -> false

    // Test with different int values to ensure consistent behavior
    // CHECK: 0
    // CHECK: 1
    // CHECK: 0
    // CHECK: 1
    outputBuffer[testIndex++] = (iZERO == fNAN) ? 1u : 0u;  // int 0 == float NaN -> false
    outputBuffer[testIndex++] = (iZERO != fNAN) ? 1u : 0u;  // int 0 != float NaN -> true
    outputBuffer[testIndex++] = (fNAN == iZERO) ? 1u : 0u;  // float NaN == int 0 -> false
    outputBuffer[testIndex++] = (fNAN != iZERO) ? 1u : 0u;  // float NaN != int 0 -> true

    // Test unsigned int with float NaN
    // CHECK: 0
    // CHECK: 1
    // CHECK: 0
    // CHECK: 1
    outputBuffer[testIndex++] = (uONE == fNAN) ? 1u : 0u;   // uint 1 == float NaN -> false
    outputBuffer[testIndex++] = (uONE != fNAN) ? 1u : 0u;   // uint 1 != float NaN -> true
    outputBuffer[testIndex++] = (fNAN == uONE) ? 1u : 0u;   // float NaN == uint 1 -> false
    outputBuffer[testIndex++] = (fNAN != uONE) ? 1u : 0u;   // float NaN != uint 1 -> true

    // Test normal int vs float comparisons (no NaN) to ensure type promotion works
    // CHECK: 1
    // CHECK: 1
    // CHECK: 1
    // CHECK: 1
    outputBuffer[testIndex++] = (iONE == fONE) ? 1u : 0u;   // int 1 == float 1.0 -> true
    outputBuffer[testIndex++] = (fONE == iONE) ? 1u : 0u;   // float 1.0 == int 1 -> true
    outputBuffer[testIndex++] = (iZERO < fONE) ? 1u : 0u;   // int 0 < float 1.0 -> true
    outputBuffer[testIndex++] = (fONE > iZERO) ? 1u : 0u;   // float 1.0 > int 0 -> true
}