2 // Fix.h : variable length fixed point data type
17 typedef unsigned short uint16
;
19 typedef unsigned long uint32
;
22 #define _Fix_min_length 1
23 #define _Fix_max_length 65535
25 #define _Fix_min_value -1.0
26 #define _Fix_max_value 1.0
28 extern uint16 Fix_default_length
;
29 extern int Fix_default_print_width
;
31 struct _Frep
// internal Fix representation
33 uint16 len
; // length in bits
34 uint16 siz
; // allocated storage
35 int16 ref
; // reference count
36 uint16 s
[1]; // start of ushort array represention
39 typedef struct _Frep
* _Fix
;
42 extern _Frep _Frep_m1
;
43 extern _Frep _Frep_quotient_bump
;
64 Fix
operator = (Fix
&);
65 Fix
operator = (double&);
67 friend int operator == (Fix
&, Fix
& );
68 friend int operator != (Fix
&, Fix
&);
70 friend int operator < (Fix
&, Fix
&);
71 friend int operator <= (Fix
&, Fix
&);
72 friend int operator > (Fix
&, Fix
&);
73 friend int operator >= (Fix
&, Fix
&);
78 friend Fix
operator + (Fix
&, Fix
&);
79 friend Fix
operator - (Fix
&, Fix
&);
80 friend Fix
operator * (Fix
&, Fix
&);
81 friend Fix
operator / (Fix
&, Fix
&);
83 friend Fix
operator * (Fix
&, int);
84 friend Fix
operator * (int, Fix
&);
85 friend Fix
operator % (Fix
&, int);
86 friend Fix
operator << (Fix
&, int);
87 friend Fix
operator >> (Fix
&, int);
90 friend Fix
operator <? (Fix
&, Fix
&); // min
91 friend Fix
operator >? (Fix
&, Fix
&); // max
94 Fix
operator += (Fix
&);
95 Fix
operator -= (Fix
&);
96 Fix
operator *= (Fix
&);
97 Fix
operator /= (Fix
&);
99 Fix
operator *= (int);
100 Fix
operator %= (int);
101 Fix
operator <<=(int);
102 Fix
operator >>=(int);
104 friend char* Ftoa(Fix
&, int width
= Fix_default_print_width
);
105 friend Fix
atoF(const char*, int len
= Fix_default_length
);
107 friend istream
& operator >> (istream
&, Fix
&);
108 friend ostream
& operator << (ostream
&, Fix
&);
110 // built-in functions
111 friend Fix
abs(Fix
); // absolute value
112 friend int sgn(Fix
&); // -1, 0, +1
113 friend Integer
mantissa(Fix
&); // integer representation
114 friend double value(Fix
&); // double value
115 friend int length(Fix
&); // field length
116 friend void show(Fix
&); // show contents
119 void error(const char* msg
); // error handler
120 void range_error(const char* msg
); // range error handler
122 // internal class functions
123 friend void mask(_Fix
);
124 friend int compare(_Fix
, _Fix
= &_Frep_0
);
126 friend _Fix
new_Fix(uint16
);
127 friend _Fix
new_Fix(uint16
, _Fix
);
128 friend _Fix
new_Fix(uint16
, double);
130 friend _Fix
copy(_Fix
, _Fix
);
131 friend _Fix
negate(_Fix
, _Fix
= NULL
);
132 friend _Fix
add(_Fix
, _Fix
, _Fix
= NULL
);
133 friend _Fix
subtract(_Fix
, _Fix
, _Fix
= NULL
);
134 friend _Fix
multiply(_Fix
, _Fix
, _Fix
= NULL
);
135 friend _Fix
multiply(_Fix
, int, _Fix
= NULL
);
136 friend _Fix
divide(_Fix
, _Fix
, _Fix
= NULL
, _Fix
= NULL
);
137 friend _Fix
shift(_Fix
, int, _Fix
= NULL
);
139 // non-operator versions for user
140 friend void negate(Fix
& x
, Fix
& r
);
141 friend void add(Fix
& x
, Fix
& y
, Fix
& r
);
142 friend void subtract(Fix
& x
, Fix
& y
, Fix
& r
);
143 friend void multiply(Fix
& x
, Fix
& y
, Fix
& r
);
144 friend void divide(Fix
& x
, Fix
& y
, Fix
& q
, Fix
& r
);
145 friend void shift(Fix
& x
, int y
, Fix
& r
);
151 default_Fix_error_handler(const char*),
152 default_Fix_range_error_handler(const char*);
154 extern one_arg_error_handler_t
156 Fix_range_error_handler
;
158 extern one_arg_error_handler_t
159 set_Fix_error_handler(one_arg_error_handler_t f
),
160 set_Fix_range_error_handler(one_arg_error_handler_t f
);
162 typedef void (*Fix_peh
)(_Fix
&);
163 extern Fix_peh Fix_overflow_handler
;
166 Fix_overflow_saturate(_Fix
&),
167 Fix_overflow_wrap(_Fix
&),
168 Fix_overflow_warning_saturate(_Fix
&),
169 Fix_overflow_warning(_Fix
&),
170 Fix_overflow_error(_Fix
&);
172 extern Fix_peh
set_overflow_handler(Fix_peh
);
174 extern int Fix_set_default_length(int);
176 // function definitions
178 #if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES)
180 inline void Fix::unique()
185 rep
= new_Fix(rep
->len
,rep
);
189 inline void mask (_Fix x
)
191 int n
= x
->len
& 0x0f;
193 x
->s
[x
->siz
- 1] &= 0xffff0000 >> n
;
196 inline _Fix
copy(_Fix from
, _Fix to
)
198 uint16
*ts
= to
->s
, *fs
= from
->s
;
199 int ilim
= to
->siz
< from
->siz
? to
->siz
: from
->siz
;
200 for ( int i
=0; i
< ilim
; i
++ )
202 for ( ; i
< to
->siz
; i
++ )
208 inline Fix::Fix(_Fix f
)
215 rep
= new_Fix(Fix_default_length
);
218 inline Fix::Fix(int len
)
220 if ( len
< _Fix_min_length
|| len
> _Fix_max_length
)
221 error("illegal length in declaration");
222 rep
= new_Fix((uint16
)len
);
225 inline Fix::Fix(double& d
)
227 rep
= new_Fix(Fix_default_length
,d
);
230 inline Fix::Fix(Fix
& y
)
232 rep
= y
.rep
; rep
->ref
++;
235 inline Fix::Fix(int len
, Fix
& y
)
237 if ( len
< _Fix_min_length
|| len
> _Fix_max_length
)
238 error("illegal length in declaration");
239 rep
= new_Fix((uint16
)len
,y
.rep
);
242 inline Fix::Fix(int len
, _Frep
* fr
)
244 if ( len
< 1 || len
> 65535 )
245 error("illegal length in declaration");
246 rep
= new_Fix((uint16
)len
,fr
);
249 inline Fix::Fix(int len
, double& d
)
251 if ( len
< _Fix_min_length
|| len
> _Fix_max_length
)
252 error("illegal length in declaration");
253 rep
= new_Fix((uint16
)len
,d
);
258 if ( --rep
->ref
<= 0 ) delete rep
;
261 inline Fix
Fix::operator = (Fix
& y
)
263 if ( rep
->len
== y
.rep
->len
) {
265 if ( --rep
->ref
<= 0 ) delete rep
;
275 inline Fix
Fix::operator = (double& d
)
277 int oldlen
= rep
->len
;
278 if ( --rep
->ref
<= 0 ) delete rep
;
279 rep
= new_Fix(oldlen
,d
);
283 inline int operator == (Fix
& x
, Fix
& y
)
285 return compare(x
.rep
, y
.rep
) == 0;
288 inline int operator != (Fix
& x
, Fix
& y
)
290 return compare(x
.rep
, y
.rep
) != 0;
293 inline int operator < (Fix
& x
, Fix
& y
)
295 return compare(x
.rep
, y
.rep
) < 0;
298 inline int operator <= (Fix
& x
, Fix
& y
)
300 return compare(x
.rep
, y
.rep
) <= 0;
303 inline int operator > (Fix
& x
, Fix
& y
)
305 return compare(x
.rep
, y
.rep
) > 0;
308 inline int operator >= (Fix
& x
, Fix
& y
)
310 return compare(x
.rep
, y
.rep
) >= 0;
313 inline Fix
& Fix::operator + ()
318 inline Fix
Fix::operator - ()
320 _Fix r
= negate(rep
); return r
;
323 inline Fix
operator + (Fix
& x
, Fix
& y
)
325 _Fix r
= add(x
.rep
, y
.rep
); return r
;
328 inline Fix
operator - (Fix
& x
, Fix
& y
)
330 _Fix r
= subtract(x
.rep
, y
.rep
); return r
;
333 inline Fix
operator * (Fix
& x
, Fix
& y
)
335 _Fix r
= multiply(x
.rep
, y
.rep
); return r
;
338 inline Fix
operator * (Fix
& x
, int y
)
340 _Fix r
= multiply(x
.rep
, y
); return r
;
343 inline Fix
operator * (int y
, Fix
& x
)
345 _Fix r
= multiply(x
.rep
, y
); return r
;
348 inline Fix
operator / (Fix
& x
, Fix
& y
)
350 _Fix r
= divide(x
.rep
, y
.rep
); return r
;
353 inline Fix
Fix::operator += (Fix
& y
)
355 unique(); add(rep
, y
.rep
, rep
); return *this;
358 inline Fix
Fix::operator -= (Fix
& y
)
360 unique(); subtract(rep
, y
.rep
, rep
); return *this;
363 inline Fix
Fix::operator *= (Fix
& y
)
365 unique(); multiply(rep
, y
.rep
, rep
); return *this;
368 inline Fix
Fix::operator *= (int y
)
370 unique(); multiply(rep
, y
, rep
); return *this;
373 inline Fix
Fix::operator /= (Fix
& y
)
375 unique(); divide(rep
, y
.rep
, rep
); return *this;
378 inline Fix
operator % (Fix
& x
, int y
)
380 Fix
r((int )x
.rep
->len
+ y
, x
); return r
;
383 inline Fix
operator << (Fix
& x
, int y
)
385 _Fix rep
= shift(x
.rep
, y
); return rep
;
388 inline Fix
operator >> (Fix
& x
, int y
)
390 _Fix rep
= shift(x
.rep
, -y
); return rep
;
393 inline Fix
Fix::operator <<= (int y
)
395 unique(); shift(rep
, y
, rep
); return *this;
398 inline Fix
Fix::operator >>= (int y
)
400 unique(); shift(rep
, -y
, rep
); return *this;
404 inline Fix
operator <? (Fix
& x
, Fix
& y
)
406 if ( compare(x
.rep
, y
.rep
) <= 0 ) return x
; else return y
;
409 inline Fix
operator >? (Fix
& x
, Fix
& y
)
411 if ( compare(x
.rep
, y
.rep
) >= 0 ) return x
; else return y
;
415 inline Fix
abs(Fix x
)
417 _Fix r
= (compare(x
.rep
) >= 0 ? new_Fix(x
.rep
->len
,x
.rep
) : negate(x
.rep
));
421 inline int sgn(Fix
& x
)
423 int a
= compare(x
.rep
);
424 return a
== 0 ? 0 : (a
> 0 ? 1 : -1);
427 inline int length(Fix
& x
)
432 inline ostream
& operator << (ostream
& s
, Fix
& y
)
437 inline void negate (Fix
& x
, Fix
& r
)
439 negate(x
.rep
, r
.rep
);
442 inline void add (Fix
& x
, Fix
& y
, Fix
& r
)
444 add(x
.rep
, y
.rep
, r
.rep
);
447 inline void subtract (Fix
& x
, Fix
& y
, Fix
& r
)
449 subtract(x
.rep
, y
.rep
, r
.rep
);
452 inline void multiply (Fix
& x
, Fix
& y
, Fix
& r
)
454 multiply(x
.rep
, y
.rep
, r
.rep
);
457 inline void divide (Fix
& x
, Fix
& y
, Fix
& q
, Fix
& r
)
459 divide(x
.rep
, y
.rep
, q
.rep
, r
.rep
);
462 inline void shift (Fix
& x
, int y
, Fix
& r
)
464 shift(x
.rep
, y
, r
.rep
);