home *** CD-ROM | disk | FTP | other *** search
/ Power GUI Programming with VisualAge C++ / powergui.iso / powergui / thread / pi / pi.cpp < prev    next >
Text File  |  1996-10-29  |  7KB  |  208 lines

  1. /***************************************************************
  2. * FILE NAME: pi.cpp                                            *
  3. *                                                              *
  4. * DESCRIPTION:                                                 *
  5. *   This file contains the implementation of                   *
  6. *   classes/functions declared in pi.hpp.                      *
  7. *                                                              *
  8. * COPYRIGHT:                                                   *
  9. *   Licensed Materials - Property of Solution Frameworks       *
  10. *   Copyright (C) 1996, Solution Frameworks                    *
  11. *   All Rights Reserved                                        *
  12. ***************************************************************/
  13. #include "pi.hpp"
  14.  
  15. #ifndef _ISTRING_
  16.   #include <istring.hpp>
  17. #endif
  18.  
  19. /*-------------------------- Number ----------------------------
  20. | Objects of this class basically represent integers with      |
  21. | arbitrary numbers of digits.  Note that only a limited set   |
  22. | of operations are guaranteed to work (but that set includes  |
  23. | all we need in this program).                                |
  24. --------------------------------------------------------------*/
  25. class Number {
  26. public:
  27. Number ( unsigned int numDigits ) {
  28.   // All Numbers == "1.00000000..." initially.
  29.   value = IString::leftJustify( "1", numDigits, '0' );
  30. }
  31. Number ( const Number &source ) {
  32.   // Force copy of source value.
  33.   this->value = IString( (char*)source.value, 
  34.                          source.value.length() );
  35. }
  36.  
  37. /*------------------------ Operators -------------------------*/
  38. IString asString ( ) const {
  39.   // Insert decimal point and drop last digit (since it 
  40.   // probably isn't right, anyway).
  41.   return IString( (char*)value, 1, 
  42.                   ".", 1,
  43.                   (char*)value+1, value.length()-1 );
  44. }
  45.  
  46. Number &operator= ( const Number &rhs ) {
  47.   // Force copy of rhs value.
  48.   this->value = IString( (char*)rhs.value, rhs.value.length() );
  49.   return *this;
  50. }
  51.  
  52. operator const void* () const {
  53.   // Return 0 iff all digits are zero.
  54.   const char
  55.    *p = value;
  56.   int
  57.     limit = value.length();
  58.   for( int i = 0; i < limit; i++ )
  59.     if ( p[i] != '0' )
  60.       return p+i;
  61.   return 0;
  62. }
  63.  
  64. Number &operator+= ( const Number &rhs ) {
  65.   // Add each element of rhs to *this.
  66.   char
  67.    *result = value,
  68.    *addend = rhs.value;
  69.   char
  70.     carry = 0;
  71.   for( int i = value.length()-1; i >= 0; i-- ) {
  72.     // If rhs is too short, effectively pad with zeros.
  73.     if ( i >= rhs.value.length() )
  74.       continue;
  75.     // Next digit is sum of result, addend, and carry.
  76.     int
  77.       digit = (result[i]-'0') + (addend[i]-'0') + carry;
  78.     // Calculate new carry and result digit.
  79.     carry = (char)( digit / 10 );
  80.     digit = digit % 10;
  81.     // Store result digit.
  82.     result[i] = (char)( digit + '0' );
  83.   }
  84.   return *this;
  85. }
  86.  
  87. Number &operator-= ( const Number &rhs ) {
  88.   // Subtract each element of rhs from *this.
  89.   char
  90.    *result = value,
  91.    *delta  = rhs.value;
  92.   char
  93.     borrow = 0;
  94.   for( int i = value.length()-1; i >= 0; i-- ) {
  95.     // If rhs is too short, effectively pad with zeros.
  96.     if ( i >= rhs.value.length() )
  97.       continue;
  98.     // Next digit is result digit - borrow - delta digit.
  99.     int
  100.       digit = (result[i]-'0') - borrow - (delta[i] - '0');
  101.     // Calculate new borrow and result digit.
  102.     borrow = (char)( digit < 0 );
  103.     digit += 10 * borrow;
  104.     // Store result digit.
  105.     result[i] = (char)( digit + '0' );
  106.   }
  107.   return *this;
  108. }
  109.  
  110. Number &operator*= ( int factor ) {
  111.   // Multiply each element of *this by factor.
  112.   int
  113.     carry = 0;
  114.   char
  115.    *result = value;
  116.   for( int i = value.length()-1; i >= 0; i-- ) {
  117.     int
  118.       digit = (result[i] - '0') * factor + carry;
  119.     // Calculate new carry and digit.
  120.     carry = digit / 10;
  121.     digit = digit % 10;
  122.     // Store result digit.
  123.     result[i] = (char)( digit + '0' );
  124.   }
  125.   return *this;
  126. }
  127.  
  128. Number &operator/= ( int divisor ) {
  129.   // Divide each element of *this by divisor.
  130.   int
  131.     remainder = 0;
  132.   char
  133.    *result = value;
  134.   int
  135.     limit = value.length();
  136.   for( int i = 0; i < limit; i++ ) {
  137.     // Get next digit and add in remainder from 
  138.     // previous digit calculation.
  139.     int
  140.       digit = (result[i] - '0') + 10 * remainder;
  141.     // Calculate digit and remainder.
  142.     remainder = digit % divisor;
  143.     digit = digit / divisor;
  144.     // Store result digit.
  145.     result[i] = (char)( digit + '0' );
  146.   }
  147.   return *this;
  148. }
  149.  
  150. private:
  151. IString
  152.   value;
  153. }; // class Number
  154.  
  155. /*------------------- arcTangentOfOneOverX ---------------------
  156. | This function returns a Number with value equal to the       |
  157. | arc tangent of 1/x.  The result is valid to numDigits        |
  158. | decimal places (maybe off in the last few digits, though).   |
  159. |                                                              |                
  160. | The result is calculated by using the power series           |
  161. | expansion for arc tangent:                                   |                                 
  162. |   arctan(x) = x - pow(x,3)/3 + pow(x,5)/5 - pow(x,7)/7 ...   |                
  163. --------------------------------------------------------------*/
  164. static Number arcTangentOfOneOverX( int x, int numDigits ) {
  165.   Number
  166.    sum( numDigits + 1 ); // "1.00000...."
  167.   sum /= x;              // "1/x"
  168.  
  169.   Number
  170.     oneOverXToTheK = sum;
  171.  
  172.   /* Continue until delta won't change sum. */
  173.   for ( int k = 1; oneOverXToTheK; k++ ) {
  174.     /* Calculate next term in series. */
  175.     oneOverXToTheK /= x*x;
  176.  
  177.     Number
  178.       delta = oneOverXToTheK;
  179.     delta /= k + k + 1; // 3, 5, 7, ...
  180.  
  181.     /* Adjust sum. */
  182.     if ( k%2 ) {
  183.       // Subtract odd terms.
  184.       sum -= delta;
  185.     } else {
  186.       // Add even terms.
  187.       sum += delta;
  188.     }
  189.   }
  190.   return sum;
  191. }
  192.  
  193. /*---------------------------- pi ------------------------------
  194. | Calculate pi to the requested number of decimal places.      |
  195. |                                                              |
  196. | We use Machin's formula:                                     |
  197. |   pi/4 == 4 * arctan( 1/5 ) - arctan( 1/239 )                |
  198. --------------------------------------------------------------*/
  199. IString pi( unsigned digits ) {
  200.   Number
  201.     pi = arcTangentOfOneOverX( 5, digits );
  202.   pi *= 4;
  203.   pi -= arcTangentOfOneOverX( 239, digits );
  204.   pi *= 4;
  205.  
  206.   return pi.asString();
  207. }
  208.