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/module.hpp"
9#include <type_traits>
10#include <limits>
11#include <concepts>
12
13namespace hi::inline v1 {
14
15template<typename T, int M>
16struct fixed {
17 using value_type = T;
18 static constexpr int multiplier = M;
19
20 T value;
21
22 fixed() = default;
23 ~fixed() = default;
24 fixed(fixed const &) = default;
25 fixed &operator=(fixed const &) = default;
26 fixed(fixed &&) = default;
27 fixed &operator=(fixed &&) = default;
28
29 explicit constexpr fixed(std::floating_point auto other) noexcept : value(static_cast<T>(other * M))
30 {
31 hi_assert(other >= (std::numeric_limits<T>::min() / M) && other <= (std::numeric_limits<T>::max() / M));
32 }
33
34 explicit constexpr fixed(std::integral auto other) noexcept : value(static_cast<T>(other) * M)
35 {
36 hi_assert(other >= (std::numeric_limits<T>::min() / M) && other <= (std::numeric_limits<T>::max() / M));
37 }
38
39 explicit fixed(std::string const &other) : fixed(stod(other)) {}
40
41 constexpr fixed &operator=(std::floating_point auto other) noexcept
42 {
43 value = static_cast<T>(other * M);
44 hi_assert(other >= (std::numeric_limits<T>::min() / M) && other <= (std::numeric_limits<T>::max() / M));
45 return *this;
46 }
47
48 constexpr fixed &operator=(std::integral auto other) noexcept
49 {
50 value = static_cast<T>(other) * M;
51 hi_assert(other >= (std::numeric_limits<T>::min() / M) && other <= (std::numeric_limits<T>::max() / M));
52 return *this;
53 }
54
55 fixed &operator=(std::string const &other)
56 {
57 value = static_cast<T>(stod(other) * M);
58 hi_assert(other >= (std::numeric_limits<T>::min() / M) && other <= (std::numeric_limits<T>::max() / M));
59 return *this;
60 }
61
62 template<std::floating_point O>
63 explicit operator O() const noexcept
64 {
65 return static_cast<O>(value) / M;
66 }
67
68 template<std::integral O>
69 explicit operator O() const noexcept
70 {
71 return static_cast<O>(value / M);
72 }
73
74 std::string string() const noexcept
75 {
76 return std::format("{}", static_cast<double>(value) / M);
77 }
78
79 static fixed from_raw_value(T value) noexcept
80 {
81 fixed r;
82 r.value = value;
83 return r;
84 }
85
86 [[nodiscard]] constexpr friend bool operator==(fixed const &lhs, fixed const &rhs) noexcept
87 {
88 return lhs.value == rhs.value;
89 }
90
91 [[nodiscard]] constexpr friend auto operator<=>(fixed const &lhs, fixed const &rhs) noexcept
92 {
93 return lhs.value <=> rhs.value;
94 }
95
96 [[nodiscard]] constexpr friend fixed operator+(fixed const &lhs, fixed const &rhs) noexcept
97 {
98 return fixed<T, M>::from_raw_value(lhs.value + rhs.value);
99 }
100
101 [[nodiscard]] constexpr friend fixed operator-(fixed const &lhs, fixed const &rhs) noexcept
102 {
103 return fixed<T, M>::from_raw_value(lhs.value - rhs.value);
104 }
105
106 [[nodiscard]] friend std::string to_string(fixed const v)
107 {
108 return v.string();
109 }
110
111 friend std::ostream &operator<<(std::ostream &lhs, fixed const &rhs)
112 {
113 return lhs << rhs.string();
114 }
115};
116
117using money = fixed<safe_int<int64_t>, 100>;
118
119} // namespace hi::inline v1
#define hi_assert(expression,...)
Assert if expression is true.
Definition assert.hpp:199
DOXYGEN BUG.
Definition algorithm.hpp:13
Definition fixed.hpp:16