Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1.  
  2. #ifndef __numbers_h__
  3. #define __numbers_h__
  4.  
  5. #include "lispenvironment.h"
  6. #include "yacasbase.h"
  7.  
  8.  
  9.  
  10. /// Whether the numeric library supports 1.0E-10 and such.
  11. LispInt NumericSupportForMantissa();
  12.  
  13. LispObject* GcdInteger(LispObject* int1, LispObject* int2, LispEnvironment& aEnvironment);
  14.  
  15. LispObject* SinFloat(LispObject* int1, LispEnvironment& aEnvironment,LispInt aPrecision);
  16. LispObject* CosFloat(LispObject* int1, LispEnvironment& aEnvironment,LispInt aPrecision);
  17. LispObject* TanFloat(LispObject* int1, LispEnvironment& aEnvironment,LispInt aPrecision);
  18. LispObject* ArcSinFloat(LispObject* int1, LispEnvironment& aEnvironment,LispInt aPrecision);
  19. LispObject* ExpFloat(LispObject* int1, LispEnvironment& aEnvironment,LispInt aPrecision);
  20. LispObject* LnFloat(LispObject* int1, LispEnvironment& aEnvironment,LispInt aPrecision);
  21.  
  22. LispObject* SqrtFloat(LispObject* int1, LispEnvironment& aEnvironment,LispInt aPrecision);
  23. LispObject* ModFloat( LispObject* int1, LispObject* int2, LispEnvironment& aEnvironment,
  24.                         LispInt aPrecision);
  25.  
  26. LispObject* PowerFloat(LispObject* int1, LispObject* int2,
  27.                          LispEnvironment& aEnvironment,LispInt aPrecision);
  28. LispObject* ShiftLeft( LispObject* int1, LispObject* int2, LispEnvironment& aEnvironment,LispInt aPrecision);
  29. LispObject* ShiftRight( LispObject* int1, LispObject* int2, LispEnvironment& aEnvironment,LispInt aPrecision);
  30. LispObject* LispFactorial(LispObject* int1, LispEnvironment& aEnvironment,LispInt aPrecision);
  31.  
  32.  
  33.  
  34. // methods generally useful for all numeric libraries
  35. const unsigned GUARD_BITS = 8;  // we leave this many guard bits untruncated in various situations when we need to truncate precision by hand
  36.  
  37. template<class T> inline T MAX(T x, T y) { if (x<y) return y; else return x; }
  38. template<class T> inline T MIN(T x, T y) { if (x>y) return y; else return x; }
  39.  
  40. const long DIST_BITS = 1;  // at least this many bits of difference - used in precision tracking
  41.  
  42. /// DIST(x, y) returns 1 if abs(x-y) >= DIST_BITS. See documentation for precision tracking.
  43. template<class T> inline T DIST(T x, T y) { return (x>=y+DIST_BITS || y>=x+DIST_BITS) ? 0 : 1; }
  44.  
  45.  
  46. /** Base number class.
  47.  */
  48.  
  49.  
  50. class ANumber;
  51.  
  52.  
  53.  
  54. /// Main class for multiple-precision arithmetic.
  55. /// All calculations are done at given precision. Integers grow as needed, floats don't grow beyond given precision.
  56. class BigNumber : public YacasBase
  57. {
  58. public: //constructors
  59.   BigNumber(const LispChar * aString,LispInt aPrecision,LispInt aBase=10);
  60. /// copy constructor
  61.   BigNumber(const BigNumber& aOther);
  62.   // no constructors from int or double to avoid automatic conversions
  63.   BigNumber(LispInt aPrecision = 20);
  64.   ~BigNumber();
  65.   // assign from another number
  66.   void SetTo(const BigNumber& aOther);
  67.   // assign from string, precision in base digits
  68.   void SetTo(const LispChar * aString,LispInt aPrecision,LispInt aBase=10);
  69.     // assign from a platform type
  70.   void SetTo(long value);
  71.   inline void SetTo(LispInt value) { SetTo(long(value)); };
  72.   void SetTo(double value);
  73. public: // Convert back to other types
  74.   /// ToString : return string representation of number in aResult to given precision (base digits)
  75.   void ToString(LispString& aResult, LispInt aPrecision, LispInt aBase=10) const;
  76.   /// Give approximate representation as a double number
  77.   double Double() const;
  78.  
  79. public://basic object manipulation
  80.   LispBoolean Equals(const BigNumber& aOther) const;
  81.   LispBoolean IsInt() const;
  82.   LispBoolean IsIntValue() const;
  83.   LispBoolean IsSmall() const;
  84.   void BecomeInt();
  85.   void BecomeFloat(LispInt aPrecision=0);
  86.   LispBoolean LessThan(const BigNumber& aOther) const;
  87. public://arithmetic
  88.   /// Multiply two numbers at given precision and put result in *this
  89.   void Multiply(const BigNumber& aX, const BigNumber& aY, LispInt aPrecision);
  90.   /** Multiply two numbers, and add to *this (this is useful and generally efficient to implement).
  91.    * This is most likely going to be used by internal functions only, using aResult as an accumulator.
  92.    */
  93.   void MultiplyAdd(const BigNumber& aX, const BigNumber& aY, LispInt aPrecision);
  94.   /// Add two numbers at given precision and return result in *this
  95.   void Add(const BigNumber& aX, const BigNumber& aY, LispInt aPrecision);
  96.   /// Negate the given number, return result in *this
  97.   void Negate(const BigNumber& aX);
  98.   /// Divide two numbers and return result in *this. Note: if the two arguments are integer, it should return an integer result!
  99.   void Divide(const BigNumber& aX, const BigNumber& aY, LispInt aPrecision);
  100.  
  101.   /// integer operation: *this = y mod z
  102.   void Mod(const BigNumber& aY, const BigNumber& aZ);
  103.  
  104.   /// For debugging purposes, dump internal state of this object into a string
  105.   void DumpDebugInfo();
  106.  
  107. public:
  108.   /// assign self to Floor(aX) if possible
  109.   void Floor(const BigNumber& aX);
  110.   /// set precision (in bits)
  111.   void Precision(LispInt aPrecision);
  112.  
  113. public:/// Bitwise operations, return result in *this.
  114.   void ShiftLeft( const BigNumber& aX, LispInt aNrToShift);
  115.   void ShiftRight( const BigNumber& aX, LispInt aNrToShift);
  116.   void BitAnd(const BigNumber& aX, const BigNumber& aY);
  117.   void BitOr(const BigNumber& aX, const BigNumber& aY);
  118.   void BitXor(const BigNumber& aX, const BigNumber& aY);
  119.   void BitNot(const BigNumber& aX);
  120.   /// Bit count operation: return the number of significant bits if integer, return the binary exponent if float (shortcut for binary logarithm)
  121.   /// give bit count as a platform integer
  122.   signed long BitCount() const;
  123.  
  124.   /// Give sign (-1, 0, 1)
  125.   LispInt Sign() const;
  126.  
  127. public:
  128.   inline LispInt GetPrecision() const {return iPrecision;};
  129.  
  130. private:
  131.   BigNumber& operator=(const BigNumber& aOther)
  132.   {
  133.     // copy constructor not written yet, hence the assert
  134.     LISPASSERT(0);
  135.     return *this;
  136.   }
  137. public:
  138.   ReferenceCount iReferenceCount;
  139. private:
  140.   LispInt iPrecision;
  141.  
  142. public:
  143.   /// Internal library wrapper starts here.
  144.     inline void SetIsInteger(LispBoolean aIsInteger) {iType = (aIsInteger ? KInt : KFloat);}
  145.     enum ENumType
  146.     {
  147.       KInt = 0,
  148.       KFloat
  149.     };
  150.     ENumType iType;
  151.     ANumber* iNumber;
  152.   /// Internal library wrapper ends here.
  153. };
  154.  
  155. /// bits_to_digits and digits_to_bits, utility functions
  156. /// to convert the number of digits in some base (usually 10) to bits and back
  157.  
  158. // lookup table for Ln(n)/Ln(2). This works whether or not we have math.h.
  159. // table range is from 2 to this value:
  160. unsigned log2_table_range();
  161. // convert the number of digits in given base to the number of bits, and back.
  162. // need to round the number of digits.
  163. // These functions only work for aBase inside the allowed table range.
  164. unsigned long digits_to_bits(unsigned long aDigits, unsigned aBase);
  165. unsigned long bits_to_digits(unsigned long abits, unsigned aBase);
  166.  
  167.  
  168. #endif
  169.  
  170.  
  171.  
  172.  
  173.  
  174.  
  175.  
  176.  
  177.  
  178.  
  179.  
  180.  
  181.  
  182.