ADTF Device Toolbox SDK
Loading...
Searching...
No Matches
pointcloud_half_float.h
1/*
2Copied from https://stackoverflow.com/a/3542975
3
4This is free and unencumbered software released into the public domain.
5
6Anyone is free to copy, modify, publish, use, compile, sell, or
7distribute this software, either in source code form or as a compiled
8binary, for any purpose, commercial or non-commercial, and by any
9means.
10
11In jurisdictions that recognize copyright laws, the author or authors
12of this software dedicate any and all copyright interest in the
13software to the public domain. We make this dedication for the benefit
14of the public at large and to the detriment of our heirs and
15successors. We intend this dedication to be an overt act of
16relinquishment in perpetuity of all present and future rights to this
17software under copyright law.
18
19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25OTHER DEALINGS IN THE SOFTWARE.
26
27For more information, please refer to <https://unlicense.org>
28*/
29
30#pragma once
31
32/*
33 Taken from car_communication
34*/
35
36#ifdef _MSC_VER
37#pragma warning(disable : 4804)
38#endif
39
40#include <cstdint> // uint32_t, uint64_t, etc.
41#include <cstring> // memcpy
42#include <climits> // CHAR_BIT
43#include <limits> // numeric_limits
44#include <utility> // is_integral_v, is_floating_point_v, forward
45
46namespace adtf::devicetb::sdk::half_float
47{
48
49namespace detail
50{
51
52template<class to, class from>
53std::enable_if_t<sizeof(to) == sizeof(from) && std::is_trivially_copyable_v<from> && std::is_trivially_copyable_v<to>,
54 to>
55 inline static bit_cast(const from& src) noexcept
56{
57 static_assert(std::is_trivially_constructible_v<to>, "This implementation additionally requires "
58 "destination type to be trivially constructible");
59
60 to dst;
61 std::memcpy(&dst, &src, sizeof(to));
62 return dst;
63}
64
65}
66
67template< typename T > struct native_float_bits;
68template<> struct native_float_bits< float >{ using type = std::uint32_t; };
69template<> struct native_float_bits< double >{ using type = std::uint64_t; };
70template< typename T > using native_float_bits_t = typename native_float_bits< T >::type;
71
72static_assert( sizeof( float ) == sizeof( native_float_bits_t< float > ) );
73static_assert( sizeof( double ) == sizeof( native_float_bits_t< double > ) );
74
75template< typename T, int SIG_BITS, int EXP_BITS >
77 using raw_type = T;
78
79 static constexpr int sig_bits = SIG_BITS;
80 static constexpr int exp_bits = EXP_BITS;
81 static constexpr int bits = sig_bits + exp_bits + 1;
82
83 static_assert( std::is_integral_v< raw_type > );
84 static_assert( sig_bits >= 0 );
85 static_assert( exp_bits >= 0 );
86 static_assert( bits <= sizeof( raw_type ) * CHAR_BIT );
87
88 static constexpr int exp_max = ( 1 << exp_bits ) - 1;
89 static constexpr int exp_bias = exp_max >> 1;
90
91 static constexpr raw_type sign = raw_type( 1 ) << ( bits - 1 );
92 static constexpr raw_type inf = raw_type( exp_max ) << sig_bits;
93 static constexpr raw_type qnan = inf | ( inf >> 1 );
94
95 static constexpr auto abs( raw_type v ) { return raw_type( v & ( sign - 1 ) ); }
96 static constexpr bool is_nan( raw_type v ) { return abs( v ) > inf; }
97 static constexpr bool is_inf( raw_type v ) { return abs( v ) == inf; }
98 static constexpr bool is_zero( raw_type v ) { return abs( v ) == 0; }
99};
100using raw_flt16_type_info = raw_float_type_info< std::uint16_t, 10, 5 >;
101using raw_flt32_type_info = raw_float_type_info< std::uint32_t, 23, 8 >;
102using raw_flt64_type_info = raw_float_type_info< std::uint64_t, 52, 11 >;
103//using raw_flt128_type_info = raw_float_type_info< uint128_t, 112, 15 >;
104
105template< typename T, int SIG_BITS = std::numeric_limits< T >::digits - 1,
106 int EXP_BITS = sizeof( T ) * CHAR_BIT - SIG_BITS - 1 >
108: raw_float_type_info< native_float_bits_t< T >, SIG_BITS, EXP_BITS > {
109 using flt_type = T;
110 static_assert( std::is_floating_point_v< flt_type > );
111};
112
113template< typename E >
115{
116 using enc = E;
117 using enc_type = typename enc::raw_type;
118
119 template< bool DO_ROUNDING, typename F >
120 static auto encode( F value )
121 {
122 using flt = float_type_info< F >;
123 using raw_type = typename flt::raw_type;
124 static constexpr auto sig_diff = flt::sig_bits - enc::sig_bits;
125 static constexpr auto bit_diff = flt::bits - enc::bits;
126 static constexpr auto do_rounding = DO_ROUNDING && sig_diff > 0;
127 static constexpr auto bias_mul = raw_type( enc::exp_bias ) << flt::sig_bits;
128 if constexpr( !do_rounding ) { // fix exp bias
129 // when not rounding, fix exp first to avoid mixing float and binary ops
130 value *= detail::bit_cast< F >( bias_mul );
131 }
132 auto bits = detail::bit_cast< raw_type >( value );
133 auto sign = bits & flt::sign; // save sign
134 bits ^= sign; // clear sign
135 auto is_nan = flt::inf < bits; // compare before rounding!!
136 if constexpr( do_rounding ) {
137 static constexpr auto min_norm = raw_type( flt::exp_bias - enc::exp_bias + 1 ) << flt::sig_bits;
138 static constexpr auto sub_rnd = enc::exp_bias < sig_diff
139 ? raw_type( 1 ) << ( flt::sig_bits - 1 + enc::exp_bias - sig_diff )
140 : raw_type( enc::exp_bias - sig_diff ) << flt::sig_bits;
141 static constexpr auto sub_mul = raw_type( flt::exp_bias + sig_diff ) << flt::sig_bits;
142 bool is_sub = bits < min_norm;
143 auto norm = detail::bit_cast< F >( bits );
144 auto subn = norm;
145 subn *= detail::bit_cast< F >( sub_rnd ); // round subnormals
146 subn *= detail::bit_cast< F >( sub_mul ); // correct subnormal exp
147 norm *= detail::bit_cast< F >( bias_mul ); // fix exp bias
148 bits = detail::bit_cast< raw_type >( norm );
149 bits += ( bits >> sig_diff ) & 1; // add tie breaking bias
150 bits += ( raw_type( 1 ) << ( sig_diff - 1 ) ) - 1; // round up to half
151 //if( is_sub ) bits = detail::bit_cast< raw_type >( subn );
152 bits ^= -is_sub & ( detail::bit_cast< raw_type >( subn ) ^ bits );
153 }
154 bits >>= sig_diff; // truncate
155 //if( enc::inf < bits ) bits = enc::inf; // fix overflow
156 bits ^= -( enc::inf < bits ) & ( enc::inf ^ bits );
157 //if( is_nan ) bits = enc::qnan;
158 bits ^= -is_nan & ( enc::qnan ^ bits );
159 bits |= sign >> bit_diff; // restore sign
160 return enc_type( bits );
161 }
162
163 template< typename F >
164 static F decode( enc_type value )
165 {
166 using flt = float_type_info< F >;
167 using raw_type = typename flt::raw_type;
168 static constexpr auto sig_diff = flt::sig_bits - enc::sig_bits;
169 static constexpr auto bit_diff = flt::bits - enc::bits;
170 static constexpr auto bias_mul = raw_type( 2 * flt::exp_bias - enc::exp_bias ) << flt::sig_bits;
171 raw_type bits = value;
172 auto sign = bits & enc::sign; // save sign
173 bits ^= sign; // clear sign
174 auto is_norm = bits < enc::inf;
175 bits = ( sign << bit_diff ) | ( bits << sig_diff );
176 auto val = detail::bit_cast< F >( bits ) * detail::bit_cast< F >( bias_mul );
177 bits = detail::bit_cast< raw_type >( val );
178 //if( !is_norm ) bits |= flt::inf;
179 bits |= -!is_norm & flt::inf;
180 return detail::bit_cast< F >( bits );
181 }
182};
183
184using flt16_encoder = raw_float_encoder< raw_flt16_type_info >;
185
186template< typename F >
187auto quick_encode_flt16( F && value )
188{ return flt16_encoder::encode< false >( std::forward< F >( value ) ); }
189
190template< typename F >
191auto encode_flt16( F && value )
192{ return flt16_encoder::encode< true >( std::forward< F >( value ) ); }
193
194template< typename F = float, typename X >
195auto decode_flt16( X && value )
196{ return flt16_encoder::decode< F >( std::forward< X >( value ) ); }
197
198} // namespace half_float
199#ifdef _MSC_VER
200#pragma warning(default : 4804)
201#endif
Definition pointcloud_half_float.h:108
Definition pointcloud_half_float.h:67
Definition pointcloud_half_float.h:115
Definition pointcloud_half_float.h:76