1 //===-- Utility class to manipulate fixed point numbers. --*- C++ -*-=========// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_LIBC_SRC___SUPPORT_FIXED_POINT_FX_REP_H 10 #define LLVM_LIBC_SRC___SUPPORT_FIXED_POINT_FX_REP_H 11 12 #include "include/llvm-libc-macros/stdfix-macros.h" 13 #include "src/__support/CPP/type_traits.h" 14 #include "src/__support/macros/attributes.h" // LIBC_INLINE, LIBC_INLINE_VAR 15 16 #include <stdint.h> 17 18 #ifdef LIBC_COMPILER_HAS_FIXED_POINT 19 20 namespace LIBC_NAMESPACE::fixed_point { 21 22 namespace internal { 23 24 template <int Bits> struct Storage { 25 static_assert(Bits > 0 && Bits <= 64, "Bits has to be between 1 and 64."); 26 using Type = typename cpp::conditional_t< 27 (Bits <= 8), uint8_t, 28 typename cpp::conditional_t< 29 (Bits <= 16 && Bits > 8), uint16_t, 30 typename cpp::conditional_t<(Bits <= 32 && Bits > 16), uint32_t, 31 uint64_t>>>; 32 }; 33 34 } // namespace internal 35 36 template <typename T> struct FXRep; 37 38 template <> struct FXRep<short fract> { 39 using Type = short _Fract; 40 41 LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1; 42 LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0; 43 LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SFRACT_FBIT; 44 LIBC_INLINE_VAR static constexpr int TOTAL_LEN = 45 SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN; 46 47 LIBC_INLINE static constexpr Type MIN() { return SFRACT_MIN; } 48 LIBC_INLINE static constexpr Type MAX() { return SFRACT_MAX; } 49 LIBC_INLINE static constexpr Type ZERO() { return 0.0HR; } 50 LIBC_INLINE static constexpr Type EPS() { return SFRACT_EPSILON; } 51 LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5HR; } 52 LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25HR; } 53 54 using StorageType = typename internal::Storage<TOTAL_LEN>::Type; 55 using CompType = cpp::make_signed_t<StorageType>; 56 }; 57 58 template <> struct FXRep<unsigned short fract> { 59 using Type = unsigned short fract; 60 61 LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0; 62 LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0; 63 LIBC_INLINE_VAR static constexpr int FRACTION_LEN = USFRACT_FBIT; 64 LIBC_INLINE_VAR static constexpr int TOTAL_LEN = 65 SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN; 66 67 LIBC_INLINE static constexpr Type MIN() { return USFRACT_MIN; } 68 LIBC_INLINE static constexpr Type MAX() { return USFRACT_MAX; } 69 LIBC_INLINE static constexpr Type ZERO() { return 0.0UHR; } 70 LIBC_INLINE static constexpr Type EPS() { return USFRACT_EPSILON; } 71 LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5UHR; } 72 LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25UHR; } 73 74 using StorageType = typename internal::Storage<TOTAL_LEN>::Type; 75 using CompType = cpp::make_unsigned_t<StorageType>; 76 }; 77 78 template <> struct FXRep<fract> { 79 using Type = fract; 80 81 LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1; 82 LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0; 83 LIBC_INLINE_VAR static constexpr int FRACTION_LEN = FRACT_FBIT; 84 LIBC_INLINE_VAR static constexpr int TOTAL_LEN = 85 SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN; 86 87 LIBC_INLINE static constexpr Type MIN() { return FRACT_MIN; } 88 LIBC_INLINE static constexpr Type MAX() { return FRACT_MAX; } 89 LIBC_INLINE static constexpr Type ZERO() { return 0.0R; } 90 LIBC_INLINE static constexpr Type EPS() { return FRACT_EPSILON; } 91 LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5R; } 92 LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25R; } 93 94 using StorageType = typename internal::Storage<TOTAL_LEN>::Type; 95 using CompType = cpp::make_signed_t<StorageType>; 96 }; 97 98 template <> struct FXRep<unsigned fract> { 99 using Type = unsigned fract; 100 101 LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0; 102 LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0; 103 LIBC_INLINE_VAR static constexpr int FRACTION_LEN = UFRACT_FBIT; 104 LIBC_INLINE_VAR static constexpr int TOTAL_LEN = 105 SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN; 106 107 LIBC_INLINE static constexpr Type MIN() { return UFRACT_MIN; } 108 LIBC_INLINE static constexpr Type MAX() { return UFRACT_MAX; } 109 LIBC_INLINE static constexpr Type ZERO() { return 0.0UR; } 110 LIBC_INLINE static constexpr Type EPS() { return UFRACT_EPSILON; } 111 LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5UR; } 112 LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25UR; } 113 114 using StorageType = typename internal::Storage<TOTAL_LEN>::Type; 115 using CompType = cpp::make_unsigned_t<StorageType>; 116 }; 117 118 template <> struct FXRep<long fract> { 119 using Type = long fract; 120 121 LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1; 122 LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0; 123 LIBC_INLINE_VAR static constexpr int FRACTION_LEN = LFRACT_FBIT; 124 LIBC_INLINE_VAR static constexpr int TOTAL_LEN = 125 SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN; 126 127 LIBC_INLINE static constexpr Type MIN() { return LFRACT_MIN; } 128 LIBC_INLINE static constexpr Type MAX() { return LFRACT_MAX; } 129 LIBC_INLINE static constexpr Type ZERO() { return 0.0LR; } 130 LIBC_INLINE static constexpr Type EPS() { return LFRACT_EPSILON; } 131 LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5LR; } 132 LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25LR; } 133 134 using StorageType = typename internal::Storage<TOTAL_LEN>::Type; 135 using CompType = cpp::make_signed_t<StorageType>; 136 }; 137 138 template <> struct FXRep<unsigned long fract> { 139 using Type = unsigned long fract; 140 141 LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0; 142 LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0; 143 LIBC_INLINE_VAR static constexpr int FRACTION_LEN = ULFRACT_FBIT; 144 LIBC_INLINE_VAR static constexpr int TOTAL_LEN = 145 SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN; 146 147 LIBC_INLINE static constexpr Type MIN() { return ULFRACT_MIN; } 148 LIBC_INLINE static constexpr Type MAX() { return ULFRACT_MAX; } 149 LIBC_INLINE static constexpr Type ZERO() { return 0.0ULR; } 150 LIBC_INLINE static constexpr Type EPS() { return ULFRACT_EPSILON; } 151 LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5ULR; } 152 LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25ULR; } 153 154 using StorageType = typename internal::Storage<TOTAL_LEN>::Type; 155 using CompType = cpp::make_unsigned_t<StorageType>; 156 }; 157 158 template <> struct FXRep<short accum> { 159 using Type = short accum; 160 161 LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1; 162 LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = SACCUM_IBIT; 163 LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SACCUM_FBIT; 164 LIBC_INLINE_VAR static constexpr int TOTAL_LEN = 165 SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN; 166 167 LIBC_INLINE static constexpr Type MIN() { return SACCUM_MIN; } 168 LIBC_INLINE static constexpr Type MAX() { return SACCUM_MAX; } 169 LIBC_INLINE static constexpr Type ZERO() { return 0.0HK; } 170 LIBC_INLINE static constexpr Type EPS() { return SACCUM_EPSILON; } 171 LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5HK; } 172 LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25HK; } 173 174 using StorageType = typename internal::Storage<TOTAL_LEN>::Type; 175 using CompType = cpp::make_signed_t<StorageType>; 176 }; 177 178 template <> struct FXRep<unsigned short accum> { 179 using Type = unsigned short accum; 180 181 LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0; 182 LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = USACCUM_IBIT; 183 LIBC_INLINE_VAR static constexpr int FRACTION_LEN = USACCUM_FBIT; 184 LIBC_INLINE_VAR static constexpr int TOTAL_LEN = 185 SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN; 186 187 LIBC_INLINE static constexpr Type MIN() { return USACCUM_MIN; } 188 LIBC_INLINE static constexpr Type MAX() { return USACCUM_MAX; } 189 LIBC_INLINE static constexpr Type ZERO() { return 0.0UHK; } 190 LIBC_INLINE static constexpr Type EPS() { return USACCUM_EPSILON; } 191 LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5UHK; } 192 LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25UHK; } 193 194 using StorageType = typename internal::Storage<TOTAL_LEN>::Type; 195 using CompType = cpp::make_unsigned_t<StorageType>; 196 }; 197 198 template <> struct FXRep<accum> { 199 using Type = accum; 200 201 LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1; 202 LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = ACCUM_IBIT; 203 LIBC_INLINE_VAR static constexpr int FRACTION_LEN = ACCUM_FBIT; 204 LIBC_INLINE_VAR static constexpr int TOTAL_LEN = 205 SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN; 206 207 LIBC_INLINE static constexpr Type MIN() { return ACCUM_MIN; } 208 LIBC_INLINE static constexpr Type MAX() { return ACCUM_MAX; } 209 LIBC_INLINE static constexpr Type ZERO() { return 0.0K; } 210 LIBC_INLINE static constexpr Type EPS() { return ACCUM_EPSILON; } 211 LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5K; } 212 LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25K; } 213 214 using StorageType = typename internal::Storage<TOTAL_LEN>::Type; 215 using CompType = cpp::make_signed_t<StorageType>; 216 }; 217 218 template <> struct FXRep<unsigned accum> { 219 using Type = unsigned accum; 220 221 LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0; 222 LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = UACCUM_IBIT; 223 LIBC_INLINE_VAR static constexpr int FRACTION_LEN = UACCUM_FBIT; 224 LIBC_INLINE_VAR static constexpr int TOTAL_LEN = 225 SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN; 226 227 LIBC_INLINE static constexpr Type MIN() { return UACCUM_MIN; } 228 LIBC_INLINE static constexpr Type MAX() { return UACCUM_MAX; } 229 LIBC_INLINE static constexpr Type ZERO() { return 0.0UK; } 230 LIBC_INLINE static constexpr Type EPS() { return UACCUM_EPSILON; } 231 LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5UK; } 232 LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25UK; } 233 234 using StorageType = typename internal::Storage<TOTAL_LEN>::Type; 235 using CompType = cpp::make_unsigned_t<StorageType>; 236 }; 237 238 template <> struct FXRep<long accum> { 239 using Type = long accum; 240 241 LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1; 242 LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = LACCUM_IBIT; 243 LIBC_INLINE_VAR static constexpr int FRACTION_LEN = LACCUM_FBIT; 244 LIBC_INLINE_VAR static constexpr int TOTAL_LEN = 245 SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN; 246 247 LIBC_INLINE static constexpr Type MIN() { return LACCUM_MIN; } 248 LIBC_INLINE static constexpr Type MAX() { return LACCUM_MAX; } 249 LIBC_INLINE static constexpr Type ZERO() { return 0.0LK; } 250 LIBC_INLINE static constexpr Type EPS() { return LACCUM_EPSILON; } 251 LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5LK; } 252 LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25LK; } 253 254 using StorageType = typename internal::Storage<TOTAL_LEN>::Type; 255 using CompType = cpp::make_signed_t<StorageType>; 256 }; 257 258 template <> struct FXRep<unsigned long accum> { 259 using Type = unsigned long accum; 260 261 LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0; 262 LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = ULACCUM_IBIT; 263 LIBC_INLINE_VAR static constexpr int FRACTION_LEN = ULACCUM_FBIT; 264 LIBC_INLINE_VAR static constexpr int TOTAL_LEN = 265 SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN; 266 267 LIBC_INLINE static constexpr Type MIN() { return ULACCUM_MIN; } 268 LIBC_INLINE static constexpr Type MAX() { return ULACCUM_MAX; } 269 LIBC_INLINE static constexpr Type ZERO() { return 0.0ULK; } 270 LIBC_INLINE static constexpr Type EPS() { return ULACCUM_EPSILON; } 271 LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5ULK; } 272 LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25ULK; } 273 274 using StorageType = typename internal::Storage<TOTAL_LEN>::Type; 275 using CompType = cpp::make_unsigned_t<StorageType>; 276 }; 277 278 template <> struct FXRep<short sat fract> : FXRep<short fract> {}; 279 template <> struct FXRep<sat fract> : FXRep<fract> {}; 280 template <> struct FXRep<long sat fract> : FXRep<long fract> {}; 281 template <> 282 struct FXRep<unsigned short sat fract> : FXRep<unsigned short fract> {}; 283 template <> struct FXRep<unsigned sat fract> : FXRep<unsigned fract> {}; 284 template <> 285 struct FXRep<unsigned long sat fract> : FXRep<unsigned long fract> {}; 286 287 template <> struct FXRep<short sat accum> : FXRep<short accum> {}; 288 template <> struct FXRep<sat accum> : FXRep<accum> {}; 289 template <> struct FXRep<long sat accum> : FXRep<long accum> {}; 290 template <> 291 struct FXRep<unsigned short sat accum> : FXRep<unsigned short accum> {}; 292 template <> struct FXRep<unsigned sat accum> : FXRep<unsigned accum> {}; 293 template <> 294 struct FXRep<unsigned long sat accum> : FXRep<unsigned long accum> {}; 295 296 } // namespace LIBC_NAMESPACE::fixed_point 297 298 #endif // LIBC_COMPILER_HAS_FIXED_POINT 299 300 #endif // LLVM_LIBC_SRC___SUPPORT_FIXED_POINT_FX_REP_H 301