/usr/include/oclgrind/half.h is in liboclgrind-dev 15.5-3build1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | // half.h (Oclgrind)
// Copyright (c) 2013-2015, James Price and Simon McIntosh-Smith,
// University of Bristol. All rights reserved.
//
// This program is provided under a three-clause BSD license. For full
// license terms please see the LICENSE file distributed with this
// source code.
#include "common.h"
static float halfToFloat(uint16_t half)
{
uint16_t h_sign, h_exponent, h_mantissa;
uint32_t f_sign, f_exponent, f_mantissa;
h_sign = half & 0x8000; // 1000 0000 0000 0000
h_exponent = half & 0x7C00; // 0111 1100 0000 0000
h_mantissa = half & 0x03FF; // 0000 0011 1111 1111
f_sign = ((uint32_t)h_sign) << 16;
if (h_exponent == 0)
{
if (h_mantissa == 0)
{
// Zero
f_exponent = 0;
f_mantissa = 0;
}
else
{
// Denorm - convert to normalized float
int e = -1;
do
{
e++;
h_mantissa <<= 1;
}
while((h_mantissa & 0x0400) == 0);
f_exponent = (-15 + 127 - e) << 23;
f_mantissa = ((uint32_t)(h_mantissa & 0x03FF)) << 13;
}
}
else if (h_exponent == 0x7C00)
{
// Inf or NaN
f_exponent = 0xFF << 23;
f_mantissa = h_mantissa;
}
else
{
// Normalized
f_exponent = (((int32_t)(h_exponent >> 10)) - 15 + 127) << 23;
f_mantissa = ((uint32_t)h_mantissa) << 13;
}
uint32_t result = f_sign | f_exponent | f_mantissa;
return *(float*)&result;
}
enum HalfRoundMode
{
// Towards negative infinity
Half_RTN,
// Towards zero
Half_RTZ,
// Towards positive infinity
Half_RTP,
// Towards nearest even
Half_RTE
};
static uint16_t floatToHalf(float sp, HalfRoundMode round = Half_RTZ)
{
uint16_t h_sign, h_exponent, h_mantissa;
uint32_t f_sign, f_exponent, f_mantissa;
union
{
float f;
uint32_t ui;
} FtoUI;
FtoUI.f = sp;
uint32_t f = FtoUI.ui;
f_sign = f & 0x80000000; // 1000 0000 0000 0000 0000 0000 0000 0000
f_exponent = f & 0x7F800000; // 0111 1111 1000 0000 0000 0000 0000 0000
f_mantissa = f & 0x007FFFFF; // 0000 0000 0111 1111 1111 1111 1111 1111
h_sign = f_sign >> 16;
if (f_exponent == 0)
{
// Zero
h_exponent = 0;
h_mantissa = 0;
}
else if (f_exponent == 0x7F800000)
{
// Inf or NaN
h_exponent = 0x7C00;
h_mantissa = f_mantissa;
}
else
{
int e = (((int32_t)(f_exponent >> 23)) - 127 + 15);
if (e >= 0x1F)
{
// Value will overflow
h_exponent = 0x7C00;
h_mantissa = 0;
}
else if (e <= 0)
{
// Value will underflow
h_exponent = 0;
if (14 - e > 24)
{
// Too small - flush to zero
h_mantissa = 0;
}
else
{
// Convert to denorm
f_mantissa |= 0x800000;
h_mantissa = (f_mantissa >> (14-e));
if ((f_mantissa >> (13 - e)) & 0x1)
{
h_mantissa += 0x1;
}
}
}
else
{
// Normalized
h_exponent = e << 10;
h_mantissa = f_mantissa >> 13;
// The current f_mantissa is done in RTZ
if (round == Half_RTE && (f & 0x00001000) != 0)
{
if ((f & 0x00002FFF) != 0)
h_mantissa += 1;
}
else if (round == Half_RTP)
{
FtoUI.ui &= 0xFFFFE000;
if (FtoUI.f < sp)
h_mantissa += 1;
}
else if (round == Half_RTN)
{
FtoUI.ui &= 0xFFFFE000;
if (sp < FtoUI.f)
h_mantissa += 1;
}
}
}
return h_sign + h_exponent + h_mantissa;
}
|