Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RFloat16.hxx
Go to the documentation of this file.
1// @(#)root/base
2
3/*************************************************************************
4 * Copyright (C) 1995-2023, Rene Brun and Fons Rademakers. *
5 * All rights reserved. *
6 * *
7 * For the licensing terms see $ROOTSYS/LICENSE. *
8 * For the list of contributors see $ROOTSYS/README/CREDITS. *
9 *************************************************************************/
10
11#include <cstdint>
12#include <cstring>
13
14#ifndef ROOT_RFloat16
15#define ROOT_RFloat16
16
17/**
18 * Conversion functions between full- and half-precision floats. The code used here is taken (with some modifications)
19 * from the `half` C++ library (https://half.sourceforge.net/index.html), distributed under the MIT license.
20 *
21 * Original license:
22 *
23 * The MIT License
24 *
25 * Copyright (c) 2012-2021 Christian Rau
26 *
27 * Permission is hereby granted, free of charge, to any person obtaining a copy
28 * of this software and associated documentation files (the "Software"), to deal
29 * in the Software without restriction, including without limitation the rights
30 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
31 * copies of the Software, and to permit persons to whom the Software is
32 * furnished to do so, subject to the following conditions:
33 *
34 * The above copyright notice and this permission notice shall be included in
35 * all copies or substantial portions of the Software.
36 *
37 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
38 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
39 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
40 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
41 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
42 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
43 * THE SOFTWARE.
44 */
45
46#ifndef HALF_ENABLE_F16C_INTRINSICS
47/// Enable F16C intruction set intrinsics.
48/// Defining this to 1 enables the use of [F16C compiler intrinsics](https://en.wikipedia.org/wiki/F16C) for converting
49/// between half-precision and single-precision values which may result in improved performance. This will not perform
50/// additional checks for support of the F16C instruction set, so an appropriate target platform is required when
51/// enabling this feature.
52///
53/// Unless predefined it will be enabled automatically when the `__F16C__` symbol is defined, which some compilers do on
54/// supporting platforms.
55#define HALF_ENABLE_F16C_INTRINSICS __F16C__
56#endif
57#if HALF_ENABLE_F16C_INTRINSICS
58#include <immintrin.h>
59#endif
60
61namespace ROOT {
62namespace Experimental {
63namespace Internal {
64////////////////////////////////////////////////////////////////////////////////
65/// \brief Get the half-precision overflow.
66///
67/// \param[in] value Half-precision value with sign bit only
68///
69/// \return Rounded overflowing half-precision value
70constexpr std::uint16_t GetOverflowedValue(std::uint16_t value = 0)
71{
72 return (value | 0x7C00);
73}
74
75////////////////////////////////////////////////////////////////////////////////
76/// \brief Round the given half-precision number to the nearest representable value.
77///
78/// \param[in] value The finite half-precision number to round
79/// \param[in] guardBit The most significant discarded bit
80/// \param[in] stickyBit Logical OR of all but the most significant discarded bits
81///
82/// \return The nearest-rounded half-precision value
83constexpr std::uint16_t GetRoundedValue(std::uint16_t value, int guardBit, int stickyBit)
84{
85 return (value + (guardBit & (stickyBit | value)));
86}
87
88////////////////////////////////////////////////////////////////////////////////
89/// \brief Convert an IEEE single-precision float to half-precision.
90///
91/// Credit for this goes to [Jeroen van der Zijp](http://fox-toolkit.org/ftp/fasthalffloatconversion.pdf).
92///
93/// \param[in] value The single-precision value to convert
94///
95/// \return The converted half-precision value
96inline std::uint16_t FloatToHalf(float value)
97{
98#if HALF_ENABLE_F16C_INTRINSICS
99 return _mm_cvtsi128_si32(_mm_cvtps_ph(_mm_set_ss(value), _MM_FROUND_TO_NEAREST_INT));
100#else
101 std::uint32_t fbits;
102 std::memcpy(&fbits, &value, sizeof(float));
103
104 std::uint16_t sign = (fbits >> 16) & 0x8000;
105 fbits &= 0x7FFFFFFF;
106 if (fbits >= 0x7F800000)
107 return sign | 0x7C00 | ((fbits > 0x7F800000) ? (0x200 | ((fbits >> 13) & 0x3FF)) : 0);
108 if (fbits >= 0x47800000)
109 return GetOverflowedValue(sign);
110 if (fbits >= 0x38800000)
111 return GetRoundedValue(sign | (((fbits >> 23) - 112) << 10) | ((fbits >> 13) & 0x3FF), (fbits >> 12) & 1,
112 (fbits & 0xFFF) != 0);
113 if (fbits >= 0x33000000) {
114 int i = 125 - (fbits >> 23);
115 fbits = (fbits & 0x7FFFFF) | 0x800000;
116 return GetRoundedValue(sign | (fbits >> (i + 1)), (fbits >> i) & 1,
117 (fbits & ((static_cast<std::uint32_t>(1) << i) - 1)) != 0);
118 }
119
120 return sign;
121#endif
122}
123
124////////////////////////////////////////////////////////////////////////////////
125/// \brief Convert an IEEE half-precision float to single-precision.
126///
127/// Credit for this goes to [Jeroen van der Zijp](http://fox-toolkit.org/ftp/fasthalffloatconversion.pdf).
128///
129/// \param[in] value The half-precision value to convert
130///
131/// \return The converted single-precision value
132inline float HalfToFloat(std::uint16_t value)
133{
134#if HALF_ENABLE_F16C_INTRINSICS
135 return _mm_cvtss_f32(_mm_cvtph_ps(_mm_cvtsi32_si128(value)));
136#else
137 std::uint32_t fbits = static_cast<std::uint32_t>(value & 0x8000) << 16;
138 int abs = value & 0x7FFF;
139 if (abs) {
140 fbits |= 0x38000000 << static_cast<unsigned>(abs >= 0x7C00);
141 for (; abs < 0x400; abs <<= 1, fbits -= 0x800000)
142 ;
143 fbits += static_cast<std::uint32_t>(abs) << 13;
144 }
145 float out;
146 std::memcpy(&out, &fbits, sizeof(float));
147 return out;
148#endif
149}
150} // namespace Internal
151} // namespace Experimental
152} // namespace ROOT
153
154#endif // ROOT_RFloat16
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
constexpr std::uint16_t GetRoundedValue(std::uint16_t value, int guardBit, int stickyBit)
Round the given half-precision number to the nearest representable value.
Definition RFloat16.hxx:83
constexpr std::uint16_t GetOverflowedValue(std::uint16_t value=0)
Get the half-precision overflow.
Definition RFloat16.hxx:70
std::uint16_t FloatToHalf(float value)
Convert an IEEE single-precision float to half-precision.
Definition RFloat16.hxx:96
float HalfToFloat(std::uint16_t value)
Convert an IEEE half-precision float to single-precision.
Definition RFloat16.hxx:132
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...