HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
fixed.hpp
1// Copyright Take Vos 2019, 2021.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "safe_int.hpp"
8#include "../utility/utility.hpp"
9#include "../macros.hpp"
10#include <type_traits>
11#include <limits>
12#include <concepts>
13
14
15
16namespace hi::inline v1 {
17
18template<typename T, int M>
19struct fixed {
20 using value_type = T;
21 constexpr static int multiplier = M;
22
23 T value;
24
25 fixed() = default;
26 ~fixed() = default;
27 fixed(fixed const &) = default;
28 fixed &operator=(fixed const &) = default;
29 fixed(fixed &&) = default;
30 fixed &operator=(fixed &&) = default;
31
32 explicit constexpr fixed(std::floating_point auto other) noexcept : value(static_cast<T>(other * M))
33 {
34 hi_assert(other >= (std::numeric_limits<T>::min() / M) && other <= (std::numeric_limits<T>::max() / M));
35 }
36
37 explicit constexpr fixed(std::integral auto other) noexcept : value(static_cast<T>(other) * M)
38 {
39 hi_assert(other >= (std::numeric_limits<T>::min() / M) && other <= (std::numeric_limits<T>::max() / M));
40 }
41
42 explicit fixed(std::string const &other) : fixed(stod(other)) {}
43
44 constexpr fixed &operator=(std::floating_point auto other) noexcept
45 {
46 value = static_cast<T>(other * M);
47 hi_assert(other >= (std::numeric_limits<T>::min() / M) && other <= (std::numeric_limits<T>::max() / M));
48 return *this;
49 }
50
51 constexpr fixed &operator=(std::integral auto other) noexcept
52 {
53 value = static_cast<T>(other) * M;
54 hi_assert(other >= (std::numeric_limits<T>::min() / M) && other <= (std::numeric_limits<T>::max() / M));
55 return *this;
56 }
57
58 fixed &operator=(std::string const &other)
59 {
60 value = static_cast<T>(stod(other) * M);
61 hi_assert(other >= (std::numeric_limits<T>::min() / M) && other <= (std::numeric_limits<T>::max() / M));
62 return *this;
63 }
64
65 template<std::floating_point O>
66 explicit operator O() const noexcept
67 {
68 return static_cast<O>(value) / M;
69 }
70
71 template<std::integral O>
72 explicit operator O() const noexcept
73 {
74 return static_cast<O>(value / M);
75 }
76
77 std::string string() const noexcept
78 {
79 return std::format("{}", static_cast<double>(value) / M);
80 }
81
82 static fixed from_raw_value(T value) noexcept
83 {
84 fixed r;
85 r.value = value;
86 return r;
87 }
88
89 [[nodiscard]] constexpr friend bool operator==(fixed const &lhs, fixed const &rhs) noexcept
90 {
91 return lhs.value == rhs.value;
92 }
93
94 [[nodiscard]] constexpr friend auto operator<=>(fixed const &lhs, fixed const &rhs) noexcept
95 {
96 return lhs.value <=> rhs.value;
97 }
98
99 [[nodiscard]] constexpr friend fixed operator+(fixed const &lhs, fixed const &rhs) noexcept
100 {
101 return fixed<T, M>::from_raw_value(lhs.value + rhs.value);
102 }
103
104 [[nodiscard]] constexpr friend fixed operator-(fixed const &lhs, fixed const &rhs) noexcept
105 {
106 return fixed<T, M>::from_raw_value(lhs.value - rhs.value);
107 }
108
109 [[nodiscard]] friend std::string to_string(fixed const v)
110 {
111 return v.string();
112 }
113
114 friend std::ostream &operator<<(std::ostream &lhs, fixed const &rhs)
115 {
116 return lhs << rhs.string();
117 }
118};
119
120using money = fixed<safe_int<int64_t>, 100>;
121
122} // namespace hi::inline v1
DOXYGEN BUG.
Definition algorithm.hpp:16
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:377
Definition fixed.hpp:19