source: trunk/src/emx/include/Attic/cpp/Fix.h@ 18

Last change on this file since 18 was 18, checked in by bird, 23 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 10.8 KB
Line 
1// -*- C++ -*-
2// Fix.h : variable length fixed point data type
3//
4
5#ifndef _Fix_h
6#ifdef __GNUG__
7#pragma interface
8#endif
9#define _Fix_h 1
10
11#include <stream.h>
12#include <std.h>
13#include <stddef.h>
14#include <Integer.h>
15#include <builtin.h>
16
17class Fix
18{
19 struct Rep // internal Fix representation
20 {
21 _G_uint16_t len; // length in bits
22 _G_uint16_t siz; // allocated storage
23 _G_int16_t ref; // reference count
24 _G_uint16_t s[1]; // start of ushort array represention
25 };
26
27public:
28
29 typedef void (*PEH)(Rep*);
30
31private:
32
33 Rep* rep;
34
35 Fix(Rep*);
36 Fix(int, const Rep*);
37
38 void unique();
39
40 static const _G_uint16_t min_length = 1;
41 static const _G_uint16_t max_length = 65535;
42 static const double min_value = -1.0;
43 static const double max_value = 1.0;
44
45 static _G_uint16_t default_length;
46 static int default_print_width;
47 static Rep Rep_0;
48 static Rep Rep_m1;
49 static Rep Rep_quotient_bump;
50
51 // internal class functions
52 static void mask(Rep*);
53 static int compare(const Rep*, const Rep* = &Rep_0);
54
55 static Rep* new_Fix(_G_uint16_t);
56 static Rep* new_Fix(_G_uint16_t, const Rep*);
57 static Rep* new_Fix(_G_uint16_t, double);
58
59 static Rep* copy(const Rep*, Rep*);
60 static Rep* negate(const Rep*, Rep* = NULL);
61 static Rep* add(const Rep*, const Rep*, Rep* = NULL);
62 static Rep* subtract(const Rep*, const Rep*, Rep* = NULL);
63 static Rep* multiply(const Rep*, const Rep*, Rep* = NULL);
64 static Rep* multiply(const Rep*, int, Rep* = NULL);
65 static Rep* divide(const Rep*, const Rep*, Rep* = NULL,
66 Rep* = NULL);
67 static Rep* shift(const Rep*, int, Rep* = NULL);
68
69 static one_arg_error_handler_t error_handler;
70 static one_arg_error_handler_t range_error_handler;
71
72 static PEH overflow_handler;
73
74public:
75 Fix();
76 Fix(const Fix&);
77 Fix(double);
78 Fix(int);
79 Fix(_G_uint16_t);
80 Fix(int, const Fix&);
81 Fix(int, double);
82
83 ~Fix();
84
85 Fix operator = (const Fix&);
86 Fix operator = (double);
87
88 friend int operator == (const Fix&, const Fix&);
89 friend int operator != (const Fix&, const Fix&);
90
91 friend int operator < (const Fix&, const Fix&);
92 friend int operator <= (const Fix&, const Fix&);
93 friend int operator > (const Fix&, const Fix&);
94 friend int operator >= (const Fix&, const Fix&);
95
96 Fix& operator + ();
97 Fix operator - ();
98
99 friend Fix operator + (const Fix&, const Fix&);
100 friend Fix operator - (const Fix&, const Fix&);
101 friend Fix operator * (const Fix&, const Fix&);
102 friend Fix operator / (const Fix&, const Fix&);
103
104 friend Fix operator * (const Fix&, int);
105 friend Fix operator * (int, const Fix&);
106 friend Fix operator % (const Fix&, int);
107 friend Fix operator << (const Fix&, int);
108 friend Fix operator >> (const Fix&, int);
109
110#if defined (__GNUG__) && ! defined (__STRICT_ANSI__)
111 friend Fix operator <? (const Fix&, const Fix&); // min
112 friend Fix operator >? (const Fix&, const Fix&); // max
113#endif
114
115 Fix operator += (const Fix&);
116 Fix operator -= (const Fix&);
117 Fix operator *= (const Fix&);
118 Fix operator /= (const Fix&);
119
120 Fix operator *= (int);
121 Fix operator %= (int);
122 Fix operator <<=(int);
123 Fix operator >>=(int);
124
125 friend char* Ftoa(const Fix&, int width = default_print_width);
126 void printon(ostream&, int width = default_print_width) const;
127 friend Fix atoF(const char*, int len = default_length);
128
129 friend istream& operator >> (istream&, Fix&);
130 friend ostream& operator << (ostream&, const Fix&);
131
132 // built-in functions
133 friend Fix abs(Fix); // absolute value
134 friend int sgn(const Fix&); // -1, 0, +1
135 friend Integer mantissa(const Fix&); // integer representation
136 friend double value(const Fix&); // double value
137 friend int length(const Fix&); // field length
138 friend void show(const Fix&); // show contents
139
140 // error handlers
141 static void error(const char* msg); // error handler
142 static void range_error(const char* msg); // range error handler
143
144 static one_arg_error_handler_t set_error_handler(one_arg_error_handler_t f);
145 static one_arg_error_handler_t
146 set_range_error_handler(one_arg_error_handler_t f);
147
148 static void default_error_handler (const char *);
149 static void default_range_error_handler (const char *);
150
151 // non-operator versions for user
152 friend void negate(const Fix& x, Fix& r);
153 friend void add(const Fix& x, const Fix& y, Fix& r);
154 friend void subtract(const Fix& x, const Fix& y, Fix& r);
155 friend void multiply(const Fix& x, const Fix& y, Fix& r);
156 friend void divide(const Fix& x, const Fix& y, Fix& q, Fix& r);
157 friend void shift(const Fix& x, int y, Fix& r);
158
159 // overflow handlers
160 static void overflow_saturate(Fix::Rep*);
161 static void overflow_wrap(Fix::Rep*);
162 static void overflow_warning_saturate(Fix::Rep*);
163 static void overflow_warning(Fix::Rep*);
164 static void overflow_error(Fix::Rep*);
165
166 static PEH set_overflow_handler(PEH);
167
168 static int set_default_length(int);
169};
170
171// function definitions
172
173inline void
174Fix::unique()
175{
176 if ( rep->ref > 1 )
177 {
178 rep->ref--;
179 rep = new_Fix(rep->len,rep);
180 }
181}
182
183inline void
184Fix::mask (Fix::Rep* x)
185{
186 int n = x->len & 0x0f;
187 if ( n )
188 x->s[x->siz - 1] &= 0xffff0000 >> n;
189}
190
191inline Fix::Rep*
192Fix::copy(const Fix::Rep* from, Fix::Rep* to)
193{
194 _G_uint16_t *ts = to->s;
195 const _G_uint16_t *fs = from->s;
196 int ilim = to->siz < from->siz ? to->siz : from->siz;
197 int i;
198 for ( i=0; i < ilim; i++ )
199 *ts++ = *fs++;
200 for ( ; i < to->siz; i++ )
201 *ts++ = 0;
202 mask(to);
203 return to;
204}
205
206inline
207Fix::Fix(Rep* f)
208{
209 rep = f;
210}
211
212inline
213Fix::Fix()
214{
215 rep = new_Fix(default_length);
216}
217
218inline
219Fix::Fix(int len)
220{
221 if ( len < min_length || len > max_length )
222 error("illegal length in declaration");
223 rep = new_Fix((_G_uint16_t) len);
224}
225
226inline
227Fix::Fix(_G_uint16_t len)
228{
229 if ( len < min_length || len > max_length )
230 error("illegal length in declaration");
231 rep = new_Fix(len);
232}
233
234inline
235Fix::Fix(double d)
236{
237 rep = new_Fix(default_length,d);
238}
239
240inline
241Fix::Fix(const Fix& y)
242{
243 rep = y.rep; rep->ref++;
244}
245
246inline
247Fix::Fix(int len, const Fix& y)
248{
249 if ( len < Fix::min_length || len > Fix::max_length )
250 error("illegal length in declaration");
251 rep = new_Fix((_G_uint16_t) len,y.rep);
252}
253
254inline
255Fix::Fix(int len, const Rep* fr)
256{
257 if ( len < Fix::min_length || len > Fix::max_length )
258 error("illegal length in declaration");
259 rep = new_Fix((_G_uint16_t) len,fr);
260}
261
262inline
263Fix::Fix(int len, double d)
264{
265 if ( len < Fix::min_length || len > Fix::max_length )
266 error("illegal length in declaration");
267 rep = new_Fix((_G_uint16_t) len,d);
268}
269
270inline
271Fix::~Fix()
272{
273 if ( --rep->ref <= 0 ) delete rep;
274}
275
276inline Fix
277Fix::operator = (const Fix& y)
278{
279 if ( rep->len == y.rep->len ) {
280 ++y.rep->ref;
281 if ( --rep->ref <= 0 ) delete rep;
282 rep = y.rep;
283 }
284 else {
285 unique();
286 copy(y.rep,rep);
287 }
288 return *this;
289}
290
291inline Fix
292Fix::operator = (double d)
293{
294 int oldlen = rep->len;
295 if ( --rep->ref <= 0 ) delete rep;
296 rep = new_Fix(oldlen,d);
297 return *this;
298}
299
300inline int
301operator == (const Fix& x, const Fix& y)
302{
303 return Fix::compare(x.rep, y.rep) == 0;
304}
305
306inline int
307operator != (const Fix& x, const Fix& y)
308{
309 return Fix::compare(x.rep, y.rep) != 0;
310}
311
312inline int
313operator < (const Fix& x, const Fix& y)
314{
315 return Fix::compare(x.rep, y.rep) < 0;
316}
317
318inline int
319operator <= (const Fix& x, const Fix& y)
320{
321 return Fix::compare(x.rep, y.rep) <= 0;
322}
323
324inline int
325operator > (const Fix& x, const Fix& y)
326{
327 return Fix::compare(x.rep, y.rep) > 0;
328}
329
330inline int
331operator >= (const Fix& x, const Fix& y)
332{
333 return Fix::compare(x.rep, y.rep) >= 0;
334}
335
336inline Fix&
337Fix::operator + ()
338{
339 return *this;
340}
341
342inline Fix
343Fix::operator - ()
344{
345 Rep* r = negate(rep); return r;
346}
347
348inline Fix
349operator + (const Fix& x, const Fix& y)
350{
351 Fix::Rep* r = Fix::add(x.rep, y.rep); return r;
352}
353
354inline Fix
355operator - (const Fix& x, const Fix& y)
356{
357 Fix::Rep* r = Fix::subtract(x.rep, y.rep); return r;
358}
359
360inline Fix
361operator * (const Fix& x, const Fix& y)
362{
363 Fix::Rep* r = Fix::multiply(x.rep, y.rep); return r;
364}
365
366inline Fix
367operator * (const Fix& x, int y)
368{
369 Fix::Rep* r = Fix::multiply(x.rep, y); return r;
370}
371
372inline Fix
373operator * (int y, const Fix& x)
374{
375 Fix::Rep* r = Fix::multiply(x.rep, y); return r;
376}
377
378inline Fix
379operator / (const Fix& x, const Fix& y)
380{
381 Fix::Rep* r = Fix::divide(x.rep, y.rep); return r;
382}
383
384inline Fix
385Fix::operator += (const Fix& y)
386{
387 unique(); Fix::add(rep, y.rep, rep); return *this;
388}
389
390inline Fix
391Fix::operator -= (const Fix& y)
392{
393 unique(); Fix::subtract(rep, y.rep, rep); return *this;
394}
395
396inline Fix
397Fix::operator *= (const Fix& y)
398{
399 unique(); Fix::multiply(rep, y.rep, rep); return *this;
400}
401
402inline Fix
403Fix::operator *= (int y)
404{
405 unique(); Fix::multiply(rep, y, rep); return *this;
406}
407
408inline Fix
409Fix::operator /= (const Fix& y)
410{
411 unique(); Fix::divide(rep, y.rep, rep); return *this;
412}
413
414inline Fix
415operator % (const Fix& x, int y)
416{
417 Fix r((int) x.rep->len + y, x); return r;
418}
419
420inline Fix
421operator << (const Fix& x, int y)
422{
423 Fix::Rep* rep = Fix::shift(x.rep, y); return rep;
424}
425
426inline Fix
427operator >> (const Fix& x, int y)
428{
429 Fix::Rep* rep = Fix::shift(x.rep, -y); return rep;
430}
431
432inline Fix
433Fix::operator <<= (int y)
434{
435 unique(); Fix::shift(rep, y, rep); return *this;
436}
437
438inline Fix
439Fix::operator >>= (int y)
440{
441 unique(); Fix::shift(rep, -y, rep); return *this;
442}
443
444#if defined (__GNUG__) && ! defined (__STRICT_ANSI__)
445inline Fix
446operator <? (const Fix& x, const Fix& y)
447{
448 if ( Fix::compare(x.rep, y.rep) <= 0 ) return x; else return y;
449}
450
451inline Fix
452operator >? (const Fix& x, const Fix& y)
453{
454 if ( Fix::compare(x.rep, y.rep) >= 0 ) return x; else return y;
455}
456#endif
457
458inline Fix
459abs(Fix x)
460{
461 Fix::Rep* r = (Fix::compare(x.rep) >= 0 ? Fix::new_Fix(x.rep->len,x.rep) :
462 Fix::negate(x.rep));
463 return r;
464}
465
466inline int
467sgn(const Fix& x)
468{
469 int a = Fix::compare(x.rep);
470 return a == 0 ? 0 : (a > 0 ? 1 : -1);
471}
472
473inline int
474length(const Fix& x)
475{
476 return x.rep->len;
477}
478
479inline ostream&
480operator << (ostream& s, const Fix& y)
481{
482 if (s.opfx())
483 y.printon(s);
484 return s;
485}
486
487inline void
488negate (const Fix& x, Fix& r)
489{
490 Fix::negate(x.rep, r.rep);
491}
492
493inline void
494add (const Fix& x, const Fix& y, Fix& r)
495{
496 Fix::add(x.rep, y.rep, r.rep);
497}
498
499inline void
500subtract (const Fix& x, const Fix& y, Fix& r)
501{
502 Fix::subtract(x.rep, y.rep, r.rep);
503}
504
505inline void
506multiply (const Fix& x, const Fix& y, Fix& r)
507{
508 Fix::multiply(x.rep, y.rep, r.rep);
509}
510
511inline void
512divide (const Fix& x, const Fix& y, Fix& q, Fix& r)
513{
514 Fix::divide(x.rep, y.rep, q.rep, r.rep);
515}
516
517inline void
518shift (const Fix& x, int y, Fix& r)
519{
520 Fix::shift(x.rep, y, r.rep);
521}
522
523#endif
Note: See TracBrowser for help on using the repository browser.