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

guar_exact.cpp

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 #include "stdafx.h"
00021 
00022 #include <iostream>
00023 
00024 #include <stdio.h>
00025 #include <math.h>
00026 #include "gul_types.h"
00027 #include "guar_exact.h"
00028 
00029 namespace guar {
00030 
00031 using gul::uint64;
00032 using gul::uint32;
00033 
00034 /* ----------------------------------------------------------------
00035   Calculates the sum of two operands
00036 ------------------------------------------------------------------ */
00037 void IntAdd( const unsigned int na, const unsigned long *a, 
00038              const unsigned int nb, const unsigned long *b, 
00039              unsigned int *nc, unsigned long *c )
00040 {
00041   uint64 l,z=0;
00042   unsigned int i,len;
00043   
00044   if( na < nb )
00045   {
00046     len = nb+1;
00047     
00048     for( i = 0; i < na; i++ )
00049     {
00050       l = (uint64)a[i] + (uint64)b[i] + z;
00051       c[i] = (unsigned long)(l & 0xffffffff);
00052       z = (l >> 32) & 0xffffffff;
00053     }
00054     for( i = na; i < nb; i++ )
00055     {
00056       l = (uint64)b[i] + z;
00057       c[i] = (unsigned long)(l & 0xffffffff);
00058       z = (l >> 32) & 0xffffffff;
00059     }
00060     if( (c[i] = (unsigned long)z) == 0 ) len -= 1;
00061   }
00062   else
00063   {
00064     len = na+1;
00065     
00066     for( i = 0; i < nb; i++ )
00067     {
00068       l = (uint64)a[i] + (uint64)b[i] + z;
00069       c[i] = (unsigned long)(l & 0xffffffff);
00070       z = (l >> 32) & 0xffffffff;
00071     }
00072     for( i = nb; i < na; i++ )
00073     {
00074       l = (uint64)a[i] + z;
00075       c[i] = (unsigned long)(l & 0xffffffff);
00076       z = (l >> 32) & 0xffffffff;
00077     }
00078     if( (c[i] = (unsigned long)z) == 0 ) len -= 1;
00079   }
00080 
00081   *nc = len;
00082 }
00083 
00084 /* ----------------------------------------------------------------
00085   Calculates the difference of two operands
00086 ------------------------------------------------------------------ */
00087 int IntSub( const unsigned int na, const unsigned long *a, 
00088             const unsigned int nb, const unsigned long *b,
00089             unsigned int *nc, unsigned long *c )
00090 {
00091   uint64 l,z=1;
00092   unsigned int i,len;
00093   int sign;
00094 
00095   /* test if b > a */
00096   
00097   if( nb > na )
00098     sign = -1;
00099   else if( na > nb )
00100     sign = 0;
00101   else        /* na == nb */
00102   {
00103     i = na-1;
00104     while( (a[i] == b[i]) && (i > 0) )
00105       i--;
00106     sign = b[i] > a[i] ? -1 : 0;
00107   }
00108  
00109   if( sign )       /* calc b - a, na <= nb */
00110   {
00111     for( i = 0; i < na; i++ )
00112     {
00113       l = 0xffffffff + (uint64)b[i] - (uint64)a[i] + z;
00114       c[i] = (unsigned long)(l & 0xffffffff);
00115       z = (l >> 32) & 0xffffffff;
00116     }
00117     for( i = na; i < nb; i++ )
00118     {
00119       l = 0xffffffff + (uint64)b[i] + z;
00120       c[i] = (unsigned long)(l & 0xffffffff);
00121       z = (l >> 32) & 0xffffffff;
00122     }   
00123     len = nb;
00124   }
00125   else             /* calc a - b, na >= nb */
00126   {
00127     for( i = 0; i < nb; i++ )
00128     {
00129       l = 0xffffffff + (uint64)a[i] - (uint64)b[i] + z;
00130       c[i] = (unsigned long)(l & 0xffffffff);
00131       z = (l >> 32) & 0xffffffff;
00132     }
00133     for( i = nb; i < na; i++ )
00134     {
00135       l = 0xffffffff + (uint64)a[i] + z;
00136       c[i] = (unsigned long)(l & 0xffffffff);
00137       z = (l >> 32) & 0xffffffff;
00138     }    
00139     len = na;
00140   }
00141 
00142   /* strip leading zeros */
00143 
00144   for( ; (len > 0) && (c[len-1] == 0); len-- );
00145 
00146   *nc = len;
00147   return( sign );
00148 }
00149 
00150 /* ---------------------------------------------------------------
00151   Short Multiplication
00152 ---------------------------------------------------------------- */
00153 unsigned long IntMultShort( 
00154          const unsigned int na, const unsigned long *a, const unsigned long b,
00155          unsigned long *c )
00156 {
00157   uint64 z, l, m;
00158   unsigned int i;
00159   
00160   z = 0;
00161   m = (uint64)b;
00162 
00163   for( i = 0; i < na; i++ )
00164   {
00165     l = (uint64)a[i]*m + z;
00166     c[i] = (unsigned long)(l & 0xffffffff);
00167     z = (l >> 32) & 0xffffffff;
00168   }
00169   return((unsigned long)z);
00170 }
00171 
00172 /* ----------------------------------------------------------------
00173   Calculates the product of two operands, slow but simple
00174   TODO: Multiplication with FFT
00175 ------------------------------------------------------------------ */
00176 void IntMult( const unsigned int na, const unsigned long *a, 
00177               const unsigned int nb, const unsigned long *b, 
00178               unsigned int *nc, unsigned long *c )
00179 {
00180   uint64 l,z;
00181   unsigned int i,j;
00182 
00183   if( (na == 0) || (nb == 0) )
00184   { *nc = 0; return; }
00185 
00186   for( i = 0; i < na; i++ )
00187     c[i] = 0;
00188 
00189   for( j = 0; j < nb; j++ )
00190   {
00191     z = 0;
00192     for( i = 0; i < na; i++ )
00193     {
00194       l = (uint64)a[i]*(uint64)b[j] + 
00195           (uint64)c[i+j] + z;
00196       c[i+j] = (unsigned long)(l & 0xffffffff);
00197       z = (l >> 32) & 0xffffffff;
00198     }
00199     c[i+j] = (unsigned long)z;
00200   }
00201 
00202   if( c[na+nb-1] == 0 ) *nc = na+nb-1;
00203   else *nc = na+nb;
00204 }
00205 
00206 /* ---------------------------------------------------------
00207   Divide a int-string by a single int
00208 ----------------------------------------------------------- */
00209 unsigned long IntDivShort( 
00210        const unsigned int na, const unsigned long *a, const unsigned long b, 
00211        unsigned int *nq, unsigned long *q )
00212 {
00213   uint64 l, z, d = b;
00214   int i;
00215   
00216   z = 0;
00217   for( i = na-1; i >= 0; i-- )
00218   {
00219     l = (z<<32) + ((uint64)a[i]);
00220     q[i] = (unsigned long)(l / d);
00221     z = l % d;
00222   }
00223 
00224   if( q[na-1] == 0 )
00225     *nq = na-1;
00226   else
00227     *nq = na;
00228 
00229   return((unsigned long)z);
00230 }
00231 
00232 /* ---------------------------------------------------------
00233   Divide a int-string by a int-string
00234 ----------------------------------------------------------- */
00235 int IntDiv( const unsigned int na, const unsigned long *a, 
00236             const unsigned int nb, const unsigned long *b, 
00237             unsigned int *nq, unsigned long *q, 
00238             unsigned int *nr, unsigned long *r )
00239 {
00240   unsigned long *ad, *bd;
00241   uint64 d, z, l, b1, b2, m, ml, qh;
00242   unsigned int i,j;
00243   int sign;
00244 
00245   if( na == 0 )
00246   {
00247     *nq = 0;
00248     *nr = 0;
00249     return(-1);
00250   }
00251 
00252   if( nb < 2 )
00253   {
00254     if( nb == 0 ) return(0);
00255     
00256     r[0] = IntDivShort( na, a, b[0], nq, q );
00257     if( r[0] != 0 ) *nr = 1; else *nr = 0;
00258     return(-1);
00259   }
00260 
00261   if( na < nb )
00262   {
00263     memcpy( r, a, na*sizeof(unsigned long) );
00264     *nr = na;
00265     *nq = 0;
00266     return(-1);
00267   }
00268   
00269   ad = (unsigned long *)alloca( sizeof(unsigned long)*(na+1) );
00270   if( ad == NULL ) return(0);
00271   bd = (unsigned long *)alloca( sizeof(unsigned long)*nb );
00272   if( bd == NULL ) return(0);
00273 
00274   d = LL(0x100000000)/(((uint64)b[nb-1]) + LL(1));
00275   
00276   ad[na] = IntMultShort( na, a, (unsigned long)d, ad );
00277   IntMultShort( nb, b, (unsigned long)d, bd );
00278   
00279   b1 = bd[nb-1];
00280   b2 = bd[nb-2];
00281 
00282   for( i = na; i >= nb; i-- )
00283   {
00284     l = (((uint64)ad[i])<<32) + (uint64)ad[i-1];
00285 
00286     if( ad[i] == bd[nb-1] )
00287       qh = 0xffffffff;
00288     else
00289       qh =  l/b1;
00290       
00291     while( b2*qh > ((l - b1*qh)<<32) + (uint64)ad[i-2] ) qh--;
00292         
00293     z = 1;    
00294     sign = 0;
00295     m = 0;
00296     for( j = 0; j < nb; j++ )
00297     {
00298       m = qh*(uint64)bd[j] + m;
00299       ml = m & 0xffffffff;
00300       m = m >> 32;
00301       
00302       l = 0xffffffff + (uint64)ad[i-nb+j] - ml + z;
00303       ad[i-nb+j] = (unsigned long)(l & 0xffffffff);
00304       z = (l >> 32) & 0xffffffff;
00305     }        
00306     l = 0xffffffff + (uint64)ad[i] - m + z;
00307     ad[i] = (unsigned long)(l & 0xffffffff);
00308     z = (l >> 32) & 0xffffffff;
00309     sign = (z - LL(1) != 0 ? -1 : 0);
00310     
00311     if( sign )        /* add borrow back */
00312     {
00313       qh--;
00314 
00315       z = 0;
00316       for( j = 0; j < nb; j++ )
00317       {
00318         l = (uint64)ad[i-nb+j] + (uint64)bd[j] + z;
00319         ad[i-nb+j] = (unsigned long)(l & 0xffffffff);
00320         z = (l >> 32) & 0xffffffff;
00321       }        
00322       l = (uint64)ad[i] + z;
00323       ad[i] = (unsigned long)(l & 0xffffffff);
00324     }
00325 
00326     q[i-nb] = (unsigned long)qh;
00327   }
00328   
00329   for( i = nb-1; (i > 0) && (ad[i]==0); i-- );
00330 
00331   if( (i > 0) || (ad[0] != 0) )
00332     // IntDivShort( nb, ad, (unsigned long)d, nr, r );
00333     IntDivShort( i+1, ad, (unsigned long)d, nr, r );
00334   else
00335     *nr = 0;
00336 
00337   if( q[na-nb] == 0 )
00338     *nq = na-nb;
00339   else
00340     *nq = na-nb+1; 
00341 
00342   return(-1);
00343 }
00344 
00345 
00346 /* ---------------------------------------------------------
00347   Converts double to int-string
00348 ----------------------------------------------------------- */
00349 int DoubleToInt( const double d, const unsigned int na, unsigned long *a,
00350                  int *retLen )
00351 {
00352   double f,m;
00353   int i,sign,len;
00354   
00355   if( d < 0.0 )
00356   {
00357     sign = -1;
00358     m = fabs( d );
00359   }
00360   else
00361   {
00362     sign = 0;
00363     m = d;
00364   }
00365 
00366   len = 0;
00367   while( m >= 1.0 )
00368   {
00369     m = m / (double)(LL(0x100000000));
00370     len++;
00371   }
00372   for( i = len-1; i >= 0; i-- )
00373   {
00374     m = m*(double)(LL(0x100000000));
00375     f = floor(m); 
00376     a[i] = (unsigned long)f;
00377     m -= f;
00378   }
00379 
00380   *retLen = len;
00381   return(sign);
00382 }
00383 
00384 /* ------------------------------------------------------------
00385   interval arithmetic functions
00386 -------------------------------------------------------------- */
00387 Interval operator*( const Interval &a, const Interval &b )
00388 {
00389   Interval c;
00390   double f1,f2;
00391   
00392   if( a.m_low >= 0.0 )       /* 0 <= alo <= ahi                   */
00393   {
00394     if( b.m_low >= 0.0 )     /* 0 <= alo <= ahi,  0 <= blo <= bhi */ 
00395     {
00396       c.m_low = a.m_low * b.m_low;
00397       c.m_high = a.m_high * b.m_high;
00398     }
00399     else                     /* blo < 0 */
00400     {
00401       if( b.m_high >= 0 )    /*  0 <= alo <= ahi,  blo < 0 <= bhi */
00402       {
00403         c.m_low = a.m_high * b.m_low;
00404         c.m_high = a.m_high * b.m_high;
00405       }
00406       else                   /*  0 <= alo <= ahi,  blo <= bhi < 0 */
00407       {
00408         c.m_low = a.m_high * b.m_low;
00409         c.m_high = a.m_low * b.m_high;
00410       }
00411     }
00412   }
00413   else                       /* alo < 0 */
00414   {
00415     if( a.m_high < 0.0 )     /* alo <= ahi < 0 */
00416     {
00417       if( b.m_low >= 0 )     /* alo <= ahi < 0,  0 <= blo <= bhi */
00418       {
00419         c.m_low = a.m_low * b.m_high;
00420         c.m_high = a.m_high * b.m_low;
00421       }
00422       else                   /* alo <= ahi < 0,  blo < 0 */
00423       {
00424         if( b.m_high < 0 )   /* alo <= ahi < 0,  blo <= bhi < 0 */
00425         {
00426           c.m_low = a.m_high * b.m_high;
00427           c.m_high = a.m_low * b.m_low;
00428         }
00429         else     /* alo <= ahi < 0,  blo < 0 <= bhi */
00430         {
00431           c.m_low = a.m_low * b.m_high;
00432           c.m_high = a.m_high * b.m_low;
00433         }
00434       }
00435     }
00436     else    /* alo < 0 <= ahi */
00437     {
00438       if( b.m_low >= 0 )   /* alo < 0 <= ahi,  0 <= blo <= bhi */
00439       {
00440         c.m_low = a.m_low * b.m_high;
00441         c.m_high = a.m_high * b.m_high;
00442       }
00443       else                 /* alo < 0 <= ahi,  blo < 0 */
00444       {
00445         if( b.m_high < 0 ) /* alo < 0 <= ahi,  blo <= bhi < 0 */
00446         { 
00447           c.m_low = a.m_high * b.m_low;
00448           c.m_high = a.m_low * b.m_high;
00449         }
00450         else              /* alo < 0 <= ahi,  blo < 0 <= bhi */
00451         {
00452           f1 = a.m_low * b.m_high;
00453           f2 = a.m_high * b.m_low;
00454           c.m_low = f1 < f2 ? f1 : f2;
00455 
00456           f1 = a.m_low * b.m_low;
00457           f2 = a.m_high * b.m_high;
00458           c.m_high = f1 > f2 ? f1 : f2;
00459         }
00460       }
00461     }
00462   }
00463       
00464   c.m_low = c.m_low - DBL_EPSILON*fabs(c.m_low);
00465   c.m_high = c.m_high + DBL_EPSILON*fabs(c.m_high);
00466     
00467   return( c );
00468 }
00469 
00470 GULAPI rational::rational( void )
00471 {
00472   size_t bsize;
00473   void *buf = gust::PoolAlloc( sizeof(rational_rep), &bsize );
00474   if( buf == NULL ) throw gul::PoolAllocError();
00475   m = new(buf) rational_rep;
00476 }
00477 
00478 GULAPI rational::rational( int na, unsigned long *a, int sign )
00479 {
00480   size_t bsize;
00481   void *buf = gust::PoolAlloc( sizeof(rational_rep), &bsize );
00482   if( buf == NULL ) throw gul::PoolAllocError();
00483   m = new(buf) rational_rep(sign,na,a);
00484 }
00485 
00486 GULAPI rational::rational( ULong a, int sign )
00487 {
00488   size_t bsize;
00489   void *buf = gust::PoolAlloc( sizeof(rational_rep), &bsize );
00490   if( buf == NULL ) throw gul::PoolAllocError();
00491   m = new(buf) rational_rep(sign,a);
00492 }
00493 
00494 GULAPI rational::rational( int sign, int size_a, int size_b )
00495 {
00496   size_t bsize;
00497   void *buf = gust::PoolAlloc( sizeof(rational_rep), &bsize );
00498   if( buf == NULL ) throw gul::PoolAllocError();
00499   m = new(buf) rational_rep( sign, size_a, size_b );
00500 }
00501 
00502 GULAPI rational& rational::operator=( const rational& other )
00503 {
00504   other.m->m_refcount++;
00505 
00506   if( --m->m_refcount == 0 ) 
00507   {
00508     m->~rational_rep();
00509     gust::PoolFree( m, sizeof(rational_rep) );      
00510   }
00511 
00512   m = other.m;
00513 
00514   return( *this );    
00515 }   
00516 
00517 GULAPI rational::~rational(void) 
00518 {
00519   if( --m->m_refcount == 0 ) 
00520   {
00521     m->~rational_rep();
00522     gust::PoolFree( m, sizeof(rational_rep) );      
00523   }
00524 }
00525 
00526 GULAPI rational rational::get_copy() const
00527 {
00528   rational C(m->m_sign,m->m_na,m->m_nb);
00529   unsigned int i;
00530     
00531   if( m->m_na )
00532     for( i = 0; i < m->m_na; i++ )
00533       C.m->m_a[i] = m->m_a[i];
00534   if( m->m_nb )
00535     for( i = 0; i < m->m_nb; i++ )
00536       C.m->m_b[i] = m->m_b[i];
00537   return C;
00538 }
00539 
00540 GULAPI void rational::calc_bounds( void ) const 
00541 { 
00542   m->calc_bounds();
00543 } 
00544 
00545 GULAPI const Interval& rational::get_bounds( void ) const
00546 {
00547   if( !m->m_bounds ) m->calc_bounds();
00548   return(m->m_i);
00549 }
00550 
00551 template< class T >
00552 GULAPI void rational::dump( T& num, T& den ) const
00553 { 
00554   m->dump( num, den );
00555 }
00556 /*
00557 template void rational::Dump( float& num, float& den ) const;
00558 template void rational::Dump( double& num, double& den ) const;
00559 */
00560 
00561 /*
00562 template< class T >
00563 void rational::Dump( T& t ) const 
00564 {
00565   T n,d;
00566 
00567   m->dump( n, d );
00568     
00569   t = n/d;
00570 } 
00571 // #ifndef NDEBUG
00572 template<> void rational::Dump( float& t ) const;
00573 template<> void rational::Dump( double& t ) const;
00574 // #endif
00575 */
00576 
00577 /* ---------------------------------------------------------------------
00578   functions for fractions
00579 ----------------------------------------------------------------------- */
00580 GULAPI rational operator*( const rational& a, const rational& b )
00581 {
00582   if( (a.m->m_na == 0) || (b.m->m_na == 0) )  /* a = 0 or b = 0 */
00583   {
00584     rational c;
00585     return(c);
00586   }
00587   else
00588   {
00589     rational c( a.m->m_sign ^ b.m->m_sign, 
00590                       a.m->m_na + b.m->m_na, a.m->m_nb + b.m->m_nb );
00591 
00592     IntMult( a.m->m_na, a.m->m_a, b.m->m_na, b.m->m_a, 
00593              &c.m->m_na, c.m->m_a );
00594 
00595     if( (a.m->m_nb != 0) && (b.m->m_nb != 0) )
00596     {
00597       IntMult( a.m->m_nb, a.m->m_b, b.m->m_nb, b.m->m_b, 
00598                     &c.m->m_nb, c.m->m_b );
00599     }
00600     else
00601     {
00602       if( b.m->m_nb != 0 )
00603       {
00604         memcpy( c.m->m_b, b.m->m_b, b.m->m_nb*sizeof(unsigned long) );
00605         c.m->m_nb = b.m->m_nb; 
00606       }       
00607       else if( a.m->m_nb != 0 )
00608       {
00609         memcpy( c.m->m_b, a.m->m_b, a.m->m_nb*sizeof(unsigned long) );
00610         c.m->m_nb = a.m->m_nb;
00611       }
00612     }
00613       
00614     return(c);
00615   }
00616 }
00617 
00618 GULAPI rational operator+( const rational& A, const rational& B )
00619 {
00620   unsigned long *a1b2,*a2b1,*a1b2_a2b1,*b1b2;
00621   unsigned int na1b2,na2b1,n_a1b2_a2b1,nb1b2;
00622   size_t size_a1b2,size_a2b1,size_a1b2_a2b1,size_b1b2;
00623   int sign,sign2;
00624   
00625   if( A.m->m_na == 0 ) return(B);
00626   if( B.m->m_na == 0 ) return(A);
00627   
00628   rational c;
00629    
00630   if( B.m->m_nb == 0 )
00631   {
00632     a1b2 = A.m->m_a;
00633     na1b2 = A.m->m_na;
00634     size_a1b2 = 0;
00635   }
00636   else
00637   {
00638     a1b2 = (unsigned long *)gust::PoolAlloc( 
00639                      (A.m->m_na+B.m->m_nb)*sizeof(unsigned long), &size_a1b2 );
00640     if( a1b2 == NULL ) throw gul::PoolAllocError();
00641     IntMult( A.m->m_na, A.m->m_a, B.m->m_nb, B.m->m_b, 
00642              &na1b2, a1b2 );
00643   }
00644 
00645   if( A.m->m_nb == 0 )
00646   {
00647     a2b1 = B.m->m_a;
00648     na2b1 = B.m->m_na;
00649     size_a2b1 = 0;
00650   }
00651   else
00652   {
00653     a2b1 = (unsigned long *)gust::PoolAlloc( 
00654                      (B.m->m_na+A.m->m_nb)*sizeof(unsigned long), &size_a2b1 );
00655     if( a2b1 == NULL ) throw gul::PoolAllocError();
00656     IntMult( B.m->m_na, B.m->m_a, A.m->m_nb, A.m->m_b, 
00657              &na2b1, a2b1 );
00658   }
00659 
00660   n_a1b2_a2b1 = na1b2 > na2b1 ? na1b2 : na2b1;
00661   if( n_a1b2_a2b1 == 0 )
00662   {
00663     if( size_a1b2 ) gust::PoolFree( a1b2, size_a1b2 );
00664     if( size_a2b1 ) gust::PoolFree( a2b1, size_a2b1 );
00665     return(c);
00666   }
00667 
00668   sign = A.m->m_sign ^ B.m->m_sign;
00669   if( !sign ) n_a1b2_a2b1++; 
00670 
00671   a1b2_a2b1 = (unsigned long *)gust::PoolAlloc( 
00672                  n_a1b2_a2b1*sizeof(unsigned long), &size_a1b2_a2b1 );
00673   if( a1b2_a2b1 == NULL ) throw gul::PoolAllocError();
00674 
00675   if( sign )
00676   {
00677     sign2 = IntSub( na1b2, a1b2, na2b1, a2b1, &n_a1b2_a2b1, a1b2_a2b1 );
00678     if( n_a1b2_a2b1 == 0 ) 
00679     {
00680       gust::PoolFree( a1b2_a2b1, size_a1b2_a2b1 );
00681       a1b2_a2b1 = NULL;
00682     }
00683   }
00684   else
00685   {
00686     sign2 = 0;
00687     IntAdd( na1b2, a1b2, na2b1, a2b1, &n_a1b2_a2b1, a1b2_a2b1 );
00688   }
00689 
00690   if( size_a1b2 ) gust::PoolFree( a1b2, size_a1b2 );
00691   if( size_a2b1 ) gust::PoolFree( a2b1, size_a2b1 );
00692   
00693   if( n_a1b2_a2b1 == 0 )  /* numerator = 0 */
00694   {
00695     sign = 0;
00696     b1b2 = NULL;
00697     nb1b2 = 0;
00698     size_b1b2 = 0;
00699   }
00700   else                    /* numerator != 0 */
00701   {  
00702     if( A.m->m_sign )
00703       sign = sign2 ^ -1;
00704     else
00705       sign = sign2;
00706      
00707     if( A.m->m_nb == 0 )
00708     {
00709       if( B.m->m_nb == 0 )
00710       {
00711         b1b2 = NULL;
00712         nb1b2 = 0;
00713         size_b1b2 = 0;
00714       }
00715       else
00716       {
00717         nb1b2 = B.m->m_nb;
00718         b1b2 = (unsigned long *)gust::PoolAlloc( 
00719                                     nb1b2*sizeof(unsigned long), &size_b1b2 );
00720         if( b1b2 == NULL ) throw gul::PoolAllocError();
00721         memcpy( b1b2, B.m->m_b, nb1b2*sizeof(unsigned long) );
00722       }
00723     }
00724     else if( B.m->m_nb == 0 )
00725     {
00726       nb1b2 = A.m->m_nb;
00727       b1b2 = (unsigned long *)gust::PoolAlloc( 
00728                                     nb1b2*sizeof(unsigned long), &size_b1b2 );
00729       if( b1b2 == NULL ) throw gul::PoolAllocError();
00730       memcpy( b1b2, A.m->m_b, nb1b2*sizeof(unsigned long) );
00731     }
00732     else
00733     {
00734       b1b2 = (unsigned long *)gust::PoolAlloc( 
00735                 (A.m->m_nb+B.m->m_nb)*sizeof(unsigned long), &size_b1b2 );
00736       if( b1b2 == NULL ) throw gul::PoolAllocError();
00737   
00738       IntMult( A.m->m_nb, A.m->m_b, B.m->m_nb, B.m->m_b,
00739                &nb1b2, b1b2 );
00740     }
00741   }
00742   
00743   c.m->m_sign = sign;
00744   c.m->m_na = n_a1b2_a2b1;
00745   c.m->m_size_a = size_a1b2_a2b1;
00746   c.m->m_a = a1b2_a2b1;
00747   c.m->m_nb = nb1b2;
00748   c.m->m_size_b = size_b1b2;
00749   c.m->m_b = b1b2;
00750   return(c);
00751 }
00752 
00753 GULAPI rational operator/( const rational& A, const rational& B )
00754 {
00755   rational c;
00756   
00757   if( A.m == B.m )
00758     return rational(ULong(1));
00759   
00760   B.m->reciprocal();
00761   c = A * B;
00762   B.m->reciprocal();
00763 
00764   return(c);
00765 }
00766 
00767 GULAPI rational operator-( const rational& A, const rational& B )
00768 {
00769   rational c;  // (= 0)
00770 
00771   if( A.m == B.m )
00772     return c;
00773 
00774   if( A.m->m_na == 0 )   /* if A=0, A+B returns B !!! */
00775   {
00776     if( B.m->m_na != 0 )
00777     {
00778       c = B.get_copy();
00779       c.m->m_sign = B.m->m_sign ^ -1;
00780     }
00781     return c;
00782   }
00783     
00784   B.m->negative();
00785   c = A + B;
00786   B.m->negative();
00787 
00788   return(c);
00789 }
00790 
00791 /* --------------------------------------------------------------------
00792   Divides numerator by denominator (modulo)
00793 ---------------------------------------------------------------------- */
00794 GULAPI void rational::div_mod( rational *q, rational *r ) const
00795 {
00796   if( (m->m_na == 0) || (m->m_nb == 0) )
00797   {
00798     *q = *this;
00799     *r = rational(); 
00800     return;
00801   }
00802   else if( m->m_na < m->m_nb ) 
00803   {
00804     *q = rational();
00805     *r = rational( 0, m->m_na, 0 );
00806     memcpy( r->m->m_a, m->m_a, m->m_na*sizeof(unsigned long) );
00807   }
00808   else 
00809   {
00810     rational Q( 0, m->m_na - m->m_nb + 1, 0 );
00811     rational R( 0, m->m_nb, 0 );
00812 
00813     if( !IntDiv( m->m_na, m->m_a, m->m_nb, m->m_b,
00814                     &Q.m->m_na, Q.m->m_a, &R.m->m_na, R.m->m_a ) )
00815       throw gul::Error();
00816 
00817     *q = Q; *r = R;
00818   }
00819 
00820   if( m->m_sign )
00821   {
00822     *q = *q + rational(ULong(1));
00823     q->m->m_sign = -1;
00824     
00825     rational h( 0, m->m_nb, 0 );
00826     memcpy( h.m->m_a, m->m_b, m->m_nb*sizeof(unsigned long) );
00827     *r = h - *r;
00828   }
00829 }
00830 
00831 /*
00832 GULAPI int rational::to_int() const
00833 {
00834   int i;
00835     
00836   if( (m->m_na != 0) && (m->m_nb != 0) )
00837   {
00838     rational Q,R;
00839   
00840     div_mod( &Q, &R );
00841 
00842     if( Q.m->m_na )
00843     {
00844       i = Q.m->m_a[0] & 0x7fffffff;
00845       if( Q.m->m_sign ) i = -i;
00846     }
00847     else
00848       i = 0;
00849   }
00850   else
00851   {
00852     if( m->m_na )  
00853     {
00854       i = m->m_a[0] & 0x7fffffff;
00855       if( m->m_sign ) i = -i;
00856     }
00857     else
00858       i = 0;
00859   }
00860 
00861   return(i);
00862 }
00863 */
00864 
00865 }
00866 
00867 

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