Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

guar_exact.h

Go to the documentation of this file.
00001 /* LIBGUL - Geometry Utility Library
00002  * Copyright (C) 1998-1999 Norbert Irmer
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Library General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Library General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Library General Public
00015  * License along with this library; if not, write to the
00016  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017  * Boston, MA 02111-1307, USA.
00018  */
00019 
00020 #ifndef GUAR_EXACT_H
00021 #define GUAR_EXACT_H
00022 
00023 #include <math.h>
00024 // #include <new.h>
00025 
00026 namespace guar {
00027 
00028 using gul::Assert;
00029 using gul::InternalError;
00030 using gul::ndebug;
00031 using gul::Swap;
00032 
00033 /* ---------------------------------------------------------
00034   Converts int-string to float
00035 ----------------------------------------------------------- */
00036 
00037 template< class T >
00038 void IntTo( const unsigned int na, const unsigned long *a, T& t )
00039 {
00040   int i;
00041 
00042   if( na == 0 )
00043   {
00044     t = (T)0.0;
00045     return;
00046   }
00047   t = (T)a[na-1];
00048   
00049   for( i = na-2; i >= 0; i-- )
00050   {
00051     t = t*(T)(LL(0x100000000)) + (T)a[i];
00052   }  
00053 }
00054 
00055 /* ----------------------------------------------------------------
00056   Calculates the sum of two operands
00057 ------------------------------------------------------------------ */
00058 void IntAdd( const unsigned int na, const unsigned long *a, 
00059              const unsigned int nb, const unsigned long *b, 
00060              unsigned int *nc, unsigned long *c );
00061 
00062 /* ---------------------------------------------------------------
00063   Calculates c=a-b with length of c = max(length(a),length(b)).
00064   If a < b the result c is a negative number (two-complement, i.e.
00065   not(fabs(c))+1), and the fuction returns -1, else it returns 0.
00066 ------------------------------------------------------------------ */
00067 int IntSub( const int unsigned na, const unsigned long *a, 
00068             const int unsigned nb, const unsigned long *b, 
00069             unsigned int *nc, unsigned long *c );
00070                  
00071 /* ---------------------------------------------------------------
00072   Short Multiplication
00073 ---------------------------------------------------------------- */
00074 unsigned long IntMultShort( 
00075          const unsigned int na, const unsigned long *a, const unsigned long b,
00076          unsigned long *c );
00077          
00078 /* ----------------------------------------------------------------
00079   Calculates the product of two operands, slow but simple
00080   TODO: Multiplication with FFT
00081 ------------------------------------------------------------------ */
00082 void IntMult( const unsigned int na, const unsigned long *a, 
00083               const unsigned int nb, const unsigned long *b,
00084               unsigned int *nc, unsigned long *c );
00085 
00086 /* ---------------------------------------------------------
00087   Divide a int-string by a single int
00088 ----------------------------------------------------------- */
00089 unsigned long IntDivShort( 
00090        const unsigned int na, const unsigned long *a, const unsigned long b, 
00091        unsigned int *nq, unsigned long *q );
00092 
00093 /* ---------------------------------------------------------
00094   Divide a int-string by a int-string
00095 ----------------------------------------------------------- */
00096 int IntDiv( const unsigned int na, const unsigned long *a, 
00097             const unsigned int nb, const unsigned long *b, 
00098             unsigned int *nq, unsigned long *q, 
00099             unsigned int *nr, unsigned long *r );
00100 
00101 /* ---------------------------------------------------------
00102   Converts double to int-string
00103 ----------------------------------------------------------- */
00104 int DoubleToInt( const double d, const unsigned int na, unsigned long *a,
00105                  unsigned int *retLen );
00106 
00107 /* ---------------------------------------------------------
00108   Converts int-string to double
00109 ----------------------------------------------------------- */
00110 double IntToDouble( const unsigned int na, const unsigned long *a );
00111 
00112 
00113 /*********************************************************************/
00114 
00115 struct Interval
00116 {
00117   friend Interval operator+( const Interval &a, const Interval &b );
00118   friend Interval operator-( const Interval &a, const Interval &b );
00119   friend Interval operator*( const Interval &a, const Interval &b );
00120   friend Interval operator/( const Interval &a, const Interval &b );
00121   friend int Test( const Interval &a, const Interval &b );
00122 
00123   double         m_low;
00124   double         m_high;
00125 
00126   Interval() { m_low = 0.0; m_high = 0.0; }
00127   Interval(double val) { m_low = val; m_high = val; }
00128   Interval(double low, double high) { m_low = low; m_high = high; }
00129 };
00130 
00131 /* -------------------------------------------------------------
00132   wrapper class, because i don't want implicit double -> long
00133   conversion
00134 ---------------------------------------------------------------*/
00135 class ULong
00136 {
00137   unsigned long l;
00138 public:
00139   explicit ULong( unsigned long ul ) : l(ul) { }
00140   operator unsigned long() const { return l; }
00141 };
00142 
00143 /*************************************************************************/
00144 
00145 class rational
00146 {
00147 public:
00148   struct rational_rep
00149   {
00150     unsigned int   m_na;  /* number of words for a */
00151     unsigned long *m_a;   /* numerator   */
00152 
00153     unsigned int   m_nb;  /* number of words for b */
00154     unsigned long *m_b;   /* denominator */
00155 
00156     size_t         m_size_a;  /* allocation size in byte of a */ 
00157     size_t         m_size_b;  /* allocation size of byte of b */ 
00158 
00159     int            m_refcount;    /* Referencecounter */ 
00160 
00161     Interval       m_i;
00162 
00163     int            m_sign   : 2;  /* -1 = negative, 0 = positive or zero */
00164     unsigned int   m_bounds : 1;  /* lower and upper bound initialized */
00165 
00166     rational_rep()
00167     {
00168       m_refcount = 1;
00169       m_sign = 0;
00170       m_bounds = m_na = m_nb = 0;
00171       m_size_a = m_size_b = 0;
00172       m_a = m_b = NULL;
00173     }
00174 
00175     rational_rep( int sign, int na, unsigned long *a )
00176     {
00177       size_t bsize;
00178 
00179       m_refcount = 1;
00180       m_sign = 0;
00181       m_bounds = m_na = m_nb = 0;
00182       m_size_b = m_size_a = 0; 
00183       m_a = m_b = 0;
00184 
00185       if( na == 0 ) return;
00186       
00187       m_a = (unsigned long *)gust::PoolAlloc( na*sizeof(unsigned long), &bsize );
00188       if( m_a == NULL ) throw gul::PoolAllocError();
00189       for( int i=0; i<na; i++ ) m_a[i] = a[i];
00190 
00191       m_sign = sign;
00192       m_na = na;
00193       m_size_a = bsize;
00194     }
00195     
00196     rational_rep( int sign, unsigned long a )
00197     {
00198       size_t bsize;
00199 
00200       m_refcount = 1;
00201       m_sign = 0;
00202       m_bounds = m_na = m_nb = 0;
00203       m_size_a = m_size_b = 0;
00204       m_a = m_b = NULL;
00205       if( a == 0 ) return; 
00206      
00207       m_a = (unsigned long *)gust::PoolAlloc( sizeof(unsigned long), &bsize );
00208       if( m_a == NULL ) throw gul::PoolAllocError();
00209       m_a[0] = a;
00210 
00211       m_sign = sign;
00212       m_na = 1;
00213       m_size_a = bsize;
00214     }
00215  
00216             // this only reserves memory, but leaves it uninitialized
00217     rational_rep( int sign, int na, int nb )
00218     {
00219       size_t bsize;
00220 
00221       m_refcount = 1;
00222       m_sign = 0;
00223       m_bounds = m_na = m_nb = 0;
00224       m_size_a = m_size_b = 0; 
00225       m_a = m_b = NULL;
00226 
00227       if( na != 0 )       
00228       {
00229         m_sign = sign;
00230         m_a = (unsigned long *)gust::PoolAlloc( na*sizeof(unsigned long),&bsize);
00231         if( m_a == NULL ) throw gul::PoolAllocError();
00232         m_size_a = bsize;
00233         m_na = na;
00234       }
00235       if( nb != 0 )       
00236       {     
00237         m_b = (unsigned long *)gust::PoolAlloc( nb*sizeof(unsigned long),&bsize);
00238         if( m_b == NULL ) throw gul::PoolAllocError();
00239         m_size_b = bsize;
00240         m_nb = nb;
00241       }
00242     }
00243 
00244     ~rational_rep()
00245     {
00246       if( (m_size_a != 0) && (m_a != NULL) ) gust::PoolFree( m_a, m_size_a );      
00247       if( (m_size_b != 0) && (m_b != NULL) ) gust::PoolFree( m_b, m_size_b );
00248     }
00249 
00250     template< class T >
00251     void dump( T& num, T& den )
00252     { 
00253       if( m_na == 0 )
00254       {  num = (T)0.0; den = (T)1.0; return; }
00255       else
00256         IntTo<T>( m_na, m_a, num );
00257 
00258       if( m_sign ) 
00259         num = -num;
00260 
00261       if( m_nb == 0 )
00262         den = (T)1.0;
00263       else
00264         IntTo<T>( m_nb, m_b, den );  
00265     }
00266 
00267     void calc_bounds( void )
00268     { 
00269       Interval inum,iden;
00270       double num,den;
00271 
00272       dump( num, den );
00273       if( num != 0.0 )
00274       {
00275         inum.m_low = num - DBL_EPSILON*fabs(num);
00276         inum.m_high = num + DBL_EPSILON*fabs(num);
00277       }
00278       else
00279       {
00280         inum.m_low = inum.m_high = 0.0;
00281       }
00282       
00283       if( den != 1.0 )
00284       {
00285         iden.m_low = den - DBL_EPSILON*fabs(den);
00286         iden.m_high = den + DBL_EPSILON*fabs(den);
00287       }
00288       else
00289       {
00290         iden.m_low = iden.m_high = 1.0;
00291       }
00292 
00293       m_i = inum/iden;
00294 
00295       m_bounds = 1;
00296     }
00297    
00298     void negative( void )    /* for internal use only, no checks !!!! */ 
00299     {      
00300       if( m_na != 0 )
00301         m_sign ^= -1;
00302     }
00303     
00304     void reciprocal( void )  /* for internal use only, no checks !!!! */
00305     {
00306       size_t bsize;
00307       unsigned long *p;
00308       int i;
00309       
00310       if( m_na == 0 ) throw gul::Error();
00311       
00312       if( (m_na == 1) && (m_a[0] == 1) )
00313       {
00314         gust::PoolFree( m_a, m_size_a );
00315         m_na = 0;
00316         m_size_a = 0;
00317         m_a = NULL;
00318       }
00319       
00320       if( m_size_b == 0 )
00321       {
00322         m_b = (unsigned long *)gust::PoolAlloc( sizeof(unsigned long), &bsize );
00323         if( m_b == NULL ) throw gul::PoolAllocError();
00324         m_nb = 1;
00325         m_b[0] = 1;
00326         m_size_b = bsize;
00327       }
00328 
00329       i = m_na; m_na = m_nb; m_nb = i;
00330       bsize = m_size_a; m_size_a = m_size_b; m_size_b = bsize;
00331       p = m_a; m_a = m_b; m_b = p;
00332     }
00333   };
00334 
00335 public:
00336   rational_rep   *m;
00337   
00338   GULAPI rational( void );
00339   GULAPI explicit rational( int na, unsigned long *a, int sign = 0 );
00340   GULAPI explicit rational( ULong a, int sign = 0 );
00341   GULAPI explicit rational( int sign, int size_a, int size_b );
00342 
00343   rational( const rational& other )
00344   {
00345     other.m->m_refcount++;
00346     m = other.m;
00347   }
00348 
00349   GULAPI rational& operator=( const rational& other );
00350   GULAPI ~rational();
00351 
00352   GULAPI rational get_copy() const;
00353 
00354   rational numerator() const
00355   { 
00356     if( m->m_na )
00357       return rational(m->m_na,m->m_a,m->m_sign);
00358 
00359     return rational();
00360   }
00361   rational denominator() const
00362   { 
00363     if( m->m_nb )
00364       return rational(m->m_nb,m->m_b,m->m_sign);
00365 
00366     return rational(ULong(1));
00367   }
00368 
00369   // GULAPI int to_int() const;
00370   GULAPI void calc_bounds( void ) const;
00371   GULAPI const Interval& get_bounds( void ) const;
00372 
00373   template< class T > GULAPI void dump( T& num, T& den ) const;
00374   template< class T > void dump( T& t ) const
00375   {
00376     T n,d;
00377 
00378     m->dump( n, d );
00379     
00380     t = n/d;
00381   } 
00382   double dump() const
00383   {
00384     double t;
00385     dump(t);
00386     return t;
00387   } 
00388 
00389   bool is_zero( void ) const { return(m->m_na == 0); }
00390 
00391   int  test( void ) const
00392   {
00393     if( m->m_sign ) return(-1);
00394     else if( m->m_na == 0 ) return(0);
00395     return(1);
00396   }
00397 
00398   GULAPI void div_mod( rational *q, rational *r ) const;
00399 
00400   GULAPI friend rational operator*( const rational& a, const rational& b );
00401   GULAPI friend rational operator+( const rational& A, const rational& B );
00402   GULAPI friend rational operator/( const rational& A, const rational& B );
00403   GULAPI friend rational operator-( const rational& A, const rational& B );
00404   // friend int gul::compare( const rational& A, const rational &B );
00405 };
00406 
00407 /*****************************************************************************/
00408 
00409 /* ---------------------------------------------------------------
00410   functions for intervall arithmetic
00411 --------------------------------------------------------------- */
00412 
00413 inline Interval operator+( const Interval &a, const Interval &b )
00414 {
00415   Interval c;
00416   
00417   c.m_low = a.m_low + b.m_low;
00418   c.m_low = c.m_low - DBL_EPSILON*fabs(c.m_low);
00419 
00420   c.m_high = a.m_high + b.m_high;
00421   c.m_high = c.m_high + DBL_EPSILON*fabs(c.m_high);
00422     
00423   return( c );
00424 }
00425 
00426 inline Interval operator-( const Interval &a, const Interval &b )
00427 {
00428   Interval c(-b.m_high,-b.m_low);
00429   
00430   return(a+c);
00431 }
00432 
00433 inline Interval operator/( const Interval &a, const Interval &b )
00434 {
00435   if( (b.m_low < 0.0) && (b.m_high > 0.0) )
00436     throw gul::IntervalDivZeroError();
00437 
00438   Interval c(1.0/b.m_high,1.0/b.m_low);
00439   
00440   return(a*c);
00441 }
00442 
00443 // according to the Ansi C standard 'sqrt' has a rounding error less then 1 ULP
00444 inline Interval Sqrt( const Interval &a )
00445 {
00446   Interval c;
00447   
00448   c.m_low = sqrt(a.m_low);
00449   c.m_low = c.m_low - DBL_EPSILON*fabs(c.m_low);
00450 
00451   c.m_high = sqrt(a.m_high);
00452   c.m_high = c.m_high + DBL_EPSILON*fabs(c.m_high);
00453     
00454   return( c );
00455 }
00456 
00457 inline int Test( const Interval &a )
00458 {
00459   if( a.m_high < 0.0 ) return(-1);
00460   if( a.m_low > 0.0 ) return(+1);
00461 
00462   return(0);   /* dunno :) */
00463 }
00464 
00465 inline int Test( const Interval &a, const Interval &b )
00466 {
00467   Interval c = a-b;
00468   return Test(c);
00469 }
00470 
00471 inline double GetRatio( const Interval &a )
00472 {
00473   double h,l;
00474 
00475   h = a.m_high;
00476   l = a.m_low;
00477 
00478   if( l < 0.0 )
00479   {
00480     if( h >= 0.0 ) return gul::rtr<double>::giant(); // relative error = inf
00481 
00482     h = -l;
00483     l = -h;
00484   }
00485    
00486   if( l == 0.0 )
00487   {
00488     if( h == 0.0 ) return 1.0;
00489     return gul::rtr<double>::giant();
00490   }
00491 
00492   return h/l;
00493 }
00494 
00495 /* ---------------------------------------------------------------
00496   functions for fractions arithmetic
00497 --------------------------------------------------------------- */
00498 
00499 /*
00500 inline bool operator<( const rational& A, int b )
00501 {
00502   rational B,C;
00503   unsigned long buf;
00504   
00505   if( b < 0 )
00506   {
00507     B.m->m_sign = -1;
00508     buf = -b;
00509     B.m->m_a = &buf;
00510     B.m->m_na = 1; 
00511   }
00512   else if( b > 0 )
00513   {
00514     buf = b;
00515     B.m->m_a = &buf;
00516     B.m->m_na = 1; 
00517   }
00518   
00519   C = A - B;
00520 
00521   return( C.m->m_sign != 0 );
00522 }
00523 
00524 inline bool operator<=( const rational& A, int b )
00525 {
00526   rational B,C;
00527   unsigned long buf;
00528   
00529   if( b < 0 )
00530   {
00531     B.m->m_sign = -1;
00532     buf = -b;
00533     B.m->m_a = &buf;
00534     B.m->m_na = 1; 
00535   }
00536   else if( b > 0 )
00537   {
00538     buf = b;
00539     B.m->m_a = &buf;
00540     B.m->m_na = 1; 
00541   }
00542   
00543   C = A - B;
00544 
00545   if( C.m->m_sign || C.m->m_na == 0)
00546     return(true);
00547 
00548   return( false );
00549 }
00550 
00551 inline bool operator>=( const rational& A, int b )
00552 {
00553   return( !(A < b) );
00554 }
00555 */
00556 
00557 /*
00558 class point2<rational>
00559 {
00560 public:
00561   rational m_x;
00562   rational m_y;
00563 
00564   point2<rational>() { }
00565   ~point2<rational>() { }
00566   explicit point2<rational>( const point2<rational>& o ) : m_x(o.m_x), m_y(o.m_y) { }
00567   explicit point2<rational>( ULong x, ULong y ) : m_x(x), m_y(y) { }
00568   explicit point2<rational>( const rational& x, const rational& y ) : 
00569                                                         m_x(x), m_y(y) { }
00570 };
00571 
00572 class PrecPoint3D
00573 {
00574 public:
00575   rational m_x;
00576   rational m_y;
00577   rational m_z;
00578 
00579   PrecPoint3D() { }
00580   ~PrecPoint3D() { }
00581   PrecPoint3D( const PrecPoint3D& o ) 
00582                     : m_x(o.m_x), m_y(o.m_y), m_z(o.m_z) { }
00583   PrecPoint3D( ULong x, ULong y, ULong z ) 
00584                     : m_x(x), m_y(y), m_z(z) { }
00585   PrecPoint3D( 
00586      const rational& x, const rational& y, const rational& z ) 
00587                     : m_x(x), m_y(y), m_z(z) { }
00588 
00589   PrecPoint3D& operator=( const PrecPoint3D& o ) 
00590                   { m_x = o.m_x; m_y = o.m_y; m_z = o.m_z; return *this; }
00591 };
00592 */
00593 
00594 }
00595 
00596 namespace gul {
00597 
00598 template<> struct rtr< guar::rational >
00599 {
00600   // these constants are needed in some templates, which i also want to 
00601   // instantiate for the rational number class, and  i do not want to write
00602   //  an operator which converts floats or ints to rationals (this is too
00603   // dangerous, because of the many (unwanted) implicit conversions, 
00604   // which c++ does)
00605   static guar::rational zero() { return guar::rational(); }
00606   static guar::rational one() { return guar::rational(guar::ULong(1)); }
00607 };
00608 
00609 template<>
00610 inline int test( const guar::rational& a )
00611 {
00612   return a.test();
00613 }
00614 
00615 #ifdef GUL_VECTOR_H
00616 template<> inline point<guar::rational> cross_product( 
00617       const point2<guar::rational>& a, const point2<guar::rational>& b )
00618 {
00619   point<guar::rational> c;
00620   c.z = a.x*b.y-b.x*a.y;
00621   return c;
00622 }
00623 #endif
00624 
00625 template<>
00626 inline int compare( const guar::rational& A, const guar::rational &B )
00627 {
00628   guar::Interval i;
00629   
00630   if( A.m == B.m )
00631     return 0;
00632 
00633   if( !A.m->m_bounds ) A.calc_bounds();
00634   if( !B.m->m_bounds ) B.calc_bounds();  
00635   i = A.m->m_i - B.m->m_i;
00636   if( i.m_high < 0.0 ) return(-1); 
00637   else if( i.m_low > 0.0 ) return(1); 
00638 
00639   guar::rational c = A - B;
00640   if( c.m->m_sign ) return(-1);
00641   if( c.m->m_na == 0 ) return(0);
00642 
00643   return(1);
00644 }
00645 
00646 inline std::ostream& operator<<( std::ostream& s, const guar::rational& r )
00647 {
00648   return s << r.dump();
00649 } 
00650 
00651 }
00652 
00653 #endif

Generated on Mon Jan 21 04:17:18 2002 for GUL 0.6 - Geometry Utility Library by doxygen1.2.13.1 written by Dimitri van Heesch, © 1997-2001