17#ifndef __AP_FIXED_BASE_H__
18#define __AP_FIXED_BASE_H__
21#error "Only ap_fixed.h and ap_int.h can be included directly in user code."
27#if _AP_ENABLE_HALF_ == 1
36#error "C++ is required to include this header file"
40#if !defined(__SYNTHESIS__) && __cplusplus >= 201103L && \
41 (defined(__gnu_linux__) || defined(_WIN32))
42#define AP_FIXED_ENABLE_CPP_FENV 1
57#define _AP_ctype_op_get_bit(var, index) _AP_ROOT_op_get_bit(var, index)
58#define _AP_ctype_op_set_bit(var, index, x) _AP_ROOT_op_set_bit(var, index, x)
59#define _AP_ctype_op_get_range(var, low, high) \
60 _AP_ROOT_op_get_range(var, low, high)
61#define _AP_ctype_op_set_range(var, low, high, x) \
62 _AP_ROOT_op_set_range(var, low, high, x)
64template <
typename _Tp1,
typename _Tp2>
65inline bool _AP_ctype_op_get_bit(_Tp1& var,
const _Tp2& index) {
66 return !!(var & (1ull << (index)));
68template <
typename _Tp1,
typename _Tp2,
typename _Tp3>
69inline _Tp1 _AP_ctype_op_set_bit(_Tp1& var,
const _Tp2& index,
const _Tp3& x) {
70 var |= (((x) ? 1ull : 0ull) << (index));
73template <
typename _Tp1,
typename _Tp2,
typename _Tp3>
74inline _Tp1 _AP_ctype_op_get_range(_Tp1& var,
const _Tp2& low,
78 mask >>= (
sizeof(_Tp1) * 8 - ((high) - (low) + 1));
83template <
typename _Tp1,
typename _Tp2,
typename _Tp3,
typename _Tp4>
84inline _Tp1 _AP_ctype_op_set_range(_Tp1& var,
const _Tp2& low,
const _Tp3& high,
87 mask >>= (_AP_SIZE_ap_slong - ((high) - (low) + 1));
88 var &= ~(
mask << (low));
89 var |= ((
mask & x) << (low));
97template <
int _AP_W2,
int _AP_I2,
bool _AP_S2>
98struct _ap_fixed_factory;
99template <
int _AP_W2,
int _AP_I2>
100struct _ap_fixed_factory<_AP_W2, _AP_I2, true> {
103template <
int _AP_W2,
int _AP_I2>
104struct _ap_fixed_factory<_AP_W2, _AP_I2, false> {
118template <
int _AP_W,
int _AP_I,
bool _AP_S, ap_q_mode _AP_Q, ap_o_mode _AP_O,
122 typedef _AP_ROOT_TYPE<_AP_W, _AP_S>
Base;
123 static const int width = _AP_W;
124 static const int iwidth = _AP_I;
125 static const ap_q_mode qmode = _AP_Q;
126 static const ap_o_mode omode = _AP_O;
129 template <
int _AP_W2,
int _AP_I2,
bool _AP_S2>
132 _AP_F = _AP_W - _AP_I,
133 F2 = _AP_W2 - _AP_I2,
134 mult_w = _AP_W + _AP_W2,
135 mult_i = _AP_I + _AP_I2,
136 mult_s = _AP_S || _AP_S2,
137 plus_w = AP_MAX(_AP_I + (_AP_S2 && !_AP_S), _AP_I2 + (_AP_S && !_AP_S2)) +
138 1 + AP_MAX(_AP_F, F2),
140 AP_MAX(_AP_I + (_AP_S2 && !_AP_S), _AP_I2 + (_AP_S && !_AP_S2)) + 1,
141 plus_s = _AP_S || _AP_S2,
143 AP_MAX(_AP_I + (_AP_S2 && !_AP_S), _AP_I2 + (_AP_S && !_AP_S2)) + 1 +
146 AP_MAX(_AP_I + (_AP_S2 && !_AP_S), _AP_I2 + (_AP_S && !_AP_S2)) + 1,
148#ifndef __SC_COMPATIBLE__
149 div_w = _AP_S2 + _AP_W + AP_MAX(F2, 0),
151 div_w = _AP_S2 + _AP_W + AP_MAX(F2, 0) + AP_MAX(_AP_I2, 0),
153 div_i = _AP_S2 + _AP_I + F2,
154 div_s = _AP_S || _AP_S2,
156 AP_MAX(_AP_I + (_AP_S2 && !_AP_S), _AP_I2 + (_AP_S && !_AP_S2)) +
158 logic_i = AP_MAX(_AP_I + (_AP_S2 && !_AP_S), _AP_I2 + (_AP_S && !_AP_S2)),
159 logic_s = _AP_S || _AP_S2
172 typedef typename _ap_fixed_factory<mult_w, mult_i, mult_s>::type mult;
173 typedef typename _ap_fixed_factory<plus_w, plus_i, plus_s>::type plus;
174 typedef typename _ap_fixed_factory<minus_w, minus_i, minus_s>::type minus;
175 typedef typename _ap_fixed_factory<logic_w, logic_i, logic_s>::type logic;
176 typedef typename _ap_fixed_factory<div_w, div_i, div_s>::type div;
177 typedef typename _ap_fixed_factory<_AP_W, _AP_I, _AP_S>::type arg1;
183 void fromString(
const std::string& val,
unsigned char radix) {
184 _AP_ERROR(!(radix == 2 || radix == 8 || radix == 10 || radix == 16),
185 "ap_fixed_base::fromString(%s, %d)", val.c_str(), radix);
189 int endPos = val.length();
190 int decPos = val.find(
".");
191 if (decPos == -1) decPos = endPos;
194 bool isNegative =
false;
198 }
else if (val[0] ==
'+')
208 ap_fixed_base<AP_MAX(_AP_I, 4) + 4, AP_MAX(_AP_I, 4) + 4,
false>
212 unsigned shift = (radix == 16 ? 4 : radix == 8 ? 3 : radix == 2 ? 1 : 0);
217 bool sticky_int =
false;
220 for (
int i = startPos; i < decPos; i++) {
222 char cdigit = val[i];
223 if (cdigit ==
'\0')
continue;
224 unsigned digit = ap_private_ops::decode_digit(cdigit, radix);
226 sticky_int |= integer_bits[AP_MAX(_AP_I, 4) + 4 - 1] |
227 integer_bits[AP_MAX(_AP_I, 4) + 4 - 2] |
228 integer_bits[AP_MAX(_AP_I, 4) + 4 - 3] |
229 integer_bits[AP_MAX(_AP_I, 4) + 4 - 4];
232 integer_bits <<= shift;
234 integer_bits *= radix;
237 integer_bits += digit;
241 integer_bits[AP_MAX(_AP_I, 4) + 4 - 3] =
242 integer_bits[AP_MAX(_AP_I, 4) + 4 - 3] | sticky_int;
244 ap_fixed_base<AP_MAX(_AP_W - _AP_I, 0) + 4 + 4, 4,
false> fractional_bits =
249 for (
int i = endPos - 1; i >= decPos + 1; i--) {
251 char cdigit = val[i];
252 if (cdigit ==
'\0')
continue;
253 unsigned digit = ap_private_ops::decode_digit(cdigit, radix);
255 fractional_bits += digit;
257 sticky |= fractional_bits[0] | fractional_bits[1] | fractional_bits[2] |
261 fractional_bits >>= shift;
263 fractional_bits /= radix;
272 fractional_bits[0] = fractional_bits[0] | sticky;
275 *
this = -(integer_bits + fractional_bits);
277 *
this = integer_bits + fractional_bits;
283 INLINE
void report() {
284 if (!_AP_S && _AP_O == AP_WRAP_SM) {
285 fprintf(stderr,
"ap_ufxied<...> cannot support AP_WRAP_SM.\n");
288 if (_AP_W > MAX_MODE(AP_INT_MAX_W) * 1024) {
290 "[E] ap_%sfixed<%d, ...>: Bitwidth exceeds the "
291 "default max value %d. Please use macro "
292 "AP_INT_MAX_W to set a larger max value.\n",
293 _AP_S ?
"" :
"u", _AP_W, MAX_MODE(AP_INT_MAX_W) * 1024);
298 INLINE
void report() {}
303 INLINE
void overflow_adjust(
bool underflow,
bool overflow,
bool lD,
305 if (!underflow && !overflow)
return;
306 if (_AP_O == AP_WRAP) {
307 if (_AP_N == 0)
return;
311 Base::V = _AP_ROOT_op_set_bit(Base::V, _AP_W - 1, sign);
315 if (sign)
mask.V = 0;
317 _AP_ROOT_op_set_range(Base::V, _AP_W - _AP_N, _AP_W - 2,
mask.V);
323 _AP_ROOT_op_set_range(Base::V, _AP_W - _AP_N, _AP_W - 1,
mask.V);
325 }
else if (_AP_O == AP_SAT_ZERO) {
327 }
else if (_AP_O == AP_WRAP_SM && _AP_S) {
328 bool Ro = _AP_ROOT_op_get_bit(Base::V, _AP_W - 1);
332 Base::V = _AP_ROOT_op_set_bit(Base::V, _AP_W - 1, lD);
335 if (_AP_N == 1 && sign != Ro) {
337 }
else if (_AP_N > 1) {
338 bool lNo = _AP_ROOT_op_get_bit(Base::V, _AP_W - _AP_N);
339 if (lNo == sign) Base::V =
~Base::V;
341 if (sign)
mask.V = 0;
343 _AP_ROOT_op_set_range(Base::V, _AP_W - _AP_N, _AP_W - 2,
mask.V);
345 Base::V = _AP_ROOT_op_set_bit(Base::V, _AP_W - 1, sign);
351 Base::V <<= _AP_W - 1;
353 }
else if (underflow) {
355 Base::V <<= _AP_W - 1;
356 if (_AP_O == AP_SAT_SYM) Base::V |= 1;
367 INLINE
bool quantization_adjust(
bool qb,
bool r,
bool s) {
368 bool carry = (bool)_AP_ROOT_op_get_bit(Base::V, _AP_W - 1);
369 if (_AP_Q == AP_TRN)
return false;
370 if (_AP_Q == AP_RND_ZERO)
372 else if (_AP_Q == AP_RND_MIN_INF)
374 else if (_AP_Q == AP_RND_INF)
376 else if (_AP_Q == AP_RND_CONV)
377 qb &= _AP_ROOT_op_get_bit(Base::V, 0) || r;
378 else if (_AP_Q == AP_TRN_ZERO)
381 return carry && (!(bool)_AP_ROOT_op_get_bit(Base::V, _AP_W - 1));
392 template <
int _AP_W2,
int _AP_I2,
bool _AP_S2, ap_q_mode _AP_Q2,
393 ap_o_mode _AP_O2,
int _AP_N2>
400 template <
int _AP_W2,
int _AP_I2,
bool _AP_S2, ap_q_mode _AP_Q2,
401 ap_o_mode _AP_O2,
int _AP_N2>
403 _AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) {
408 template <
int _AP_W2,
bool _AP_S2>
416 template <
int _AP_W2,
bool _AP_S2>
427 unsigned char radix = rd;
429 ap_private_ops::parseString(s, radix);
430 _AP_ERROR(radix == 0,
431 "ap_fixed_base(const char* \"%s\", %d), str=%s, radix = %d", s,
432 rd, str.c_str(), radix);
433 fromString(str, radix);
446 _ssdm_string2bits((
void*)(&t), (
const char*)(s), 10, _AP_I, _AP_S, _AP_Q,
447 _AP_O, _AP_N, _AP_C99);
452 _ssdm_string2bits((
void*)(&t), (
const char*)(s), rd, _AP_I, _AP_S, _AP_Q,
453 _AP_O, _AP_N, _AP_C99);
458 template <
int _AP_W2,
bool _AP_S2>
464 template <
int _AP_W2,
bool _AP_S2>
470 template <
int _AP_W2,
typename _AP_T2,
int _AP_W3,
typename _AP_T3>
477 template <
int _AP_W2,
int _AP_I2,
bool _AP_S2, ap_q_mode _AP_Q2,
478 ap_o_mode _AP_O2,
int _AP_N2>
485 template <
int _AP_W2,
int _AP_I2,
bool _AP_S2, ap_q_mode _AP_Q2,
486 ap_o_mode _AP_O2,
int _AP_N2>
495#define CTOR_FROM_INT(C_TYPE, _AP_W2, _AP_S2) \
496 INLINE ap_fixed_base(const C_TYPE x) { \
497 ap_fixed_base<(_AP_W2), (_AP_W2), (_AP_S2)> tmp; \
502 CTOR_FROM_INT(
bool, 1,
false)
503 CTOR_FROM_INT(
char, 8, CHAR_IS_SIGNED)
504 CTOR_FROM_INT(
signed char, 8, true)
505 CTOR_FROM_INT(
unsigned char, 8, false)
506 CTOR_FROM_INT(
short, _AP_SIZE_short, true)
507 CTOR_FROM_INT(
unsigned short, _AP_SIZE_short, false)
508 CTOR_FROM_INT(
int, _AP_SIZE_int, true)
509 CTOR_FROM_INT(
unsigned int, _AP_SIZE_int, false)
510 CTOR_FROM_INT(
long, _AP_SIZE_long, true)
511 CTOR_FROM_INT(
unsigned long, _AP_SIZE_long, false)
512 CTOR_FROM_INT(ap_slong, _AP_SIZE_ap_slong, true)
513 CTOR_FROM_INT(ap_ulong, _AP_SIZE_ap_slong, false)
523 ireg.V = doubleToRawBits(d);
524 bool isneg = _AP_ROOT_op_get_bit(ireg.V, 63);
529 _AP_ROOT_op_get_range(ireg.V, DOUBLE_MAN, DOUBLE_MAN + DOUBLE_EXP - 1);
530 exp = exp_tmp - DOUBLE_BIAS;
532 man.V = _AP_ROOT_op_get_range(ireg.V, 0, DOUBLE_MAN - 1);
534 _AP_WARNING(exp == APFX_IEEE_DOUBLE_E_MAX + 1 && man.V != 0,
535 "assign NaN to fixed point value");
536 man.V = _AP_ROOT_op_set_bit(man.V, DOUBLE_MAN, 1);
537 if (isneg) man = -man;
538 if ((ireg.V & 0x7fffffffffffffffLL) == 0) {
541 int _AP_W2 = DOUBLE_MAN + 2, _AP_I2 = exp.V + 2, _AP_F = _AP_W - _AP_I,
542 F2 = _AP_W2 - _AP_I2;
544 QUAN_INC = F2 > _AP_F &&
545 !(_AP_Q == AP_TRN || (_AP_Q == AP_TRN_ZERO && !_AP_S2));
548 unsigned sh_amt = (F2 > _AP_F) ? F2 - _AP_F : _AP_F - F2;
551 else if (F2 > _AP_F) {
552 if (sh_amt < DOUBLE_MAN + 2)
553 Base::V = man.V >> sh_amt;
555 Base::V = isneg ? -1 : 0;
557 if ((_AP_Q != AP_TRN) && !((_AP_Q == AP_TRN_ZERO) && !_AP_S2)) {
558 bool qb = (F2 - _AP_F > _AP_W2)
560 : (bool)_AP_ROOT_op_get_bit(man.V, F2 - _AP_F - 1);
561 bool r = (F2 > _AP_F + 1)
562 ? _AP_ROOT_op_get_range(man.V, 0,
563 (F2 - _AP_F - 2 < _AP_W2)
567 carry = quantization_adjust(qb, r, isneg);
572 Base::V = Base::V << sh_amt;
577 if ((_AP_O != AP_WRAP || _AP_N != 0) &&
578 ((!_AP_S && _AP_S2) ||
582 (_AP_S2 && (_AP_O == AP_SAT_SYM))))) {
583 bool deleted_zeros = _AP_S2 ? true : !carry, deleted_ones =
true;
584 bool neg_src = isneg;
586 int pos1 = F2 - _AP_F + _AP_W;
587 int pos2 = F2 - _AP_F + _AP_W + 1;
588 bool newsignbit = _AP_ROOT_op_get_bit(Base::V, _AP_W - 1);
589 if (pos1 < _AP_W2 && pos1 >= 0)
591 lD = (man.V >> pos1) & 1;
593 bool Range1_all_ones =
true;
594 bool Range1_all_zeros =
true;
595 bool Range2_all_ones =
true;
599 if (pos2 >= 0 && pos2 < _AP_W2) {
604 Range2_all_ones = Range2 == (all_ones >> pos2);
606 Range2_all_ones =
false;
607 if (pos1 >= 0 && pos2 < _AP_W2) {
608 Range1_all_ones = Range2_all_ones && lD;
609 Range1_all_zeros = !Range2.V && !lD;
610 }
else if (pos2 == _AP_W2) {
611 Range1_all_ones = lD;
612 Range1_all_zeros = !lD;
613 }
else if (pos1 < 0) {
614 Range1_all_zeros = !man.V;
615 Range1_all_ones =
false;
619 deleted_zeros && (carry ? Range1_all_ones : Range1_all_zeros);
621 carry ? Range2_all_ones && (pos1 < 0 || !lD) : Range1_all_ones;
622 neg_src = isneg && !(carry && Range1_all_ones);
624 neg_src = isneg && newsignbit;
625 bool neg_trg = _AP_S && newsignbit;
626 bool overflow = (neg_trg || !deleted_zeros) && !isneg;
627 bool underflow = (!neg_trg || !deleted_ones) && neg_src;
628 if ((_AP_O == AP_SAT_SYM) && _AP_S2 && _AP_S)
629 underflow |= neg_src && (_AP_W > 1 ? _AP_ROOT_op_get_range(
630 Base::V, 0, _AP_W - 2) == 0
632 overflow_adjust(underflow, overflow, lD, neg_src);
641#if _AP_ENABLE_HALF_ == 1
657 template <
int _AP_W2,
int _AP_I2,
bool _AP_S2, ap_q_mode _AP_Q2,
658 ap_o_mode _AP_O2,
int _AP_N2>
661 const int _AP_F = _AP_W - _AP_I;
662 const int F2 = _AP_W2 - _AP_I2;
664 F2 > _AP_F && !(_AP_Q == AP_TRN || (_AP_Q == AP_TRN_ZERO && !_AP_S2));
666 if (!op) Base::V = 0;
668 bool signbit = _AP_ROOT_op_get_bit(op.V, _AP_W2 - 1);
669 bool isneg = signbit && _AP_S2;
672 else if (F2 > _AP_F) {
673 unsigned int sh_amt = F2 - _AP_F;
675 if (sh_amt < _AP_W2) {
676 Base::V = op.V >> sh_amt;
678 Base::V = isneg ? -1 : 0;
680 if (_AP_Q != AP_TRN && !(_AP_Q == AP_TRN_ZERO && !_AP_S2)) {
681 bool qbit = _AP_ROOT_op_get_bit(op.V, F2 - _AP_F - 1);
683 bool qb = (F2 - _AP_F > _AP_W2) ? _AP_S2 && signbit : qbit;
685 hi = ((F2 - _AP_F - 2) < _AP_W2) ? (F2 - _AP_F - 2) : (_AP_W2 - 1)
688 bool r = (F2 > _AP_F + 1) ? (_AP_ROOT_op_get_range(op.V, 0, hi) != 0)
690 carry = quantization_adjust(qb, r, isneg);
693 unsigned sh_amt = _AP_F - F2;
695 if (sh_amt < _AP_W) {
696 if (_AP_W > _AP_W2) {
702 Base::V = op.V << sh_amt;
709 if ((_AP_O != AP_WRAP || _AP_N != 0) &&
710 ((!_AP_S && _AP_S2) ||
714 (_AP_S2 && _AP_O == AP_SAT_SYM)))) {
715 bool deleted_zeros = _AP_S2 ? true : !carry;
716 bool deleted_ones =
true;
717 bool neg_src = isneg;
718 bool newsignbit = _AP_ROOT_op_get_bit(Base::V, _AP_W - 1);
719 enum { pos1 = F2 - _AP_F + _AP_W, pos2 = F2 - _AP_F + _AP_W + 1 };
720 bool lD = (pos1 < _AP_W2 && pos1 >= 0) ? _AP_ROOT_op_get_bit(op.V, pos1)
723 bool Range1_all_ones =
true;
724 bool Range1_all_zeros =
true;
725 bool Range2_all_ones =
true;
728 if (pos2 < _AP_W2 && pos2 >= 0) {
730 Range2.V = _AP_ROOT_op_get_range(op.V, pos2, _AP_W2 - 1);
731 Range2_all_ones = Range2 == (all_ones >> pos2);
732 }
else if (pos2 < 0) {
733 Range2_all_ones =
false;
736 if (pos1 >= 0 && pos2 < _AP_W2) {
738 Range1.V = _AP_ROOT_op_get_range(op.V, pos1, _AP_W2 - 1);
739 Range1_all_ones = Range1 == (all_ones >> pos1);
740 Range1_all_zeros = !Range1.V;
741 }
else if (pos2 == _AP_W2) {
742 Range1_all_ones = lD;
743 Range1_all_zeros = !lD;
744 }
else if (pos1 < 0) {
745 Range1_all_zeros = !op.V;
746 Range1_all_ones =
false;
750 deleted_zeros && (carry ? Range1_all_ones : Range1_all_zeros);
752 carry ? Range2_all_ones && (pos1 < 0 || !lD) : Range1_all_ones;
753 neg_src = isneg && !(carry && Range1_all_ones);
755 neg_src = isneg && newsignbit;
756 bool neg_trg = _AP_S && newsignbit;
757 bool overflow = (neg_trg || !deleted_zeros) && !isneg;
758 bool underflow = (!neg_trg || !deleted_ones) && neg_src;
759 if ((_AP_O == AP_SAT_SYM) && _AP_S2 && _AP_S)
760 underflow |= neg_src && (_AP_W > 1 ? _AP_ROOT_op_get_range(
761 Base::V, 0, _AP_W - 2) == 0
764 overflow_adjust(underflow, overflow, lD, neg_src);
769 template <
int _AP_W2,
int _AP_I2,
bool _AP_S2, ap_q_mode _AP_Q2,
770 ap_o_mode _AP_O2,
int _AP_N2>
772 const volatile ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2,
774 operator=(
const_cast<const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2,
775 _AP_O2, _AP_N2
>&>(op));
802 INLINE
ap_int_base<AP_MAX(_AP_I, 1), _AP_S> to_ap_int_base(
803 bool Cnative =
true)
const {
807 }
else if (_AP_I > 0 && _AP_I <= _AP_W) {
808 ret.V = _AP_ROOT_op_get_range(Base::V, _AP_W - _AP_I, _AP_W - 1);
809 }
else if (_AP_I > _AP_W) {
810 ret.V = _AP_ROOT_op_get_range(Base::V, 0, _AP_W - 1);
811 ret.V <<= (_AP_I - _AP_W);
821 if (Cnative && _AP_I < _AP_W) {
823 if (_AP_S && _AP_ROOT_op_get_bit(Base::V, _AP_W - 1) && (_AP_I < _AP_W) &&
824 (_AP_ROOT_op_get_range(
825 Base::V, 0, _AP_I < 0 ? _AP_W - 1 : _AP_W - _AP_I - 1) != 0))
834 template <
int _AP_W2,
bool _AP_S2>
840 INLINE
char to_char()
const {
return to_ap_int_base().to_char(); }
842 INLINE
int to_int()
const {
return to_ap_int_base().to_int(); }
844 INLINE
unsigned to_uint()
const {
return to_ap_int_base().to_uint(); }
846 INLINE ap_slong to_int64()
const {
return to_ap_int_base().to_int64(); }
848 INLINE ap_ulong to_uint64()
const {
return to_ap_int_base().to_uint64(); }
852 INLINE
double to_double()
const {
853#if defined(AP_FIXED_ENABLE_CPP_FENV)
854 _AP_WARNING(std::fegetround() != FE_TONEAREST,
855 "Only FE_TONEAREST is supported");
857 enum { BITS = DOUBLE_MAN + DOUBLE_EXP + 1 };
858 if (!Base::V)
return 0.0f;
859 bool s = _AP_S && _AP_ROOT_op_get_bit(Base::V, _AP_W - 1);
865 int l = tmp.countLeadingZeros();
866 int e = _AP_I - l - 1 + DOUBLE_BIAS;
867 int lsb_index = _AP_W - l - 1 - DOUBLE_MAN;
869 bool a = (lsb_index >= 2)
870 ? (_AP_ROOT_op_get_range(tmp.V, 0, lsb_index - 2) != 0)
873 a |= (lsb_index >= 0) ? _AP_ROOT_op_get_bit(tmp.V, lsb_index) : 0;
878 m = (lsb_index >= 1) ? (ap_ulong)(tmp.V >> (lsb_index - 1))
879 : (ap_ulong)(tmp.V << (1 - lsb_index));
882 m = (lsb_index >= 1) ? (m >> (lsb_index - 1)) : (m << (1 - lsb_index));
888 if (_AP_ctype_op_get_bit(m, DOUBLE_MAN + 1)) {
892 m = _AP_ctype_op_set_bit(m, BITS - 1, s);
894 m = _AP_ctype_op_set_range(m, DOUBLE_MAN, DOUBLE_MAN + DOUBLE_EXP - 1, e);
897 return rawBitsToDouble(m);
902 INLINE
float to_float()
const {
903#if defined(AP_FIXED_ENABLE_CPP_FENV)
904 _AP_WARNING(std::fegetround() != FE_TONEAREST,
905 "Only FE_TONEAREST is supported");
907 enum { BITS = FLOAT_MAN + FLOAT_EXP + 1 };
908 if (!Base::V)
return 0.0f;
909 bool s = _AP_S && _AP_ROOT_op_get_bit(Base::V, _AP_W - 1);
915 int l = tmp.countLeadingZeros();
916 int e = _AP_I - l - 1 + FLOAT_BIAS;
917 int lsb_index = _AP_W - l - 1 - FLOAT_MAN;
919 bool a = (lsb_index >= 2)
920 ? (_AP_ROOT_op_get_range(tmp.V, 0, lsb_index - 2) != 0)
923 a |= (lsb_index >= 0) ? _AP_ROOT_op_get_bit(tmp.V, lsb_index) : 0;
928 m = (lsb_index >= 1) ? (
unsigned long)(tmp.V >> (lsb_index - 1))
929 : (
unsigned long)(tmp.V << (1 - lsb_index));
931 m = (
unsigned long)tmp.V;
932 m = (lsb_index >= 1) ? (m >> (lsb_index - 1)) : (m << (1 - lsb_index));
937 if (_AP_ctype_op_get_bit(m, FLOAT_MAN + 1)) {
941 m = _AP_ctype_op_set_bit(m, BITS - 1, s);
942 m = _AP_ctype_op_set_range(m, FLOAT_MAN, FLOAT_MAN + FLOAT_EXP - 1, e);
944 return rawBitsToFloat(m);
947#if _AP_ENABLE_HALF_ == 1
950 INLINE half to_half()
const {
951#if defined(AP_FIXED_ENABLE_CPP_FENV)
952 _AP_WARNING(std::fegetround() != FE_TONEAREST,
953 "Only FE_TONEAREST is supported");
955 enum {BITS = HALF_MAN + HALF_EXP + 1};
956 if (!Base::V)
return 0.0f;
957 bool s = _AP_S && _AP_ROOT_op_get_bit(Base::V, _AP_W - 1);
963 int l = tmp.countLeadingZeros();
964 int e = _AP_I - l - 1 + HALF_BIAS;
965 int lsb_index = _AP_W - l - 1 - HALF_MAN;
967 bool a = (lsb_index >= 2)
968 ? (_AP_ROOT_op_get_range(tmp.V, 0, lsb_index - 2) != 0)
971 a |= (lsb_index >= 0) ? _AP_ROOT_op_get_bit(tmp.V, lsb_index) : 0;
976 m = (lsb_index >= 1) ? (
unsigned short)(tmp.V >> (lsb_index - 1))
977 : (
unsigned short)(tmp.V << (1 - lsb_index));
979 m = (
unsigned short)tmp.V;
980 m = (lsb_index >= 1) ? (m >> (lsb_index - 1)) : (m << (1 - lsb_index));
985 if (_AP_ctype_op_get_bit(m, HALF_MAN + 1)) {
989 m = _AP_ctype_op_set_bit(m, BITS - 1, s);
990 m = _AP_ctype_op_set_range(m, HALF_MAN, HALF_MAN + HALF_EXP - 1, e);
992 return rawBitsToHalf(m);
997 INLINE
operator long double()
const {
return (
long double)to_double(); }
999 INLINE
operator double()
const {
return to_double(); }
1001 INLINE
operator float()
const {
return to_float(); }
1003#if _AP_ENABLE_HALF_ == 1
1004 INLINE
operator half()
const {
return to_half(); }
1007 INLINE
operator bool()
const {
return (
bool)Base::V != 0; }
1009 INLINE
operator char()
const {
return (
char)to_int(); }
1011 INLINE
operator signed char()
const {
return (
signed char)to_int(); }
1013 INLINE
operator unsigned char()
const {
return (
unsigned char)to_uint(); }
1015 INLINE
operator short()
const {
return (
short)to_int(); }
1017 INLINE
operator unsigned short()
const {
return (
unsigned short)to_uint(); }
1019 INLINE
operator int()
const {
return to_int(); }
1021 INLINE
operator unsigned int()
const {
return to_uint(); }
1025 INLINE
operator long()
const {
return (
long)to_int64(); }
1027 INLINE
operator unsigned long()
const {
return (
unsigned long)to_uint64(); }
1029 INLINE
operator long()
const {
return (
long)to_int(); }
1031 INLINE
operator unsigned long()
const {
return (
unsigned long)to_uint(); }
1034 INLINE
operator ap_ulong()
const {
return to_uint64(); }
1036 INLINE
operator ap_slong()
const {
return to_int64(); }
1038 INLINE
int length()
const {
return _AP_W; };
1041#ifndef __SYNTHESIS__
1043 INLINE ap_ulong bits_to_uint64()
const {
return (Base::V).to_uint64(); }
1049 INLINE
int countLeadingZeros() {
1054 t.range(_AP_W - 1, 0) = this->range(0, _AP_W - 1);
1055 return __builtin_ctz(t.V);
1056 }
else if (_AP_W <= 64) {
1058 t.range(_AP_W - 1, 0) = this->range(0, _AP_W - 1);
1059 return __builtin_ctzll(t.V);
1061 enum {__N = (_AP_W + 63) / 64};
1064 bool hitNonZero =
false;
1065 for (i = 0; i < __N - 1; ++i) {
1067 t.range(0, 63) = this->range(_AP_W - i * 64 - 64, _AP_W - i * 64 - 1);
1068 NZeros += hitNonZero ? 0 : __builtin_clzll(t.V);
1069 hitNonZero |= (t != 0);
1073 t.range(63 - (_AP_W - 1) % 64, 63) = this->range(0, (_AP_W - 1) % 64);
1074 NZeros += __builtin_clzll(t.V);
1079 return Base::V.countLeadingZeros();
1085 template <
int _AP_W2,
int _AP_I2,
bool _AP_S2, ap_q_mode _AP_Q2,
1086 ap_o_mode _AP_O2,
int _AP_N2>
1087 INLINE
typename RType<_AP_W2, _AP_I2, _AP_S2>::mult operator*(
1090 typename RType<_AP_W2, _AP_I2, _AP_S2>::mult_base r, t;
1099 template <
int _AP_W2,
int _AP_I2,
bool _AP_S2, ap_q_mode _AP_Q2,
1100 ap_o_mode _AP_O2,
int _AP_N2>
1101 INLINE
typename RType<_AP_W2, _AP_I2, _AP_S2>::div operator/(
1104 typename RType<_AP_W2, _AP_I2, _AP_S2>::div_base r;
1105#ifndef __SYNTHESIS__
1106 enum {F2 = _AP_W2 - _AP_I2,
1107 _W1 = AP_MAX(_AP_W + AP_MAX(F2, 0) + ((_AP_S2 && !_AP_S) ? 1 : 0),
1108 _AP_W2 + ((_AP_S && !_AP_S2) ? 1 : 0))};
1113 tmp1.V <<= AP_MAX(F2, 0);
1117 r.V = ((_AP_S || _AP_S2) ? dividend.V.sdiv(divisior.V)
1118 : dividend.V.udiv(divisior.V));
1120#ifndef __SC_COMPATIBLE__
1121 ap_fixed_base<_AP_W + AP_MAX(_AP_W2 - _AP_I2, 0), _AP_I, _AP_S> t(*
this);
1123 ap_fixed_base<_AP_W + AP_MAX(_AP_W2 - _AP_I2, 0) + AP_MAX(_AP_I2, 0), _AP_I,
1160#define OP_BIN_AF(Sym, Rty) \
1161 template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2, \
1162 ap_o_mode _AP_O2, int _AP_N2> \
1163 INLINE typename RType<_AP_W2, _AP_I2, _AP_S2>::Rty operator Sym( \
1164 const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& \
1166 typename RType<_AP_W2, _AP_I2, _AP_S2>::Rty##_base ret, lhs(*this), \
1168 ret.V = lhs.V Sym rhs.V; \
1180#define OP_ASSIGN_AF(Sym) \
1181 template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2, \
1182 ap_o_mode _AP_O2, int _AP_N2> \
1183 INLINE ap_fixed_base& operator Sym##=( \
1184 const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& \
1186 *this = operator Sym(op2); \
1245 INLINE
bool operator!()
const {
return Base::V == 0; }
1259 template <
int _AP_SHIFT>
1266 template <
int _AP_SHIFT>
1267 INLINE
ap_fixed_base<_AP_W, _AP_I - _AP_SHIFT, _AP_S> rshift()
const {
1279 r.V = Base::V << sh;
1281#ifdef __SC_COMPATIBLE__
1282 if (sh == 0)
return r;
1283 if (_AP_O != AP_WRAP || _AP_N != 0) {
1284 bool neg_src = _AP_S && _AP_ROOT_op_get_bit(Base::V, _AP_W - 1);
1285 bool allones, allzeros;
1289 range1.V = _AP_ROOT_op_get_range(
1290 const_cast<ap_fixed_base*
>(
this)->Base::V, _AP_W - sh, _AP_W - 1);
1291 allones = range1 == (ones >> (_AP_W - sh));
1292 allzeros = range1 == 0;
1295 allzeros = Base::V == 0;
1297 bool overflow = !allzeros && !neg_src;
1298 bool underflow = !allones && neg_src;
1299 if ((_AP_O == AP_SAT_SYM) && _AP_S)
1302 (_AP_W > 1 ? _AP_ROOT_op_get_range(r.V, 0, _AP_W - 2) == 0 :
true);
1304 if (sh < _AP_W) lD = _AP_ROOT_op_get_bit(Base::V, _AP_W - sh - 1);
1305 r.overflow_adjust(underflow, overflow, lD, neg_src);
1313 r.V = Base::V >> sh;
1315#ifdef __SC_COMPATIBLE__
1316 if (sh == 0)
return r;
1317 if (_AP_Q != AP_TRN) {
1319 if (sh <= _AP_W) qb = _AP_ROOT_op_get_bit(Base::V, sh - 1);
1321 if (sh > 1 && sh <= _AP_W)
1322 rb = _AP_ROOT_op_get_range(
const_cast<ap_fixed_base*
>(
this)->Base::V, 0,
1324 else if (sh > _AP_W)
1326 r.quantization_adjust(qb, rb,
1327 _AP_S && _AP_ROOT_op_get_bit(Base::V, _AP_W - 1));
1336 bool isNeg = sh < 0;
1337 unsigned int ush = isNeg ? -sh : sh;
1339 return operator>>(ush);
1341 return operator<<(ush);
1346 bool isNeg = sh < 0;
1347 unsigned int ush = isNeg ? -sh : sh;
1349 return operator<<(ush);
1351 return operator>>(ush);
1356 template <
int _AP_W2>
1360 int sh = op2.to_int();
1361 return operator<<(sh);
1364 template <
int _AP_W2>
1366 int sh = op2.to_int();
1367 return operator>>(sh);
1371 template <
int _AP_W2>
1373 unsigned int sh = op2.to_uint();
1374 return operator<<(sh);
1377 template <
int _AP_W2>
1379 unsigned int sh = op2.to_uint();
1380 return operator>>(sh);
1384 template <
int _AP_W2,
int _AP_I2,
bool _AP_S2, ap_q_mode _AP_Q2,
1385 ap_o_mode _AP_O2,
int _AP_N2>
1389 return operator<<(op2.to_ap_int_base());
1392 template <
int _AP_W2,
int _AP_I2,
bool _AP_S2, ap_q_mode _AP_Q2,
1393 ap_o_mode _AP_O2,
int _AP_N2>
1397 return operator>>(op2.to_ap_int_base());
1405 *
this = operator<<(sh);
1410 *
this = operator<<(sh);
1414 template <
int _AP_W2,
bool _AP_S2>
1416 *
this = operator<<(sh.to_int());
1420 template <
int _AP_W2,
int _AP_I2,
bool _AP_S2, ap_q_mode _AP_Q2,
1421 ap_o_mode _AP_O2,
int _AP_N2>
1424 *
this = operator<<(sh.to_int());
1430 *
this = operator>>(sh);
1435 *
this = operator>>(sh);
1439 template <
int _AP_W2,
bool _AP_S2>
1441 *
this = operator>>(sh.to_int());
1445 template <
int _AP_W2,
int _AP_I2,
bool _AP_S2, ap_q_mode _AP_Q2,
1446 ap_o_mode _AP_O2,
int _AP_N2>
1449 *
this = operator>>(sh.to_int());
1455#define OP_CMP_AF(Sym) \
1456 template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2, \
1457 ap_o_mode _AP_O2, int _AP_N2> \
1458 INLINE bool operator Sym(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, \
1459 _AP_O2, _AP_N2>& op2) const { \
1460 enum { _AP_F = _AP_W - _AP_I, F2 = _AP_W2 - _AP_I2 }; \
1462 return Base::V Sym op2.V; \
1463 else if (_AP_F > F2) \
1464 return Base::V Sym ap_fixed_base<AP_MAX(_AP_W2 + _AP_F - F2, 1), _AP_I2, \
1465 _AP_S2, _AP_Q2, _AP_O2, _AP_N2>(op2) \
1468 return ap_fixed_base<AP_MAX(_AP_W + F2 - _AP_F + 1, 1), _AP_I + 1, \
1469 _AP_S, _AP_Q, _AP_O, _AP_N>(*this) \
1482#define DOUBLE_CMP_AF(Sym) \
1483 INLINE bool operator Sym(double d) const { return to_double() Sym d; }
1493 INLINE
af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> operator[](
1495 _AP_WARNING(index >= _AP_W,
"Attempting to read bit beyond MSB");
1499 template <
int _AP_W2,
bool _AP_S2>
1502 _AP_WARNING(index < 0,
"Attempting to read bit with negative index");
1503 _AP_WARNING(index >= _AP_W,
"Attempting to read bit beyond MSB");
1508 INLINE
bool operator[](
unsigned index)
const {
1509 _AP_WARNING(index >= _AP_W,
"Attempting to read bit beyond MSB");
1510 return _AP_ROOT_op_get_bit(
const_cast<ap_fixed_base*
>(
this)->V, index);
1515 _AP_WARNING(index >= _AP_W,
"Attempting to read bit beyond MSB");
1519 template <
int _AP_W2,
bool _AP_S2>
1522 _AP_WARNING(index < 0,
"Attempting to read bit with negative index");
1523 _AP_WARNING(index >= _AP_W,
"Attempting to read bit beyond MSB");
1528 INLINE
bool bit(
unsigned index)
const {
1529 _AP_WARNING(index >= _AP_W,
"Attempting to read bit beyond MSB");
1530 return _AP_ROOT_op_get_bit(
const_cast<ap_fixed_base*
>(
this)->V, index);
1533 template <
int _AP_W2>
1536 _AP_WARNING(index < _AP_I - _AP_W,
1537 "Attempting to read bit with negative index");
1538 _AP_WARNING(index >= _AP_I,
"Attempting to read bit beyond MSB");
1540 this, index.to_int() + _AP_W - _AP_I);
1543 INLINE
bool get_bit(
int index)
const {
1544 _AP_WARNING(index >= _AP_I,
"Attempting to read bit beyond MSB");
1545 _AP_WARNING(index < _AP_I - _AP_W,
"Attempting to read bit beyond MSB");
1546 return _AP_ROOT_op_get_bit(
const_cast<ap_fixed_base*
>(
this)->V,
1547 index + _AP_W - _AP_I);
1552 _AP_WARNING(index < _AP_I - _AP_W,
1553 "Attempting to read bit with negative index");
1554 _AP_WARNING(index >= _AP_I,
"Attempting to read bit beyond MSB");
1556 this, index + _AP_W - _AP_I);
1560 template <
int _AP_W2>
1562 _AP_WARNING(index >= _AP_I,
"Attempting to read bit beyond MSB");
1563 _AP_WARNING(index < _AP_I - _AP_W,
"Attempting to read bit beyond MSB");
1564 return _AP_ROOT_op_get_bit(
const_cast<ap_fixed_base*
>(
this)->V,
1565 index.to_int() + _AP_W - _AP_I);
1570 _AP_WARNING((Hi >= _AP_W) || (Lo >= _AP_W),
"Out of bounds in range()");
1576 int Hi,
int Lo)
const {
1577 _AP_WARNING((Hi >= _AP_W) || (Lo >= _AP_W),
"Out of bounds in range()");
1582 template <
int _AP_W2,
bool _AP_S2,
int _AP_W3,
bool _AP_S3>
1586 int Hi = HiIdx.to_int();
1587 int Lo = LoIdx.to_int();
1588 return this->range(Hi, Lo);
1591 template <
int _AP_W2,
bool _AP_S2,
int _AP_W3,
bool _AP_S3>
1595 int Hi = HiIdx.to_int();
1596 int Lo = LoIdx.to_int();
1597 return this->range(Hi, Lo);
1601 return this->range(_AP_W - 1, 0);
1605 return this->range(_AP_W - 1, 0);
1610 return this->range(Hi, Lo);
1614 int Hi,
int Lo)
const {
1615 return this->range(Hi, Lo);
1618 template <
int _AP_W2,
bool _AP_S2,
int _AP_W3,
bool _AP_S3>
1622 int Hi = HiIdx.to_int();
1623 int Lo = LoIdx.to_int();
1624 return this->range(Hi, Lo);
1627 template <
int _AP_W2,
bool _AP_S2,
int _AP_W3,
bool _AP_S3>
1631 int Hi = HiIdx.to_int();
1632 int Lo = LoIdx.to_int();
1633 return this->range(Hi, Lo);
1636 INLINE
bool is_zero()
const {
return Base::V == 0; }
1638 INLINE
bool is_neg()
const {
1639 if (_AP_S && _AP_ROOT_op_get_bit(Base::V, _AP_W - 1))
return true;
1643 INLINE
int wl()
const {
return _AP_W; }
1645 INLINE
int iwl()
const {
return _AP_I; }
1647 INLINE ap_q_mode q_mode()
const {
return _AP_Q; }
1649 INLINE ap_o_mode o_mode()
const {
return _AP_O; }
1651 INLINE
int n_bits()
const {
return _AP_N; }
1660#ifndef __SYNTHESIS__
1661 std::string to_string(
unsigned char radix = 2,
bool sign = _AP_S)
const {
1664 if (radix == 2) sign =
false;
1669 bool isNeg = sign && (Base::V < 0);
1700 ap_int_base<AP_MAX(_AP_I + 1, 1),
false> int_part;
1705 int_part.V = _AP_ROOT_op_get_range(tmp.V, _AP_W - _AP_I, _AP_W);
1706 str += int_part.to_string(radix,
false);
1712 ap_fixed_base<AP_MAX(_AP_W - _AP_I, 1), 0,
false> frac_part = tmp;
1715 if (frac_part != 0) {
1717 while (frac_part != 0) {
1718 char digit = (frac_part * radix).to_char();
1719 str +=
static_cast<char>(digit +
'0');
1724 if (frac_part != 0) {
1726 for (
signed i = _AP_W - _AP_I - 1; i >= 0; i -= step) {
1727 char digit = frac_part.range(i, AP_MAX(0, i - step + 1)).to_char();
1730 int offset = AP_MIN(0, i - step + 1);
1732 str += digit < 10 ? static_cast<char>(digit +
'0')
1733 : static_cast<char>(digit - 10 +
'a');
1743 INLINE
char* to_string(
unsigned char radix = 2,
bool sign = _AP_S)
const {
1749template <
int _AP_W,
int _AP_I,
bool _AP_S, ap_q_mode _AP_Q, ap_o_mode _AP_O,
1757template <
int _AP_W,
int _AP_I,
bool _AP_S, ap_q_mode _AP_Q, ap_o_mode _AP_O,
1763 ret.V = op1.V & op2.V;
1766template <
int _AP_W,
int _AP_I,
bool _AP_S, ap_q_mode _AP_Q, ap_o_mode _AP_O,
1772 ret.V = op1.V | op2.V;
1775template <
int _AP_W,
int _AP_I,
bool _AP_S, ap_q_mode _AP_Q, ap_o_mode _AP_O,
1781 ret.V = op1.V ^ op2.V;
1784template <
int _AP_W,
int _AP_I,
bool _AP_S, ap_q_mode _AP_Q, ap_o_mode _AP_O,
1785 int _AP_N,
int _AP_W2,
int _AP_I2,
bool _AP_S2, ap_q_mode _AP_Q2,
1786 ap_o_mode _AP_O2,
int _AP_N2>
1790 ap_fixed_base<_AP_W2 + !_AP_S2, _AP_I2 + !_AP_S2,
true, _AP_Q2, _AP_O2,
1797template <
int _AP_W,
int _AP_I,
bool _AP_S, ap_q_mode _AP_Q, ap_o_mode _AP_O,
1798 int _AP_N,
int _AP_W2,
int _AP_I2,
bool _AP_S2, ap_q_mode _AP_Q2,
1799 ap_o_mode _AP_O2,
int _AP_N2>
1805 F2 = _AP_W2 - _AP_I2,
1806 _AP_I3 = AP_MAX(_AP_I, _AP_I2),
1807 _AP_W3 = _AP_I3 + F2,
1817template <
int _AP_W,
int _AP_I,
bool _AP_S, ap_q_mode _AP_Q, ap_o_mode _AP_O,
1818 int _AP_N,
int _AP_W2,
int _AP_I2,
bool _AP_S2, ap_q_mode _AP_Q2,
1819 ap_o_mode _AP_O2,
int _AP_N2>
1826 F2 = _AP_W2 - _AP_I2,
1828 _AP_W3 = _AP_I2 + F3,
1834 if (sh >= 0) t.V <<= (int)sh;
1847#ifndef __SYNTHESIS__
1848INLINE std::string scientificFormat(std::string& input) {
1849 if (input.length() == 0)
return input;
1851 size_t decPosition = input.find(
'.');
1852 if (decPosition == std::string::npos) decPosition = input.length();
1854 size_t firstNonZeroPos = 0;
1855 for (; input[firstNonZeroPos] >
'9' || input[firstNonZeroPos] <
'1';
1860 if (firstNonZeroPos > decPosition)
1861 exp = decPosition - firstNonZeroPos;
1863 exp = decPosition - firstNonZeroPos - 1;
1864 std::string expString =
"";
1873 if (exp < 10 && exp > 0) {
1875 expString += (char)(
'0' + exp);
1876 }
else if (exp != 0) {
1879 std::ostringstream oss;
1886 int lastNonZeroPos = (int)(input.length() - 1);
1887 for (; lastNonZeroPos >= 0; --lastNonZeroPos)
1888 if (input[lastNonZeroPos] <=
'9' && input[lastNonZeroPos] >
'0')
break;
1890 std::string ans =
"";
1891 ans += input[firstNonZeroPos];
1892 if (firstNonZeroPos != (
size_t)lastNonZeroPos) {
1894 for (
int i = firstNonZeroPos + 1; i <= lastNonZeroPos; i++)
1895 if (input[i] !=
'.') ans += input[i];
1902INLINE std::string reduceToPrecision(std::string& input,
int precision) {
1904 size_t inputLen = input.length();
1905 for (
size_t i = 0; i < inputLen && isZero; i++)
1906 if (input[i] !=
'.' && input[i] !=
'0') isZero =
false;
1907 if (isZero)
return "0";
1910 int FirstNonZeroPos = 0;
1911 int LastNonZeroPos = (int)inputLen - 1;
1912 int truncBitPosition = 0;
1913 size_t decPosition = input.find(
'.');
1914 for (; input[FirstNonZeroPos] <
'1' || input[FirstNonZeroPos] >
'9';
1918 for (; input[LastNonZeroPos] <
'1' || input[LastNonZeroPos] >
'9';
1922 if (decPosition == std::string::npos) decPosition = inputLen;
1924 if ((
int)decPosition > LastNonZeroPos) {
1925 if (LastNonZeroPos - FirstNonZeroPos + 1 <= precision)
return input;
1926 truncBitPosition = FirstNonZeroPos + precision;
1927 }
else if ((
int)decPosition < FirstNonZeroPos) {
1928 if (LastNonZeroPos - FirstNonZeroPos + 1 <= precision) {
1929 if (FirstNonZeroPos - decPosition - 1 < 4) {
1932 if (input[0] ==
'-') {
1933 std::string tmp = input.substr(1, inputLen - 1);
1934 return std::string(
"-") + scientificFormat(tmp);
1936 return scientificFormat(input);
1939 truncBitPosition = FirstNonZeroPos + precision;
1941 if (LastNonZeroPos - FirstNonZeroPos <= precision)
return input;
1942 truncBitPosition = FirstNonZeroPos + precision + 1;
1947 std::string ans =
"";
1948 std::string dupInput =
"0";
1949 if (input[0] ==
'-') {
1951 dupInput += input.substr(1, inputLen - 1);
1953 dupInput += input.substr(0, inputLen);
1958 bool carry = dupInput[truncBitPosition] >
'4';
1959 for (
int i = truncBitPosition - 1; i >= 0 && carry; i--) {
1960 if (dupInput[i] ==
'.')
continue;
1961 if (dupInput[i] ==
'9')
1970 if (dupInput[0] ==
'1')
1971 FirstNonZeroPos = 0;
1973 FirstNonZeroPos = 0;
1974 while (dupInput[FirstNonZeroPos] <
'1' || dupInput[FirstNonZeroPos] >
'9')
1978 unsigned it = FirstNonZeroPos;
1979 int NValidNumber = 0;
1980 while (it < dupInput.length()) {
1981 if (dupInput[it] ==
'.') {
1986 if (NValidNumber > precision) dupInput[it] =
'0';
1991 decPosition = dupInput.find(
'.');
1992 if (decPosition == std::string::npos)
1993 truncBitPosition = (int)dupInput.length();
1995 for (truncBitPosition = (
int)(dupInput.length() - 1); truncBitPosition >= 0;
1996 --truncBitPosition) {
1997 if (dupInput[truncBitPosition] ==
'.')
break;
1998 if (dupInput[truncBitPosition] !=
'0') {
2004 if (dupInput[0] ==
'1')
2005 dupInput = dupInput.substr(0, truncBitPosition);
2007 dupInput = dupInput.substr(1, truncBitPosition - 1);
2009 decPosition = dupInput.find(
'.');
2010 if (decPosition != std::string::npos) {
2012 for (it = decPosition + 1; dupInput[it] ==
'0'; it++)
2014 if (it - decPosition - 1 < 4) {
2018 ans += scientificFormat(dupInput);
2021 }
else if ((
int)(dupInput.length()) <= precision) {
2026 ans += scientificFormat(dupInput);
2030template <
int _AP_W,
int _AP_I,
bool _AP_S, ap_q_mode _AP_Q, ap_o_mode _AP_O,
2036 p1.V = x.V >> (_AP_W - _AP_I);
2042 if (_AP_I < _AP_W) {
2044 p2.V = _AP_ROOT_op_get_range(x.V, 0, _AP_W - _AP_I);
2058#ifndef __SYNTHESIS__
2059template <
int _AP_W,
int _AP_I,
bool _AP_S, ap_q_mode _AP_Q, ap_o_mode _AP_O,
2061INLINE std::ostream& operator<<(
2065 unsigned width = out.width();
2066 unsigned precision = out.precision();
2067 char fill = out.fill();
2068 std::string str = x.to_string(10, _AP_S);
2069 str = reduceToPrecision(str, precision);
2070 if (width > str.length()) {
2071 for (
unsigned i = 0; i < width - str.length(); ++i) out << fill;
2080#ifndef __SYNTHESIS__
2081template <
int _AP_W,
int _AP_I,
bool _AP_S, ap_q_mode _AP_Q, ap_o_mode _AP_O,
2083INLINE std::istream& operator>>(
2096#define AF_BIN_OP_WITH_INT_SF(BIN_OP, C_TYPE, _AP_W2, _AP_S2, RTYPE) \
2097 template <int _AP_W, int _AP_I, bool _AP_S, ap_q_mode _AP_Q, \
2098 ap_o_mode _AP_O, int _AP_N> \
2099 INLINE typename ap_fixed_base<_AP_W, _AP_I, _AP_S>::template RType< \
2100 _AP_W2, _AP_W2, _AP_S2>::RTYPE \
2102 const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, \
2104 return op.operator BIN_OP(ap_int_base<_AP_W2, _AP_S2>(i_op)); \
2107#define AF_BIN_OP_WITH_INT(BIN_OP, C_TYPE, _AP_W2, _AP_S2, RTYPE) \
2108 template <int _AP_W, int _AP_I, bool _AP_S, ap_q_mode _AP_Q, \
2109 ap_o_mode _AP_O, int _AP_N> \
2110 INLINE typename ap_fixed_base<_AP_W, _AP_I, _AP_S>::template RType< \
2111 _AP_W2, _AP_W2, _AP_S2>::RTYPE \
2113 const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, \
2115 return op.operator BIN_OP(ap_fixed_base<_AP_W2, _AP_W2, _AP_S2>(i_op)); \
2117 template <int _AP_W, int _AP_I, bool _AP_S, ap_q_mode _AP_Q, \
2118 ap_o_mode _AP_O, int _AP_N> \
2119 INLINE typename ap_fixed_base<_AP_W, _AP_I, _AP_S>::template RType< \
2120 _AP_W2, _AP_W2, _AP_S2>::RTYPE \
2123 const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { \
2124 return ap_fixed_base<_AP_W2, _AP_W2, _AP_S2>(i_op).operator BIN_OP(op); \
2127#define AF_REL_OP_WITH_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \
2128 template <int _AP_W, int _AP_I, bool _AP_S, ap_q_mode _AP_Q, \
2129 ap_o_mode _AP_O, int _AP_N> \
2130 INLINE bool operator REL_OP( \
2131 const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, \
2133 return op.operator REL_OP(ap_fixed_base<_AP_W2, _AP_W2, _AP_S2>(i_op)); \
2135 template <int _AP_W, int _AP_I, bool _AP_S, ap_q_mode _AP_Q, \
2136 ap_o_mode _AP_O, int _AP_N> \
2137 INLINE bool operator REL_OP( \
2139 const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { \
2140 return ap_fixed_base<_AP_W2, _AP_W2, _AP_S2>(i_op).operator REL_OP(op); \
2143#define AF_ASSIGN_OP_WITH_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \
2144 template <int _AP_W, int _AP_I, bool _AP_S, ap_q_mode _AP_Q, \
2145 ap_o_mode _AP_O, int _AP_N> \
2146 INLINE ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& \
2147 operator ASSIGN_OP( \
2148 ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, \
2150 return op.operator ASSIGN_OP(ap_fixed_base<_AP_W2, _AP_W2, _AP_S2>(i_op)); \
2153#define AF_ASSIGN_OP_WITH_INT_SF(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \
2154 template <int _AP_W, int _AP_I, bool _AP_S, ap_q_mode _AP_Q, \
2155 ap_o_mode _AP_O, int _AP_N> \
2156 INLINE ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& \
2157 operator ASSIGN_OP( \
2158 ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, \
2160 return op.operator ASSIGN_OP(ap_int_base<_AP_W2, _AP_S2>(i_op)); \
2163#define ALL_AF_OP_WITH_INT(C_TYPE, BITS, SIGN) \
2164 AF_BIN_OP_WITH_INT(+, C_TYPE, (BITS), (SIGN), plus) \
2165 AF_BIN_OP_WITH_INT(-, C_TYPE, (BITS), (SIGN), minus) \
2166 AF_BIN_OP_WITH_INT(*, C_TYPE, (BITS), (SIGN), mult) \
2167 AF_BIN_OP_WITH_INT(/, C_TYPE, (BITS), (SIGN), div) \
2168 AF_BIN_OP_WITH_INT(&, C_TYPE, (BITS), (SIGN), logic) \
2169 AF_BIN_OP_WITH_INT(|, C_TYPE, (BITS), (SIGN), logic) \
2170 AF_BIN_OP_WITH_INT(^, C_TYPE, (BITS), (SIGN), logic) \
2171 AF_BIN_OP_WITH_INT_SF(>>, C_TYPE, (BITS), (SIGN), lhs) \
2172 AF_BIN_OP_WITH_INT_SF(<<, C_TYPE, (BITS), (SIGN), lhs) \
2174 AF_ASSIGN_OP_WITH_INT(+=, C_TYPE, (BITS), (SIGN)) \
2175 AF_ASSIGN_OP_WITH_INT(-=, C_TYPE, (BITS), (SIGN)) \
2176 AF_ASSIGN_OP_WITH_INT(*=, C_TYPE, (BITS), (SIGN)) \
2177 AF_ASSIGN_OP_WITH_INT(/=, C_TYPE, (BITS), (SIGN)) \
2178 AF_ASSIGN_OP_WITH_INT(&=, C_TYPE, (BITS), (SIGN)) \
2179 AF_ASSIGN_OP_WITH_INT(|=, C_TYPE, (BITS), (SIGN)) \
2180 AF_ASSIGN_OP_WITH_INT(^=, C_TYPE, (BITS), (SIGN)) \
2181 AF_ASSIGN_OP_WITH_INT_SF(>>=, C_TYPE, (BITS), (SIGN)) \
2182 AF_ASSIGN_OP_WITH_INT_SF(<<=, C_TYPE, (BITS), (SIGN)) \
2184 AF_REL_OP_WITH_INT(>, C_TYPE, (BITS), (SIGN)) \
2185 AF_REL_OP_WITH_INT(<, C_TYPE, (BITS), (SIGN)) \
2186 AF_REL_OP_WITH_INT(>=, C_TYPE, (BITS), (SIGN)) \
2187 AF_REL_OP_WITH_INT(<=, C_TYPE, (BITS), (SIGN)) \
2188 AF_REL_OP_WITH_INT(==, C_TYPE, (BITS), (SIGN)) \
2189 AF_REL_OP_WITH_INT(!=, C_TYPE, (BITS), (SIGN))
2191ALL_AF_OP_WITH_INT(
bool, 1,
false)
2192ALL_AF_OP_WITH_INT(
char, 8, CHAR_IS_SIGNED)
2193ALL_AF_OP_WITH_INT(
signed char, 8, true)
2194ALL_AF_OP_WITH_INT(
unsigned char, 8, false)
2195ALL_AF_OP_WITH_INT(
short, _AP_SIZE_short, true)
2196ALL_AF_OP_WITH_INT(
unsigned short, _AP_SIZE_short, false)
2197ALL_AF_OP_WITH_INT(
int, _AP_SIZE_int, true)
2198ALL_AF_OP_WITH_INT(
unsigned int, _AP_SIZE_int, false)
2199ALL_AF_OP_WITH_INT(
long, _AP_SIZE_long, true)
2200ALL_AF_OP_WITH_INT(
unsigned long, _AP_SIZE_long, false)
2201ALL_AF_OP_WITH_INT(ap_slong, _AP_SIZE_ap_slong, true)
2202ALL_AF_OP_WITH_INT(ap_ulong, _AP_SIZE_ap_slong, false)
2204#undef ALL_AF_OP_WITH_INT
2205#undef AF_BIN_OP_WITH_INT
2206#undef AF_BIN_OP_WITH_INT_SF
2207#undef AF_ASSIGN_OP_WITH_INT
2208#undef AF_ASSIGN_OP_WITH_INT_SF
2209#undef AF_REL_OP_WITH_INT
2223#define AF_BIN_OP_WITH_AP_INT(BIN_OP, RTYPE) \
2224 template <int _AP_W, int _AP_I, bool _AP_S, ap_q_mode _AP_Q, \
2225 ap_o_mode _AP_O, int _AP_N, int _AP_W2, bool _AP_S2> \
2226 INLINE typename ap_fixed_base<_AP_W2, _AP_W2, _AP_S2>::template RType< \
2227 _AP_W, _AP_I, _AP_S>::RTYPE \
2229 const ap_int_base<_AP_W2, _AP_S2>& i_op, \
2230 const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { \
2231 return ap_fixed_base<_AP_W2, _AP_W2, _AP_S2>(i_op).operator BIN_OP(op); \
2234 template <int _AP_W, int _AP_I, bool _AP_S, ap_q_mode _AP_Q, \
2235 ap_o_mode _AP_O, int _AP_N, int _AP_W2, bool _AP_S2> \
2236 INLINE typename ap_fixed_base<_AP_W, _AP_I, _AP_S>::template RType< \
2237 _AP_W2, _AP_W2, _AP_S2>::RTYPE \
2239 const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, \
2240 const ap_int_base<_AP_W2, _AP_S2>& i_op) { \
2241 return op.operator BIN_OP(ap_fixed_base<_AP_W2, _AP_W2, _AP_S2>(i_op)); \
2244#define AF_REL_OP_WITH_AP_INT(REL_OP) \
2245 template <int _AP_W, int _AP_I, bool _AP_S, ap_q_mode _AP_Q, \
2246 ap_o_mode _AP_O, int _AP_N, int _AP_W2, bool _AP_S2> \
2247 INLINE bool operator REL_OP( \
2248 const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, \
2249 const ap_int_base<_AP_W2, _AP_S2>& i_op) { \
2250 return op.operator REL_OP(ap_fixed_base<_AP_W2, _AP_W2, _AP_S2>(i_op)); \
2253 template <int _AP_W, int _AP_I, bool _AP_S, ap_q_mode _AP_Q, \
2254 ap_o_mode _AP_O, int _AP_N, int _AP_W2, bool _AP_S2> \
2255 INLINE bool operator REL_OP( \
2256 const ap_int_base<_AP_W2, _AP_S2>& i_op, \
2257 const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { \
2258 return ap_fixed_base<_AP_W2, _AP_W2, _AP_S2>(i_op).operator REL_OP(op); \
2261#define AF_ASSIGN_OP_WITH_AP_INT(ASSIGN_OP) \
2262 template <int _AP_W, int _AP_I, bool _AP_S, ap_q_mode _AP_Q, \
2263 ap_o_mode _AP_O, int _AP_N, int _AP_W2, bool _AP_S2> \
2264 INLINE ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& \
2265 operator ASSIGN_OP( \
2266 ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, \
2267 const ap_int_base<_AP_W2, _AP_S2>& i_op) { \
2268 return op.operator ASSIGN_OP(ap_fixed_base<_AP_W2, _AP_W2, _AP_S2>(i_op)); \
2271 template <int _AP_W, int _AP_I, bool _AP_S, ap_q_mode _AP_Q, \
2272 ap_o_mode _AP_O, int _AP_N, int _AP_W2, bool _AP_S2> \
2273 INLINE ap_int_base<_AP_W2, _AP_S2>& operator ASSIGN_OP( \
2274 ap_int_base<_AP_W2, _AP_S2>& i_op, \
2275 const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { \
2276 return i_op.operator ASSIGN_OP(op.to_ap_int_base()); \
2279AF_BIN_OP_WITH_AP_INT(+, plus)
2280AF_BIN_OP_WITH_AP_INT(-, minus)
2281AF_BIN_OP_WITH_AP_INT(*, mult)
2282AF_BIN_OP_WITH_AP_INT(/, div)
2283AF_BIN_OP_WITH_AP_INT(&, logic)
2284AF_BIN_OP_WITH_AP_INT(|, logic)
2285AF_BIN_OP_WITH_AP_INT(^, logic)
2287#undef AF_BIN_OP_WITH_AP_INT
2289AF_ASSIGN_OP_WITH_AP_INT(+=)
2290AF_ASSIGN_OP_WITH_AP_INT(-=)
2291AF_ASSIGN_OP_WITH_AP_INT(*=)
2292AF_ASSIGN_OP_WITH_AP_INT(/=)
2293AF_ASSIGN_OP_WITH_AP_INT(&=)
2294AF_ASSIGN_OP_WITH_AP_INT(|=)
2295AF_ASSIGN_OP_WITH_AP_INT(^=)
2297#undef AF_ASSIGN_OP_WITH_AP_INT
2299AF_REL_OP_WITH_AP_INT(==)
2300AF_REL_OP_WITH_AP_INT(!=)
2301AF_REL_OP_WITH_AP_INT(>)
2302AF_REL_OP_WITH_AP_INT(>=)
2303AF_REL_OP_WITH_AP_INT(<)
2304AF_REL_OP_WITH_AP_INT(<=)
2306#undef AF_REL_OP_WITH_AP_INT
2309template <
int _AP_W,
int _AP_I,
bool _AP_S, ap_q_mode _AP_Q, ap_o_mode _AP_O,
2311INLINE
bool operator==(
2314 return op2.operator==(op1);
2317template <
int _AP_W,
int _AP_I,
bool _AP_S, ap_q_mode _AP_Q, ap_o_mode _AP_O,
2319INLINE
bool operator!=(
2322 return op2.operator!=(op1);
2325template <
int _AP_W,
int _AP_I,
bool _AP_S, ap_q_mode _AP_Q, ap_o_mode _AP_O,
2327INLINE
bool operator>(
2330 return op2.operator<(op1);
2333template <
int _AP_W,
int _AP_I,
bool _AP_S, ap_q_mode _AP_Q, ap_o_mode _AP_O,
2335INLINE
bool operator>=(
2338 return op2.operator<=(op1);
2341template <
int _AP_W,
int _AP_I,
bool _AP_S, ap_q_mode _AP_Q, ap_o_mode _AP_O,
2343INLINE
bool operator<(
2346 return op2.operator>(op1);
2349template <
int _AP_W,
int _AP_I,
bool _AP_S, ap_q_mode _AP_Q, ap_o_mode _AP_O,
2351INLINE
bool operator<=(
2354 return op2.operator>=(op1);
conditions objects which are tables indexed by raw detector id values
Signed Arbitrary Precision Fixed-Point Type.