libfxd 0.2.dev
A fixed-point library for C++.
Loading...
Searching...
No Matches
round-mul.hpp
Go to the documentation of this file.
1/*
2 * libfxd - a fixed-point library for C++
3 *
4 * Copyright 2023 Daniel K. O.
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8#ifndef LIBFXD_ROUND_MUL_HPP
9#define LIBFXD_ROUND_MUL_HPP
10
11#include "concepts.hpp"
12
13#include "detail/add.hpp"
14#include "detail/raw-mul.hpp"
15#include "detail/shift.hpp"
16
17
18namespace fxd {
19
20 namespace zero {
21
23 template<fixed_point Fxd>
24 constexpr
25 Fxd
26 mul(Fxd a,
27 Fxd b)
28 noexcept
29 {
30 constexpr int w = detail::type_width<typename Fxd::raw_type>;
31
32 // offset used for shifting left
33 constexpr int offset = w - Fxd::frac_bits;
34
35 const auto raw_a = a.raw_value;
36 const auto raw_b = b.raw_value;
37 const auto c = detail::raw::mul<Fxd::bits>(raw_a, raw_b);
38
39 if constexpr (Fxd::frac_bits <= 0) {
40
41 // no lower bits will be lost, no rounding is needed
42 const auto d = detail::shl(c, offset);
43 return Fxd::from_raw(detail::high(d));
44
45 } else {
46
47 // will lose lower bits
48 if (detail::is_negative(c)) {
49
50 // negative numbers need a bias to zero to round up
51 const auto bias = detail::make_bias_for(Fxd::frac_bits, c);
52 const auto biased_c = detail::add(c, bias);
53 const auto d = detail::shl(biased_c, offset);
54 return Fxd::from_raw(detail::high(d));
55
56 } else {
57
58 const auto d = detail::shl(c, offset);
59 return Fxd::from_raw(detail::high(d));
60
61 }
62
63 }
64
65 }
66
67 } // namespace zero
68
69
70
71 namespace up {
72
74 template<fixed_point Fxd>
75 constexpr
76 Fxd
77 mul(Fxd a,
78 Fxd b)
79 noexcept
80 {
81 constexpr int w = detail::type_width<typename Fxd::raw_type>;
82
83 // offset used for shifting left
84 constexpr int offset = w - Fxd::frac_bits;
85
86 const auto raw_a = a.raw_value;
87 const auto raw_b = b.raw_value;
88 const auto c = detail::raw::mul<Fxd::bits>(raw_a, raw_b);
89
90 if constexpr (Fxd::frac_bits <= 0) {
91
92 const auto d = detail::shl(c, offset);
93 return Fxd::from_raw(detail::high(d));
94
95 } else {
96
97 const auto bias = detail::make_bias_for(Fxd::frac_bits, c);
98 const auto biased_c = detail::add(c, bias);
99 const auto d = detail::shl(biased_c, offset);
100
101 return Fxd::from_raw(detail::high(d));
102
103 }
104
105 }
106
107 } // namespace up
108
109
110
111 namespace down {
112
114 template<fixed_point Fxd>
115 constexpr
116 Fxd
117 mul(Fxd a,
118 Fxd b)
119 noexcept
120 {
121 constexpr int w = detail::type_width<typename Fxd::raw_type>;
122
123 // offset used for shifting left
124 constexpr int offset = w - Fxd::frac_bits;
125
126 const auto raw_a = a.raw_value;
127 const auto raw_b = b.raw_value;
128 const auto c = detail::raw::mul<Fxd::bits>(raw_a, raw_b);
129
130 const auto d = detail::shl(c, offset);
131
132 return Fxd::from_raw(detail::high(d));
133 }
134
135 } // namespace down
136
137
138} // namespace fxd
139
140
141#endif
This is the namespace where the entire library is defined.
Definition: casting.hpp:19