home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.3 (Developer) / NeXT_Developer-3.3.iso / NextDeveloper / Headers / g++ / Fix.h < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-06  |  9.9 KB  |  482 lines

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