File: nextafter.cl

package info (click to toggle)
intel-graphics-compiler 1.0.12504.6-1%2Bdeb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 83,912 kB
  • sloc: cpp: 910,147; lisp: 202,655; ansic: 15,197; python: 4,025; yacc: 2,241; lex: 1,570; pascal: 244; sh: 104; makefile: 25
file content (134 lines) | stat: -rw-r--r-- 4,015 bytes parent folder | download | duplicates (3)
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*========================== begin_copyright_notice ============================

Copyright (C) 2017-2021 Intel Corporation

SPDX-License-Identifier: MIT

============================= end_copyright_notice ===========================*/

#include "../include/BiF_Definitions.cl"
#include "../../Headers/spirv.h"

float SPIRV_OVERLOADABLE SPIRV_OCL_BUILTIN(nextafter, _f32_f32, )( float x, float y )
{
    const int maxneg = FLOAT_SIGN_MASK;

    // The way this algorithm works is as follows:
    //
    // - Treat the incoming float as an integer.  Note that the integer
    //   representation of floats are ordered if the integer is interpreted
    //   as being sign-magnitude encoded.
    // - Convert each incoming float from sign-magnitude to twos-complement
    //   encoded, so we can use usual comparison and math operations on them.
    // - Based on the twos complement encoding of the integer representation
    //   of each float, either add or subtract one from the twos-complement
    //   encoding of the integer representation of x.  This gives a twos-
    //   complement encoding of the result.
    // - Convert from the twos-complement encoding of the result back
    //   to a sign-magnitude encoding of the result, and interpret as
    //   a float.  We're done!  Well, almost.
    // - Handle two special-cases:
    //    - When the two floats are equal then there is no delta.
    //    - When either float is NaN the result is NaN.
    //
    // The code is written so it does not need flow control.

    int smix = as_int(x);
    int nx = maxneg - smix;
    int tcix = ( smix < 0 ) ? nx : smix;

    int smiy = as_int(y);
    int ny = maxneg - smiy;
    int tciy = ( smiy < 0 ) ? ny : smiy;

    int delta = ( tcix < tciy ) ? 1 : -1;

    int tcir = tcix + delta;
    int nr = maxneg - tcir;
    int smir = ( tcir < 0 ) ? nr : tcir;

    float result = as_float(smir);
    result = (tcix == tciy) ? y : result;

    {
        float n = SPIRV_OCL_BUILTIN(nan, _i32, )(0);
        int test = __intel_relaxed_isnan(x) | __intel_relaxed_isnan(y);
        result = test ? n : result;
    }

    return result;
}

GENERATE_SPIRV_OCL_VECTOR_FUNCTIONS_2ARGS( nextafter, float, float, f32 )

#if defined(cl_khr_fp64)

double SPIRV_OVERLOADABLE SPIRV_OCL_BUILTIN(nextafter, _f64_f64, )( double x, double y )
{
    const long maxneg = DOUBLE_SIGN_MASK;

    long smix = as_long(x);
    long nx = maxneg - smix;
    long tcix = ( smix < 0 ) ? nx : smix;

    long smiy = as_long(y);
    long ny = maxneg - smiy;
    long tciy = ( smiy < 0 ) ? ny : smiy;

    long delta = ( tcix < tciy ) ? 1 : -1;

    long tcir = tcix + delta;
    long nr = maxneg - tcir;
    long smir = ( tcir < 0 ) ? nr : tcir;

    double result = as_double(smir);
    result = (tcix == tciy) ? y : result;

    {
        double n = SPIRV_OCL_BUILTIN(nan, _i64, )(0);
        int test = SPIRV_BUILTIN(IsNan, _f64, )(x) | SPIRV_BUILTIN(IsNan, _f64, )(y);
        result = test ? n : result;
    }

    return result;
}

GENERATE_SPIRV_OCL_VECTOR_FUNCTIONS_2ARGS( nextafter, double, double, f64 )

#endif // defined(cl_khr_fp64)

#if defined(cl_khr_fp16)

half SPIRV_OVERLOADABLE SPIRV_OCL_BUILTIN(nextafter, _f16_f16, )( half x, half y )
{
    const short maxneg = HALF_SIGN_MASK;

    short smix = as_short(x);
    short nx = maxneg - smix;
    short tcix = ( smix < 0 ) ? nx : smix;

    short smiy = as_short(y);
    short ny = maxneg - smiy;
    short tciy = ( smiy < 0 ) ? ny : smiy;

    short delta = ( tcix < tciy ) ? 1 : -1;

    short tcir = tcix + delta;
    short nr = maxneg - tcir;
    short smir = ( tcir < 0 ) ? nr : tcir;

    half result = as_half(smir);
    result = (tcix == tciy) ? y : result;

    {
        half n = SPIRV_OCL_BUILTIN(nan, _i32, )(0);
        int test = SPIRV_BUILTIN(IsNan, _f16, )(x) | SPIRV_BUILTIN(IsNan, _f16, )(y);
        result = test ? n : result;
    }

    return result;
}

GENERATE_SPIRV_OCL_VECTOR_FUNCTIONS_2ARGS( nextafter, half, half, f16 )

#endif // defined(cl_khr_fp16)