home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.2 (Developer) / NS_dev_3.2.iso / NextDeveloper / Headers / g++ / Fix.h < prev    next >
C/C++ Source or Header  |  1993-06-29  |  10KB  |  470 lines

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