25#ifndef DCCLNumeric20260127H
26#define DCCLNumeric20260127H
61template<std::
size_t N>
62inline void increment(std::bitset<N> &bits) {
63 for (
auto i = 0ul; i < N; ++i) {
64 if ((bits[i] = !bits[i]) ==
true) {
70template<std::
size_t N>
71inline bool is_negative(
const std::bitset<N> &bits) {
75template<std::
size_t N>
76inline void negate(std::bitset<N> &bits) {
81template<std::
size_t N>
82inline std::bitset<N> negated(
const std::bitset<N> &bits) {
88template<std::
size_t N>
89inline void add_to(std::bitset<N> &a,
const std::bitset<N> &b) {
90 bool carry_bit =
false;
91 for (
auto i = 0ul; i < N; ++i) {
92 auto sum = carry_bit + a[i] + b[i];
98template<std::
size_t N>
99inline std::bitset<N> sum(
const std::bitset<N> &a,
const std::bitset<N> &b) {
105template<std::
size_t N>
106inline std::bitset<N> difference(
const std::bitset<N> &a,
const std::bitset<N> &b) {
107 auto ret_val = negated(b);
112template<std::
size_t N>
113inline bool unsigned_geq(
const std::bitset<N> &a,
const std::bitset<N> &b) {
114 for (
auto k = 0ul; k < N; ++k) {
115 const auto i = N - 1 - k;
118 }
else if (b[i] > a[i]) {
126template<std::
size_t N>
127inline std::bitset<N> unsigned_quotient(
const std::bitset<N> &n,
const std::bitset<N> &d) {
128 auto q = std::bitset<N>{0};
129 auto r = std::bitset<N>{0};
130 for (
auto k = 0ul; k < N; ++k) {
131 const auto i = N - 1 - k;
134 if (unsigned_geq(r, d)) {
135 r = difference(r, d);
142 if (unsigned_geq(r, d)) {
150template<std::
size_t N>
151inline std::bitset<2*N> unsigned_product(
const std::bitset<N> &a,
const std::bitset<N> &b) {
152 auto p = std::bitset<2*N>{0};
153 for (
auto b_i = 0ul; b_i < N; ++b_i) {
155 for (
auto a_i = 0ul; a_i < N; ++a_i) {
156 auto sum = p[a_i + b_i] + carry + (a[a_i] * b[b_i]);
157 carry =
static_cast<bool>(sum >> 1);
158 p[a_i + b_i] =
static_cast<bool>(sum % 2);
166template <std::
size_t N>
167inline void rounding_shift_right(std::bitset<N> &bits, uint16_t num_pos) {
169 bool need_to_increment = bits[num_pos-1];
171 if (need_to_increment) {
180template <std::
size_t N>
181inline int16_t drop_to_sig_fig(std::bitset<N> &bits, uint16_t target_sig_fig) {
182 if (target_sig_fig == 0) {
183 bits = std::bitset<N>{0};
187 auto curr_sig_fig =
static_cast<int16_t
>(N);
188 while (curr_sig_fig > target_sig_fig) {
189 if (bits[curr_sig_fig-1]) {
196 auto num_bits_to_drop = curr_sig_fig - target_sig_fig;
197 if (num_bits_to_drop > 0) {
198 rounding_shift_right(bits, num_bits_to_drop);
200 return num_bits_to_drop;
203template <
typename T, std::
size_t N>
204inline T fill_unsigned(
const std::bitset<N> &bits) {
207 constexpr auto num_type_bits =
sizeof(T)*8;
208 constexpr auto num_iter = std::min(N, num_type_bits);
209 for (
auto k = 0ul; k < num_iter; ++k) {
210 const auto i = num_iter - 1 - k;
218template <typename Integral, std::enable_if_t<std::is_integral<Integral>::value,
bool> =
true>
219uint64 encode(Integral value,
double min,
double res) {
223 wire_value -=
quantize(
static_cast<Integral
>(min), res);
227 wire_value *= (1.0 / res);
228 return static_cast<uint64>(round(wire_value, 0));
231template <typename Float, std::enable_if_t<std::is_floating_point<Float>::value,
bool> =
true>
232uint64 encode(Float value,
double min,
double res) {
238 int16_t val_exp, res_exp, min_exp;
246 using sig_t =
decltype(val_sig_raw);
247 using unsigned_sig_t =
typename std::make_unsigned<sig_t>::type;
248 constexpr auto num_wider_bits = 2*
sizeof(sig_t)*8;
249 using wider_t = std::bitset<num_wider_bits>;
250 const auto val_sign = std::signbit(val_sig_raw);
251 const auto res_sign = std::signbit(res_sig_raw);
252 const auto min_sign = std::signbit(min_sig_raw);
256 auto val_pos_sig = wider_t{
static_cast<unsigned_sig_t
>(std::abs(val_sig_raw))};
257 auto res_pos_sig = wider_t{
static_cast<unsigned_sig_t
>(res_sig_raw)};
258 auto min_pos_sig = wider_t{
static_cast<unsigned_sig_t
>(std::abs(min_sig_raw))};
261 auto common_exp = std::min({val_exp, min_exp, res_exp});
263 auto val_diff = val_exp - common_exp;
264 val_pos_sig <<= val_diff;
267 auto min_diff = min_exp - common_exp;
268 min_pos_sig <<= min_diff;
271 auto res_diff = res_exp - common_exp;
272 res_pos_sig <<= res_diff;
276 auto quant_val_sig = unsigned_quotient(val_pos_sig, res_pos_sig);
277 auto quant_val_exp = val_exp - res_exp;
278 auto quant_min_sig = unsigned_quotient(min_pos_sig, res_pos_sig);
279 auto quant_min_exp = min_exp - res_exp;
282 if (quant_val_exp < 0) {
283 rounding_shift_right(quant_val_sig,
static_cast<uint16_t
>(-quant_val_exp));
285 quant_val_sig <<= quant_val_exp;
288 if (quant_min_exp < 0) {
289 rounding_shift_right(quant_min_sig,
static_cast<uint16_t
>(-quant_min_exp));
291 quant_min_sig <<= quant_min_exp;
297 negate(quant_val_sig);
300 negate(quant_min_sig);
303 const auto value_enc_bits = difference(quant_val_sig, quant_min_sig);
305 assert(!is_negative(value_enc_bits));
307 const auto value_enc = fill_unsigned<unsigned_sig_t>(value_enc_bits);
309 return static_cast<uint64>(value_enc);
312template <typename Integral, std::enable_if_t<std::is_integral<Integral>::value,
bool> =
true>
313Integral decode(
uint64 value_enc,
double min,
double res) {
314 auto wire_value =
static_cast<Integral
>(value_enc);
318 wire_value /= (1.0 / res);
327template <typename Float, std::enable_if_t<std::is_floating_point<Float>::value,
bool> =
true>
328Float decode(
uint64 value_enc,
double min,
double res) {
329 int16_t res_exp, min_exp;
333 using sig_t =
decltype(res_sig_raw);
334 using unsigned_sig_t =
typename std::make_unsigned<sig_t>::type;
335 constexpr auto num_narrow_bits =
sizeof(sig_t)*8;
336 constexpr auto num_wider_bits = 2*num_narrow_bits;
337 using wider_t = std::bitset<num_wider_bits>;
339 const auto res_sign = std::signbit(res_sig_raw);
340 const auto min_sign = std::signbit(min_sig_raw);
344 auto res_pos_sig = wider_t{
static_cast<unsigned_sig_t
>(res_sig_raw)};
345 auto min_pos_sig = wider_t{
static_cast<unsigned_sig_t
>(std::abs(min_sig_raw))};
346 const auto val_enc_sig = wider_t{value_enc};
347 const auto val_enc_exp = 0;
350 const auto exp_diff = min_exp - res_exp;
352 min_pos_sig <<= exp_diff;
355 res_pos_sig <<= -exp_diff;
356 res_exp -= -exp_diff;
359 auto quant_min_sig = unsigned_quotient(min_pos_sig, res_pos_sig);
360 auto quant_min_exp = min_exp - res_exp;
362 if (quant_min_exp < 0) {
363 rounding_shift_right(quant_min_sig,
static_cast<uint16_t
>(-quant_min_exp));
365 quant_min_sig <<= quant_min_exp;
371 negate(quant_min_sig);
374 auto sum_pos_bits = sum(val_enc_sig, quant_min_sig);
375 const auto sum_sign = is_negative(sum_pos_bits);
377 negate(sum_pos_bits);
379 const auto sum_exp = 0;
381 const auto sum_pos_raw_unsigned = fill_unsigned<unsigned_sig_t>(sum_pos_bits);
383 auto value = sum_pos_raw_unsigned * res;
392 return static_cast<Float
>(value);
Dynamic Compact Control Language namespace.
google::protobuf::uint64 uint64
an unsigned 64 bit integer
int32_t decompose_float_format(float val, int16_t &exponent)
std::enable_if< std::is_floating_point< Float >::value, Float >::type quantize(Float value, double interval)
float compose_float_format(int32_t significand, int16_t exponent)