DCCL v5
Loading...
Searching...
No Matches
numeric.cpp
1// Copyright 2009-2025:
2// GobySoft, LLC (2013-)
3// Massachusetts Institute of Technology (2007-2014)
4// Community contributors (see AUTHORS file)
5// File authors:
6// Toby Schneider <toby@gobysoft.org>
7// Cadmus To <cadmus.to+dev@gmail.com>
8//
9//
10// This file is part of the Dynamic Compact Control Language Library
11// ("DCCL").
12//
13// DCCL is free software: you can redistribute it and/or modify
14// it under the terms of the GNU Lesser General Public License as published by
15// the Free Software Foundation, either version 2.1 of the License, or
16// (at your option) any later version.
17//
18// DCCL is distributed in the hope that it will be useful,
19// but WITHOUT ANY WARRANTY; without even the implied warranty of
20// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21// GNU Lesser General Public License for more details.
22//
23// You should have received a copy of the GNU Lesser General Public License
24// along with DCCL. If not, see <http://www.gnu.org/licenses/>.
25#include "common.h"
26
27namespace dccl
28{
29
43int32_t decompose_float_format(float val, int16_t& exponent) {
44 uint32_t val_bits;
45 std::memcpy(&val_bits, &val, sizeof(val_bits));
46
47 constexpr auto num_exp_bits = 8;
48 constexpr auto num_frac_bits = 23;
49 constexpr auto exponent_bias = 127;
50
51 constexpr auto sign_bit_mask = static_cast<uint32_t>(0b1) << (num_exp_bits + num_frac_bits);
52 constexpr auto exp_bits = (static_cast<uint32_t>(1u)<<num_exp_bits) - 1;
53 constexpr auto exp_bit_mask = exp_bits << num_frac_bits;
54 constexpr auto frac_bit_mask = (static_cast<uint32_t>(1u) << num_frac_bits) - 1;
55
56 uint32_t signed_bit = val_bits & sign_bit_mask;
57 uint16_t val_exp_bits = static_cast<uint16_t>((val_bits & exp_bit_mask) >> num_frac_bits);
58 uint32_t frac_bits = val_bits & frac_bit_mask;
59 if (val_exp_bits == exp_bits) {
60 if (frac_bits == 0) {
61 // val is an infinity
62 if (signed_bit > 0) {
63 return std::numeric_limits<int32_t>::lowest();
64 } else {
65 return std::numeric_limits<int32_t>::max();
66 }
67 } else {
68 // val is a NaN
69 return std::numeric_limits<int32_t>::lowest() + 1;
70 }
71 }
72
73 if (val_exp_bits == 0) {
74 if (frac_bits == 0) {
75 exponent = 0;
76 // val is zero
77 return 0;
78 } else {
79 // val is a subnormal number
80 exponent = -exponent_bias + 1 - num_frac_bits; // shift so that the fraction can be interpreted as full integer
81 if (signed_bit > 0) {
82 return -static_cast<int32_t>(frac_bits);
83 } else {
84 return static_cast<int32_t>(frac_bits);
85 }
86 }
87 }
88
89 // val is a normal number
90 constexpr auto implicit_bit_mask = static_cast<uint32_t>(1u) << num_frac_bits;
91
92 int32_t exponent_tmp = static_cast<int32_t>(val_exp_bits) - exponent_bias - num_frac_bits; // shift so that the fraction can be interpreted as full integer
93 exponent = static_cast<int16_t>(exponent_tmp);
94
95 if (signed_bit > 0) {
96 return -static_cast<int32_t>(frac_bits | implicit_bit_mask);
97 } else {
98 return static_cast<int32_t>(frac_bits | implicit_bit_mask);
99 }
100}
101
102int64_t decompose_float_format(double val, int16_t& exponent) {
103 uint64_t val_bits;
104 std::memcpy(&val_bits, &val, sizeof(val_bits));
105
106 constexpr auto num_exp_bits = 11;
107 constexpr auto num_frac_bits = 52;
108 constexpr auto exponent_bias = 1023;
109
110 constexpr auto sign_bit_mask = static_cast<uint64_t>(0b1) << (num_exp_bits + num_frac_bits);
111 constexpr auto exp_bits = (static_cast<uint64_t>(1u)<<num_exp_bits) - 1;
112 constexpr auto exp_bit_mask = exp_bits << num_frac_bits;
113 constexpr auto frac_bit_mask = (static_cast<uint64_t>(1u) << num_frac_bits) - 1;
114
115 uint64_t signed_bit = val_bits & sign_bit_mask;
116 uint16_t val_exp_bits = static_cast<uint16_t>((val_bits & exp_bit_mask) >> num_frac_bits);
117 uint64_t frac_bits = val_bits & frac_bit_mask;
118 if (val_exp_bits == exp_bits) {
119 if (frac_bits == 0) {
120 // val is an infinity
121 if (signed_bit > 0) {
122 return std::numeric_limits<int64_t>::lowest();
123 } else {
124 return std::numeric_limits<int64_t>::max();
125 }
126 } else {
127 // val is a NaN
128 return std::numeric_limits<int64_t>::lowest() + 1;
129 }
130 }
131
132 if (val_exp_bits == 0) {
133 if (frac_bits == 0) {
134 exponent = 0;
135 // val is zero
136 return 0;
137 } else {
138 // val is a subnormal number
139 exponent = -exponent_bias + 1 - num_frac_bits; // shift so that the fraction can be interpreted as full integer
140 if (signed_bit > 0) {
141 return -static_cast<int64_t>(frac_bits);
142 } else {
143 return static_cast<int64_t>(frac_bits);
144 }
145 }
146 }
147
148 // val is a normal number
149 constexpr auto implicit_bit_mask = static_cast<uint64_t>(1u) << num_frac_bits;
150 exponent = static_cast<uint64_t>(val_exp_bits) - exponent_bias - num_frac_bits; // shift so that the fraction can be interpreted as full integer
151 if (signed_bit > 0) {
152 return -static_cast<int64_t>(frac_bits | implicit_bit_mask);
153 } else {
154 return static_cast<int64_t>(frac_bits | implicit_bit_mask);
155 }
156}
157
158float compose_float_format(int32_t significand, int16_t exponent) {
159 if (significand == std::numeric_limits<int32_t>::lowest()) {
160 return -std::numeric_limits<float>::infinity();
161 } else if (significand == std::numeric_limits<int32_t>::max()) {
162 return std::numeric_limits<float>::infinity();
163 } else if (significand == std::numeric_limits<int32_t>::lowest() + 1) {
164 return std::numeric_limits<float>::quiet_NaN();
165 } else if (significand == 0) {
166 return 0.0f;
167 }
168
169 return ldexp(static_cast<float>(significand), exponent);
170}
171
172double compose_float_format(int64_t significand, int16_t exponent) {
173 if (significand == std::numeric_limits<int64_t>::lowest()) {
174 return -std::numeric_limits<double>::infinity();
175 } else if (significand == std::numeric_limits<int64_t>::max()) {
176 return std::numeric_limits<double>::infinity();
177 } else if (significand == std::numeric_limits<int64_t>::lowest() + 1) {
178 return std::numeric_limits<double>::quiet_NaN();
179 } else if (significand == 0) {
180 return 0.0;
181 }
182
183 return ldexp(static_cast<double>(significand), exponent);
184}
185
186} // namespace dccl
Dynamic Compact Control Language namespace.
Definition any.h:28
int32_t decompose_float_format(float val, int16_t &exponent)
Definition numeric.cpp:43
float compose_float_format(int32_t significand, int16_t exponent)
Definition numeric.cpp:158