1 // This may look like C code, but it is really -*- C++ -*-
3 Copyright (C) 1988 Free Software Foundation
4 written by Kurt Baudendistel (gt-eedsp!baud@gatech.edu)
5 adapted for libg++ by Doug Lea (dl@rocky.oswego.edu)
7 This file is part of GNU CC.
9 GNU CC is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY. No author or distributor
11 accepts responsibility to anyone for the consequences of using it
12 or for whether it serves any particular purpose or works at all,
13 unless he says so in writing. Refer to the GNU CC General Public
14 License for full details.
16 Everyone is granted permission to copy, modify and redistribute
17 GNU CC, but only under the conditions described in the
18 GNU CC General Public License. A copy of this license is
19 supposed to have been given to you along with GNU CC so you
20 can know your rights and responsibilities. It should be in a
21 file named COPYING. Among other things, the copyright notice
22 and this notice must be preserved on all copies.
35 // extra type definitions
42 // constant definitions
48 Fix24_fs
= 2147483648., // 2^Fix24_shift
49 Fix24_mult
= Fix24_fs
,
50 Fix24_div
= 1./Fix24_fs
,
51 Fix24_max
= 1. - .5/Fix24_fs
,
54 static const unsigned long
55 Fix24_msb
= 0x80000000L
,
56 Fix24_lsb
= 0x00000100L
,
57 Fix24_m_max
= 0x7fffff00L
,
58 Fix24_m_min
= 0x80000000L
;
61 Fix48_fs
= 36028797018963968., // 2^(24+Fix24_shift)
62 Fix48_max
= 1. - .5/Fix48_fs
,
64 Fix48_div_u
= 1./Fix24_fs
,
65 Fix48_div_l
= 1./Fix48_fs
;
68 Fix48_msb
= { 0x80000000L
, 0L },
69 Fix48_lsb
= { 0L, 0x00000100L
},
70 Fix48_m_max
= { 0x7fffff00L
, 0xffffff00L
},
71 Fix48_m_min
= { 0x80000000L
, 0L };
74 // Fix24 class: 24-bit Fixed point data type
76 // consists of a 24-bit mantissa (sign bit & 23 data bits).
85 long assign(double d
);
99 Fix24
& operator=(Fix24
& f
);
100 Fix24
& operator=(double d
);
101 Fix24
& operator=(Fix48
& f
);
103 friend long& mantissa(Fix24
& f
);
104 friend double value(Fix24
& f
);
109 friend Fix24
operator + (Fix24
& f
, Fix24
& g
);
110 friend Fix24
operator - (Fix24
& f
, Fix24
& g
);
111 friend Fix48
operator * (Fix24
& f
, Fix24
& g
);
112 friend Fix24
operator * (Fix24
& f
, int g
);
113 friend Fix24
operator * (int g
, Fix24
& f
);
114 friend Fix24
operator / (Fix24
& f
, Fix24
& g
);
115 friend Fix24
operator << (Fix24
& f
, int b
);
116 friend Fix24
operator >> (Fix24
& f
, int b
);
118 Fix24
& operator += (Fix24
& f
);
119 Fix24
& operator -= (Fix24
& f
);
120 Fix24
& operator *= (Fix24
& f
);
121 Fix24
& operator *= (int b
);
122 Fix24
& operator /= (Fix24
& f
);
124 Fix24
& operator <<=(int b
);
125 Fix24
& operator >>=(int b
);
127 friend int operator == (Fix24
& f
, Fix24
& g
);
128 friend int operator != (Fix24
& f
, Fix24
& g
);
129 friend int operator >= (Fix24
& f
, Fix24
& g
);
130 friend int operator <= (Fix24
& f
, Fix24
& g
);
131 friend int operator > (Fix24
& f
, Fix24
& g
);
132 friend int operator < (Fix24
& f
, Fix24
& g
);
134 friend istream
& operator >> (istream
& s
, Fix24
& f
);
135 friend ostream
& operator << (ostream
& s
, Fix24
& f
);
137 void overflow(long&);
138 void range_error(long&);
143 // Fix48 class: 48-bit Fixed point data type
145 // consists of a 48-bit mantissa (sign bit & 47 data bits).
154 twolongs
assign(double d
);
165 Fix48
& operator = (Fix48
& f
);
166 Fix48
& operator = (Fix24
& f
);
167 Fix48
& operator = (double d
);
169 friend twolongs
& mantissa(Fix48
& f
);
170 friend double value(Fix48
& f
);
175 friend Fix48
operator + (Fix48
& f
, Fix48
& g
);
176 friend Fix48
operator - (Fix48
& f
, Fix48
& g
);
177 friend Fix48
operator * (Fix48
& f
, int g
);
178 friend Fix48
operator * (int g
, Fix48
& f
);
179 friend Fix48
operator << (Fix48
& f
, int b
);
180 friend Fix48
operator >> (Fix48
& f
, int b
);
182 friend Fix48
operator * (Fix24
& f
, Fix24
& g
);
184 Fix48
& operator += (Fix48
& f
);
185 Fix48
& operator -= (Fix48
& f
);
186 Fix48
& operator *= (int b
);
187 Fix48
& operator <<=(int b
);
188 Fix48
& operator >>=(int b
);
190 friend int operator == (Fix48
& f
, Fix48
& g
);
191 friend int operator != (Fix48
& f
, Fix48
& g
);
192 friend int operator >= (Fix48
& f
, Fix48
& g
);
193 friend int operator <= (Fix48
& f
, Fix48
& g
);
194 friend int operator > (Fix48
& f
, Fix48
& g
);
195 friend int operator < (Fix48
& f
, Fix48
& g
);
197 friend istream
& operator >> (istream
& s
, Fix48
& f
);
198 friend ostream
& operator << (ostream
& s
, Fix48
& f
);
200 void overflow(twolongs
& i
);
201 void range_error(twolongs
& i
);
205 // active error handler declarations
207 typedef void (*Fix24_peh
)(long&);
208 typedef void (*Fix48_peh
)(twolongs
&);
210 extern Fix24_peh Fix24_overflow_handler
;
211 extern Fix48_peh Fix48_overflow_handler
;
213 extern Fix24_peh Fix24_range_error_handler
;
214 extern Fix48_peh Fix48_range_error_handler
;
217 // error handler declarations
219 #if defined(SHORT_NAMES) || defined(VMS)
220 #define set_overflow_handler sohndl
221 #define set_range_error_handler srnghdl
224 extern Fix24_peh
set_Fix24_overflow_handler(Fix24_peh
);
225 extern Fix48_peh
set_Fix48_overflow_handler(Fix48_peh
);
226 extern void set_overflow_handler(Fix24_peh
, Fix48_peh
);
228 extern Fix24_peh
set_Fix24_range_error_handler(Fix24_peh
);
229 extern Fix48_peh
set_Fix48_range_error_handler(Fix48_peh
);
230 extern void set_range_error_handler(Fix24_peh
, Fix48_peh
);
234 Fix24_overflow_saturate(long&),
235 Fix24_overflow_warning_saturate(long&),
236 Fix24_warning(long&),
240 Fix48_ignore(twolongs
&),
241 Fix48_overflow_saturate(twolongs
&),
242 Fix48_overflow_warning_saturate(twolongs
&),
243 Fix48_warning(twolongs
&),
244 Fix48_abort(twolongs
&);
246 #if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES)
248 inline Fix24::~Fix24() {}
250 inline Fix24::Fix24(long i
)
255 inline Fix24::Fix24(int i
)
260 inline Fix24::operator double()
262 return Fix24_div
* m
;
265 inline Fix24::Fix24()
270 inline Fix24::Fix24(Fix24
& f
)
275 inline Fix24::Fix24(double d
)
280 inline Fix24::Fix24(Fix48
& f
)
285 inline Fix24
& Fix24::operator=(Fix24
& f
)
291 inline Fix24
& Fix24::operator=(double d
)
297 inline Fix24
& Fix24::operator=(Fix48
& f
)
303 inline long& mantissa(Fix24
& f
)
308 inline double value(Fix24
& f
)
313 inline Fix24
Fix24::operator+()
318 inline Fix24
Fix24::operator-()
323 inline Fix24
operator+(Fix24
& f
, Fix24
& g
)
325 long sum
= f
.m
+ g
.m
;
326 if ( (f
.m
^ sum
) & (g
.m
^ sum
) & Fix24_msb
)
331 inline Fix24
operator-(Fix24
& f
, Fix24
& g
)
333 long sum
= f
.m
- g
.m
;
334 if ( (f
.m
^ sum
) & (-g
.m
^ sum
) & Fix24_msb
)
339 inline Fix24
operator*(Fix24
& a
, int b
)
344 inline Fix24
operator*(int b
, Fix24
& a
)
349 inline Fix24
operator<<(Fix24
& a
, int b
)
354 inline Fix24
operator>>(Fix24
& a
, int b
)
356 return (a
.m
>> b
) & 0xffffff00L
;
359 inline Fix24
& Fix24:: operator+=(Fix24
& f
)
361 return *this = *this + f
;
364 inline Fix24
& Fix24:: operator-=(Fix24
& f
)
366 return *this = *this - f
;
369 inline Fix24
& Fix24::operator*=(Fix24
& f
)
371 return *this = *this * f
;
374 inline Fix24
& Fix24:: operator/=(Fix24
& f
)
376 return *this = *this / f
;
379 inline Fix24
& Fix24:: operator<<=(int b
)
381 return *this = *this << b
;
384 inline Fix24
& Fix24:: operator>>=(int b
)
386 return *this = *this >> b
;
389 inline Fix24
& Fix24::operator*=(int b
)
391 return *this = *this * b
;
394 inline int operator==(Fix24
& f
, Fix24
& g
)
399 inline int operator!=(Fix24
& f
, Fix24
& g
)
404 inline int operator>=(Fix24
& f
, Fix24
& g
)
409 inline int operator<=(Fix24
& f
, Fix24
& g
)
414 inline int operator>(Fix24
& f
, Fix24
& g
)
419 inline int operator<(Fix24
& f
, Fix24
& g
)
424 inline istream
& operator>>(istream
& s
, Fix24
& f
)
432 inline ostream
& operator<<(ostream
& s
, Fix24
& f
)
434 return s
<< double(f
);
437 inline Fix48::~Fix48() {}
439 inline Fix48::Fix48(twolongs i
)
444 inline Fix48:: operator double()
447 * Note: can't simply do Fix48_div_u * m.u + Fix48_div_l * m.l, because
448 * m.u is signed and m.l is unsigned.
450 return (m
.u
>= 0)? Fix48_div_u
* m
.u
+ Fix48_div_l
* m
.l
:
451 (Fix48_div_u
* ((unsigned long)(m
.u
& 0xffffff00))
452 + Fix48_div_l
* m
.l
) - 2;
455 inline Fix48::Fix48()
461 inline Fix48::Fix48(Fix48
& f
)
466 inline Fix48::Fix48(Fix24
& f
)
472 inline Fix48::Fix48(double d
)
477 inline Fix48
& Fix48::operator=(Fix48
& f
)
483 inline Fix48
& Fix48::operator=(Fix24
& f
)
490 inline Fix48
& Fix48::operator=(double d
)
496 inline twolongs
& mantissa(Fix48
& f
)
501 inline double value(Fix48
& f
)
506 inline Fix48
Fix48::operator+()
511 inline Fix48
Fix48::operator-()
515 n
.u
= ~m
.u
+ ((n
.l
^ m
.l
) & Fix24_msb
? 0 : Fix24_lsb
);
519 inline Fix48
operator*(int b
, Fix48
& a
)
524 inline Fix48
& Fix48::operator+=(Fix48
& f
)
526 return *this = *this + f
;
529 inline Fix48
& Fix48::operator-=(Fix48
& f
)
531 return *this = *this - f
;
534 inline Fix48
& Fix48::operator*=(int b
)
536 return *this = *this * b
;
539 inline Fix48
& Fix48::operator<<=(int b
)
541 return *this = *this << b
;
544 inline Fix48
& Fix48::operator>>=(int b
)
546 return *this = *this >> b
;
549 inline int operator==(Fix48
& f
, Fix48
& g
)
551 return f
.m
.u
== g
.m
.u
&& f
.m
.l
== g
.m
.l
;
554 inline int operator!=(Fix48
& f
, Fix48
& g
)
556 return f
.m
.u
!= g
.m
.u
|| f
.m
.l
!= g
.m
.l
;
559 inline int operator>=(Fix48
& f
, Fix48
& g
)
561 return f
.m
.u
>= g
.m
.u
|| (f
.m
.u
== g
.m
.u
&& f
.m
.l
>= g
.m
.l
);
564 inline int operator<=(Fix48
& f
, Fix48
& g
)
566 return f
.m
.u
<= g
.m
.u
|| (f
.m
.u
== g
.m
.u
&& f
.m
.l
<= g
.m
.l
);
569 inline int operator>(Fix48
& f
, Fix48
& g
)
571 return f
.m
.u
> g
.m
.u
|| (f
.m
.u
== g
.m
.u
&& f
.m
.l
> g
.m
.l
);
574 inline int operator<(Fix48
& f
, Fix48
& g
)
576 return f
.m
.u
< g
.m
.u
|| (f
.m
.u
== g
.m
.u
&& f
.m
.l
< g
.m
.l
);
579 inline istream
& operator>>(istream
& s
, Fix48
& f
)
587 inline ostream
& operator<<(ostream
& s
, Fix48
& f
)
589 return s
<< double(f
);