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