Deleted Added
sdiff udiff text old ( 12854:c95c35407325 ) new ( 13322:7391057615bd )
full compact
1/*****************************************************************************
2
3 Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
4 more contributor license agreements. See the NOTICE file distributed
5 with this work for additional information regarding copyright ownership.
6 Accellera licenses this file to you under the Apache License, Version 2.0
7 (the "License"); you may not use this file except in compliance with the
8 License. You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 implied. See the License for the specific language governing
16 permissions and limitations under the License.
17
18 *****************************************************************************/
19
20/*****************************************************************************
21
22 sc_fxval.cpp -
23
24 Original Author: Martin Janssen, Synopsys, Inc.
25
26 *****************************************************************************/
27
28/*****************************************************************************
29
30 MODIFICATION LOG - modifiers, enter your name, affiliation, date and
31 changes you are making here.
32
33 Name, Affiliation, Date:
34 Description of Modification:
35
36 *****************************************************************************/
37
38
39// $Log: sc_fxval.cpp,v $
40// Revision 1.1.1.1 2006/12/15 20:20:04 acg
41// SystemC 2.3
42//
43// Revision 1.3 2006/01/13 18:53:58 acg
44// Andy Goodrich: added $Log command so that CVS comments are reproduced in
45// the source.
46//
47
48#include <cctype>
49#include <cfloat>
50#include <cmath>
51#include <cstdlib>
52
53#include "systemc/ext/dt/fx/sc_fxval.hh"
54
55namespace sc_dt
56{
57
58// ----------------------------------------------------------------------------
59// CLASS : sc_fxval
60//
61// Fixed-point value type; arbitrary precision.
62// ----------------------------------------------------------------------------
63
64// explicit conversion to character string
65
66const std::string
67sc_fxval::to_string() const
68{
69 return std::string(m_rep->to_string(SC_DEC, -1, SC_E));
70}
71
72const std::string
73sc_fxval::to_string(sc_numrep numrep) const
74{
75 return std::string(m_rep->to_string(numrep, -1, SC_E));
76}
77
78const std::string
79sc_fxval::to_string(sc_numrep numrep, bool w_prefix) const
80{
81 return std::string(m_rep->to_string(numrep, (w_prefix ? 1 : 0), SC_E));
82}
83
84const std::string
85sc_fxval::to_string(sc_fmt fmt) const
86{
87 return std::string(m_rep->to_string(SC_DEC, -1, fmt));
88}
89
90const std::string
91sc_fxval::to_string(sc_numrep numrep, sc_fmt fmt) const
92{
93 return std::string(m_rep->to_string(numrep, -1, fmt));
94}
95
96const std::string
97sc_fxval::to_string(sc_numrep numrep, bool w_prefix, sc_fmt fmt) const
98{
99 return std::string(m_rep->to_string(numrep, (w_prefix ? 1 : 0), fmt));
100}
101
102
103const std::string
104sc_fxval::to_dec() const
105{
106 return std::string(m_rep->to_string(SC_DEC, -1, SC_E));
107}
108
109const std::string
110sc_fxval::to_bin() const
111{
112 return std::string(m_rep->to_string(SC_BIN, -1, SC_E));
113}
114
115const std::string
116sc_fxval::to_oct() const
117{
118 return std::string(m_rep->to_string(SC_OCT, -1, SC_E));
119}
120
121const std::string
122sc_fxval::to_hex() const
123{
124 return std::string(m_rep->to_string(SC_HEX, -1, SC_E));
125}
126
127
128// print or dump content
129
130void sc_fxval::print(::std::ostream &os) const { m_rep->print(os); }
131
132void
133sc_fxval::scan(::std::istream &is)
134{
135 std::string s;
136 is >> s;
137 *this = s.c_str();
138}
139
140void
141sc_fxval::dump(::std::ostream &os) const
142{
143 os << "sc_fxval" << ::std::endl;
144 os << "(" << ::std::endl;
145 os << "rep = ";
146 m_rep->dump(os);
147 // TO BE COMPLETED
148 // os << "r_flag = " << m_r_flag << ::std::endl;
149 // os << "observer = ";
150 // if (m_observer != 0)
151 // m_observer->dump(os);
152 // else
153 // os << "0" << ::std::endl;
154 os << ")" << ::std::endl;
155}
156
157// protected methods and friend functions
158sc_fxval_observer *
159sc_fxval::lock_observer() const
160{
161 SC_ASSERT_(m_observer != 0, "lock observer failed");
162 sc_fxval_observer *tmp = m_observer;
163 m_observer = 0;
164 return tmp;
165}
166
167void
168sc_fxval::unlock_observer(sc_fxval_observer *observer_) const
169{
170 SC_ASSERT_(observer_ != 0, "unlock observer failed");
171 m_observer = observer_;
172}
173
174
175// ----------------------------------------------------------------------------
176// CLASS : sc_fxval_fast
177//
178// Fixed-point value types; limited precision.
179// ----------------------------------------------------------------------------
180
181static void
182print_dec(scfx_string &s, scfx_ieee_double id, int w_prefix, sc_fmt fmt)
183{
184 if (id.negative() != 0) {
185 id.negative(0);
186 s += '-';
187 }
188
189 if (w_prefix == 1) {
190 scfx_print_prefix(s, SC_DEC);
191 }
192
193 if (id.is_zero()) {
194 s += '0';
195 return;
196 }
197
198 // split 'id' into its integer and fractional part
199 double int_part;
200 double frac_part = std::modf(static_cast<double>(id), &int_part);
201
202 int i;
203
204 // print integer part
205 int int_digits = 0;
206 int int_zeros = 0;
207
208 if (int_part != 0.0) {
209 int_digits = (int)std::ceil(std::log10(int_part + 1.0));
210
211 int len = s.length();
212 s.append(int_digits);
213
214 bool zero_digits = (frac_part == 0.0 && fmt != SC_F);
215
216 for (i = int_digits + len - 1; i >= len; i--) {
217 unsigned int remainder = (unsigned int)std::fmod(int_part, 10.0);
218 s[i] = static_cast<char>('0' + remainder);
219
220 if (zero_digits) {
221 if (remainder == 0)
222 int_zeros++;
223 else
224 zero_digits = false;
225 }
226
227 int_part /= 10.0;
228 }
229
230 // discard trailing zeros from int_part
231 s.discard(int_zeros);
232
233 if (s[len] == '0') {
234 // int_digits was overestimated by one
235 s.remove(len);
236 --int_digits;
237 }
238 }
239
240 // print fractional part
241 int frac_digits = 0;
242 int frac_zeros = 0;
243
244 if (frac_part != 0.0) {
245 s += '.';
246
247 bool zero_digits = (int_digits == 0 && fmt != SC_F);
248
249 frac_zeros = (int)std::floor(-std::log10(frac_part + DBL_EPSILON));
250
251 frac_part *= std::pow(10.0, frac_zeros);
252
253 frac_digits = frac_zeros;
254 if (!zero_digits) {
255 for (i = 0; i < frac_zeros; i++)
256 s += '0';
257 frac_zeros = 0;
258 }
259
260 while (frac_part != 0.0) {
261 frac_part *= 10.0;
262 int n = static_cast<int>(frac_part);
263
264 if (zero_digits) {
265 if (n == 0)
266 frac_zeros++;
267 else
268 zero_digits = false;
269 }
270
271 if (!zero_digits)
272 s += static_cast<char>('0' + n);
273
274 frac_part -= n;
275 frac_digits++;
276 }
277 }
278
279 // print exponent
280 if (fmt != SC_F) {
281 if (frac_digits == 0)
282 scfx_print_exp(s, int_zeros);
283 else if (int_digits == 0)
284 scfx_print_exp(s, -frac_zeros);
285 }
286}
287
288static void
289print_other(scfx_string &s, const scfx_ieee_double &id, sc_numrep numrep,
290 int w_prefix, sc_fmt fmt, const scfx_params *params)
291{
292 scfx_ieee_double id2 = id;
293
294 sc_numrep numrep2 = numrep;
295
296 bool numrep_is_sm = (numrep == SC_BIN_SM ||
297 numrep == SC_OCT_SM ||
298 numrep == SC_HEX_SM);
299
300 if (numrep_is_sm) {
301 if (id2.negative() != 0) {
302 s += '-';
303 id2.negative(0);
304 }
305 switch (numrep) {
306 case SC_BIN_SM:
307 numrep2 = SC_BIN_US;
308 break;
309 case SC_OCT_SM:
310 numrep2 = SC_OCT_US;
311 break;
312 case SC_HEX_SM:
313 numrep2 = SC_HEX_US;
314 break;
315 default:
316 ;
317 }
318 }
319
320 if (w_prefix != 0) {
321 scfx_print_prefix(s, numrep);
322 }
323
324 numrep = numrep2;
325
326 sc_fxval_fast a(id2);
327
328 int msb, lsb;
329
330 if (params != 0) {
331 msb = params->iwl() - 1;
332 lsb = params->iwl() - params->wl();
333
334 if (params->enc() == SC_TC_ &&
335 (numrep == SC_BIN_US ||
336 numrep == SC_OCT_US ||
337 numrep == SC_HEX_US) &&
338 !numrep_is_sm &&
339 params->wl() > 1) {
340 --msb;
341 } else if (params->enc() == SC_US_ &&
342 (numrep == SC_BIN ||
343 numrep == SC_OCT ||
344 numrep == SC_HEX ||
345 numrep == SC_CSD)) {
346 ++msb;
347 }
348 } else {
349 if (a.is_zero()) {
350 msb = 0;
351 lsb = 0;
352 } else {
353 msb = id2.exponent() + 1;
354 while (a.get_bit(msb) == a.get_bit(msb - 1))
355 --msb;
356
357 if (numrep == SC_BIN_US ||
358 numrep == SC_OCT_US ||
359 numrep == SC_HEX_US) {
360 --msb;
361 }
362
363 lsb = id2.exponent() - 52;
364 while (!a.get_bit(lsb))
365 ++lsb;
366 }
367 }
368
369 int step;
370
371 switch (numrep) {
372 case SC_BIN:
373 case SC_BIN_US:
374 case SC_CSD:
375 step = 1;
376 break;
377 case SC_OCT:
378 case SC_OCT_US:
379 step = 3;
380 break;
381 case SC_HEX:
382 case SC_HEX_US:
383 step = 4;
384 break;
385 default:
386 SC_REPORT_FATAL("assertion failed", "unexpected sc_numrep");
387 sc_core::sc_abort();
388 }
389
390 msb = (int)std::ceil(double(msb + 1) / step) * step - 1;
391
392 lsb = (int)std::floor(double(lsb) / step) * step;
393
394 if (msb < 0) {
395 s += '.';
396 if (fmt == SC_F) {
397 int sign = (id2.negative() != 0) ? (1 << step) - 1 : 0;
398 for (int i = (msb + 1) / step; i < 0; i++) {
399 if (sign < 10)
400 s += static_cast<char>(sign + '0');
401 else
402 s += static_cast<char>(sign + 'a' - 10);
403 }
404 }
405 }
406
407 int i = msb;
408 while (i >= lsb) {
409 int value = 0;
410 for (int j = step - 1; j >= 0; --j) {
411 value += static_cast<int>(a.get_bit(i)) << j;
412 --i;
413 }
414 if (value < 10)
415 s += static_cast<char>(value + '0');
416 else
417 s += static_cast<char>(value + 'a' - 10);
418 if (i == -1)
419 s += '.';
420 }
421
422 if (lsb > 0 && fmt == SC_F) {
423 for (int i = lsb / step; i > 0; i--)
424 s += '0';
425 }
426
427 if (s[s.length() - 1] == '.')
428 s.discard(1);
429
430 if (fmt != SC_F) {
431 if (msb < 0)
432 scfx_print_exp(s, (msb + 1) / step);
433 else if (lsb > 0)
434 scfx_print_exp(s, lsb / step);
435 }
436
437 if (numrep == SC_CSD)
438 scfx_tc2csd(s, w_prefix);
439}
440
441const char *
442to_string(const scfx_ieee_double &id, sc_numrep numrep, int w_prefix,
443 sc_fmt fmt, const scfx_params *params=0)
444{
445 static scfx_string s;
446
447 s.clear();
448
449 if (id.is_nan()) {
450 scfx_print_nan(s);
451 } else if (id.is_inf()) {
452 scfx_print_inf(s, static_cast<bool>(id.negative()));
453 } else if (id.negative() && !id.is_zero() &&
454 (numrep == SC_BIN_US ||
455 numrep == SC_OCT_US ||
456 numrep == SC_HEX_US)) {
457 s += "negative";
458 } else if (numrep == SC_DEC) {
459 sc_dt::print_dec(s, id, w_prefix, fmt);
460 } else {
461 sc_dt::print_other(s, id, numrep, w_prefix, fmt, params);
462 }
463
464 return s;
465}
466
467
468// explicit conversion to character string
469const std::string
470sc_fxval_fast::to_string() const
471{
472 return std::string(sc_dt::to_string(m_val, SC_DEC, -1, SC_E));
473}
474
475const std::string
476sc_fxval_fast::to_string(sc_numrep numrep) const
477{
478 return std::string(sc_dt::to_string(m_val, numrep, -1, SC_E));
479}
480
481const std::string
482sc_fxval_fast::to_string(sc_numrep numrep, bool w_prefix) const
483{
484 return std::string(sc_dt::to_string(m_val, numrep, (w_prefix ? 1 : 0),
485 SC_E));
486}
487
488const std::string
489sc_fxval_fast::to_string(sc_fmt fmt) const
490{
491 return std::string(sc_dt::to_string(m_val, SC_DEC, -1, fmt));
492}
493
494const std::string
495sc_fxval_fast::to_string(sc_numrep numrep, sc_fmt fmt) const
496{
497 return std::string(sc_dt::to_string(m_val, numrep, -1, fmt));
498}
499
500const std::string
501sc_fxval_fast::to_string(sc_numrep numrep, bool w_prefix, sc_fmt fmt) const
502{
503 return std::string(sc_dt::to_string(m_val, numrep, (w_prefix ? 1 : 0),
504 fmt));
505}
506
507const std::string
508sc_fxval_fast::to_dec() const
509{
510 return std::string(sc_dt::to_string(m_val, SC_DEC, -1, SC_E));
511}
512
513const std::string
514sc_fxval_fast::to_bin() const
515{
516 return std::string(sc_dt::to_string(m_val, SC_BIN, -1, SC_E));
517}
518
519const std::string
520sc_fxval_fast::to_oct() const
521{
522 return std::string(sc_dt::to_string(m_val, SC_OCT, -1, SC_E));
523}
524
525const std::string
526sc_fxval_fast::to_hex() const
527{
528 return std::string(sc_dt::to_string(m_val, SC_HEX, -1, SC_E));
529}
530
531
532// print or dump content
533
534void
535sc_fxval_fast::print(::std::ostream &os) const
536{
537 os << sc_dt::to_string(m_val, SC_DEC, -1, SC_E);
538}
539
540void
541sc_fxval_fast::scan(::std::istream &is)
542{
543 std::string s;
544 is >> s;
545 *this = s.c_str();
546}
547
548void
549sc_fxval_fast::dump(::std::ostream &os) const
550{
551 os << "sc_fxval_fast" << ::std::endl;
552 os << "(" << ::std::endl;
553 os << "val = " << m_val << ::std::endl;
554 // TO BE COMPLETED
555 // os << "r_flag = " << m_r_flag << ::std::endl;
556 // os << "observer = ";
557 // if (m_observer != 0)
558 // m_observer->dump(os);
559 // else
560 // os << "0" << ::std::endl;
561 os << ")" << ::std::endl;
562}
563
564
565// internal use only;
566bool
567sc_fxval_fast::get_bit(int i) const
568{
569 scfx_ieee_double id(m_val);
570 if (id.is_zero() || id.is_nan() || id.is_inf())
571 return false;
572
573 // convert to two's complement
574 unsigned int m0 = id.mantissa0();
575 unsigned int m1 = id.mantissa1();
576
577 if (id.is_normal())
578 m0 += 1U << 20;
579
580 if (id.negative() != 0) {
581 m0 = ~ m0;
582 m1 = ~ m1;
583 unsigned int tmp = m1;
584 m1 += 1U;
585 if (m1 <= tmp)
586 m0 += 1U;
587 }
588
589 // get the right bit
590 int j = i - id.exponent();
591 if ((j += 20) >= 32)
592 return ((m0 & 1U << 31) != 0);
593 else if (j >= 0)
594 return ((m0 & 1U << j) != 0);
595 else if ((j += 32) >= 0)
596 return ((m1 & 1U << j) != 0);
597 else
598 return false;
599}
600
601
602// protected methods and friend functions
603sc_fxval_fast_observer *
604sc_fxval_fast::lock_observer() const
605{
606 SC_ASSERT_(m_observer != 0, "lock observer failed");
607 sc_fxval_fast_observer *tmp = m_observer;
608 m_observer = 0;
609 return tmp;
610}
611
612void
613sc_fxval_fast::unlock_observer(sc_fxval_fast_observer *observer_) const
614{
615 SC_ASSERT_(observer_ != 0, "unlock observer failed");
616 m_observer = observer_;
617}
618
619#define SCFX_FAIL_IF_(cnd) \
620{ \
621 if ((cnd)) \
622 return static_cast<double>(scfx_ieee_double::nan()); \
623}
624
625double
626sc_fxval_fast::from_string(const char *s)
627{
628 SCFX_FAIL_IF_(s == 0 || *s == 0);
629
630 scfx_string s2;
631 s2 += s;
632 s2 += '\0';
633
634 bool sign_char;
635 int sign = scfx_parse_sign(s, sign_char);
636
637 sc_numrep numrep = scfx_parse_prefix(s);
638
639 int base = 0;
640
641 switch (numrep) {
642 case SC_DEC:
643 {
644 base = 10;
645 if (scfx_is_nan(s)) // special case: NaN
646 return static_cast<double>(scfx_ieee_double::nan());
647 if (scfx_is_inf(s)) // special case: Infinity
648 return static_cast<double>(scfx_ieee_double::inf(sign));
649 break;
650 }
651 case SC_BIN:
652 case SC_BIN_US:
653 {
654 SCFX_FAIL_IF_(sign_char);
655 base = 2;
656 break;
657 }
658
659 case SC_BIN_SM:
660 {
661 base = 2;
662 break;
663 }
664 case SC_OCT:
665 case SC_OCT_US:
666 {
667 SCFX_FAIL_IF_(sign_char);
668 base = 8;
669 break;
670 }
671 case SC_OCT_SM:
672 {
673 base = 8;
674 break;
675 }
676 case SC_HEX:
677 case SC_HEX_US:
678 {
679 SCFX_FAIL_IF_(sign_char);
680 base = 16;
681 break;
682 }
683 case SC_HEX_SM:
684 {
685 base = 16;
686 break;
687 }
688 case SC_CSD:
689 {
690 SCFX_FAIL_IF_(sign_char);
691 base = 2;
692 scfx_csd2tc(s2);
693 s = (const char*) s2 + 4;
694 numrep = SC_BIN;
695 break;
696 }
697 default:;// Martin, what is default???
698 }
699
700 //
701 // find end of mantissa and count the digits and points
702 //
703
704 const char *end = s;
705 bool based_point = false;
706 int int_digits = 0;
707 int frac_digits = 0;
708
709 while (*end) {
710 if (scfx_exp_start(end))
711 break;
712
713 if (*end == '.') {
714 SCFX_FAIL_IF_(based_point);
715 based_point = true;
716 } else {
717 SCFX_FAIL_IF_(!scfx_is_digit(*end, numrep));
718 if (based_point)
719 frac_digits++;
720 else
721 int_digits++;
722 }
723
724 end++;
725 }
726
727 SCFX_FAIL_IF_(int_digits == 0 && frac_digits == 0);
728
729 // [ exponent ]
730 int exponent = 0;
731 if (*end) {
732 for (const char *e = end + 2; *e; e++)
733 SCFX_FAIL_IF_(!scfx_is_digit(*e, SC_DEC));
734 exponent = std::atoi(end + 1);
735 }
736
737 //
738 // convert the mantissa
739 //
740 double integer = 0.0;
741 if (int_digits != 0) {
742 bool first_digit = true;
743
744 for (; s < end; s++) {
745 if (*s == '.')
746 break;
747
748 if (first_digit) {
749 integer = scfx_to_digit(*s, numrep);
750 switch (numrep) {
751 case SC_BIN:
752 case SC_OCT:
753 case SC_HEX:
754 {
755 if (integer >= (base >> 1))
756 integer -= base; // two's complement
757 break;
758 }
759 default:
760 ;
761 }
762 first_digit = false;
763 } else {
764 integer *= base;
765 integer += scfx_to_digit(*s, numrep);
766 }
767 }
768 }
769
770 // [ . fraction ]
771 double fraction = 0.0;
772 if (frac_digits != 0) {
773 s++; // skip '.'
774
775 bool first_digit = (int_digits == 0);
776 double scale = 1.0;
777 for (; s < end; s++) {
778 scale /= base;
779
780 if (first_digit) {
781 fraction = scfx_to_digit(*s, numrep);
782 switch (numrep) {
783 case SC_BIN:
784 case SC_OCT:
785 case SC_HEX:
786 {
787 if (fraction >= (base >> 1))
788 fraction -= base; // two's complement
789 break;
790 }
791 default:
792 ;
793 }
794 fraction *= scale;
795 first_digit = false;
796 } else {
797 fraction += scfx_to_digit(*s, numrep) * scale;
798 }
799 }
800 }
801
802 double exp =
803 (exponent != 0) ? std::pow((double) base, (double) exponent) : 1;
804
805 return (sign * (integer + fraction) * exp);
806}
807
808#undef SCFX_FAIL_IF_
809
810} // namespace sc_dt