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