home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / libg++-2.7.1-bin.lha / lib / g++-include / Fix.h < prev    next >
C/C++ Source or Header  |  1996-10-12  |  11KB  |  524 lines

  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.  
  17. class 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.  
  27. public:
  28.  
  29.   typedef void (*PEH)(Rep*);
  30.  
  31. private:
  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.  
  74. public:
  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.  
  173. inline void
  174. Fix::unique()
  175. {
  176.   if ( rep->ref > 1 )
  177.   {
  178.     rep->ref--;
  179.     rep = new_Fix(rep->len,rep);
  180.   }
  181. }
  182.  
  183. inline void
  184. Fix::mask (Fix::Rep* x)
  185. {
  186.   int n = x->len & 0x0f;
  187.   if ( n )
  188.     x->s[x->siz - 1] &= 0xffff0000 >> n; 
  189. }
  190.  
  191. inline Fix::Rep*
  192. Fix::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.  
  206. inline
  207. Fix::Fix(Rep* f)
  208. {
  209.   rep = f;
  210. }
  211.  
  212. inline
  213. Fix::Fix()
  214. {
  215.   rep = new_Fix(default_length);
  216. }
  217.  
  218. inline
  219. Fix::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.  
  226. inline
  227. Fix::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.  
  234. inline
  235. Fix::Fix(double d)
  236. {
  237.   rep = new_Fix(default_length,d);
  238. }
  239.  
  240. inline
  241. Fix::Fix(const Fix&  y)
  242. {
  243.   rep = y.rep; rep->ref++;
  244. }
  245.  
  246. inline
  247. 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((_G_uint16_t) len,y.rep);
  252. }
  253.  
  254. inline
  255. Fix::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.  
  262. inline
  263. Fix::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.  
  270. inline
  271. Fix::~Fix()
  272. {
  273.   if ( --rep->ref <= 0 ) delete rep;
  274. }
  275.  
  276. inline Fix
  277. Fix::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.  
  291. inline Fix
  292. Fix::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.  
  300. inline int
  301. operator == (const Fix&  x, const Fix&  y)
  302. {
  303.   return Fix::compare(x.rep, y.rep) == 0; 
  304. }
  305.  
  306. inline int
  307. operator != (const Fix&  x, const Fix&  y)
  308. {
  309.   return Fix::compare(x.rep, y.rep) != 0; 
  310. }
  311.  
  312. inline int
  313. operator <  (const Fix&  x, const Fix&  y)
  314. {
  315.   return Fix::compare(x.rep, y.rep) <  0; 
  316. }
  317.  
  318. inline int
  319. operator <= (const Fix&  x, const Fix&  y)
  320. {
  321.   return Fix::compare(x.rep, y.rep) <= 0; 
  322. }
  323.  
  324. inline int
  325. operator >  (const Fix&  x, const Fix&  y)
  326. {
  327.   return Fix::compare(x.rep, y.rep) >  0; 
  328. }
  329.  
  330. inline int
  331. operator >= (const Fix&  x, const Fix&  y)
  332. {
  333.   return Fix::compare(x.rep, y.rep) >= 0; 
  334. }
  335.  
  336. inline Fix&
  337. Fix::operator +  ()
  338. {
  339.   return *this;
  340. }
  341.  
  342. inline Fix
  343. Fix::operator -  ()
  344. {
  345.   Rep* r = negate(rep); return r;
  346. }
  347.  
  348. inline Fix
  349. operator +  (const Fix& x, const Fix& y)
  350. {
  351.   Fix::Rep* r = Fix::add(x.rep, y.rep); return r;
  352. }
  353.  
  354. inline Fix
  355. operator -  (const Fix& x, const Fix& y)
  356. {
  357.   Fix::Rep* r = Fix::subtract(x.rep, y.rep); return r;
  358. }
  359.  
  360. inline Fix
  361. operator *  (const Fix& x, const Fix& y)
  362. {
  363.   Fix::Rep* r = Fix::multiply(x.rep, y.rep); return r;
  364. }
  365.  
  366. inline Fix
  367. operator *  (const Fix& x, int y)
  368. {
  369.   Fix::Rep* r = Fix::multiply(x.rep, y); return r;
  370. }
  371.  
  372. inline Fix
  373. operator *  (int y, const Fix& x)
  374. {
  375.   Fix::Rep* r = Fix::multiply(x.rep, y); return r;
  376. }
  377.  
  378. inline Fix
  379. operator / (const Fix& x, const Fix& y)
  380. {
  381.   Fix::Rep* r = Fix::divide(x.rep, y.rep); return r;
  382. }
  383.  
  384. inline Fix
  385. Fix::operator += (const Fix& y)
  386. {
  387.   unique(); Fix::add(rep, y.rep, rep); return *this;
  388. }
  389.  
  390. inline Fix
  391. Fix::operator -= (const Fix& y)
  392. {
  393.   unique(); Fix::subtract(rep, y.rep, rep); return *this;
  394. }
  395.  
  396. inline Fix
  397. Fix::operator *= (const Fix& y)
  398. {
  399.   unique(); Fix::multiply(rep, y.rep, rep); return *this;
  400. }
  401.  
  402. inline Fix
  403. Fix::operator *= (int y)
  404. {
  405.   unique(); Fix::multiply(rep, y, rep); return *this;
  406. }
  407.  
  408. inline Fix
  409. Fix::operator /= (const Fix& y)
  410. {
  411.   unique(); Fix::divide(rep, y.rep, rep); return *this;
  412. }
  413.  
  414. inline Fix
  415. operator % (const Fix& x, int y)
  416. {
  417.   Fix r((int) x.rep->len + y, x); return r;
  418. }
  419.  
  420. inline Fix
  421. operator << (const Fix&  x, int y)
  422. {
  423.   Fix::Rep* rep = Fix::shift(x.rep, y); return rep;
  424. }
  425.  
  426. inline Fix
  427. operator >> (const Fix&  x, int y)
  428. {  
  429.   Fix::Rep* rep = Fix::shift(x.rep, -y); return rep;
  430. }
  431.  
  432. inline Fix
  433. Fix::operator <<= (int y)
  434. {
  435.   unique(); Fix::shift(rep, y, rep); return *this;
  436. }
  437.  
  438. inline Fix
  439. Fix::operator >>= (int y)
  440. {
  441.   unique(); Fix::shift(rep, -y, rep); return *this;
  442. }
  443.  
  444. #if defined (__GNUG__) && ! defined (__STRICT_ANSI__)
  445. inline Fix
  446. operator <? (const Fix& x, const Fix& y)
  447. {
  448.   if ( Fix::compare(x.rep, y.rep) <= 0 ) return x; else return y;
  449. }
  450.  
  451. inline Fix
  452. operator >? (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.  
  458. inline Fix
  459. abs(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.  
  466. inline int
  467. sgn(const Fix& x)
  468. {
  469.   int a = Fix::compare(x.rep);
  470.   return a == 0 ? 0 : (a > 0 ? 1 : -1);
  471. }
  472.  
  473. inline int
  474. length(const Fix& x)
  475. {
  476.   return x.rep->len;
  477. }
  478.  
  479. inline ostream&
  480. operator << (ostream& s, const Fix& y)
  481. {
  482.   if (s.opfx())
  483.     y.printon(s);
  484.   return s;
  485. }
  486.  
  487. inline void
  488. negate (const Fix& x, Fix& r)
  489. {
  490.   Fix::negate(x.rep, r.rep);
  491. }
  492.  
  493. inline void
  494. add (const Fix& x, const Fix& y, Fix& r)
  495. {
  496.   Fix::add(x.rep, y.rep, r.rep);
  497. }
  498.  
  499. inline void
  500. subtract (const Fix& x, const Fix& y, Fix& r)
  501. {
  502.   Fix::subtract(x.rep, y.rep, r.rep);
  503. }
  504.  
  505. inline void
  506. multiply (const Fix& x, const Fix& y, Fix& r)
  507. {
  508.   Fix::multiply(x.rep, y.rep, r.rep);
  509. }
  510.  
  511. inline void
  512. divide (const Fix& x, const Fix& y, Fix& q, Fix& r)
  513. {
  514.   Fix::divide(x.rep, y.rep, q.rep, r.rep);
  515. }
  516.  
  517. inline void
  518. shift (const Fix& x, int y, Fix& r)
  519. {
  520.   Fix::shift(x.rep, y, r.rep);
  521. }
  522.  
  523. #endif
  524.