|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r69054 - in trunk/boost/geometry: algorithms core extensions/contrib extensions/contrib/ttmath extensions/gis/io/wkt geometries/adapted/boost_polygon geometries/concepts util
From: barend.gehrels_at_[hidden]
Date: 2011-02-19 08:33:21
Author: barendgehrels
Date: 2011-02-19 08:33:14 EST (Sat, 19 Feb 2011)
New Revision: 69054
URL: http://svn.boost.org/trac/boost/changeset/69054
Log:
Enhanced mutable polygon concept with respect to proxies. Now Boost.Polygon is supported for both reading/writing.
Upgraded ttmath
Added coordinate_cast to support "lexical_cast" of ttmath numbers
Added:
trunk/boost/geometry/util/coordinate_cast.hpp (contents, props changed)
Text files modified:
trunk/boost/geometry/algorithms/append.hpp | 2
trunk/boost/geometry/algorithms/clear.hpp | 6
trunk/boost/geometry/core/container_access.hpp | 58
trunk/boost/geometry/extensions/contrib/ttmath/ttmath.h | 54
trunk/boost/geometry/extensions/contrib/ttmath/ttmathbig.h | 9984 +++++++++++++++++++++------------------
trunk/boost/geometry/extensions/contrib/ttmath/ttmathint.h | 2853 ++++++----
trunk/boost/geometry/extensions/contrib/ttmath/ttmathmisc.h | 9
trunk/boost/geometry/extensions/contrib/ttmath/ttmathobjects.h | 49
trunk/boost/geometry/extensions/contrib/ttmath/ttmathparser.h | 41
trunk/boost/geometry/extensions/contrib/ttmath/ttmathtypes.h | 173
trunk/boost/geometry/extensions/contrib/ttmath/ttmathuint.h | 6247 +++++++++++++-----------
trunk/boost/geometry/extensions/contrib/ttmath/ttmathuint_noasm.h | 10
trunk/boost/geometry/extensions/contrib/ttmath/ttmathuint_x86_64.h | 122
trunk/boost/geometry/extensions/contrib/ttmath/ttmathuint_x86_64_msvc.asm | 6
trunk/boost/geometry/extensions/contrib/ttmath_stub.hpp | 34
trunk/boost/geometry/extensions/gis/io/wkt/read_wkt.hpp | 38
trunk/boost/geometry/extensions/gis/io/wkt/write_wkt.hpp | 2
trunk/boost/geometry/geometries/adapted/boost_polygon/holes_proxy.hpp | 42
trunk/boost/geometry/geometries/adapted/boost_polygon/ring.hpp | 4
trunk/boost/geometry/geometries/adapted/boost_polygon/ring_proxy.hpp | 37
trunk/boost/geometry/geometries/concepts/linestring_concept.hpp | 2
trunk/boost/geometry/geometries/concepts/ring_concept.hpp | 2
22 files changed, 10845 insertions(+), 8930 deletions(-)
Modified: trunk/boost/geometry/algorithms/append.hpp
==============================================================================
--- trunk/boost/geometry/algorithms/append.hpp (original)
+++ trunk/boost/geometry/algorithms/append.hpp 2011-02-19 08:33:14 EST (Sat, 19 Feb 2011)
@@ -38,7 +38,7 @@
{
typename geometry::point_type<Geometry>::type copy;
copy_coordinates(point, copy);
- write::push_back(geometry, copy);
+ traits::push_back<Geometry&>::apply(geometry, copy);
}
};
Modified: trunk/boost/geometry/algorithms/clear.hpp
==============================================================================
--- trunk/boost/geometry/algorithms/clear.hpp (original)
+++ trunk/boost/geometry/algorithms/clear.hpp 2011-02-19 08:33:14 EST (Sat, 19 Feb 2011)
@@ -33,7 +33,7 @@
{
static inline void apply(Geometry& geometry)
{
- write::clear(geometry);
+ traits::clear<Geometry&>::apply(geometry);
}
};
@@ -42,8 +42,8 @@
{
static inline void apply(Polygon& polygon)
{
- write::clear(interior_rings(polygon));
- write::clear(exterior_ring(polygon));
+ traits::clear<typename traits::interior_mutable_type<Polygon>::type>::apply(interior_rings(polygon));
+ traits::clear<typename traits::ring_mutable_type<Polygon>::type>::apply(exterior_ring(polygon));
}
};
Modified: trunk/boost/geometry/core/container_access.hpp
==============================================================================
--- trunk/boost/geometry/core/container_access.hpp (original)
+++ trunk/boost/geometry/core/container_access.hpp 2011-02-19 08:33:14 EST (Sat, 19 Feb 2011)
@@ -25,87 +25,59 @@
namespace traits
{
-
/*!
\brief Traits class to clear a geometry
\ingroup traits
*/
-template <typename Container>
+template <typename Range>
struct clear
{
- static inline void apply(Container& container)
+ static inline void apply(Range range)
{
// The default action: act as it it is a std:: container
- container.clear();
+ range.clear();
}
};
/*!
-\brief Traits class to append a point to a container (ring, linestring, multi*)
+\brief Traits class to append a point to a range (ring, linestring, multi*)
\ingroup traits
*/
-template <typename Container>
+template <typename Range>
struct push_back
{
- static inline void apply(Container& container,
- typename boost::range_value<Container>::type const& item)
+ static inline void apply(Range range,
+ typename boost::range_value
+ <
+ typename boost::remove_reference<Range>::type
+ >::type const& item)
{
// The default action: act as it it is a std:: container
- container.push_back(item);
+ range.push_back(item);
}
};
/*!
-\brief Traits class to append a point to a container (ring, linestring, multi*)
+\brief Traits class to append a point to a range (ring, linestring, multi*)
\ingroup traits
*/
-template <typename Container>
+template <typename Range>
struct resize
{
- static inline void apply(Container& container, std::size_t new_size)
+ static inline void apply(Range range, std::size_t new_size)
{
// The default action: act as it it is a std:: container
- container.resize(new_size);
+ range.resize(new_size);
}
};
-
} // namespace traits
-namespace write
-{
-
-// Free functions to conveniently avoid complex metafunctions
-// (Mainly) or internal usage
-
-
-template <typename Container>
-inline void clear(Container& container)
-{
- traits::clear<Container>::apply(container);
-}
-
-template <typename Container>
-inline void resize(Container& container, std::size_t new_size)
-{
- traits::resize<Container>::apply(container, new_size);
-}
-
-template <typename Container>
-inline void push_back(Container& container, typename boost::range_value<Container>::type const& item)
-{
- traits::push_back<Container>::apply(container, item);
-}
-
-
-}
-
-
}} // namespace boost::geometry
Modified: trunk/boost/geometry/extensions/contrib/ttmath/ttmath.h
==============================================================================
--- trunk/boost/geometry/extensions/contrib/ttmath/ttmath.h (original)
+++ trunk/boost/geometry/extensions/contrib/ttmath/ttmath.h 2011-02-19 08:33:14 EST (Sat, 19 Feb 2011)
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (c) 2006-2009, Tomasz Sowa
+ * Copyright (c) 2006-2010, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -273,12 +273,16 @@
template<class ValueType>
ValueType Log(const ValueType & x, const ValueType & base, ErrorCode * err = 0)
{
- if( x.IsNan() || base.IsNan() )
+ if( x.IsNan() )
{
- if( err )
- *err = err_improper_argument;
+ if( err ) *err = err_improper_argument;
+ return x;
+ }
- return ValueType(); // default NaN
+ if( base.IsNan() )
+ {
+ if( err ) *err = err_improper_argument;
+ return base;
}
ValueType result;
@@ -523,7 +527,7 @@
if( err )
*err = err_improper_argument;
- return result; // NaN is set by default
+ return x;
}
if( err )
@@ -854,7 +858,7 @@
if( err )
*err = err_improper_argument;
- return result; // NaN is set by default
+ return x;
}
if( x.GreaterWithoutSignThan(one) )
@@ -1080,7 +1084,7 @@
bool change_sign = false;
if( x.IsNan() )
- return result; // NaN is set by default
+ return x;
// if x is negative we're using the formula:
// atan(-x) = -atan(x)
@@ -1548,7 +1552,7 @@
if( err )
*err = err_improper_argument;
- return result; // NaN is set by default
+ return x;
}
result = x;
@@ -1584,7 +1588,7 @@
if( err )
*err = err_improper_argument;
- return result; // NaN is set by default
+ return x;
}
result = 180;
@@ -1629,7 +1633,9 @@
if( err )
*err = err_improper_argument;
- return delimiter ; // NaN is set by default
+ delimiter.SetZeroNan(); // not needed, only to get rid of GCC warning about an uninitialized variable
+
+ return delimiter;
}
multipler = 60;
@@ -1683,7 +1689,7 @@
if( err )
*err = err_improper_argument;
- return result; // NaN is set by default
+ return x;
}
result = x;
@@ -1719,7 +1725,7 @@
if( err )
*err = err_improper_argument;
- return result; // NaN is set by default
+ return x;
}
result = 200;
@@ -1751,7 +1757,7 @@
if( err )
*err = err_improper_argument;
- return result; // NaN is set by default
+ return x;
}
result = x;
@@ -1801,7 +1807,7 @@
if( err )
*err = err_improper_argument;
- return result; // NaN is set by default
+ return x;
}
result = x;
@@ -1842,7 +1848,9 @@
if( err )
*err = err_improper_argument;
- return ValueType(); // NaN is set by default
+ x.SetNan();
+
+ return x;
}
uint c = x.Sqrt();
@@ -2065,7 +2073,9 @@
if( err )
*err = err_improper_argument;
- return ValueType(); // NaN is set by default
+ x.SetNan();
+
+ return x;
}
if( RootCheckIndexSign(x, index, err) ) return x;
@@ -2154,7 +2164,9 @@
if( err )
*err = err_improper_argument;
- return ValueType(); // NaN is set by default
+ a.SetNan();
+
+ return a;
}
uint c = a.Mod(b);
@@ -2652,7 +2664,7 @@
if( err )
*err = err_improper_argument;
- return result; // NaN is set by default
+ return n;
}
if( cgamma.history.Get(n, result, err_tmp) )
@@ -2731,7 +2743,9 @@
if( err )
*err = err_improper_argument;
- return result; // NaN set by default
+ x.SetNan();
+
+ return x;
}
one.SetOne();
Modified: trunk/boost/geometry/extensions/contrib/ttmath/ttmathbig.h
==============================================================================
--- trunk/boost/geometry/extensions/contrib/ttmath/ttmathbig.h (original)
+++ trunk/boost/geometry/extensions/contrib/ttmath/ttmathbig.h 2011-02-19 08:33:14 EST (Sat, 19 Feb 2011)
@@ -4,20 +4,20 @@
* Author: Tomasz Sowa <t.sowa_at_[hidden]>
*/
-/*
- * Copyright (c) 2006-2010, Tomasz Sowa
+/*
+ * Copyright (c) 2006-2011, Tomasz Sowa
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
- *
+ *
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
- *
+ *
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* * Neither the name Tomasz Sowa nor the names of contributors to this
* project may be used to endorse or promote products derived
* from this software without specific prior written permission.
@@ -39,7 +39,7 @@
#define headerfilettmathbig
/*!
- \file ttmathbig.h
+ \file ttmathbig.h
\brief A Class for representing floating point numbers
*/
@@ -57,28 +57,28 @@
/*!
- \brief Big implements the floating point numbers
+ \brief Big implements the floating point numbers
*/
template <uint exp, uint man>
class Big
{
/*
- value = mantissa * 2^exponent
+ value = mantissa * 2^exponent
- exponent - an integer value with a sign
- mantissa - an integer value without a sing
+ exponent - an integer value with a sign
+ mantissa - an integer value without a sing
- mantissa must be pushed into the left side that is the highest bit from
- mantissa must be one (of course if there's another value than zero) -- this job
- (pushing bits into the left side) making Standardizing() method
-
- for example:
- if we want to store value one (1) into our Big object we must:
- set mantissa to 1
- set exponent to 0
- set info to 0
- and call method Standardizing()
+ mantissa must be pushed into the left side that is the highest bit from
+ mantissa must be one (of course if there's another value than zero) -- this job
+ (pushing bits into the left side) making Standardizing() method
+
+ for example:
+ if we want to store value one (1) into our Big object we must:
+ set mantissa to 1
+ set exponent to 0
+ set info to 0
+ and call method Standardizing()
*/
@@ -90,5129 +90,5971 @@
/*!
- Sign
- the mask of a bit from 'info' which means that there is a sign
- (when the bit is set)
+ Sign
+ the mask of a bit from 'info' which means that there is a sign
+ (when the bit is set)
*/
#define TTMATH_BIG_SIGN 128
/*!
- Not a number
- if this bit is set that there is not a valid number
+ Not a number
+ if this bit is set that there is not a valid number
*/
#define TTMATH_BIG_NAN 64
/*!
- Zero
- if this bit is set that there is value zero
- mantissa should be zero and exponent should be zero too
- (the Standardizing() method does this)
+ Zero
+ if this bit is set that there is value zero
+ mantissa should be zero and exponent should be zero too
+ (the Standardizing() method does this)
*/
#define TTMATH_BIG_ZERO 32
- /*!
- this method sets NaN if there was a carry (and returns 1 in such a case)
+ /*!
+ this method sets NaN if there was a carry (and returns 1 in such a case)
- c can be 0, 1 or other value different from zero
- */
- uint CheckCarry(uint c)
- {
- if( c != 0 )
- {
- SetNan();
- return 1;
- }
+ c can be 0, 1 or other value different from zero
+ */
+ uint CheckCarry(uint c)
+ {
+ if( c != 0 )
+ {
+ SetNan();
+ return 1;
+ }
- return 0;
- }
+ return 0;
+ }
public:
- /*!
- returning the string represents the currect type of the library
- we have following types:
- asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits)
- asm_gcc_32 - with asm code designed for GCC (32 bits)
- asm_vc_64 - with asm for VC (64 bit)
- asm_gcc_64 - with asm for GCC (64 bit)
- no_asm_32 - pure C++ version (32 bit) - without any asm code
- no_asm_64 - pure C++ version (64 bit) - without any asm code
- */
- static const char * LibTypeStr()
- {
- return UInt<man>::LibTypeStr();
- }
-
-
- /*!
- returning the currect type of the library
- */
- static LibTypeCode LibType()
- {
- return UInt<man>::LibType();
- }
+ /*!
+ returning the string represents the currect type of the library
+ we have following types:
+ asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits)
+ asm_gcc_32 - with asm code designed for GCC (32 bits)
+ asm_vc_64 - with asm for VC (64 bit)
+ asm_gcc_64 - with asm for GCC (64 bit)
+ no_asm_32 - pure C++ version (32 bit) - without any asm code
+ no_asm_64 - pure C++ version (64 bit) - without any asm code
+ */
+ static const char * LibTypeStr()
+ {
+ return UInt<man>::LibTypeStr();
+ }
+
+
+ /*!
+ returning the currect type of the library
+ */
+ static LibTypeCode LibType()
+ {
+ return UInt<man>::LibType();
+ }
- /*!
- this method moves all bits from mantissa into its left side
- (suitably changes the exponent) or if the mantissa is zero
- it sets the exponent to zero as well
- (and clears the sign bit and sets the zero bit)
-
- it can return a carry
- the carry will be when we don't have enough space in the exponent
-
- you don't have to use this method if you don't change the mantissa
- and exponent directly
- */
- uint Standardizing()
- {
- if( mantissa.IsTheHighestBitSet() )
- {
- ClearInfoBit(TTMATH_BIG_ZERO);
- return 0;
- }
+ /*!
+ this method moves all bits from mantissa into its left side
+ (suitably changes the exponent) or if the mantissa is zero
+ it sets the exponent to zero as well
+ (and clears the sign bit and sets the zero bit)
+
+ it can return a carry
+ the carry will be when we don't have enough space in the exponent
+
+ you don't have to use this method if you don't change the mantissa
+ and exponent directly
+ */
+ uint Standardizing()
+ {
+ if( mantissa.IsTheHighestBitSet() )
+ {
+ ClearInfoBit(TTMATH_BIG_ZERO);
+ return 0;
+ }
- if( CorrectZero() )
- return 0;
+ if( CorrectZero() )
+ return 0;
- uint comp = mantissa.CompensationToLeft();
+ uint comp = mantissa.CompensationToLeft();
- return exponent.Sub( comp );
- }
+ return exponent.Sub( comp );
+ }
private:
- /*!
- if the mantissa is equal zero this method sets exponent to zero and
- info without the sign
-
- it returns true if there was the correction
- */
- bool CorrectZero()
- {
- if( mantissa.IsZero() )
- {
- SetInfoBit(TTMATH_BIG_ZERO);
- ClearInfoBit(TTMATH_BIG_SIGN);
- exponent.SetZero();
-
- return true;
- }
- else
- {
- ClearInfoBit(TTMATH_BIG_ZERO);
- }
+ /*!
+ if the mantissa is equal zero this method sets exponent to zero and
+ info without the sign
+
+ it returns true if there was the correction
+ */
+ bool CorrectZero()
+ {
+ if( mantissa.IsZero() )
+ {
+ SetInfoBit(TTMATH_BIG_ZERO);
+ ClearInfoBit(TTMATH_BIG_SIGN);
+ exponent.SetZero();
+
+ return true;
+ }
+ else
+ {
+ ClearInfoBit(TTMATH_BIG_ZERO);
+ }
- return false;
- }
+ return false;
+ }
public:
- /*!
- this method clears a specific bit in the 'info' variable
+ /*!
+ this method clears a specific bit in the 'info' variable
- bit is one of: TTMATH_BIG_SIGN, TTMATH_BIG_NAN etc.
- */
- void ClearInfoBit(unsigned char bit)
- {
- info = info & (~bit);
- }
-
-
- /*!
- this method sets a specific bit in the 'info' variable
-
- bit is one of: TTMATH_BIG_SIGN, TTMATH_BIG_NAN etc.
-
- */
- void SetInfoBit(unsigned char bit)
- {
- info = info | bit;
- }
-
-
- /*!
- this method returns true if a specific bit in the 'info' variable is set
-
- bit is one of: TTMATH_BIG_SIGN, TTMATH_BIG_NAN etc.
- */
- bool IsInfoBit(unsigned char bit) const
- {
- return (info & bit) != 0;
- }
-
-
- /*!
- this method sets zero
- */
- void SetZero()
- {
- info = TTMATH_BIG_ZERO;
- exponent.SetZero();
- mantissa.SetZero();
-
- /*
- we don't have to compensate zero
- */
- }
-
-
- /*!
- this method sets one
- */
- void SetOne()
- {
- FromUInt(1);
- }
-
-
- /*!
- this method sets value 0.5
- */
- void Set05()
- {
- FromUInt(1);
- exponent.SubOne();
- }
-
-
- /*!
- this method sets NaN flag (Not a Number)
- when this flag is set that means there is no a valid number
- */
- void SetNan()
- {
- SetInfoBit(TTMATH_BIG_NAN);
- }
+ bit is one of: TTMATH_BIG_SIGN, TTMATH_BIG_NAN etc.
+ */
+ void ClearInfoBit(unsigned char bit)
+ {
+ info = info & (~bit);
+ }
+
+
+ /*!
+ this method sets a specific bit in the 'info' variable
+
+ bit is one of: TTMATH_BIG_SIGN, TTMATH_BIG_NAN etc.
+
+ */
+ void SetInfoBit(unsigned char bit)
+ {
+ info = info | bit;
+ }
+
+
+ /*!
+ this method returns true if a specific bit in the 'info' variable is set
+
+ bit is one of: TTMATH_BIG_SIGN, TTMATH_BIG_NAN etc.
+ */
+ bool IsInfoBit(unsigned char bit) const
+ {
+ return (info & bit) != 0;
+ }
+
+
+ /*!
+ this method sets zero
+ */
+ void SetZero()
+ {
+ info = TTMATH_BIG_ZERO;
+ exponent.SetZero();
+ mantissa.SetZero();
+
+ /*
+ we don't have to compensate zero
+ */
+ }
+
+
+ /*!
+ this method sets one
+ */
+ void SetOne()
+ {
+ info = 0;
+ mantissa.SetZero();
+ mantissa.table[man-1] = TTMATH_UINT_HIGHEST_BIT;
+ exponent = -sint(man * TTMATH_BITS_PER_UINT - 1);
+
+ // don't have to Standardize() - the last bit from mantissa is set
+ }
+
+
+ /*!
+ this method sets value 0.5
+ */
+ void Set05()
+ {
+ SetOne();
+ exponent.SubOne();
+ }
+
+
+ /*!
+ this method sets NaN flag (Not a Number)
+ when this flag is set that means there is no a valid number
+ */
+ void SetNan()
+ {
+ SetInfoBit(TTMATH_BIG_NAN);
+ }
+
+
+ /*!
+ this method sets NaN flag (Not a Number)
+ also clears the mantissa and exponent (similarly as it would be a zero value)
+ */
+ void SetZeroNan()
+ {
+ SetZero();
+ SetNan();
+ }
+
+
+ /*!
+ this method swappes this for an argument
+ */
+ void Swap(Big<exp, man> & ss2)
+ {
+ unsigned char info_temp = info;
+ info = ss2.info;
+ ss2.info = info_temp;
+
+ exponent.Swap(ss2.exponent);
+ mantissa.Swap(ss2.mantissa);
+ }
private:
- /*!
- this method sets the mantissa of the value of pi
- */
- void SetMantissaPi()
- {
- // this is a static table which represents the value of Pi (mantissa of it)
- // (first is the highest word)
- // we must define this table as 'unsigned int' because
- // both on 32bit and 64bit platforms this table is 32bit
- static const unsigned int temp_table[] = {
- 0xc90fdaa2, 0x2168c234, 0xc4c6628b, 0x80dc1cd1, 0x29024e08, 0x8a67cc74, 0x020bbea6, 0x3b139b22,
- 0x514a0879, 0x8e3404dd, 0xef9519b3, 0xcd3a431b, 0x302b0a6d, 0xf25f1437, 0x4fe1356d, 0x6d51c245,
- 0xe485b576, 0x625e7ec6, 0xf44c42e9, 0xa637ed6b, 0x0bff5cb6, 0xf406b7ed, 0xee386bfb, 0x5a899fa5,
- 0xae9f2411, 0x7c4b1fe6, 0x49286651, 0xece45b3d, 0xc2007cb8, 0xa163bf05, 0x98da4836, 0x1c55d39a,
- 0x69163fa8, 0xfd24cf5f, 0x83655d23, 0xdca3ad96, 0x1c62f356, 0x208552bb, 0x9ed52907, 0x7096966d,
- 0x670c354e, 0x4abc9804, 0xf1746c08, 0xca18217c, 0x32905e46, 0x2e36ce3b, 0xe39e772c, 0x180e8603,
- 0x9b2783a2, 0xec07a28f, 0xb5c55df0, 0x6f4c52c9, 0xde2bcbf6, 0x95581718, 0x3995497c, 0xea956ae5,
- 0x15d22618, 0x98fa0510, 0x15728e5a, 0x8aaac42d, 0xad33170d, 0x04507a33, 0xa85521ab, 0xdf1cba64,
- 0xecfb8504, 0x58dbef0a, 0x8aea7157, 0x5d060c7d, 0xb3970f85, 0xa6e1e4c7, 0xabf5ae8c, 0xdb0933d7,
- 0x1e8c94e0, 0x4a25619d, 0xcee3d226, 0x1ad2ee6b, 0xf12ffa06, 0xd98a0864, 0xd8760273, 0x3ec86a64,
- 0x521f2b18, 0x177b200c, 0xbbe11757, 0x7a615d6c, 0x770988c0, 0xbad946e2, 0x08e24fa0, 0x74e5ab31,
- 0x43db5bfc, 0xe0fd108e, 0x4b82d120, 0xa9210801, 0x1a723c12, 0xa787e6d7, 0x88719a10, 0xbdba5b26,
- 0x99c32718, 0x6af4e23c, 0x1a946834, 0xb6150bda, 0x2583e9ca, 0x2ad44ce8, 0xdbbbc2db, 0x04de8ef9,
- 0x2e8efc14, 0x1fbecaa6, 0x287c5947, 0x4e6bc05d, 0x99b2964f, 0xa090c3a2, 0x233ba186, 0x515be7ed,
- 0x1f612970, 0xcee2d7af, 0xb81bdd76, 0x2170481c, 0xd0069127, 0xd5b05aa9, 0x93b4ea98, 0x8d8fddc1,
- 0x86ffb7dc, 0x90a6c08f, 0x4df435c9, 0x34028492, 0x36c3fab4, 0xd27c7026, 0xc1d4dcb2, 0x602646de,
- 0xc9751e76, 0x3dba37bd, 0xf8ff9406, 0xad9e530e, 0xe5db382f, 0x413001ae, 0xb06a53ed, 0x9027d831,
- 0x179727b0, 0x865a8918, 0xda3edbeb, 0xcf9b14ed, 0x44ce6cba, 0xced4bb1b, 0xdb7f1447, 0xe6cc254b,
- 0x33205151, 0x2bd7af42, 0x6fb8f401, 0x378cd2bf, 0x5983ca01, 0xc64b92ec, 0xf032ea15, 0xd1721d03,
- 0xf482d7ce, 0x6e74fef6, 0xd55e702f, 0x46980c82, 0xb5a84031, 0x900b1c9e, 0x59e7c97f, 0xbec7e8f3,
- 0x23a97a7e, 0x36cc88be, 0x0f1d45b7, 0xff585ac5, 0x4bd407b2, 0x2b4154aa, 0xcc8f6d7e, 0xbf48e1d8,
- 0x14cc5ed2, 0x0f8037e0, 0xa79715ee, 0xf29be328, 0x06a1d58b, 0xb7c5da76, 0xf550aa3d, 0x8a1fbff0,
- 0xeb19ccb1, 0xa313d55c, 0xda56c9ec, 0x2ef29632, 0x387fe8d7, 0x6e3c0468, 0x043e8f66, 0x3f4860ee,
- 0x12bf2d5b, 0x0b7474d6, 0xe694f91e, 0x6dbe1159, 0x74a3926f, 0x12fee5e4, 0x38777cb6, 0xa932df8c,
- 0xd8bec4d0, 0x73b931ba, 0x3bc832b6, 0x8d9dd300, 0x741fa7bf, 0x8afc47ed, 0x2576f693, 0x6ba42466,
- 0x3aab639c, 0x5ae4f568, 0x3423b474, 0x2bf1c978, 0x238f16cb, 0xe39d652d, 0xe3fdb8be, 0xfc848ad9,
- 0x22222e04, 0xa4037c07, 0x13eb57a8, 0x1a23f0c7, 0x3473fc64, 0x6cea306b, 0x4bcbc886, 0x2f8385dd,
- 0xfa9d4b7f, 0xa2c087e8, 0x79683303, 0xed5bdd3a, 0x062b3cf5, 0xb3a278a6, 0x6d2a13f8, 0x3f44f82d,
- 0xdf310ee0, 0x74ab6a36, 0x4597e899, 0xa0255dc1, 0x64f31cc5, 0x0846851d, 0xf9ab4819, 0x5ded7ea1,
- 0xb1d510bd, 0x7ee74d73, 0xfaf36bc3, 0x1ecfa268, 0x359046f4, 0xeb879f92, 0x4009438b, 0x481c6cd7,
- 0x889a002e, 0xd5ee382b, 0xc9190da6, 0xfc026e47, 0x9558e447, 0x5677e9aa, 0x9e3050e2, 0x765694df,
- 0xc81f56e8, 0x80b96e71, 0x60c980dd, 0x98a573ea, 0x4472065a, 0x139cd290, 0x6cd1cb72, 0x9ec52a53 // last one was: 0x9ec52a52
- //0x86d44014, ...
- // (the last word 0x9ec52a52 was rounded up because the next one is 0x86d44014 -- first bit is one 0x8..)
- // 256 32bit words for the mantissa -- about 2464 valid decimal digits
- };
- // the value of PI is comming from the website http://zenwerx.com/pi.php
- // 3101 digits were taken from this website
- // (later the digits were compared with:
- // http://www.eveandersson.com/pi/digits/1000000 and http://www.geom.uiuc.edu/~huberty/math5337/groupe/digits.html )
- // and they were set into Big<1,400> type (using operator=(const char*) on a 32bit platform)
- // and then the first 256 words were taken into this table
- // (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256,
- // and on 64bit platform value 128 (256/2=128))
-
- mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int));
- }
+ /*!
+ this method sets the mantissa of the value of pi
+ */
+ void SetMantissaPi()
+ {
+ // this is a static table which represents the value of Pi (mantissa of it)
+ // (first is the highest word)
+ // we must define this table as 'unsigned int' because
+ // both on 32bit and 64bit platforms this table is 32bit
+ static const unsigned int temp_table[] = {
+ 0xc90fdaa2, 0x2168c234, 0xc4c6628b, 0x80dc1cd1, 0x29024e08, 0x8a67cc74, 0x020bbea6, 0x3b139b22,
+ 0x514a0879, 0x8e3404dd, 0xef9519b3, 0xcd3a431b, 0x302b0a6d, 0xf25f1437, 0x4fe1356d, 0x6d51c245,
+ 0xe485b576, 0x625e7ec6, 0xf44c42e9, 0xa637ed6b, 0x0bff5cb6, 0xf406b7ed, 0xee386bfb, 0x5a899fa5,
+ 0xae9f2411, 0x7c4b1fe6, 0x49286651, 0xece45b3d, 0xc2007cb8, 0xa163bf05, 0x98da4836, 0x1c55d39a,
+ 0x69163fa8, 0xfd24cf5f, 0x83655d23, 0xdca3ad96, 0x1c62f356, 0x208552bb, 0x9ed52907, 0x7096966d,
+ 0x670c354e, 0x4abc9804, 0xf1746c08, 0xca18217c, 0x32905e46, 0x2e36ce3b, 0xe39e772c, 0x180e8603,
+ 0x9b2783a2, 0xec07a28f, 0xb5c55df0, 0x6f4c52c9, 0xde2bcbf6, 0x95581718, 0x3995497c, 0xea956ae5,
+ 0x15d22618, 0x98fa0510, 0x15728e5a, 0x8aaac42d, 0xad33170d, 0x04507a33, 0xa85521ab, 0xdf1cba64,
+ 0xecfb8504, 0x58dbef0a, 0x8aea7157, 0x5d060c7d, 0xb3970f85, 0xa6e1e4c7, 0xabf5ae8c, 0xdb0933d7,
+ 0x1e8c94e0, 0x4a25619d, 0xcee3d226, 0x1ad2ee6b, 0xf12ffa06, 0xd98a0864, 0xd8760273, 0x3ec86a64,
+ 0x521f2b18, 0x177b200c, 0xbbe11757, 0x7a615d6c, 0x770988c0, 0xbad946e2, 0x08e24fa0, 0x74e5ab31,
+ 0x43db5bfc, 0xe0fd108e, 0x4b82d120, 0xa9210801, 0x1a723c12, 0xa787e6d7, 0x88719a10, 0xbdba5b26,
+ 0x99c32718, 0x6af4e23c, 0x1a946834, 0xb6150bda, 0x2583e9ca, 0x2ad44ce8, 0xdbbbc2db, 0x04de8ef9,
+ 0x2e8efc14, 0x1fbecaa6, 0x287c5947, 0x4e6bc05d, 0x99b2964f, 0xa090c3a2, 0x233ba186, 0x515be7ed,
+ 0x1f612970, 0xcee2d7af, 0xb81bdd76, 0x2170481c, 0xd0069127, 0xd5b05aa9, 0x93b4ea98, 0x8d8fddc1,
+ 0x86ffb7dc, 0x90a6c08f, 0x4df435c9, 0x34028492, 0x36c3fab4, 0xd27c7026, 0xc1d4dcb2, 0x602646de,
+ 0xc9751e76, 0x3dba37bd, 0xf8ff9406, 0xad9e530e, 0xe5db382f, 0x413001ae, 0xb06a53ed, 0x9027d831,
+ 0x179727b0, 0x865a8918, 0xda3edbeb, 0xcf9b14ed, 0x44ce6cba, 0xced4bb1b, 0xdb7f1447, 0xe6cc254b,
+ 0x33205151, 0x2bd7af42, 0x6fb8f401, 0x378cd2bf, 0x5983ca01, 0xc64b92ec, 0xf032ea15, 0xd1721d03,
+ 0xf482d7ce, 0x6e74fef6, 0xd55e702f, 0x46980c82, 0xb5a84031, 0x900b1c9e, 0x59e7c97f, 0xbec7e8f3,
+ 0x23a97a7e, 0x36cc88be, 0x0f1d45b7, 0xff585ac5, 0x4bd407b2, 0x2b4154aa, 0xcc8f6d7e, 0xbf48e1d8,
+ 0x14cc5ed2, 0x0f8037e0, 0xa79715ee, 0xf29be328, 0x06a1d58b, 0xb7c5da76, 0xf550aa3d, 0x8a1fbff0,
+ 0xeb19ccb1, 0xa313d55c, 0xda56c9ec, 0x2ef29632, 0x387fe8d7, 0x6e3c0468, 0x043e8f66, 0x3f4860ee,
+ 0x12bf2d5b, 0x0b7474d6, 0xe694f91e, 0x6dbe1159, 0x74a3926f, 0x12fee5e4, 0x38777cb6, 0xa932df8c,
+ 0xd8bec4d0, 0x73b931ba, 0x3bc832b6, 0x8d9dd300, 0x741fa7bf, 0x8afc47ed, 0x2576f693, 0x6ba42466,
+ 0x3aab639c, 0x5ae4f568, 0x3423b474, 0x2bf1c978, 0x238f16cb, 0xe39d652d, 0xe3fdb8be, 0xfc848ad9,
+ 0x22222e04, 0xa4037c07, 0x13eb57a8, 0x1a23f0c7, 0x3473fc64, 0x6cea306b, 0x4bcbc886, 0x2f8385dd,
+ 0xfa9d4b7f, 0xa2c087e8, 0x79683303, 0xed5bdd3a, 0x062b3cf5, 0xb3a278a6, 0x6d2a13f8, 0x3f44f82d,
+ 0xdf310ee0, 0x74ab6a36, 0x4597e899, 0xa0255dc1, 0x64f31cc5, 0x0846851d, 0xf9ab4819, 0x5ded7ea1,
+ 0xb1d510bd, 0x7ee74d73, 0xfaf36bc3, 0x1ecfa268, 0x359046f4, 0xeb879f92, 0x4009438b, 0x481c6cd7,
+ 0x889a002e, 0xd5ee382b, 0xc9190da6, 0xfc026e47, 0x9558e447, 0x5677e9aa, 0x9e3050e2, 0x765694df,
+ 0xc81f56e8, 0x80b96e71, 0x60c980dd, 0x98a573ea, 0x4472065a, 0x139cd290, 0x6cd1cb72, 0x9ec52a53 // last one was: 0x9ec52a52
+ //0x86d44014, ...
+ // (the last word 0x9ec52a52 was rounded up because the next one is 0x86d44014 -- first bit is one 0x8..)
+ // 256 32bit words for the mantissa -- about 2464 valid decimal digits
+ };
+ // the value of PI is comming from the website http://zenwerx.com/pi.php
+ // 3101 digits were taken from this website
+ // (later the digits were compared with:
+ // http://www.eveandersson.com/pi/digits/1000000 and http://www.geom.uiuc.edu/~huberty/math5337/groupe/digits.html )
+ // and they were set into Big<1,400> type (using operator=(const char*) on a 32bit platform)
+ // and then the first 256 words were taken into this table
+ // (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256,
+ // and on 64bit platform value 128 (256/2=128))
+
+ mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int));
+ }
public:
- /*!
- this method sets the value of pi
- */
- void SetPi()
- {
- SetMantissaPi();
- info = 0;
- exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2;
- }
-
-
- /*!
- this method sets the value of 0.5 * pi
- */
- void Set05Pi()
- {
- SetMantissaPi();
- info = 0;
- exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 1;
- }
-
-
- /*!
- this method sets the value of 2 * pi
- */
- void Set2Pi()
- {
- SetMantissaPi();
- info = 0;
- exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 3;
- }
-
-
- /*!
- this method sets the value of e
- (the base of the natural logarithm)
- */
- void SetE()
- {
- static const unsigned int temp_table[] = {
- 0xadf85458, 0xa2bb4a9a, 0xafdc5620, 0x273d3cf1, 0xd8b9c583, 0xce2d3695, 0xa9e13641, 0x146433fb,
- 0xcc939dce, 0x249b3ef9, 0x7d2fe363, 0x630c75d8, 0xf681b202, 0xaec4617a, 0xd3df1ed5, 0xd5fd6561,
- 0x2433f51f, 0x5f066ed0, 0x85636555, 0x3ded1af3, 0xb557135e, 0x7f57c935, 0x984f0c70, 0xe0e68b77,
- 0xe2a689da, 0xf3efe872, 0x1df158a1, 0x36ade735, 0x30acca4f, 0x483a797a, 0xbc0ab182, 0xb324fb61,
- 0xd108a94b, 0xb2c8e3fb, 0xb96adab7, 0x60d7f468, 0x1d4f42a3, 0xde394df4, 0xae56ede7, 0x6372bb19,
- 0x0b07a7c8, 0xee0a6d70, 0x9e02fce1, 0xcdf7e2ec, 0xc03404cd, 0x28342f61, 0x9172fe9c, 0xe98583ff,
- 0x8e4f1232, 0xeef28183, 0xc3fe3b1b, 0x4c6fad73, 0x3bb5fcbc, 0x2ec22005, 0xc58ef183, 0x7d1683b2,
- 0xc6f34a26, 0xc1b2effa, 0x886b4238, 0x611fcfdc, 0xde355b3b, 0x6519035b, 0xbc34f4de, 0xf99c0238,
- 0x61b46fc9, 0xd6e6c907, 0x7ad91d26, 0x91f7f7ee, 0x598cb0fa, 0xc186d91c, 0xaefe1309, 0x85139270,
- 0xb4130c93, 0xbc437944, 0xf4fd4452, 0xe2d74dd3, 0x64f2e21e, 0x71f54bff, 0x5cae82ab, 0x9c9df69e,
- 0xe86d2bc5, 0x22363a0d, 0xabc52197, 0x9b0deada, 0x1dbf9a42, 0xd5c4484e, 0x0abcd06b, 0xfa53ddef,
- 0x3c1b20ee, 0x3fd59d7c, 0x25e41d2b, 0x669e1ef1, 0x6e6f52c3, 0x164df4fb, 0x7930e9e4, 0xe58857b6,
- 0xac7d5f42, 0xd69f6d18, 0x7763cf1d, 0x55034004, 0x87f55ba5, 0x7e31cc7a, 0x7135c886, 0xefb4318a,
- 0xed6a1e01, 0x2d9e6832, 0xa907600a, 0x918130c4, 0x6dc778f9, 0x71ad0038, 0x092999a3, 0x33cb8b7a,
- 0x1a1db93d, 0x7140003c, 0x2a4ecea9, 0xf98d0acc, 0x0a8291cd, 0xcec97dcf, 0x8ec9b55a, 0x7f88a46b,
- 0x4db5a851, 0xf44182e1, 0xc68a007e, 0x5e0dd902, 0x0bfd64b6, 0x45036c7a, 0x4e677d2c, 0x38532a3a,
- 0x23ba4442, 0xcaf53ea6, 0x3bb45432, 0x9b7624c8, 0x917bdd64, 0xb1c0fd4c, 0xb38e8c33, 0x4c701c3a,
- 0xcdad0657, 0xfccfec71, 0x9b1f5c3e, 0x4e46041f, 0x388147fb, 0x4cfdb477, 0xa52471f7, 0xa9a96910,
- 0xb855322e, 0xdb6340d8, 0xa00ef092, 0x350511e3, 0x0abec1ff, 0xf9e3a26e, 0x7fb29f8c, 0x183023c3,
- 0x587e38da, 0x0077d9b4, 0x763e4e4b, 0x94b2bbc1, 0x94c6651e, 0x77caf992, 0xeeaac023, 0x2a281bf6,
- 0xb3a739c1, 0x22611682, 0x0ae8db58, 0x47a67cbe, 0xf9c9091b, 0x462d538c, 0xd72b0374, 0x6ae77f5e,
- 0x62292c31, 0x1562a846, 0x505dc82d, 0xb854338a, 0xe49f5235, 0xc95b9117, 0x8ccf2dd5, 0xcacef403,
- 0xec9d1810, 0xc6272b04, 0x5b3b71f9, 0xdc6b80d6, 0x3fdd4a8e, 0x9adb1e69, 0x62a69526, 0xd43161c1,
- 0xa41d570d, 0x7938dad4, 0xa40e329c, 0xcff46aaa, 0x36ad004c, 0xf600c838, 0x1e425a31, 0xd951ae64,
- 0xfdb23fce, 0xc9509d43, 0x687feb69, 0xedd1cc5e, 0x0b8cc3bd, 0xf64b10ef, 0x86b63142, 0xa3ab8829,
- 0x555b2f74, 0x7c932665, 0xcb2c0f1c, 0xc01bd702, 0x29388839, 0xd2af05e4, 0x54504ac7, 0x8b758282,
- 0x2846c0ba, 0x35c35f5c, 0x59160cc0, 0x46fd8251, 0x541fc68c, 0x9c86b022, 0xbb709987, 0x6a460e74,
- 0x51a8a931, 0x09703fee, 0x1c217e6c, 0x3826e52c, 0x51aa691e, 0x0e423cfc, 0x99e9e316, 0x50c1217b,
- 0x624816cd, 0xad9a95f9, 0xd5b80194, 0x88d9c0a0, 0xa1fe3075, 0xa577e231, 0x83f81d4a, 0x3f2fa457,
- 0x1efc8ce0, 0xba8a4fe8, 0xb6855dfe, 0x72b0a66e, 0xded2fbab, 0xfbe58a30, 0xfafabe1c, 0x5d71a87e,
- 0x2f741ef8, 0xc1fe86fe, 0xa6bbfde5, 0x30677f0d, 0x97d11d49, 0xf7a8443d, 0x0822e506, 0xa9f4614e,
- 0x011e2a94, 0x838ff88c, 0xd68c8bb7, 0xc51eef6d, 0x49ea8ab4, 0xf2c3df5b, 0xb4e0735a, 0xb0d68749
- // 0x2fe26dd4, ...
- // 256 32bit words for the mantissa -- about 2464 valid decimal digits
- };
-
- // above value was calculated using Big<1,400> type on a 32bit platform
- // and then the first 256 words were taken,
- // the calculating was made by using ExpSurrounding0(1) method
- // which took 1420 iterations
- // (the result was compared with e taken from http://antwrp.gsfc.nasa.gov/htmltest/gifcity/e.2mil)
- // (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256,
- // and on 64bit platform value 128 (256/2=128))
-
- mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int));
- exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2;
- info = 0;
- }
-
-
- /*!
- this method sets the value of ln(2)
- the natural logarithm from 2
- */
- void SetLn2()
- {
- static const unsigned int temp_table[] = {
- 0xb17217f7, 0xd1cf79ab, 0xc9e3b398, 0x03f2f6af, 0x40f34326, 0x7298b62d, 0x8a0d175b, 0x8baafa2b,
- 0xe7b87620, 0x6debac98, 0x559552fb, 0x4afa1b10, 0xed2eae35, 0xc1382144, 0x27573b29, 0x1169b825,
- 0x3e96ca16, 0x224ae8c5, 0x1acbda11, 0x317c387e, 0xb9ea9bc3, 0xb136603b, 0x256fa0ec, 0x7657f74b,
- 0x72ce87b1, 0x9d6548ca, 0xf5dfa6bd, 0x38303248, 0x655fa187, 0x2f20e3a2, 0xda2d97c5, 0x0f3fd5c6,
- 0x07f4ca11, 0xfb5bfb90, 0x610d30f8, 0x8fe551a2, 0xee569d6d, 0xfc1efa15, 0x7d2e23de, 0x1400b396,
- 0x17460775, 0xdb8990e5, 0xc943e732, 0xb479cd33, 0xcccc4e65, 0x9393514c, 0x4c1a1e0b, 0xd1d6095d,
- 0x25669b33, 0x3564a337, 0x6a9c7f8a, 0x5e148e82, 0x074db601, 0x5cfe7aa3, 0x0c480a54, 0x17350d2c,
- 0x955d5179, 0xb1e17b9d, 0xae313cdb, 0x6c606cb1, 0x078f735d, 0x1b2db31b, 0x5f50b518, 0x5064c18b,
- 0x4d162db3, 0xb365853d, 0x7598a195, 0x1ae273ee, 0x5570b6c6, 0x8f969834, 0x96d4e6d3, 0x30af889b,
- 0x44a02554, 0x731cdc8e, 0xa17293d1, 0x228a4ef9, 0x8d6f5177, 0xfbcf0755, 0x268a5c1f, 0x9538b982,
- 0x61affd44, 0x6b1ca3cf, 0x5e9222b8, 0x8c66d3c5, 0x422183ed, 0xc9942109, 0x0bbb16fa, 0xf3d949f2,
- 0x36e02b20, 0xcee886b9, 0x05c128d5, 0x3d0bd2f9, 0x62136319, 0x6af50302, 0x0060e499, 0x08391a0c,
- 0x57339ba2, 0xbeba7d05, 0x2ac5b61c, 0xc4e9207c, 0xef2f0ce2, 0xd7373958, 0xd7622658, 0x901e646a,
- 0x95184460, 0xdc4e7487, 0x156e0c29, 0x2413d5e3, 0x61c1696d, 0xd24aaebd, 0x473826fd, 0xa0c238b9,
- 0x0ab111bb, 0xbd67c724, 0x972cd18b, 0xfbbd9d42, 0x6c472096, 0xe76115c0, 0x5f6f7ceb, 0xac9f45ae,
- 0xcecb72f1, 0x9c38339d, 0x8f682625, 0x0dea891e, 0xf07afff3, 0xa892374e, 0x175eb4af, 0xc8daadd8,
- 0x85db6ab0, 0x3a49bd0d, 0xc0b1b31d, 0x8a0e23fa, 0xc5e5767d, 0xf95884e0, 0x6425a415, 0x26fac51c,
- 0x3ea8449f, 0xe8f70edd, 0x062b1a63, 0xa6c4c60c, 0x52ab3316, 0x1e238438, 0x897a39ce, 0x78b63c9f,
- 0x364f5b8a, 0xef22ec2f, 0xee6e0850, 0xeca42d06, 0xfb0c75df, 0x5497e00c, 0x554b03d7, 0xd2874a00,
- 0x0ca8f58d, 0x94f0341c, 0xbe2ec921, 0x56c9f949, 0xdb4a9316, 0xf281501e, 0x53daec3f, 0x64f1b783,
- 0x154c6032, 0x0e2ff793, 0x33ce3573, 0xfacc5fdc, 0xf1178590, 0x3155bbd9, 0x0f023b22, 0x0224fcd8,
- 0x471bf4f4, 0x45f0a88a, 0x14f0cd97, 0x6ea354bb, 0x20cdb5cc, 0xb3db2392, 0x88d58655, 0x4e2a0e8a,
- 0x6fe51a8c, 0xfaa72ef2, 0xad8a43dc, 0x4212b210, 0xb779dfe4, 0x9d7307cc, 0x846532e4, 0xb9694eda,
- 0xd162af05, 0x3b1751f3, 0xa3d091f6, 0x56658154, 0x12b5e8c2, 0x02461069, 0xac14b958, 0x784934b8,
- 0xd6cce1da, 0xa5053701, 0x1aa4fb42, 0xb9a3def4, 0x1bda1f85, 0xef6fdbf2, 0xf2d89d2a, 0x4b183527,
- 0x8fd94057, 0x89f45681, 0x2b552879, 0xa6168695, 0xc12963b0, 0xff01eaab, 0x73e5b5c1, 0x585318e7,
- 0x624f14a5, 0x1a4a026b, 0x68082920, 0x57fd99b6, 0x6dc085a9, 0x8ac8d8ca, 0xf9eeeea9, 0x8a2400ca,
- 0xc95f260f, 0xd10036f9, 0xf91096ac, 0x3195220a, 0x1a356b2a, 0x73b7eaad, 0xaf6d6058, 0x71ef7afb,
- 0x80bc4234, 0x33562e94, 0xb12dfab4, 0x14451579, 0xdf59eae0, 0x51707062, 0x4012a829, 0x62c59cab,
- 0x347f8304, 0xd889659e, 0x5a9139db, 0x14efcc30, 0x852be3e8, 0xfc99f14d, 0x1d822dd6, 0xe2f76797,
- 0xe30219c8, 0xaa9ce884, 0x8a886eb3, 0xc87b7295, 0x988012e8, 0x314186ed, 0xbaf86856, 0xccd3c3b6,
- 0xee94e62f, 0x110a6783, 0xd2aae89c, 0xcc3b76fc, 0x435a0ce1, 0x34c2838f, 0xd571ec6c, 0x1366a993 // last one was: 0x1366a992
- //0xcbb9ac40, ...
- // (the last word 0x1366a992 was rounded up because the next one is 0xcbb9ac40 -- first bit is one 0xc..)
- // 256 32bit words for the mantissa -- about 2464 valid decimal digits
- };
-
- // above value was calculated using Big<1,400> type on a 32bit platform
- // and then the first 256 words were taken,
- // the calculating was made by using LnSurrounding1(2) method
- // which took 4035 iterations
- // (the result was compared with ln(2) taken from http://ja0hxv.calico.jp/pai/estart.html)
- // (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256,
- // and on 64bit platform value 128 (256/2=128))
-
- mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int));
- exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT);
- info = 0;
- }
-
-
- /*!
- this method sets the value of ln(10)
- the natural logarithm from 10
-
- I introduced this constant especially to make the conversion ToString()
- being faster. In fact the method ToString() is keeping values of logarithms
- it has calculated but it must calculate the logarithm at least once.
- If a program, which uses this library, is running for a long time this
- would be ok, but for programs which are running shorter, for example for
- CGI applications which only once are printing values, this would be much
- inconvenience. Then if we're printing with base (radix) 10 and the mantissa
- of our value is smaller than or equal to TTMATH_BUILTIN_VARIABLES_SIZE
- we don't calculate the logarithm but take it from this constant.
- */
- void SetLn10()
- {
- static const unsigned int temp_table[] = {
- 0x935d8ddd, 0xaaa8ac16, 0xea56d62b, 0x82d30a28, 0xe28fecf9, 0xda5df90e, 0x83c61e82, 0x01f02d72,
- 0x962f02d7, 0xb1a8105c, 0xcc70cbc0, 0x2c5f0d68, 0x2c622418, 0x410be2da, 0xfb8f7884, 0x02e516d6,
- 0x782cf8a2, 0x8a8c911e, 0x765aa6c3, 0xb0d831fb, 0xef66ceb0, 0x4ab3c6fa, 0x5161bb49, 0xd219c7bb,
- 0xca67b35b, 0x23605085, 0x8e93368d, 0x44789c4f, 0x5b08b057, 0xd5ede20f, 0x469ea58e, 0x9305e981,
- 0xe2478fca, 0xad3aee98, 0x9cd5b42e, 0x6a271619, 0xa47ecb26, 0x978c5d4f, 0xdb1d28ea, 0x57d4fdc0,
- 0xe40bf3cc, 0x1e14126a, 0x45765cde, 0x268339db, 0xf47fa96d, 0xeb271060, 0xaf88486e, 0xa9b7401e,
- 0x3dfd3c51, 0x748e6d6e, 0x3848c8d2, 0x5faf1bca, 0xe88047f1, 0x7b0d9b50, 0xa949eaaa, 0xdf69e8a5,
- 0xf77e3760, 0x4e943960, 0xe38a5700, 0xffde2db1, 0xad6bfbff, 0xd821ba0a, 0x4cb0466d, 0x61ba648e,
- 0xef99c8e5, 0xf6974f36, 0x3982a78c, 0xa45ddfc8, 0x09426178, 0x19127a6e, 0x3b70fcda, 0x2d732d47,
- 0xb5e4b1c8, 0xc0e5a10a, 0xaa6604a5, 0x324ec3dc, 0xbc64ea80, 0x6e198566, 0x1f1d366c, 0x20663834,
- 0x4d5e843f, 0x20642b97, 0x0a62d18e, 0x478f7bd5, 0x8fcd0832, 0x4a7b32a6, 0xdef85a05, 0xeb56323a,
- 0x421ef5e0, 0xb00410a0, 0xa0d9c260, 0x794a976f, 0xf6ff363d, 0xb00b6b33, 0xf42c58de, 0xf8a3c52d,
- 0xed69b13d, 0xc1a03730, 0xb6524dc1, 0x8c167e86, 0x99d6d20e, 0xa2defd2b, 0xd006f8b4, 0xbe145a2a,
- 0xdf3ccbb3, 0x189da49d, 0xbc1261c8, 0xb3e4daad, 0x6a36cecc, 0xb2d5ae5b, 0x89bf752f, 0xb5dfb353,
- 0xff3065c4, 0x0cfceec8, 0x1be5a9a9, 0x67fddc57, 0xc4b83301, 0x006bf062, 0x4b40ed7a, 0x56c6cdcd,
- 0xa2d6fe91, 0x388e9e3e, 0x48a93f5f, 0x5e3b6eb4, 0xb81c4a5b, 0x53d49ea6, 0x8e668aea, 0xba83c7f8,
- 0xfb5f06c3, 0x58ac8f70, 0xfa9d8c59, 0x8c574502, 0xbaf54c96, 0xc84911f0, 0x0482d095, 0x1a0af022,
- 0xabbab080, 0xec97efd3, 0x671e4e0e, 0x52f166b6, 0xcd5cd226, 0x0dc67795, 0x2e1e34a3, 0xf799677f,
- 0x2c1d48f1, 0x2944b6c5, 0x2ba1307e, 0x704d67f9, 0x1c1035e4, 0x4e927c63, 0x03cf12bf, 0xe2cd2e31,
- 0xf8ee4843, 0x344d51b0, 0xf37da42b, 0x9f0b0fd9, 0x134fb2d9, 0xf815e490, 0xd966283f, 0x23962766,
- 0xeceab1e4, 0xf3b5fc86, 0x468127e2, 0xb606d10d, 0x3a45f4b6, 0xb776102d, 0x2fdbb420, 0x80c8fa84,
- 0xd0ff9f45, 0xc58aef38, 0xdb2410fd, 0x1f1cebad, 0x733b2281, 0x52ca5f36, 0xddf29daa, 0x544334b8,
- 0xdeeaf659, 0x4e462713, 0x1ed485b4, 0x6a0822e1, 0x28db471c, 0xa53938a8, 0x44c3bef7, 0xf35215c8,
- 0xb382bc4e, 0x3e4c6f15, 0x6285f54c, 0x17ab408e, 0xccbf7f5e, 0xd16ab3f6, 0xced2846d, 0xf457e14f,
- 0xbb45d9c5, 0x646ad497, 0xac697494, 0x145de32e, 0x93907128, 0xd263d521, 0x79efb424, 0xd64651d6,
- 0xebc0c9f0, 0xbb583a44, 0xc6412c84, 0x85bb29a6, 0x4d31a2cd, 0x92954469, 0xa32b1abd, 0xf7f5202c,
- 0xa4aa6c93, 0x2e9b53cf, 0x385ab136, 0x2741f356, 0x5de9c065, 0x6009901c, 0x88abbdd8, 0x74efcf73,
- 0x3f761ad4, 0x35f3c083, 0xfd6b8ee0, 0x0bef11c7, 0xc552a89d, 0x58ce4a21, 0xd71e54f2, 0x4157f6c7,
- 0xd4622316, 0xe98956d7, 0x450027de, 0xcbd398d8, 0x4b98b36a, 0x0724c25c, 0xdb237760, 0xe9324b68,
- 0x7523e506, 0x8edad933, 0x92197f00, 0xb853a326, 0xb330c444, 0x65129296, 0x34bc0670, 0xe177806d,
- 0xe338dac4, 0x5537492a, 0xe19add83, 0xcf45000f, 0x5b423bce, 0x6497d209, 0xe30e18a1, 0x3cbf0687,
- 0x67973103, 0xd9485366, 0x81506bba, 0x2e93a9a4, 0x7dd59d3f, 0xf17cd746, 0x8c2075be, 0x552a4348 // last one was: 0x552a4347
- // 0xb4a638ef, ...
- //(the last word 0x552a4347 was rounded up because the next one is 0xb4a638ef -- first bit is one 0xb..)
- // 256 32bit words for the mantissa -- about 2464 valid digits (decimal)
- };
-
- // above value was calculated using Big<1,400> type on a 32bit platform
- // and then the first 256 32bit words were taken,
- // the calculating was made by using LnSurrounding1(10) method
- // which took 22080 iterations
- // (the result was compared with ln(10) taken from http://ja0hxv.calico.jp/pai/estart.html)
- // (the formula used in LnSurrounding1(x) converges badly when
- // the x is greater than one but in fact we can use it, only the
- // number of iterations will be greater)
- // (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256,
- // and on 64bit platform value 128 (256/2=128))
-
- mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int));
- exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2;
- info = 0;
- }
-
-
- /*!
- this method sets the maximum value which can be held in this type
- */
- void SetMax()
- {
- info = 0;
- mantissa.SetMax();
- exponent.SetMax();
-
- // we don't have to use 'Standardizing()' because the last bit from
- // the mantissa is set
- }
-
-
- /*!
- this method sets the minimum value which can be held in this type
- */
- void SetMin()
- {
- info = 0;
-
- mantissa.SetMax();
- exponent.SetMax();
- SetSign();
-
- // we don't have to use 'Standardizing()' because the last bit from
- // the mantissa is set
- }
-
-
- /*!
- testing whether there is a value zero or not
- */
- bool IsZero() const
- {
- return IsInfoBit(TTMATH_BIG_ZERO);
- }
-
-
- /*!
- this method returns true when there's the sign set
- also we don't check the NaN flag
- */
- bool IsSign() const
- {
- return IsInfoBit(TTMATH_BIG_SIGN);
- }
-
-
- /*!
- this method returns true when there is not a valid number
- */
- bool IsNan() const
- {
- return IsInfoBit(TTMATH_BIG_NAN);
- }
-
-
-
- /*!
- this method clears the sign
- (there'll be an absolute value)
-
- e.g.
- -1 -> 1
- 2 -> 2
- */
- void Abs()
- {
- ClearInfoBit(TTMATH_BIG_SIGN);
- }
-
-
- /*!
- this method remains the 'sign' of the value
- e.g. -2 = -1
- 0 = 0
- 10 = 1
- */
- void Sgn()
- {
- // we have to check the NaN flag, because the next SetOne() method would clear it
- if( IsNan() )
- return;
-
- if( IsSign() )
- {
- SetOne();
- SetSign();
- }
- else
- if( IsZero() )
- SetZero();
- else
- SetOne();
- }
-
-
-
- /*!
- this method sets the sign
-
- e.g.
- -1 -> -1
- 2 -> -2
-
- we do not check whether there is a zero or not, if you're using this method
- you must be sure that the value is (or will be afterwards) different from zero
- */
- void SetSign()
- {
- SetInfoBit(TTMATH_BIG_SIGN);
- }
-
-
- /*!
- this method changes the sign
- when there is a value of zero then the sign is not changed
-
- e.g.
- -1 -> 1
- 2 -> -2
- */
- void ChangeSign()
- {
- // we don't have to check the NaN flag here
-
- if( IsZero() )
- return;
-
- if( IsSign() )
- ClearInfoBit(TTMATH_BIG_SIGN);
- else
- SetInfoBit(TTMATH_BIG_SIGN);
- }
-
-
-
-private:
-
- /*!
- this method does the half-to-even rounding (banker's rounding)
-
- if is_half is:
- true - that means the rest was equal the half (0.5 decimal)
- false - that means the rest was greater than a half (greater than 0.5 decimal)
-
- if the rest was less than a half then don't call this method
- (the rounding should does nothing then)
- */
- uint RoundHalfToEven(bool is_half, bool rounding_up = true)
- {
- uint c = 0;
-
- if( !is_half || mantissa.IsTheLowestBitSet() )
- {
- if( rounding_up )
- {
- if( mantissa.AddOne() )
- {
- mantissa.Rcr(1, 1);
- c = exponent.AddOne();
- }
- }
- else
- {
- #ifdef TTMATH_DEBUG
- uint c_from_zero =
- #endif
- mantissa.SubOne();
-
- // we're using rounding_up=false in Add() when the mantissas have different signs
- // mantissa can be zero only when previous mantissa was equal to ss2.mantissa
- // but in such a case 'last_bit_set' will not be set and consequently 'do_rounding' will be false
- TTMATH_ASSERT( c_from_zero == 0 )
- }
- }
-
- return c;
- }
+ /*!
+ this method sets the value of pi
+ */
+ void SetPi()
+ {
+ SetMantissaPi();
+ info = 0;
+ exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2;
+ }
+
+
+ /*!
+ this method sets the value of 0.5 * pi
+ */
+ void Set05Pi()
+ {
+ SetMantissaPi();
+ info = 0;
+ exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 1;
+ }
+
+
+ /*!
+ this method sets the value of 2 * pi
+ */
+ void Set2Pi()
+ {
+ SetMantissaPi();
+ info = 0;
+ exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 3;
+ }
+
+
+ /*!
+ this method sets the value of e
+ (the base of the natural logarithm)
+ */
+ void SetE()
+ {
+ static const unsigned int temp_table[] = {
+ 0xadf85458, 0xa2bb4a9a, 0xafdc5620, 0x273d3cf1, 0xd8b9c583, 0xce2d3695, 0xa9e13641, 0x146433fb,
+ 0xcc939dce, 0x249b3ef9, 0x7d2fe363, 0x630c75d8, 0xf681b202, 0xaec4617a, 0xd3df1ed5, 0xd5fd6561,
+ 0x2433f51f, 0x5f066ed0, 0x85636555, 0x3ded1af3, 0xb557135e, 0x7f57c935, 0x984f0c70, 0xe0e68b77,
+ 0xe2a689da, 0xf3efe872, 0x1df158a1, 0x36ade735, 0x30acca4f, 0x483a797a, 0xbc0ab182, 0xb324fb61,
+ 0xd108a94b, 0xb2c8e3fb, 0xb96adab7, 0x60d7f468, 0x1d4f42a3, 0xde394df4, 0xae56ede7, 0x6372bb19,
+ 0x0b07a7c8, 0xee0a6d70, 0x9e02fce1, 0xcdf7e2ec, 0xc03404cd, 0x28342f61, 0x9172fe9c, 0xe98583ff,
+ 0x8e4f1232, 0xeef28183, 0xc3fe3b1b, 0x4c6fad73, 0x3bb5fcbc, 0x2ec22005, 0xc58ef183, 0x7d1683b2,
+ 0xc6f34a26, 0xc1b2effa, 0x886b4238, 0x611fcfdc, 0xde355b3b, 0x6519035b, 0xbc34f4de, 0xf99c0238,
+ 0x61b46fc9, 0xd6e6c907, 0x7ad91d26, 0x91f7f7ee, 0x598cb0fa, 0xc186d91c, 0xaefe1309, 0x85139270,
+ 0xb4130c93, 0xbc437944, 0xf4fd4452, 0xe2d74dd3, 0x64f2e21e, 0x71f54bff, 0x5cae82ab, 0x9c9df69e,
+ 0xe86d2bc5, 0x22363a0d, 0xabc52197, 0x9b0deada, 0x1dbf9a42, 0xd5c4484e, 0x0abcd06b, 0xfa53ddef,
+ 0x3c1b20ee, 0x3fd59d7c, 0x25e41d2b, 0x669e1ef1, 0x6e6f52c3, 0x164df4fb, 0x7930e9e4, 0xe58857b6,
+ 0xac7d5f42, 0xd69f6d18, 0x7763cf1d, 0x55034004, 0x87f55ba5, 0x7e31cc7a, 0x7135c886, 0xefb4318a,
+ 0xed6a1e01, 0x2d9e6832, 0xa907600a, 0x918130c4, 0x6dc778f9, 0x71ad0038, 0x092999a3, 0x33cb8b7a,
+ 0x1a1db93d, 0x7140003c, 0x2a4ecea9, 0xf98d0acc, 0x0a8291cd, 0xcec97dcf, 0x8ec9b55a, 0x7f88a46b,
+ 0x4db5a851, 0xf44182e1, 0xc68a007e, 0x5e0dd902, 0x0bfd64b6, 0x45036c7a, 0x4e677d2c, 0x38532a3a,
+ 0x23ba4442, 0xcaf53ea6, 0x3bb45432, 0x9b7624c8, 0x917bdd64, 0xb1c0fd4c, 0xb38e8c33, 0x4c701c3a,
+ 0xcdad0657, 0xfccfec71, 0x9b1f5c3e, 0x4e46041f, 0x388147fb, 0x4cfdb477, 0xa52471f7, 0xa9a96910,
+ 0xb855322e, 0xdb6340d8, 0xa00ef092, 0x350511e3, 0x0abec1ff, 0xf9e3a26e, 0x7fb29f8c, 0x183023c3,
+ 0x587e38da, 0x0077d9b4, 0x763e4e4b, 0x94b2bbc1, 0x94c6651e, 0x77caf992, 0xeeaac023, 0x2a281bf6,
+ 0xb3a739c1, 0x22611682, 0x0ae8db58, 0x47a67cbe, 0xf9c9091b, 0x462d538c, 0xd72b0374, 0x6ae77f5e,
+ 0x62292c31, 0x1562a846, 0x505dc82d, 0xb854338a, 0xe49f5235, 0xc95b9117, 0x8ccf2dd5, 0xcacef403,
+ 0xec9d1810, 0xc6272b04, 0x5b3b71f9, 0xdc6b80d6, 0x3fdd4a8e, 0x9adb1e69, 0x62a69526, 0xd43161c1,
+ 0xa41d570d, 0x7938dad4, 0xa40e329c, 0xcff46aaa, 0x36ad004c, 0xf600c838, 0x1e425a31, 0xd951ae64,
+ 0xfdb23fce, 0xc9509d43, 0x687feb69, 0xedd1cc5e, 0x0b8cc3bd, 0xf64b10ef, 0x86b63142, 0xa3ab8829,
+ 0x555b2f74, 0x7c932665, 0xcb2c0f1c, 0xc01bd702, 0x29388839, 0xd2af05e4, 0x54504ac7, 0x8b758282,
+ 0x2846c0ba, 0x35c35f5c, 0x59160cc0, 0x46fd8251, 0x541fc68c, 0x9c86b022, 0xbb709987, 0x6a460e74,
+ 0x51a8a931, 0x09703fee, 0x1c217e6c, 0x3826e52c, 0x51aa691e, 0x0e423cfc, 0x99e9e316, 0x50c1217b,
+ 0x624816cd, 0xad9a95f9, 0xd5b80194, 0x88d9c0a0, 0xa1fe3075, 0xa577e231, 0x83f81d4a, 0x3f2fa457,
+ 0x1efc8ce0, 0xba8a4fe8, 0xb6855dfe, 0x72b0a66e, 0xded2fbab, 0xfbe58a30, 0xfafabe1c, 0x5d71a87e,
+ 0x2f741ef8, 0xc1fe86fe, 0xa6bbfde5, 0x30677f0d, 0x97d11d49, 0xf7a8443d, 0x0822e506, 0xa9f4614e,
+ 0x011e2a94, 0x838ff88c, 0xd68c8bb7, 0xc51eef6d, 0x49ea8ab4, 0xf2c3df5b, 0xb4e0735a, 0xb0d68749
+ // 0x2fe26dd4, ...
+ // 256 32bit words for the mantissa -- about 2464 valid decimal digits
+ };
+
+ // above value was calculated using Big<1,400> type on a 32bit platform
+ // and then the first 256 words were taken,
+ // the calculating was made by using ExpSurrounding0(1) method
+ // which took 1420 iterations
+ // (the result was compared with e taken from http://antwrp.gsfc.nasa.gov/htmltest/gifcity/e.2mil)
+ // (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256,
+ // and on 64bit platform value 128 (256/2=128))
+
+ mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int));
+ exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2;
+ info = 0;
+ }
+
+
+ /*!
+ this method sets the value of ln(2)
+ the natural logarithm from 2
+ */
+ void SetLn2()
+ {
+ static const unsigned int temp_table[] = {
+ 0xb17217f7, 0xd1cf79ab, 0xc9e3b398, 0x03f2f6af, 0x40f34326, 0x7298b62d, 0x8a0d175b, 0x8baafa2b,
+ 0xe7b87620, 0x6debac98, 0x559552fb, 0x4afa1b10, 0xed2eae35, 0xc1382144, 0x27573b29, 0x1169b825,
+ 0x3e96ca16, 0x224ae8c5, 0x1acbda11, 0x317c387e, 0xb9ea9bc3, 0xb136603b, 0x256fa0ec, 0x7657f74b,
+ 0x72ce87b1, 0x9d6548ca, 0xf5dfa6bd, 0x38303248, 0x655fa187, 0x2f20e3a2, 0xda2d97c5, 0x0f3fd5c6,
+ 0x07f4ca11, 0xfb5bfb90, 0x610d30f8, 0x8fe551a2, 0xee569d6d, 0xfc1efa15, 0x7d2e23de, 0x1400b396,
+ 0x17460775, 0xdb8990e5, 0xc943e732, 0xb479cd33, 0xcccc4e65, 0x9393514c, 0x4c1a1e0b, 0xd1d6095d,
+ 0x25669b33, 0x3564a337, 0x6a9c7f8a, 0x5e148e82, 0x074db601, 0x5cfe7aa3, 0x0c480a54, 0x17350d2c,
+ 0x955d5179, 0xb1e17b9d, 0xae313cdb, 0x6c606cb1, 0x078f735d, 0x1b2db31b, 0x5f50b518, 0x5064c18b,
+ 0x4d162db3, 0xb365853d, 0x7598a195, 0x1ae273ee, 0x5570b6c6, 0x8f969834, 0x96d4e6d3, 0x30af889b,
+ 0x44a02554, 0x731cdc8e, 0xa17293d1, 0x228a4ef9, 0x8d6f5177, 0xfbcf0755, 0x268a5c1f, 0x9538b982,
+ 0x61affd44, 0x6b1ca3cf, 0x5e9222b8, 0x8c66d3c5, 0x422183ed, 0xc9942109, 0x0bbb16fa, 0xf3d949f2,
+ 0x36e02b20, 0xcee886b9, 0x05c128d5, 0x3d0bd2f9, 0x62136319, 0x6af50302, 0x0060e499, 0x08391a0c,
+ 0x57339ba2, 0xbeba7d05, 0x2ac5b61c, 0xc4e9207c, 0xef2f0ce2, 0xd7373958, 0xd7622658, 0x901e646a,
+ 0x95184460, 0xdc4e7487, 0x156e0c29, 0x2413d5e3, 0x61c1696d, 0xd24aaebd, 0x473826fd, 0xa0c238b9,
+ 0x0ab111bb, 0xbd67c724, 0x972cd18b, 0xfbbd9d42, 0x6c472096, 0xe76115c0, 0x5f6f7ceb, 0xac9f45ae,
+ 0xcecb72f1, 0x9c38339d, 0x8f682625, 0x0dea891e, 0xf07afff3, 0xa892374e, 0x175eb4af, 0xc8daadd8,
+ 0x85db6ab0, 0x3a49bd0d, 0xc0b1b31d, 0x8a0e23fa, 0xc5e5767d, 0xf95884e0, 0x6425a415, 0x26fac51c,
+ 0x3ea8449f, 0xe8f70edd, 0x062b1a63, 0xa6c4c60c, 0x52ab3316, 0x1e238438, 0x897a39ce, 0x78b63c9f,
+ 0x364f5b8a, 0xef22ec2f, 0xee6e0850, 0xeca42d06, 0xfb0c75df, 0x5497e00c, 0x554b03d7, 0xd2874a00,
+ 0x0ca8f58d, 0x94f0341c, 0xbe2ec921, 0x56c9f949, 0xdb4a9316, 0xf281501e, 0x53daec3f, 0x64f1b783,
+ 0x154c6032, 0x0e2ff793, 0x33ce3573, 0xfacc5fdc, 0xf1178590, 0x3155bbd9, 0x0f023b22, 0x0224fcd8,
+ 0x471bf4f4, 0x45f0a88a, 0x14f0cd97, 0x6ea354bb, 0x20cdb5cc, 0xb3db2392, 0x88d58655, 0x4e2a0e8a,
+ 0x6fe51a8c, 0xfaa72ef2, 0xad8a43dc, 0x4212b210, 0xb779dfe4, 0x9d7307cc, 0x846532e4, 0xb9694eda,
+ 0xd162af05, 0x3b1751f3, 0xa3d091f6, 0x56658154, 0x12b5e8c2, 0x02461069, 0xac14b958, 0x784934b8,
+ 0xd6cce1da, 0xa5053701, 0x1aa4fb42, 0xb9a3def4, 0x1bda1f85, 0xef6fdbf2, 0xf2d89d2a, 0x4b183527,
+ 0x8fd94057, 0x89f45681, 0x2b552879, 0xa6168695, 0xc12963b0, 0xff01eaab, 0x73e5b5c1, 0x585318e7,
+ 0x624f14a5, 0x1a4a026b, 0x68082920, 0x57fd99b6, 0x6dc085a9, 0x8ac8d8ca, 0xf9eeeea9, 0x8a2400ca,
+ 0xc95f260f, 0xd10036f9, 0xf91096ac, 0x3195220a, 0x1a356b2a, 0x73b7eaad, 0xaf6d6058, 0x71ef7afb,
+ 0x80bc4234, 0x33562e94, 0xb12dfab4, 0x14451579, 0xdf59eae0, 0x51707062, 0x4012a829, 0x62c59cab,
+ 0x347f8304, 0xd889659e, 0x5a9139db, 0x14efcc30, 0x852be3e8, 0xfc99f14d, 0x1d822dd6, 0xe2f76797,
+ 0xe30219c8, 0xaa9ce884, 0x8a886eb3, 0xc87b7295, 0x988012e8, 0x314186ed, 0xbaf86856, 0xccd3c3b6,
+ 0xee94e62f, 0x110a6783, 0xd2aae89c, 0xcc3b76fc, 0x435a0ce1, 0x34c2838f, 0xd571ec6c, 0x1366a993 // last one was: 0x1366a992
+ //0xcbb9ac40, ...
+ // (the last word 0x1366a992 was rounded up because the next one is 0xcbb9ac40 -- first bit is one 0xc..)
+ // 256 32bit words for the mantissa -- about 2464 valid decimal digits
+ };
+
+ // above value was calculated using Big<1,400> type on a 32bit platform
+ // and then the first 256 words were taken,
+ // the calculating was made by using LnSurrounding1(2) method
+ // which took 4035 iterations
+ // (the result was compared with ln(2) taken from http://ja0hxv.calico.jp/pai/estart.html)
+ // (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256,
+ // and on 64bit platform value 128 (256/2=128))
+
+ mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int));
+ exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT);
+ info = 0;
+ }
+
+
+ /*!
+ this method sets the value of ln(10)
+ the natural logarithm from 10
+
+ I introduced this constant especially to make the conversion ToString()
+ being faster. In fact the method ToString() is keeping values of logarithms
+ it has calculated but it must calculate the logarithm at least once.
+ If a program, which uses this library, is running for a long time this
+ would be ok, but for programs which are running shorter, for example for
+ CGI applications which only once are printing values, this would be much
+ inconvenience. Then if we're printing with base (radix) 10 and the mantissa
+ of our value is smaller than or equal to TTMATH_BUILTIN_VARIABLES_SIZE
+ we don't calculate the logarithm but take it from this constant.
+ */
+ void SetLn10()
+ {
+ static const unsigned int temp_table[] = {
+ 0x935d8ddd, 0xaaa8ac16, 0xea56d62b, 0x82d30a28, 0xe28fecf9, 0xda5df90e, 0x83c61e82, 0x01f02d72,
+ 0x962f02d7, 0xb1a8105c, 0xcc70cbc0, 0x2c5f0d68, 0x2c622418, 0x410be2da, 0xfb8f7884, 0x02e516d6,
+ 0x782cf8a2, 0x8a8c911e, 0x765aa6c3, 0xb0d831fb, 0xef66ceb0, 0x4ab3c6fa, 0x5161bb49, 0xd219c7bb,
+ 0xca67b35b, 0x23605085, 0x8e93368d, 0x44789c4f, 0x5b08b057, 0xd5ede20f, 0x469ea58e, 0x9305e981,
+ 0xe2478fca, 0xad3aee98, 0x9cd5b42e, 0x6a271619, 0xa47ecb26, 0x978c5d4f, 0xdb1d28ea, 0x57d4fdc0,
+ 0xe40bf3cc, 0x1e14126a, 0x45765cde, 0x268339db, 0xf47fa96d, 0xeb271060, 0xaf88486e, 0xa9b7401e,
+ 0x3dfd3c51, 0x748e6d6e, 0x3848c8d2, 0x5faf1bca, 0xe88047f1, 0x7b0d9b50, 0xa949eaaa, 0xdf69e8a5,
+ 0xf77e3760, 0x4e943960, 0xe38a5700, 0xffde2db1, 0xad6bfbff, 0xd821ba0a, 0x4cb0466d, 0x61ba648e,
+ 0xef99c8e5, 0xf6974f36, 0x3982a78c, 0xa45ddfc8, 0x09426178, 0x19127a6e, 0x3b70fcda, 0x2d732d47,
+ 0xb5e4b1c8, 0xc0e5a10a, 0xaa6604a5, 0x324ec3dc, 0xbc64ea80, 0x6e198566, 0x1f1d366c, 0x20663834,
+ 0x4d5e843f, 0x20642b97, 0x0a62d18e, 0x478f7bd5, 0x8fcd0832, 0x4a7b32a6, 0xdef85a05, 0xeb56323a,
+ 0x421ef5e0, 0xb00410a0, 0xa0d9c260, 0x794a976f, 0xf6ff363d, 0xb00b6b33, 0xf42c58de, 0xf8a3c52d,
+ 0xed69b13d, 0xc1a03730, 0xb6524dc1, 0x8c167e86, 0x99d6d20e, 0xa2defd2b, 0xd006f8b4, 0xbe145a2a,
+ 0xdf3ccbb3, 0x189da49d, 0xbc1261c8, 0xb3e4daad, 0x6a36cecc, 0xb2d5ae5b, 0x89bf752f, 0xb5dfb353,
+ 0xff3065c4, 0x0cfceec8, 0x1be5a9a9, 0x67fddc57, 0xc4b83301, 0x006bf062, 0x4b40ed7a, 0x56c6cdcd,
+ 0xa2d6fe91, 0x388e9e3e, 0x48a93f5f, 0x5e3b6eb4, 0xb81c4a5b, 0x53d49ea6, 0x8e668aea, 0xba83c7f8,
+ 0xfb5f06c3, 0x58ac8f70, 0xfa9d8c59, 0x8c574502, 0xbaf54c96, 0xc84911f0, 0x0482d095, 0x1a0af022,
+ 0xabbab080, 0xec97efd3, 0x671e4e0e, 0x52f166b6, 0xcd5cd226, 0x0dc67795, 0x2e1e34a3, 0xf799677f,
+ 0x2c1d48f1, 0x2944b6c5, 0x2ba1307e, 0x704d67f9, 0x1c1035e4, 0x4e927c63, 0x03cf12bf, 0xe2cd2e31,
+ 0xf8ee4843, 0x344d51b0, 0xf37da42b, 0x9f0b0fd9, 0x134fb2d9, 0xf815e490, 0xd966283f, 0x23962766,
+ 0xeceab1e4, 0xf3b5fc86, 0x468127e2, 0xb606d10d, 0x3a45f4b6, 0xb776102d, 0x2fdbb420, 0x80c8fa84,
+ 0xd0ff9f45, 0xc58aef38, 0xdb2410fd, 0x1f1cebad, 0x733b2281, 0x52ca5f36, 0xddf29daa, 0x544334b8,
+ 0xdeeaf659, 0x4e462713, 0x1ed485b4, 0x6a0822e1, 0x28db471c, 0xa53938a8, 0x44c3bef7, 0xf35215c8,
+ 0xb382bc4e, 0x3e4c6f15, 0x6285f54c, 0x17ab408e, 0xccbf7f5e, 0xd16ab3f6, 0xced2846d, 0xf457e14f,
+ 0xbb45d9c5, 0x646ad497, 0xac697494, 0x145de32e, 0x93907128, 0xd263d521, 0x79efb424, 0xd64651d6,
+ 0xebc0c9f0, 0xbb583a44, 0xc6412c84, 0x85bb29a6, 0x4d31a2cd, 0x92954469, 0xa32b1abd, 0xf7f5202c,
+ 0xa4aa6c93, 0x2e9b53cf, 0x385ab136, 0x2741f356, 0x5de9c065, 0x6009901c, 0x88abbdd8, 0x74efcf73,
+ 0x3f761ad4, 0x35f3c083, 0xfd6b8ee0, 0x0bef11c7, 0xc552a89d, 0x58ce4a21, 0xd71e54f2, 0x4157f6c7,
+ 0xd4622316, 0xe98956d7, 0x450027de, 0xcbd398d8, 0x4b98b36a, 0x0724c25c, 0xdb237760, 0xe9324b68,
+ 0x7523e506, 0x8edad933, 0x92197f00, 0xb853a326, 0xb330c444, 0x65129296, 0x34bc0670, 0xe177806d,
+ 0xe338dac4, 0x5537492a, 0xe19add83, 0xcf45000f, 0x5b423bce, 0x6497d209, 0xe30e18a1, 0x3cbf0687,
+ 0x67973103, 0xd9485366, 0x81506bba, 0x2e93a9a4, 0x7dd59d3f, 0xf17cd746, 0x8c2075be, 0x552a4348 // last one was: 0x552a4347
+ // 0xb4a638ef, ...
+ //(the last word 0x552a4347 was rounded up because the next one is 0xb4a638ef -- first bit is one 0xb..)
+ // 256 32bit words for the mantissa -- about 2464 valid digits (decimal)
+ };
+
+ // above value was calculated using Big<1,400> type on a 32bit platform
+ // and then the first 256 32bit words were taken,
+ // the calculating was made by using LnSurrounding1(10) method
+ // which took 22080 iterations
+ // (the result was compared with ln(10) taken from http://ja0hxv.calico.jp/pai/estart.html)
+ // (the formula used in LnSurrounding1(x) converges badly when
+ // the x is greater than one but in fact we can use it, only the
+ // number of iterations will be greater)
+ // (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256,
+ // and on 64bit platform value 128 (256/2=128))
+
+ mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int));
+ exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2;
+ info = 0;
+ }
+
+
+ /*!
+ this method sets the maximum value which can be held in this type
+ */
+ void SetMax()
+ {
+ info = 0;
+ mantissa.SetMax();
+ exponent.SetMax();
+
+ // we don't have to use 'Standardizing()' because the last bit from
+ // the mantissa is set
+ }
+
+
+ /*!
+ this method sets the minimum value which can be held in this type
+ */
+ void SetMin()
+ {
+ info = 0;
+
+ mantissa.SetMax();
+ exponent.SetMax();
+ SetSign();
+
+ // we don't have to use 'Standardizing()' because the last bit from
+ // the mantissa is set
+ }
+
+
+ /*!
+ testing whether there is a value zero or not
+ */
+ bool IsZero() const
+ {
+ return IsInfoBit(TTMATH_BIG_ZERO);
+ }
+
+
+ /*!
+ this method returns true when there's the sign set
+ also we don't check the NaN flag
+ */
+ bool IsSign() const
+ {
+ return IsInfoBit(TTMATH_BIG_SIGN);
+ }
+
+
+ /*!
+ this method returns true when there is not a valid number
+ */
+ bool IsNan() const
+ {
+ return IsInfoBit(TTMATH_BIG_NAN);
+ }
+
+
+
+ /*!
+ this method clears the sign
+ (there'll be an absolute value)
+
+ e.g.
+ -1 -> 1
+ 2 -> 2
+ */
+ void Abs()
+ {
+ ClearInfoBit(TTMATH_BIG_SIGN);
+ }
+
+
+ /*!
+ this method remains the 'sign' of the value
+ e.g. -2 = -1
+ 0 = 0
+ 10 = 1
+ */
+ void Sgn()
+ {
+ // we have to check the NaN flag, because the next SetOne() method would clear it
+ if( IsNan() )
+ return;
+
+ if( IsSign() )
+ {
+ SetOne();
+ SetSign();
+ }
+ else
+ if( IsZero() )
+ SetZero(); // !! is nedeed here?
+ else
+ SetOne();
+ }
+
+
+
+ /*!
+ this method sets the sign
+
+ e.g.
+ -1 -> -1
+ 2 -> -2
+
+ we do not check whether there is a zero or not, if you're using this method
+ you must be sure that the value is (or will be afterwards) different from zero
+ */
+ void SetSign()
+ {
+ SetInfoBit(TTMATH_BIG_SIGN);
+ }
+
+
+ /*!
+ this method changes the sign
+ when there is a value of zero then the sign is not changed
+
+ e.g.
+ -1 -> 1
+ 2 -> -2
+ */
+ void ChangeSign()
+ {
+ // we don't have to check the NaN flag here
+
+ if( IsZero() )
+ return;
+
+ if( IsSign() )
+ ClearInfoBit(TTMATH_BIG_SIGN);
+ else
+ SetInfoBit(TTMATH_BIG_SIGN);
+ }
-
-
- /*!
- *
- * basic mathematic functions
- *
- */
-
private:
+ /*!
+ this method does the half-to-even rounding (banker's rounding)
- /*!
- an auxiliary method for adding
- */
- void AddCheckExponents( Big<exp, man> & ss2,
- Int<exp> & exp_offset,
- bool & last_bit_set,
- bool & rest_zero,
- bool & do_adding,
- bool & do_rounding)
- {
- Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
-
- if( exp_offset == mantissa_size_in_bits )
- {
- last_bit_set = ss2.mantissa.IsTheHighestBitSet();
- rest_zero = ss2.mantissa.AreFirstBitsZero(man*TTMATH_BITS_PER_UINT - 1);
- do_rounding = true; // we'are only rounding
- }
- else
- if( exp_offset < mantissa_size_in_bits )
- {
- uint moved = exp_offset.ToInt(); // how many times we must move ss2.mantissa
- rest_zero = true;
-
- if( moved > 0 )
- {
- last_bit_set = static_cast<bool>( ss2.mantissa.GetBit(moved-1) );
-
- if( moved > 1 )
- rest_zero = ss2.mantissa.AreFirstBitsZero(moved - 1);
-
- // (2) moving 'exp_offset' times
- ss2.mantissa.Rcr(moved, 0);
- }
-
- do_adding = true;
- do_rounding = true;
- }
-
- // if exp_offset is greater than mantissa_size_in_bits then we do nothing
- // ss2 is too small for taking into consideration in the sum
- }
-
-
- /*!
- an auxiliary method for adding
- */
- uint AddMantissas( Big<exp, man> & ss2,
- bool & last_bit_set,
- bool & rest_zero,
- bool & rounding_up)
- {
- uint c = 0;
-
- if( IsSign() == ss2.IsSign() )
- {
- // values have the same signs
- if( mantissa.Add(ss2.mantissa) )
- {
- // we have one bit more from addition (carry)
- // now rest_zero means the old rest_zero with the old last_bit_set
- rest_zero = (!last_bit_set && rest_zero);
- last_bit_set = mantissa.Rcr(1,1);
- c += exponent.AddOne();
- }
-
- rounding_up = true;
- }
- else
- {
- // values have different signs
- // there shouldn't be a carry here because
- // (1) (2) guarantee that the mantissa of this
- // is greater than or equal to the mantissa of the ss2
-
- #ifdef TTMATH_DEBUG
- uint c_temp =
- #endif
- mantissa.Sub(ss2.mantissa);
-
- TTMATH_ASSERT( c_temp == 0 )
- }
-
- return c;
- }
-
-
-public:
-
-
- /*!
- Addition this = this + ss2
-
- it returns carry if the sum is too big
- */
- uint Add(Big<exp, man> ss2, bool round = true)
- {
- bool last_bit_set, rest_zero, do_adding, do_rounding, rounding_up;
- Int<exp> exp_offset( exponent );
- uint c = 0;
-
- if( IsNan() || ss2.IsNan() )
- return CheckCarry(1);
-
- exp_offset.Sub( ss2.exponent );
- exp_offset.Abs();
-
- // (1) abs(this) will be >= abs(ss2)
- if( SmallerWithoutSignThan(ss2) )
- {
- // !! use Swap here (not implemented yet)
- Big<exp, man> temp(ss2);
-
- ss2 = *this;
- *this = temp;
- }
-
- if( ss2.IsZero() )
- return 0;
-
- last_bit_set = rest_zero = do_adding = do_rounding = rounding_up = false;
- AddCheckExponents(ss2, exp_offset, last_bit_set, rest_zero, do_adding, do_rounding);
-
- if( do_adding )
- c += AddMantissas(ss2, last_bit_set, rest_zero, rounding_up);
-
- if( !round || !last_bit_set )
- do_rounding = false;
+ if is_half is:
+ true - that means the rest was equal the half (0.5 decimal)
+ false - that means the rest was greater than a half (greater than 0.5 decimal)
+
+ if the rest was less than a half then don't call this method
+ (the rounding should does nothing then)
+ */
+ uint RoundHalfToEven(bool is_half, bool rounding_up = true)
+ {
+ uint c = 0;
+
+ if( !is_half || mantissa.IsTheLowestBitSet() )
+ {
+ if( rounding_up )
+ {
+ if( mantissa.AddOne() )
+ {
+ mantissa.Rcr(1, 1);
+ c = exponent.AddOne();
+ }
+ }
+ else
+ {
+ #ifdef TTMATH_DEBUG
+ uint c_from_zero =
+ #endif
+ mantissa.SubOne();
+
+ // we're using rounding_up=false in Add() when the mantissas have different signs
+ // mantissa can be zero only when previous mantissa was equal to ss2.mantissa
+ // but in such a case 'last_bit_set' will not be set and consequently 'do_rounding' will be false
+ TTMATH_ASSERT( c_from_zero == 0 )
+ }
+ }
+
+ return c;
+ }
- if( do_rounding )
- c += RoundHalfToEven(rest_zero, rounding_up);
- if( do_adding || do_rounding )
- c += Standardizing();
- return CheckCarry(c);
- }
+ /*!
+ *
+ * basic mathematic functions
+ *
+ */
+
+
+ /*!
+ this method adds one to the existing value
+ */
+ uint AddOne()
+ {
+ Big<exp, man> one;
+
+ one.SetOne();
+
+ return Add(one);
+ }
+
+
+ /*!
+ this method subtracts one from the existing value
+ */
+ uint SubOne()
+ {
+ Big<exp, man> one;
- /*!
- Subtraction this = this - ss2
+ one.SetOne();
- it returns carry if the result is too big
- */
- uint Sub(Big<exp, man> ss2, bool round = true)
- {
- ss2.ChangeSign();
+ return Sub(one);
+ }
- return Add(ss2, round);
- }
+private:
- /*!
- bitwise AND
-
- this and ss2 must be >= 0
- return values:
- 0 - ok
- 1 - carry
- 2 - this or ss2 was negative
- */
- uint BitAnd(Big<exp, man> ss2)
- {
- if( IsNan() || ss2.IsNan() )
- return CheckCarry(1);
-
- if( IsSign() || ss2.IsSign() )
- return 2;
-
- if( IsZero() )
- return 0;
-
- if( ss2.IsZero() )
- {
- SetZero();
- return 0;
- }
-
- Int<exp> exp_offset( exponent );
- Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
-
- uint c = 0;
-
- exp_offset.Sub( ss2.exponent );
- exp_offset.Abs();
-
- // abs(this) will be >= abs(ss2)
- if( SmallerWithoutSignThan(ss2) )
- {
- Big<exp, man> temp(ss2);
-
- ss2 = *this;
- *this = temp;
- }
-
- if( exp_offset >= mantissa_size_in_bits )
- {
- // the second value is too small
- SetZero();
- return 0;
- }
-
- // exp_offset < mantissa_size_in_bits, moving 'exp_offset' times
- ss2.mantissa.Rcr( exp_offset.ToInt(), 0 );
- mantissa.BitAnd(ss2.mantissa);
-
- c += Standardizing();
-
- return CheckCarry(c);
- }
+ /*!
+ an auxiliary method for adding
+ */
+ void AddCheckExponents( Big<exp, man> & ss2,
+ Int<exp> & exp_offset,
+ bool & last_bit_set,
+ bool & rest_zero,
+ bool & do_adding,
+ bool & do_rounding)
+ {
+ Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
+
+ if( exp_offset == mantissa_size_in_bits )
+ {
+ last_bit_set = ss2.mantissa.IsTheHighestBitSet();
+ rest_zero = ss2.mantissa.AreFirstBitsZero(man*TTMATH_BITS_PER_UINT - 1);
+ do_rounding = true; // we'are only rounding
+ }
+ else
+ if( exp_offset < mantissa_size_in_bits )
+ {
+ uint moved = exp_offset.ToInt(); // how many times we must move ss2.mantissa
+ rest_zero = true;
+
+ if( moved > 0 )
+ {
+ last_bit_set = static_cast<bool>( ss2.mantissa.GetBit(moved-1) );
+
+ if( moved > 1 )
+ rest_zero = ss2.mantissa.AreFirstBitsZero(moved - 1);
+
+ // (2) moving 'exp_offset' times
+ ss2.mantissa.Rcr(moved, 0);
+ }
+
+ do_adding = true;
+ do_rounding = true;
+ }
+
+ // if exp_offset is greater than mantissa_size_in_bits then we do nothing
+ // ss2 is too small for taking into consideration in the sum
+ }
+
+
+ /*!
+ an auxiliary method for adding
+ */
+ uint AddMantissas( Big<exp, man> & ss2,
+ bool & last_bit_set,
+ bool & rest_zero)
+ {
+ uint c = 0;
+
+ if( IsSign() == ss2.IsSign() )
+ {
+ // values have the same signs
+ if( mantissa.Add(ss2.mantissa) )
+ {
+ // we have one bit more from addition (carry)
+ // now rest_zero means the old rest_zero with the old last_bit_set
+ rest_zero = (!last_bit_set && rest_zero);
+ last_bit_set = mantissa.Rcr(1,1);
+ c += exponent.AddOne();
+ }
+ }
+ else
+ {
+ // values have different signs
+ // there shouldn't be a carry here because
+ // (1) (2) guarantee that the mantissa of this
+ // is greater than or equal to the mantissa of the ss2
+
+ #ifdef TTMATH_DEBUG
+ uint c_temp =
+ #endif
+ mantissa.Sub(ss2.mantissa);
- /*!
- bitwise OR
+ TTMATH_ASSERT( c_temp == 0 )
+ }
- this and ss2 must be >= 0
- return values:
- 0 - ok
- 1 - carry
- 2 - this or ss2 was negative
- */
- uint BitOr(Big<exp, man> ss2)
- {
- if( IsNan() || ss2.IsNan() )
- return CheckCarry(1);
+ return c;
+ }
- if( IsSign() || ss2.IsSign() )
- return 2;
- if( IsZero() )
- {
- *this = ss2;
- return 0;
- }
+public:
- if( ss2.IsZero() )
- return 0;
- Int<exp> exp_offset( exponent );
- Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
+ /*!
+ Addition this = this + ss2
- uint c = 0;
+ it returns carry if the sum is too big
+ */
+ uint Add(Big<exp, man> ss2, bool round = true, bool adding = true)
+ {
+ bool last_bit_set, rest_zero, do_adding, do_rounding, rounding_up;
+ Int<exp> exp_offset( exponent );
+ uint c = 0;
+
+ if( IsNan() || ss2.IsNan() )
+ return CheckCarry(1);
+
+ if( !adding )
+ ss2.ChangeSign(); // subtracting
+
+ exp_offset.Sub( ss2.exponent );
+ exp_offset.Abs();
+
+ // (1) abs(this) will be >= abs(ss2)
+ if( SmallerWithoutSignThan(ss2) )
+ Swap(ss2);
+
+ if( ss2.IsZero() )
+ return 0;
+
+ last_bit_set = rest_zero = do_adding = do_rounding = false;
+ rounding_up = (IsSign() == ss2.IsSign());
+
+ AddCheckExponents(ss2, exp_offset, last_bit_set, rest_zero, do_adding, do_rounding);
+
+ if( do_adding )
+ c += AddMantissas(ss2, last_bit_set, rest_zero);
+
+ if( !round || !last_bit_set )
+ do_rounding = false;
+
+ if( do_rounding )
+ c += RoundHalfToEven(rest_zero, rounding_up);
+
+ if( do_adding || do_rounding )
+ c += Standardizing();
+
+ return CheckCarry(c);
+ }
+
+
+ /*!
+ Subtraction this = this - ss2
+
+ it returns carry if the result is too big
+ */
+ uint Sub(const Big<exp, man> & ss2, bool round = true)
+ {
+ return Add(ss2, round, false);
+ }
+
+
+ /*!
+ bitwise AND
+
+ this and ss2 must be >= 0
+ return values:
+ 0 - ok
+ 1 - carry
+ 2 - this or ss2 was negative
+ */
+ uint BitAnd(Big<exp, man> ss2)
+ {
+ if( IsNan() || ss2.IsNan() )
+ return CheckCarry(1);
+
+ if( IsSign() || ss2.IsSign() )
+ {
+ SetNan();
+ return 2;
+ }
+
+ if( IsZero() )
+ return 0;
+
+ if( ss2.IsZero() )
+ {
+ SetZero();
+ return 0;
+ }
+
+ Int<exp> exp_offset( exponent );
+ Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
+
+ uint c = 0;
+
+ exp_offset.Sub( ss2.exponent );
+ exp_offset.Abs();
+
+ // abs(this) will be >= abs(ss2)
+ if( SmallerWithoutSignThan(ss2) )
+ Swap(ss2);
+
+ if( exp_offset >= mantissa_size_in_bits )
+ {
+ // the second value is too small
+ SetZero();
+ return 0;
+ }
+
+ // exp_offset < mantissa_size_in_bits, moving 'exp_offset' times
+ ss2.mantissa.Rcr( exp_offset.ToInt(), 0 );
+ mantissa.BitAnd(ss2.mantissa);
+
+ c += Standardizing();
+
+ return CheckCarry(c);
+ }
+
+
+ /*!
+ bitwise OR
+
+ this and ss2 must be >= 0
+ return values:
+ 0 - ok
+ 1 - carry
+ 2 - this or ss2 was negative
+ */
+ uint BitOr(Big<exp, man> ss2)
+ {
+ if( IsNan() || ss2.IsNan() )
+ return CheckCarry(1);
+
+ if( IsSign() || ss2.IsSign() )
+ {
+ SetNan();
+ return 2;
+ }
+
+ if( IsZero() )
+ {
+ *this = ss2;
+ return 0;
+ }
+
+ if( ss2.IsZero() )
+ return 0;
+
+ Int<exp> exp_offset( exponent );
+ Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
+
+ uint c = 0;
+
+ exp_offset.Sub( ss2.exponent );
+ exp_offset.Abs();
+
+ // abs(this) will be >= abs(ss2)
+ if( SmallerWithoutSignThan(ss2) )
+ Swap(ss2);
+
+ if( exp_offset >= mantissa_size_in_bits )
+ // the second value is too small
+ return 0;
+
+ // exp_offset < mantissa_size_in_bits, moving 'exp_offset' times
+ ss2.mantissa.Rcr( exp_offset.ToInt(), 0 );
+ mantissa.BitOr(ss2.mantissa);
+
+ c += Standardizing();
+
+ return CheckCarry(c);
+ }
+
+
+ /*!
+ bitwise XOR
+
+ this and ss2 must be >= 0
+ return values:
+ 0 - ok
+ 1 - carry
+ 2 - this or ss2 was negative
+ */
+ uint BitXor(Big<exp, man> ss2)
+ {
+ if( IsNan() || ss2.IsNan() )
+ return CheckCarry(1);
+
+ if( IsSign() || ss2.IsSign() )
+ {
+ SetNan();
+ return 2;
+ }
+
+ if( ss2.IsZero() )
+ return 0;
+
+ if( IsZero() )
+ {
+ *this = ss2;
+ return 0;
+ }
+
+ Int<exp> exp_offset( exponent );
+ Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
+
+ uint c = 0;
+
+ exp_offset.Sub( ss2.exponent );
+ exp_offset.Abs();
+
+ // abs(this) will be >= abs(ss2)
+ if( SmallerWithoutSignThan(ss2) )
+ Swap(ss2);
+
+ if( exp_offset >= mantissa_size_in_bits )
+ // the second value is too small
+ return 0;
+
+ // exp_offset < mantissa_size_in_bits, moving 'exp_offset' times
+ ss2.mantissa.Rcr( exp_offset.ToInt(), 0 );
+ mantissa.BitXor(ss2.mantissa);
+
+ c += Standardizing();
+
+ return CheckCarry(c);
+ }
+
+
+
+ /*!
+ Multiplication this = this * ss2 (ss2 is uint)
+
+ ss2 without a sign
+ */
+ uint MulUInt(uint ss2)
+ {
+ UInt<man+1> man_result;
+ uint i,c = 0;
+
+ if( IsNan() )
+ return 1;
+
+ if( IsZero() )
+ return 0;
+
+ if( ss2 == 0 )
+ {
+ SetZero();
+ return 0;
+ }
+
+ // man_result = mantissa * ss2.mantissa
+ mantissa.MulInt(ss2, man_result);
+
+ sint bit = UInt<man>::FindLeadingBitInWord(man_result.table[man]); // man - last word
+
+ if( bit!=-1 && uint(bit) > (TTMATH_BITS_PER_UINT/2) )
+ {
+ // 'i' will be from 0 to TTMATH_BITS_PER_UINT
+ i = man_result.CompensationToLeft();
+ c = exponent.Add( TTMATH_BITS_PER_UINT - i );
+
+ for(i=0 ; i<man ; ++i)
+ mantissa.table[i] = man_result.table[i+1];
+ }
+ else
+ {
+ if( bit != -1 )
+ {
+ man_result.Rcr(bit+1, 0);
+ c += exponent.Add(bit+1);
+ }
+
+ for(i=0 ; i<man ; ++i)
+ mantissa.table[i] = man_result.table[i];
+ }
+
+ c += Standardizing();
+
+ return CheckCarry(c);
+ }
+
+
+ /*!
+ Multiplication this = this * ss2 (ss2 is sint)
+
+ ss2 with a sign
+ */
+ uint MulInt(sint ss2)
+ {
+ if( IsNan() )
+ return 1;
+
+ if( ss2 == 0 )
+ {
+ SetZero();
+ return 0;
+ }
+
+ if( IsZero() )
+ return 0;
+
+ if( IsSign() == (ss2<0) )
+ {
+ // the signs are the same (both are either - or +), the result is positive
+ Abs();
+ }
+ else
+ {
+ // the signs are different, the result is negative
+ SetSign();
+ }
- exp_offset.Sub( ss2.exponent );
- exp_offset.Abs();
+ if( ss2<0 )
+ ss2 = -ss2;
- // abs(this) will be >= abs(ss2)
- if( SmallerWithoutSignThan(ss2) )
- {
- Big<exp, man> temp(ss2);
- ss2 = *this;
- *this = temp;
- }
+ return MulUInt( uint(ss2) );
+ }
- if( exp_offset >= mantissa_size_in_bits )
- // the second value is too small
- return 0;
- // exp_offset < mantissa_size_in_bits, moving 'exp_offset' times
- ss2.mantissa.Rcr( exp_offset.ToInt(), 0 );
- mantissa.BitOr(ss2.mantissa);
+private:
- c += Standardizing();
- return CheckCarry(c);
- }
+ /*!
+ this method checks whether a table pointed by 'tab' and 'len'
+ has the value 0.5 decimal
+ (it is treated as the comma operator would be before the highest bit)
+ call this method only if the highest bit is set - you have to test it beforehand
+
+ return:
+ true - tab was equal the half (0.5 decimal)
+ false - tab was greater than a half (greater than 0.5 decimal)
+
+ */
+ bool CheckGreaterOrEqualHalf(uint * tab, uint len)
+ {
+ uint i;
+
+ TTMATH_ASSERT( len>0 && (tab[len-1] & TTMATH_UINT_HIGHEST_BIT)!=0 )
+
+ for(i=0 ; i<len-1 ; ++i)
+ if( tab[i] != 0 )
+ return false;
+ if( tab[i] != TTMATH_UINT_HIGHEST_BIT )
+ return false;
- /*!
- bitwise XOR
+ return true;
+ }
- this and ss2 must be >= 0
- return values:
- 0 - ok
- 1 - carry
- 2 - this or ss2 was negative
- */
- uint BitXor(Big<exp, man> ss2)
- {
- if( IsNan() || ss2.IsNan() )
- return CheckCarry(1);
- if( IsSign() || ss2.IsSign() )
- return 2;
+private:
- if( ss2.IsZero() )
- return 0;
+ /*!
+ multiplication this = this * ss2
+ this method returns a carry
+ */
+ uint MulRef(const Big<exp, man> & ss2, bool round = true)
+ {
+ TTMATH_REFERENCE_ASSERT( ss2 )
+
+ UInt<man*2> man_result;
+ uint c = 0;
+ uint i;
+
+ if( IsNan() || ss2.IsNan() )
+ return CheckCarry(1);
+
+ if( IsZero() )
+ return 0;
+
+ if( ss2.IsZero() )
+ {
+ SetZero();
+ return 0;
+ }
+
+ // man_result = mantissa * ss2.mantissa
+ mantissa.MulBig(ss2.mantissa, man_result);
+
+ // 'i' will be from 0 to man*TTMATH_BITS_PER_UINT
+ // because mantissa and ss2.mantissa are standardized
+ // (the highest bit in man_result is set to 1 or
+ // if there is a zero value in man_result the method CompensationToLeft()
+ // returns 0 but we'll correct this at the end in Standardizing() method)
+ i = man_result.CompensationToLeft();
+ uint exp_add = man * TTMATH_BITS_PER_UINT - i;
+
+ if( exp_add )
+ c += exponent.Add( exp_add );
+
+ c += exponent.Add( ss2.exponent );
+
+ for(i=0 ; i<man ; ++i)
+ mantissa.table[i] = man_result.table[i+man];
+
+ if( round && (man_result.table[man-1] & TTMATH_UINT_HIGHEST_BIT) != 0 )
+ {
+ bool is_half = CheckGreaterOrEqualHalf(man_result.table, man);
+ c += RoundHalfToEven(is_half);
+ }
+
+ if( IsSign() == ss2.IsSign() )
+ {
+ // the signs are the same, the result is positive
+ Abs();
+ }
+ else
+ {
+ // the signs are different, the result is negative
+ // if the value is zero it will be corrected later in Standardizing method
+ SetSign();
+ }
+
+ c += Standardizing();
+
+ return CheckCarry(c);
+ }
+
- if( IsZero() )
- {
- *this = ss2;
- return 0;
- }
+public:
- Int<exp> exp_offset( exponent );
- Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
- uint c = 0;
+ /*!
+ multiplication this = this * ss2
+ this method returns a carry
+ */
+ uint Mul(const Big<exp, man> & ss2, bool round = true)
+ {
+ if( this == &ss2 )
+ {
+ Big<exp, man> copy_ss2(ss2);
+ return MulRef(copy_ss2, round);
+ }
+ else
+ {
+ return MulRef(ss2, round);
+ }
+ }
- exp_offset.Sub( ss2.exponent );
- exp_offset.Abs();
- // abs(this) will be >= abs(ss2)
- if( SmallerWithoutSignThan(ss2) )
- {
- Big<exp, man> temp(ss2);
+private:
- ss2 = *this;
- *this = temp;
- }
+ /*!
+ division this = this / ss2
- if( exp_offset >= mantissa_size_in_bits )
- // the second value is too small
- return 0;
+ return value:
+ 0 - ok
+ 1 - carry (in a division carry can be as well)
+ 2 - improper argument (ss2 is zero)
+ */
+ uint DivRef(const Big<exp, man> & ss2, bool round = true)
+ {
+ TTMATH_REFERENCE_ASSERT( ss2 )
+
+ UInt<man*2> man1;
+ UInt<man*2> man2;
+ uint i,c = 0;
+
+ if( IsNan() || ss2.IsNan() )
+ return CheckCarry(1);
+
+ if( ss2.IsZero() )
+ {
+ SetNan();
+ return 2;
+ }
+
+ if( IsZero() )
+ return 0;
+
+ // !! this two loops can be joined together
+
+ for(i=0 ; i<man ; ++i)
+ {
+ man1.table[i+man] = mantissa.table[i];
+ man2.table[i] = ss2.mantissa.table[i];
+ }
+
+ for(i=0 ; i<man ; ++i)
+ {
+ man1.table[i] = 0;
+ man2.table[i+man] = 0;
+ }
+
+ man1.Div(man2);
+
+ i = man1.CompensationToLeft();
+
+ if( i )
+ c += exponent.Sub(i);
+
+ c += exponent.Sub(ss2.exponent);
+
+ for(i=0 ; i<man ; ++i)
+ mantissa.table[i] = man1.table[i+man];
+
+ if( round && (man1.table[man-1] & TTMATH_UINT_HIGHEST_BIT) != 0 )
+ {
+ bool is_half = CheckGreaterOrEqualHalf(man1.table, man);
+ c += RoundHalfToEven(is_half);
+ }
+
+ if( IsSign() == ss2.IsSign() )
+ Abs();
+ else
+ SetSign(); // if there is a zero it will be corrected in Standardizing()
- // exp_offset < mantissa_size_in_bits, moving 'exp_offset' times
- ss2.mantissa.Rcr( exp_offset.ToInt(), 0 );
- mantissa.BitXor(ss2.mantissa);
+ c += Standardizing();
- c += Standardizing();
+ return CheckCarry(c);
+ }
- return CheckCarry(c);
- }
+public:
+ /*!
+ division this = this / ss2
- /*!
- Multiplication this = this * ss2 (ss2 is uint)
+ return value:
+ 0 - ok
+ 1 - carry (in a division carry can be as well)
+ 2 - improper argument (ss2 is zero)
+ */
+ uint Div(const Big<exp, man> & ss2, bool round = true)
+ {
+ if( this == &ss2 )
+ {
+ Big<exp, man> copy_ss2(ss2);
+ return DivRef(copy_ss2, round);
+ }
+ else
+ {
+ return DivRef(ss2, round);
+ }
+ }
- ss2 without a sign
- */
- uint MulUInt(uint ss2)
- {
- UInt<man+1> man_result;
- uint i,c = 0;
- if( IsNan() )
- return 1;
+private:
- if( IsZero() )
- return 0;
+ /*!
+ the remainder from a division
+ */
+ uint ModRef(const Big<exp, man> & ss2)
+ {
+ TTMATH_REFERENCE_ASSERT( ss2 )
+
+ uint c = 0;
+
+ if( IsNan() || ss2.IsNan() )
+ return CheckCarry(1);
+
+ if( ss2.IsZero() )
+ {
+ SetNan();
+ return 2;
+ }
+
+ if( !SmallerWithoutSignThan(ss2) )
+ {
+ Big<exp, man> temp(*this);
+
+ c = temp.Div(ss2);
+ temp.SkipFraction();
+ c += temp.Mul(ss2);
+ c += Sub(temp);
+
+ if( !SmallerWithoutSignThan( ss2 ) )
+ c += 1;
+ }
- if( ss2 == 0 )
- {
- SetZero();
- return 0;
- }
+ return CheckCarry(c);
+ }
- // man_result = mantissa * ss2.mantissa
- mantissa.MulInt(ss2, man_result);
- sint bit = UInt<man>::FindLeadingBitInWord(man_result.table[man]); // man - last word
+public:
- if( bit!=-1 && uint(bit) > (TTMATH_BITS_PER_UINT/2) )
- {
- // 'i' will be from 0 to TTMATH_BITS_PER_UINT
- i = man_result.CompensationToLeft();
- c = exponent.Add( TTMATH_BITS_PER_UINT - i );
+ /*!
+ the remainder from a division
- for(i=0 ; i<man ; ++i)
- mantissa.table[i] = man_result.table[i+1];
- }
- else
- {
- if( bit != -1 )
- {
- man_result.Rcr(bit+1, 0);
- c += exponent.Add(bit+1);
- }
+ e.g.
+ 12.6 mod 3 = 0.6 because 12.6 = 3*4 + 0.6
+ -12.6 mod 3 = -0.6 bacause -12.6 = 3*(-4) + (-0.6)
+ 12.6 mod -3 = 0.6
+ -12.6 mod -3 = -0.6
+
+ it means:
+ in other words: this(old) = ss2 * q + this(new)
+
+ return value:
+ 0 - ok
+ 1 - carry
+ 2 - improper argument (ss2 is zero)
+ */
+ uint Mod(const Big<exp, man> & ss2)
+ {
+ if( this == &ss2 )
+ {
+ Big<exp, man> copy_ss2(ss2);
+ return ModRef(copy_ss2);
+ }
+ else
+ {
+ return ModRef(ss2);
+ }
+ }
+
+
+ /*!
+ this method returns: 'this' mod 2
+ (either zero or one)
+
+ this method is much faster than using Mod( object_with_value_two )
+ */
+ uint Mod2() const
+ {
+ if( exponent>sint(0) || exponent<=-sint(man*TTMATH_BITS_PER_UINT) )
+ return 0;
+
+ sint exp_int = exponent.ToInt();
+ // 'exp_int' is negative (or zero), we set it as positive
+ exp_int = -exp_int;
+
+ return mantissa.GetBit(exp_int);
+ }
+
+
+ /*!
+ power this = this ^ pow
+ (pow without a sign)
+
+ binary algorithm (r-to-l)
+
+ return values:
+ 0 - ok
+ 1 - carry
+ 2 - incorrect arguments (0^0)
+ */
+ template<uint pow_size>
+ uint Pow(UInt<pow_size> pow)
+ {
+ if( IsNan() )
+ return 1;
+
+ if( IsZero() )
+ {
+ if( pow.IsZero() )
+ {
+ // we don't define zero^zero
+ SetNan();
+ return 2;
+ }
+
+ // 0^(+something) is zero
+ return 0;
+ }
+
+ Big<exp, man> start(*this);
+ Big<exp, man> result;
+ result.SetOne();
+ uint c = 0;
+
+ while( !c )
+ {
+ if( pow.table[0] & 1 )
+ c += result.Mul(start);
+
+ pow.Rcr(1);
+
+ if( pow.IsZero() )
+ break;
+
+ c += start.Mul(start);
+ }
+
+ *this = result;
+
+ return CheckCarry(c);
+ }
+
+
+ /*!
+ power this = this ^ pow
+ p can be negative
+
+ return values:
+ 0 - ok
+ 1 - carry
+ 2 - incorrect arguments 0^0 or 0^(-something)
+ */
+ template<uint pow_size>
+ uint Pow(Int<pow_size> pow)
+ {
+ if( IsNan() )
+ return 1;
+
+ if( !pow.IsSign() )
+ return Pow( UInt<pow_size>(pow) );
+
+ if( IsZero() )
+ {
+ // if 'p' is negative then
+ // 'this' must be different from zero
+ SetNan();
+ return 2;
+ }
+
+ uint c = pow.ChangeSign();
+
+ Big<exp, man> t(*this);
+ c += t.Pow( UInt<pow_size>(pow) ); // here can only be a carry (return:1)
+
+ SetOne();
+ c += Div(t);
+
+ return CheckCarry(c);
+ }
+
+
+ /*!
+ power this = this ^ abs([pow])
+ pow is treated as a value without a sign and without a fraction
+ if pow has a sign then the method pow.Abs() is used
+ if pow has a fraction the fraction is skipped (not used in calculation)
+
+ return values:
+ 0 - ok
+ 1 - carry
+ 2 - incorrect arguments (0^0)
+ */
+ uint PowUInt(Big<exp, man> pow)
+ {
+ if( IsNan() || pow.IsNan() )
+ return CheckCarry(1);
+
+ if( IsZero() )
+ {
+ if( pow.IsZero() )
+ {
+ SetNan();
+ return 2;
+ }
+
+ // 0^(+something) is zero
+ return 0;
+ }
+
+ if( pow.IsSign() )
+ pow.Abs();
+
+ Big<exp, man> start(*this);
+ Big<exp, man> result;
+ Big<exp, man> one;
+ uint c = 0;
+ one.SetOne();
+ result = one;
+
+ while( !c )
+ {
+ if( pow.Mod2() )
+ c += result.Mul(start);
+
+ c += pow.exponent.SubOne();
+
+ if( pow < one )
+ break;
+
+ c += start.Mul(start);
+ }
+
+ *this = result;
+
+ return CheckCarry(c);
+ }
+
+
+ /*!
+ power this = this ^ [pow]
+ pow is treated as a value without a fraction
+ pow can be negative
+
+ return values:
+ 0 - ok
+ 1 - carry
+ 2 - incorrect arguments 0^0 or 0^(-something)
+ */
+ uint PowInt(const Big<exp, man> & pow)
+ {
+ if( IsNan() || pow.IsNan() )
+ return CheckCarry(1);
+
+ if( !pow.IsSign() )
+ return PowUInt(pow);
+
+ if( IsZero() )
+ {
+ // if 'pow' is negative then
+ // 'this' must be different from zero
+ SetNan();
+ return 2;
+ }
+
+ Big<exp, man> temp(*this);
+ uint c = temp.PowUInt(pow); // here can only be a carry (result:1)
+
+ SetOne();
+ c += Div(temp);
+
+ return CheckCarry(c);
+ }
+
+
+ /*!
+ power this = this ^ pow
+ this must be greater than zero (this > 0)
+ pow can be negative and with fraction
+
+ return values:
+ 0 - ok
+ 1 - carry
+ 2 - incorrect argument ('this' <= 0)
+ */
+ uint PowFrac(const Big<exp, man> & pow)
+ {
+ if( IsNan() || pow.IsNan() )
+ return CheckCarry(1);
+
+ Big<exp, man> temp;
+ uint c = temp.Ln(*this);
+
+ if( c != 0 ) // can be 2 from Ln()
+ {
+ SetNan();
+ return c;
+ }
+
+ c += temp.Mul(pow);
+ c += Exp(temp);
+
+ return CheckCarry(c);
+ }
+
+
+ /*!
+ power this = this ^ pow
+ pow can be negative and with fraction
+
+ return values:
+ 0 - ok
+ 1 - carry
+ 2 - incorrect argument ('this' or 'pow')
+ */
+ uint Pow(const Big<exp, man> & pow)
+ {
+ if( IsNan() || pow.IsNan() )
+ return CheckCarry(1);
+
+ if( IsZero() )
+ {
+ // 0^pow will be 0 only for pow>0
+ if( pow.IsSign() || pow.IsZero() )
+ {
+ SetNan();
+ return 2;
+ }
+
+ SetZero();
+
+ return 0;
+ }
+
+ if( pow.exponent>-sint(man*TTMATH_BITS_PER_UINT) && pow.exponent<=0 )
+ {
+ if( pow.IsInteger() )
+ return PowInt( pow );
+ }
+
+ return PowFrac(pow);
+ }
+
+
+ /*!
+ this function calculates the square root
+ e.g. let this=9 then this.Sqrt() gives 3
+
+ return: 0 - ok
+ 1 - carry
+ 2 - improper argument (this<0 or NaN)
+ */
+ uint Sqrt()
+ {
+ if( IsNan() || IsSign() )
+ {
+ SetNan();
+ return 2;
+ }
+
+ if( IsZero() )
+ return 0;
+
+ Big<exp, man> old(*this);
+ Big<exp, man> ln;
+ uint c = 0;
+
+ // we're using the formula: sqrt(x) = e ^ (ln(x) / 2)
+ c += ln.Ln(*this);
+ c += ln.exponent.SubOne(); // ln = ln / 2
+ c += Exp(ln);
+
+ // above formula doesn't give accurate results for some integers
+ // e.g. Sqrt(81) would not be 9 but a value very closed to 9
+ // we're rounding the result, calculating result*result and comparing
+ // with the old value, if they are equal then the result is an integer too
+
+ if( !c && old.IsInteger() && !IsInteger() )
+ {
+ Big<exp, man> temp(*this);
+ c += temp.Round();
+
+ Big<exp, man> temp2(temp);
+ c += temp.Mul(temp2);
+
+ if( temp == old )
+ *this = temp2;
+ }
- for(i=0 ; i<man ; ++i)
- mantissa.table[i] = man_result.table[i];
- }
+ return CheckCarry(c);
+ }
- c += Standardizing();
- return CheckCarry(c);
- }
+private:
+#ifdef TTMATH_CONSTANTSGENERATOR
+public:
+#endif
- /*!
- Multiplication this = this * ss2 (ss2 is sint)
+ /*!
+ Exponent this = exp(x) = e^x where x is in (-1,1)
- ss2 with a sign
- */
- uint MulInt(sint ss2)
- {
- if( IsNan() )
- return 1;
+ we're using the formula exp(x) = 1 + (x)/(1!) + (x^2)/(2!) + (x^3)/(3!) + ...
+ */
+ void ExpSurrounding0(const Big<exp,man> & x, uint * steps = 0)
+ {
+ TTMATH_REFERENCE_ASSERT( x )
+
+ Big<exp,man> denominator, denominator_i;
+ Big<exp,man> one, old_value, next_part;
+ Big<exp,man> numerator = x;
+
+ SetOne();
+ one.SetOne();
+ denominator.SetOne();
+ denominator_i.SetOne();
+
+ uint i;
+ old_value = *this;
+
+ // we begin from 1 in order to not test at the beginning
+ #ifdef TTMATH_CONSTANTSGENERATOR
+ for(i=1 ; true ; ++i)
+ #else
+ for(i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i)
+ #endif
+ {
+ bool testing = ((i & 3) == 0); // it means '(i % 4) == 0'
+
+ next_part = numerator;
+
+ if( next_part.Div( denominator ) )
+ // if there is a carry here we only break the loop
+ // however the result we return as good
+ // it means there are too many parts of the formula
+ break;
+
+ // there shouldn't be a carry here
+ Add( next_part );
+
+ if( testing )
+ {
+ if( old_value == *this )
+ // we've added next few parts of the formula but the result
+ // is still the same then we break the loop
+ break;
+ else
+ old_value = *this;
+ }
+
+ // we set the denominator and the numerator for a next part of the formula
+ if( denominator_i.Add(one) )
+ // if there is a carry here the result we return as good
+ break;
+
+ if( denominator.Mul(denominator_i) )
+ break;
+
+ if( numerator.Mul(x) )
+ break;
+ }
+
+ if( steps )
+ *steps = i;
+ }
- if( ss2 == 0 )
- {
- SetZero();
- return 0;
- }
+public:
- if( IsZero() )
- return 0;
- if( IsSign() == (ss2<0) )
- {
- // the signs are the same (both are either - or +), the result is positive
- Abs();
- }
- else
- {
- // the signs are different, the result is negative
- SetSign();
- }
+ /*!
+ Exponent this = exp(x) = e^x
- if( ss2<0 )
- ss2 = -ss2;
+ we're using the fact that our value is stored in form of:
+ x = mantissa * 2^exponent
+ then
+ e^x = e^(mantissa* 2^exponent) or
+ e^x = (e^mantissa)^(2^exponent)
+
+ 'Exp' returns a carry if we can't count the result ('x' is too big)
+ */
+ uint Exp(const Big<exp,man> & x)
+ {
+ uint c = 0;
+
+ if( x.IsNan() )
+ return CheckCarry(1);
+
+ if( x.IsZero() )
+ {
+ SetOne();
+ return 0;
+ }
+
+ // m will be the value of the mantissa in range (-1,1)
+ Big<exp,man> m(x);
+ m.exponent = -sint(man*TTMATH_BITS_PER_UINT);
+
+ // 'e_' will be the value of '2^exponent'
+ // e_.mantissa.table[man-1] = TTMATH_UINT_HIGHEST_BIT; and
+ // e_.exponent.Add(1) mean:
+ // e_.mantissa.table[0] = 1;
+ // e_.Standardizing();
+ // e_.exponent.Add(man*TTMATH_BITS_PER_UINT)
+ // (we must add 'man*TTMATH_BITS_PER_UINT' because we've taken it from the mantissa)
+ Big<exp,man> e_(x);
+ e_.mantissa.SetZero();
+ e_.mantissa.table[man-1] = TTMATH_UINT_HIGHEST_BIT;
+ c += e_.exponent.Add(1);
+ e_.Abs();
+
+ /*
+ now we've got:
+ m - the value of the mantissa in range (-1,1)
+ e_ - 2^exponent
+
+ e_ can be as:
+ ...2^-2, 2^-1, 2^0, 2^1, 2^2 ...
+ ...1/4 , 1/2 , 1 , 2 , 4 ...
+
+ above one e_ is integer
+
+ if e_ is greater than 1 we calculate the exponent as:
+ e^(m * e_) = ExpSurrounding0(m) ^ e_
+ and if e_ is smaller or equal one we calculate the exponent in this way:
+ e^(m * e_) = ExpSurrounding0(m* e_)
+ because if e_ is smaller or equal 1 then the product of m*e_ is smaller or equal m
+ */
+
+ if( e_ <= 1 )
+ {
+ m.Mul(e_);
+ ExpSurrounding0(m);
+ }
+ else
+ {
+ ExpSurrounding0(m);
+ c += PowUInt(e_);
+ }
+
+ return CheckCarry(c);
+ }
- return MulUInt( uint(ss2) );
- }
private:
+#ifdef TTMATH_CONSTANTSGENERATOR
+public:
+#endif
- /*!
- this method checks whether a table pointed by 'tab' and 'len'
- has the value 0.5 decimal
- (it is treated as the comma operator would be before the highest bit)
- call this method only if the highest bit is set - you have to test it beforehand
-
- return:
- true - tab was equal the half (0.5 decimal)
- false - tab was greater than a half (greater than 0.5 decimal)
-
- */
- bool CheckGreaterOrEqualHalf(uint * tab, uint len)
- {
- uint i;
-
- TTMATH_ASSERT( len>0 && (tab[len-1] & TTMATH_UINT_HIGHEST_BIT)!=0 )
-
- for(i=0 ; i<len-1 ; ++i)
- if( tab[i] != 0 )
- return false;
+ /*!
+ Natural logarithm this = ln(x) where x in range <1,2)
- if( tab[i] != TTMATH_UINT_HIGHEST_BIT )
- return false;
+ we're using the formula:
+ ln x = 2 * [ (x-1)/(x+1) + (1/3)((x-1)/(x+1))^3 + (1/5)((x-1)/(x+1))^5 + ... ]
+ */
+ void LnSurrounding1(const Big<exp,man> & x, uint * steps = 0)
+ {
+ Big<exp,man> old_value, next_part, denominator, one, two, x1(x), x2(x);
+
+ one.SetOne();
+
+ if( x == one )
+ {
+ // LnSurrounding1(1) is 0
+ SetZero();
+ return;
+ }
+
+ two = 2;
+
+ x1.Sub(one);
+ x2.Add(one);
+
+ x1.Div(x2);
+ x2 = x1;
+ x2.Mul(x1);
+
+ denominator.SetOne();
+ SetZero();
+
+ old_value = *this;
+ uint i;
+
+
+ #ifdef TTMATH_CONSTANTSGENERATOR
+ for(i=1 ; true ; ++i)
+ #else
+ // we begin from 1 in order to not test at the beginning
+ for(i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i)
+ #endif
+ {
+ bool testing = ((i & 3) == 0); // it means '(i % 4) == 0'
+
+ next_part = x1;
+
+ if( next_part.Div(denominator) )
+ // if there is a carry here we only break the loop
+ // however the result we return as good
+ // it means there are too many parts of the formula
+ break;
+
+ // there shouldn't be a carry here
+ Add(next_part);
+
+ if( testing )
+ {
+ if( old_value == *this )
+ // we've added next (step_test) parts of the formula but the result
+ // is still the same then we break the loop
+ break;
+ else
+ old_value = *this;
+ }
+
+ if( x1.Mul(x2) )
+ // if there is a carry here the result we return as good
+ break;
+
+ if( denominator.Add(two) )
+ break;
+ }
+
+ // this = this * 2
+ // ( there can't be a carry here because we calculate the logarithm between <1,2) )
+ exponent.AddOne();
+
+ if( steps )
+ *steps = i;
+ }
- return true;
- }
public:
- /*!
- multiplication this = this * ss2
- this method returns a carry
- */
- uint Mul(const Big<exp, man> & ss2, bool round = true)
- {
- TTMATH_REFERENCE_ASSERT( ss2 )
-
- UInt<man*2> man_result;
- uint c = 0;
- uint i;
-
- if( IsNan() || ss2.IsNan() )
- return CheckCarry(1);
-
- if( IsZero() )
- return 0;
-
- if( ss2.IsZero() )
- {
- SetZero();
- return 0;
- }
-
- // man_result = mantissa * ss2.mantissa
- mantissa.MulBig(ss2.mantissa, man_result);
-
- // 'i' will be from 0 to man*TTMATH_BITS_PER_UINT
- // because mantissa and ss2.mantissa are standardized
- // (the highest bit in man_result is set to 1 or
- // if there is a zero value in man_result the method CompensationToLeft()
- // returns 0 but we'll correct this at the end in Standardizing() method)
- i = man_result.CompensationToLeft();
- uint exp_add = man * TTMATH_BITS_PER_UINT - i;
-
- if( exp_add )
- c += exponent.Add( exp_add );
-
- c += exponent.Add( ss2.exponent );
-
- for(i=0 ; i<man ; ++i)
- mantissa.table[i] = man_result.table[i+man];
-
- if( round && (man_result.table[man-1] & TTMATH_UINT_HIGHEST_BIT) != 0 )
- {
- bool is_half = CheckGreaterOrEqualHalf(man_result.table, man);
- c += RoundHalfToEven(is_half);
- }
-
- if( IsSign() == ss2.IsSign() )
- {
- // the signs are the same, the result is positive
- Abs();
- }
- else
- {
- // the signs are different, the result is negative
- // if the value is zero it will be corrected later in Standardizing method
- SetSign();
- }
-
- c += Standardizing();
-
- return CheckCarry(c);
- }
-
-
- /*!
- division this = this / ss2
-
- return value:
- 0 - ok
- 1 - carry (in a division carry can be as well)
- 2 - improper argument (ss2 is zero)
- */
- uint Div(const Big<exp, man> & ss2, bool round = true)
- {
- TTMATH_REFERENCE_ASSERT( ss2 )
-
- UInt<man*2> man1;
- UInt<man*2> man2;
- uint i,c = 0;
-
- if( IsNan() || ss2.IsNan() )
- return CheckCarry(1);
-
- if( ss2.IsZero() )
- {
- SetNan();
- return 2;
- }
-
- if( IsZero() )
- return 0;
-
- for(i=0 ; i<man ; ++i)
- {
- man1.table[i+man] = mantissa.table[i];
- man2.table[i] = ss2.mantissa.table[i];
- }
-
- for(i=0 ; i<man ; ++i)
- {
- man1.table[i] = 0;
- man2.table[i+man] = 0;
- }
-
- man1.Div(man2);
-
- i = man1.CompensationToLeft();
-
- if( i )
- c += exponent.Sub(i);
-
- c += exponent.Sub(ss2.exponent);
-
- for(i=0 ; i<man ; ++i)
- mantissa.table[i] = man1.table[i+man];
-
- if( round && (man1.table[man-1] & TTMATH_UINT_HIGHEST_BIT) != 0 )
- {
- bool is_half = CheckGreaterOrEqualHalf(man1.table, man);
- c += RoundHalfToEven(is_half);
- }
-
- if( IsSign() == ss2.IsSign() )
- Abs();
- else
- SetSign(); // if there is a zero it will be corrected in Standardizing()
-
- c += Standardizing();
-
- return CheckCarry(c);
- }
-
-
- /*!
- the remainder from a division
-
- e.g.
- 12.6 mod 3 = 0.6 because 12.6 = 3*4 + 0.6
- -12.6 mod 3 = -0.6 bacause -12.6 = 3*(-4) + (-0.6)
- 12.6 mod -3 = 0.6
- -12.6 mod -3 = -0.6
-
- it means:
- in other words: this(old) = ss2 * q + this(new)
-
- return value:
- 0 - ok
- 1 - carry
- 2 - improper argument (ss2 is zero)
- */
- uint Mod(const Big<exp, man> & ss2)
- {
- TTMATH_REFERENCE_ASSERT( ss2 )
-
- uint c = 0;
-
- if( IsNan() || ss2.IsNan() )
- return CheckCarry(1);
-
- if( ss2.IsZero() )
- {
- SetNan();
- return 2;
- }
-
- if( !SmallerWithoutSignThan(ss2) )
- {
- Big<exp, man> temp(*this);
-
- c = temp.Div(ss2);
- temp.SkipFraction();
- c += temp.Mul(ss2);
- c += Sub(temp);
-
- if( !SmallerWithoutSignThan( ss2 ) )
- c += 1;
- }
-
- return CheckCarry(c);
- }
-
-
-
-
- /*!
- power this = this ^ pow
- (pow without a sign)
-
- binary algorithm (r-to-l)
-
- return values:
- 0 - ok
- 1 - carry
- 2 - incorrect arguments (0^0)
- */
- template<uint pow_size>
- uint Pow(UInt<pow_size> pow)
- {
- if( IsNan() )
- return 1;
-
- if( IsZero() )
- {
- if( pow.IsZero() )
- {
- // we don't define zero^zero
- SetNan();
- return 2;
- }
-
- // 0^(+something) is zero
- return 0;
- }
-
- Big<exp, man> start(*this), start_temp;
- Big<exp, man> result;
- result.SetOne();
- uint c = 0;
-
- while( !c )
- {
- if( pow.table[0] & 1 )
- c += result.Mul(start);
-
- pow.Rcr(1);
-
- if( pow.IsZero() )
- break;
-
- start_temp = start;
- c += start.Mul(start_temp);
- }
-
- *this = result;
-
- return CheckCarry(c);
- }
-
-
- /*!
- power this = this ^ pow
- p can be negative
-
- return values:
- 0 - ok
- 1 - carry
- 2 - incorrect arguments 0^0 or 0^(-something)
- */
- template<uint pow_size>
- uint Pow(Int<pow_size> pow)
- {
- if( IsNan() )
- return 1;
-
- if( !pow.IsSign() )
- return Pow( UInt<pow_size>(pow) );
-
- if( IsZero() )
- {
- // if 'p' is negative then
- // 'this' must be different from zero
- SetNan();
- return 2;
- }
-
- uint c = pow.ChangeSign();
-
- Big<exp, man> t(*this);
- c += t.Pow( UInt<pow_size>(pow) ); // here can only be a carry (return:1)
-
- SetOne();
- c += Div(t);
-
- return CheckCarry(c);
- }
-
-
- /*!
- this method returns: 'this' mod 2
- (either zero or one)
-
- this method is much faster than using Mod( object_with_value_two )
- */
- uint Mod2() const
- {
- if( exponent>sint(0) || exponent<=-sint(man*TTMATH_BITS_PER_UINT) )
- return 0;
-
- sint exp_int = exponent.ToInt();
- // 'exp_int' is negative (or zero), we set it as positive
- exp_int = -exp_int;
-
- return mantissa.GetBit(exp_int);
- }
-
-
-
- /*!
- power this = this ^ abs([pow])
- pow is treated as a value without a sign and without a fraction
- if pow has a sign then the method pow.Abs() is used
- if pow has a fraction the fraction is skipped (not used in calculation)
-
- return values:
- 0 - ok
- 1 - carry
- 2 - incorrect arguments (0^0)
- */
- uint PowUInt(Big<exp, man> pow)
- {
- if( IsNan() || pow.IsNan() )
- return CheckCarry(1);
-
- if( IsZero() )
- {
- if( pow.IsZero() )
- {
- SetNan();
- return 2;
- }
-
- // 0^(+something) is zero
- return 0;
- }
-
- if( pow.IsSign() )
- pow.Abs();
-
- Big<exp, man> start(*this), start_temp;
- Big<exp, man> result;
- Big<exp, man> one;
- Int<exp> e_one;
- uint c = 0;
-
- e_one.SetOne();
- one.SetOne();
- result = one;
-
- while( !c )
- {
- if( pow.Mod2() )
- c += result.Mul(start);
-
- c += pow.exponent.Sub( e_one ); // !! may use SubOne() here?
-
- if( pow < one )
- break;
-
- start_temp = start;
- c += start.Mul(start_temp);
- }
-
- *this = result;
-
- return CheckCarry(c);
- }
-
-
- /*!
- power this = this ^ [pow]
- pow is treated as a value without a fraction
- pow can be negative
-
- return values:
- 0 - ok
- 1 - carry
- 2 - incorrect arguments 0^0 or 0^(-something)
- */
- uint PowInt(const Big<exp, man> & pow)
- {
- TTMATH_REFERENCE_ASSERT( pow )
-
- if( IsNan() || pow.IsNan() )
- return CheckCarry(1);
-
- if( !pow.IsSign() )
- return PowUInt(pow);
-
- if( IsZero() )
- {
- // if 'pow' is negative then
- // 'this' must be different from zero
- SetNan();
- return 2;
- }
-
- Big<exp, man> temp(*this);
- uint c = temp.PowUInt(pow); // here can only be a carry (result:1)
-
- SetOne();
- c += Div(temp);
-
- return CheckCarry(c);
- }
-
-
- /*!
- power this = this ^ pow
- this must be greater than zero (this > 0)
- pow can be negative and with fraction
-
- return values:
- 0 - ok
- 1 - carry
- 2 - incorrect argument ('this' <= 0)
- */
- uint PowFrac(const Big<exp, man> & pow)
- {
- TTMATH_REFERENCE_ASSERT( pow )
-
- if( IsNan() || pow.IsNan() )
- return CheckCarry(1);
-
- Big<exp, man> temp;
- uint c = temp.Ln(*this);
-
- if( c != 0 ) // can be 2 from Ln()
- {
- SetNan();
- return c;
- }
-
- c += temp.Mul(pow);
- c += Exp(temp);
-
- return CheckCarry(c);
- }
-
-
-
- /*!
- power this = this ^ pow
- pow can be negative and with fraction
-
- return values:
- 0 - ok
- 1 - carry
- 2 - incorrect argument ('this' or 'pow')
- */
- uint Pow(const Big<exp, man> & pow)
- {
- TTMATH_REFERENCE_ASSERT( pow )
-
- if( IsNan() || pow.IsNan() )
- return CheckCarry(1);
-
- if( IsZero() )
- {
- // 0^pow will be 0 only for pow>0
- if( pow.IsSign() || pow.IsZero() )
- {
- SetNan();
- return 2;
- }
-
- SetZero();
-
- return 0;
- }
-
- if( pow.exponent>-int(man*TTMATH_BITS_PER_UINT) && pow.exponent<=0 )
- {
- if( pow.IsInteger() )
- return PowInt( pow );
- }
-
- return PowFrac(pow);
- }
-
-
- /*!
- this function calculates the square root
- e.g. let this=9 then this.Sqrt() gives 3
-
- return: 0 - ok
- 1 - carry
- 2 - improper argument (this<0 or NaN)
- */
- uint Sqrt()
- {
- if( IsNan() || IsSign() )
- {
- SetNan();
- return 2;
- }
-
- if( IsZero() )
- return 0;
-
- Big<exp, man> old(*this);
- Big<exp, man> ln;
- uint c = 0;
-
- // we're using the formula: sqrt(x) = e ^ (ln(x) / 2)
- c += ln.Ln(*this);
- c += ln.exponent.SubOne(); // ln = ln / 2
- c += Exp(ln);
-
- // above formula doesn't give accurate results for some integers
- // e.g. Sqrt(81) would not be 9 but a value very closed to 9
- // we're rounding the result, calculating result*result and comparing
- // with the old value, if they are equal then the result is an integer too
-
- if( !c && old.IsInteger() && !IsInteger() )
- {
- Big<exp, man> temp(*this);
- c += temp.Round();
-
- Big<exp, man> temp2(temp);
- c += temp.Mul(temp2);
-
- if( temp == old )
- *this = temp2;
- }
+ /*!
+ Natural logarithm this = ln(x)
+ (a logarithm with the base equal 'e')
+
+ we're using the fact that our value is stored in form of:
+ x = mantissa * 2^exponent
+ then
+ ln(x) = ln (mantissa * 2^exponent) = ln (mantissa) + (exponent * ln (2))
+
+ the mantissa we'll show as a value from range <1,2) because the logarithm
+ is decreasing too fast when 'x' is going to 0
+
+ return values:
+ 0 - ok
+ 1 - overflow (carry)
+ 2 - incorrect argument (x<=0)
+ */
+ uint Ln(const Big<exp,man> & x)
+ {
+ if( x.IsNan() )
+ return CheckCarry(1);
+
+ if( x.IsSign() || x.IsZero() )
+ {
+ SetNan();
+ return 2;
+ }
+
+ Big<exp,man> exponent_temp;
+ exponent_temp.FromInt( x.exponent );
+
+ // m will be the value of the mantissa in range <1,2)
+ Big<exp,man> m(x);
+ m.exponent = -sint(man*TTMATH_BITS_PER_UINT - 1);
+
+ // we must add 'man*TTMATH_BITS_PER_UINT-1' because we've taken it from the mantissa
+ uint c = exponent_temp.Add(man*TTMATH_BITS_PER_UINT-1);
+
+ LnSurrounding1(m);
+
+ Big<exp,man> ln2;
+ ln2.SetLn2();
+ c += exponent_temp.Mul(ln2);
+ c += Add(exponent_temp);
+
+ return CheckCarry(c);
+ }
+
+
+ /*!
+ Logarithm from 'x' with a 'base'
+
+ we're using the formula:
+ Log(x) with 'base' = ln(x) / ln(base)
+
+ return values:
+ 0 - ok
+ 1 - overflow
+ 2 - incorrect argument (x<=0)
+ 3 - incorrect base (a<=0 lub a=1)
+ */
+ uint Log(const Big<exp,man> & x, const Big<exp,man> & base)
+ {
+ if( x.IsNan() || base.IsNan() )
+ return CheckCarry(1);
+
+ if( x.IsSign() || x.IsZero() )
+ {
+ SetNan();
+ return 2;
+ }
+
+ Big<exp,man> denominator;;
+ denominator.SetOne();
+
+ if( base.IsSign() || base.IsZero() || base==denominator )
+ {
+ SetNan();
+ return 3;
+ }
+
+ if( x == denominator ) // (this is: if x == 1)
+ {
+ // log(1) is 0
+ SetZero();
+ return 0;
+ }
+
+ // another error values we've tested at the beginning
+ // there can only be a carry
+ uint c = Ln(x);
+
+ c += denominator.Ln(base);
+ c += Div(denominator);
+
+ return CheckCarry(c);
+ }
+
+
+
+
+ /*!
+ *
+ * converting methods
+ *
+ */
+
+
+ /*!
+ converting from another type of a Big object
+ */
+ template<uint another_exp, uint another_man>
+ uint FromBig(const Big<another_exp, another_man> & another)
+ {
+ info = another.info;
+
+ if( IsNan() )
+ return 1;
+
+ if( exponent.FromInt(another.exponent) )
+ {
+ SetNan();
+ return 1;
+ }
+
+ uint man_len_min = (man < another_man)? man : another_man;
+ uint i;
+ uint c = 0;
+
+ for( i = 0 ; i<man_len_min ; ++i )
+ mantissa.table[man-1-i] = another.mantissa.table[another_man-1-i];
+
+ for( ; i<man ; ++i )
+ mantissa.table[man-1-i] = 0;
+
+
+ // MS Visual Express 2005 reports a warning (in the lines with 'uint man_diff = ...'):
+ // warning C4307: '*' : integral constant overflow
+ // but we're using 'if( man > another_man )' and 'if( man < another_man )' and there'll be no such situation here
+ #ifdef _MSC_VER
+ #pragma warning( disable: 4307 )
+ #endif
+
+ if( man > another_man )
+ {
+ uint man_diff = (man - another_man) * TTMATH_BITS_PER_UINT;
+ c += exponent.SubInt(man_diff, 0);
+ }
+ else
+ if( man < another_man )
+ {
+ uint man_diff = (another_man - man) * TTMATH_BITS_PER_UINT;
+ c += exponent.AddInt(man_diff, 0);
+ }
+
+ #ifdef _MSC_VER
+ #pragma warning( default: 4307 )
+ #endif
+
+ // mantissa doesn't have to be standardized (either the highest bit is set or all bits are equal zero)
+ CorrectZero();
- return CheckCarry(c);
- }
+ return CheckCarry(c);
+ }
private:
-#ifdef TTMATH_CONSTANTSGENERATOR
-public:
-#endif
+ /*!
+ an auxiliary method for converting 'this' into 'result'
+ if the value is too big this method returns a carry (1)
+ */
+ uint ToUIntOrInt(uint & result) const
+ {
+ result = 0;
+
+ if( IsZero() )
+ return 0;
+
+ sint maxbit = -sint(man*TTMATH_BITS_PER_UINT);
+
+ if( exponent > maxbit + sint(TTMATH_BITS_PER_UINT) )
+ // if exponent > (maxbit + sint(TTMATH_BITS_PER_UINT)) the value can't be passed
+ // into the 'sint' type (it's too big)
+ return 1;
+
+ if( exponent <= maxbit )
+ // our value is from the range of (-1,1) and we return zero
+ return 0;
+
+ // exponent is from a range of (maxbit, maxbit + sint(TTMATH_BITS_PER_UINT) >
+ // and [maxbit + sint(TTMATH_BITS_PER_UINT] <= 0
+ sint how_many_bits = exponent.ToInt();
+
+ // how_many_bits is negative, we'll make it positive
+ how_many_bits = -how_many_bits;
+
+ result = (mantissa.table[man-1] >> (how_many_bits % TTMATH_BITS_PER_UINT));
- /*!
- Exponent this = exp(x) = e^x where x is in (-1,1)
+ return 0;
+ }
- we're using the formula exp(x) = 1 + (x)/(1!) + (x^2)/(2!) + (x^3)/(3!) + ...
- */
- void ExpSurrounding0(const Big<exp,man> & x, uint * steps = 0)
- {
- TTMATH_REFERENCE_ASSERT( x )
-
- Big<exp,man> denominator, denominator_i;
- Big<exp,man> one, old_value, next_part;
- Big<exp,man> numerator = x;
-
- SetOne();
- one.SetOne();
- denominator.SetOne();
- denominator_i.SetOne();
-
- uint i;
- old_value = *this;
-
- // we begin from 1 in order to not test at the beginning
- #ifdef TTMATH_CONSTANTSGENERATOR
- for(i=1 ; true ; ++i)
- #else
- for(i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i)
- #endif
- {
- bool testing = ((i & 3) == 0); // it means '(i % 4) == 0'
-
- next_part = numerator;
-
- if( next_part.Div( denominator ) )
- // if there is a carry here we only break the loop
- // however the result we return as good
- // it means there are too many parts of the formula
- break;
-
- // there shouldn't be a carry here
- Add( next_part );
-
- if( testing )
- {
- if( old_value == *this )
- // we've added next few parts of the formula but the result
- // is still the same then we break the loop
- break;
- else
- old_value = *this;
- }
-
- // we set the denominator and the numerator for a next part of the formula
- if( denominator_i.Add(one) )
- // if there is a carry here the result we return as good
- break;
-
- if( denominator.Mul(denominator_i) )
- break;
-
- if( numerator.Mul(x) )
- break;
- }
-
- if( steps )
- *steps = i;
- }
public:
+ /*!
+ this method converts 'this' into uint
+ */
+ uint ToUInt() const
+ {
+ uint result;
- /*!
- Exponent this = exp(x) = e^x
+ ToUInt(result);
- we're using the fact that our value is stored in form of:
- x = mantissa * 2^exponent
- then
- e^x = e^(mantissa* 2^exponent) or
- e^x = (e^mantissa)^(2^exponent)
-
- 'Exp' returns a carry if we can't count the result ('x' is too big)
- */
- uint Exp(const Big<exp,man> & x)
- {
- uint c = 0;
-
- if( x.IsNan() )
- return CheckCarry(1);
-
- if( x.IsZero() )
- {
- SetOne();
- return 0;
- }
-
- // m will be the value of the mantissa in range (-1,1)
- Big<exp,man> m(x);
- m.exponent = -sint(man*TTMATH_BITS_PER_UINT);
-
- // 'e_' will be the value of '2^exponent'
- // e_.mantissa.table[man-1] = TTMATH_UINT_HIGHEST_BIT; and
- // e_.exponent.Add(1) mean:
- // e_.mantissa.table[0] = 1;
- // e_.Standardizing();
- // e_.exponent.Add(man*TTMATH_BITS_PER_UINT)
- // (we must add 'man*TTMATH_BITS_PER_UINT' because we've taken it from the mantissa)
- Big<exp,man> e_(x);
- e_.mantissa.SetZero();
- e_.mantissa.table[man-1] = TTMATH_UINT_HIGHEST_BIT;
- c += e_.exponent.Add(1);
- e_.Abs();
-
- /*
- now we've got:
- m - the value of the mantissa in range (-1,1)
- e_ - 2^exponent
-
- e_ can be as:
- ...2^-2, 2^-1, 2^0, 2^1, 2^2 ...
- ...1/4 , 1/2 , 1 , 2 , 4 ...
-
- above one e_ is integer
-
- if e_ is greater than 1 we calculate the exponent as:
- e^(m * e_) = ExpSurrounding0(m) ^ e_
- and if e_ is smaller or equal one we calculate the exponent in this way:
- e^(m * e_) = ExpSurrounding0(m* e_)
- because if e_ is smaller or equal 1 then the product of m*e_ is smaller or equal m
- */
-
- if( e_ <= 1 )
- {
- m.Mul(e_);
- ExpSurrounding0(m);
- }
- else
- {
- ExpSurrounding0(m);
- c += PowUInt(e_);
- }
+ return result;
+ }
- return CheckCarry(c);
- }
+ /*!
+ this method converts 'this' into 'result'
+ if the value is too big this method returns a carry (1)
+ */
+ uint ToUInt(uint & result) const
+ {
+ if( ToUIntOrInt(result) )
+ return 1;
+ if( IsSign() )
+ return 1;
-private:
+ return 0;
+ }
-#ifdef TTMATH_CONSTANTSGENERATOR
-public:
-#endif
- /*!
- Natural logarithm this = ln(x) where x in range <1,2)
+ /*!
+ this method converts 'this' into sint
+ */
+ sint ToInt() const
+ {
+ sint result;
- we're using the formula:
- ln x = 2 * [ (x-1)/(x+1) + (1/3)((x-1)/(x+1))^3 + (1/5)((x-1)/(x+1))^5 + ... ]
- */
- void LnSurrounding1(const Big<exp,man> & x, uint * steps = 0)
- {
- Big<exp,man> old_value, next_part, denominator, one, two, x1(x), x2(x);
-
- one.SetOne();
-
- if( x == one )
- {
- // LnSurrounding1(1) is 0
- SetZero();
- return;
- }
-
- two = 2;
-
- x1.Sub(one);
- x2.Add(one);
-
- x1.Div(x2);
- x2 = x1;
- x2.Mul(x1);
-
- denominator.SetOne();
- SetZero();
-
- old_value = *this;
- uint i;
-
-
- #ifdef TTMATH_CONSTANTSGENERATOR
- for(i=1 ; true ; ++i)
- #else
- // we begin from 1 in order to not test at the beginning
- for(i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i)
- #endif
- {
- bool testing = ((i & 3) == 0); // it means '(i % 4) == 0'
-
- next_part = x1;
-
- if( next_part.Div(denominator) )
- // if there is a carry here we only break the loop
- // however the result we return as good
- // it means there are too many parts of the formula
- break;
-
- // there shouldn't be a carry here
- Add(next_part);
-
- if( testing )
- {
- if( old_value == *this )
- // we've added next (step_test) parts of the formula but the result
- // is still the same then we break the loop
- break;
- else
- old_value = *this;
- }
-
- if( x1.Mul(x2) )
- // if there is a carry here the result we return as good
- break;
-
- if( denominator.Add(two) )
- break;
- }
-
- // this = this * 2
- // ( there can't be a carry here because we calculate the logarithm between <1,2) )
- exponent.AddOne();
-
- if( steps )
- *steps = i;
- }
+ ToInt(result);
+ return result;
+ }
+ /*!
+ this method converts 'this' into 'result'
-public:
+ if the value is too big this method returns a carry (1)
+ */
+ uint ToInt(uint & result) const
+ {
+ return ToUInt(result);
+ }
- /*!
- Natural logarithm this = ln(x)
- (a logarithm with the base equal 'e')
+ /*!
+ this method converts 'this' into 'result'
- we're using the fact that our value is stored in form of:
- x = mantissa * 2^exponent
- then
- ln(x) = ln (mantissa * 2^exponent) = ln (mantissa) + (exponent * ln (2))
+ if the value is too big this method returns a carry (1)
+ */
+ uint ToInt(sint & result) const
+ {
+ uint result_uint;
- the mantissa we'll show as a value from range <1,2) because the logarithm
- is decreasing too fast when 'x' is going to 0
+ uint c = ToUIntOrInt(result_uint);
+ result = sint(result_uint);
- return values:
- 0 - ok
- 1 - overflow (carry)
- 2 - incorrect argument (x<=0)
- */
- uint Ln(const Big<exp,man> & x)
- {
- TTMATH_REFERENCE_ASSERT( x )
+ if( c )
+ return 1;
- if( x.IsNan() )
- return CheckCarry(1);
+ uint mask = 0;
- if( x.IsSign() || x.IsZero() )
- {
- SetNan();
- return 2;
- }
+ if( IsSign() )
+ {
+ mask = TTMATH_UINT_MAX_VALUE;
+ result = -result;
+ }
- // m will be the value of the mantissa in range <1,2)
- Big<exp,man> m(x);
- m.exponent = -sint(man*TTMATH_BITS_PER_UINT - 1);
+ return ((result & TTMATH_UINT_HIGHEST_BIT) == (mask & TTMATH_UINT_HIGHEST_BIT)) ? 0 : 1;
+ }
- LnSurrounding1(m);
- Big<exp,man> exponent_temp;
- exponent_temp.FromInt( x.exponent );
+private:
- // we must add 'man*TTMATH_BITS_PER_UINT-1' because we've taken it from the mantissa
- uint c = exponent_temp.Add(man*TTMATH_BITS_PER_UINT-1);
+ /*!
+ an auxiliary method for converting 'this' into 'result'
- Big<exp,man> ln2;
- ln2.SetLn2();
- c += exponent_temp.Mul(ln2);
- c += Add(exponent_temp);
+ if the value is too big this method returns a carry (1)
+ */
+ template<uint int_size>
+ uint ToUIntOrInt(UInt<int_size> & result) const
+ {
+ result.SetZero();
+
+ if( IsZero() )
+ return 0;
+
+ sint maxbit = -sint(man*TTMATH_BITS_PER_UINT);
+
+ if( exponent > maxbit + sint(int_size*TTMATH_BITS_PER_UINT) )
+ // if exponent > (maxbit + sint(int_size*TTMATH_BITS_PER_UINT)) the value can't be passed
+ // into the 'UInt<int_size>' type (it's too big)
+ return 1;
+
+ if( exponent <= maxbit )
+ // our value is from range (-1,1) and we return zero
+ return 0;
+
+ sint how_many_bits = exponent.ToInt();
+
+ if( how_many_bits < 0 )
+ {
+ how_many_bits = -how_many_bits;
+ uint index = how_many_bits / TTMATH_BITS_PER_UINT;
+
+ UInt<man> mantissa_temp(mantissa);
+ mantissa_temp.Rcr( how_many_bits % TTMATH_BITS_PER_UINT, 0 );
+
+ for(uint i=index, a=0 ; i<man ; ++i,++a)
+ result.table[a] = mantissa_temp.table[i];
+ }
+ else
+ {
+ uint index = how_many_bits / TTMATH_BITS_PER_UINT;
+
+ if( index + (man-1) < int_size )
+ {
+ // above 'if' is always true
+ // this is only to get rid of a warning "warning: array subscript is above array bounds"
+ // (from gcc)
+ // we checked the condition there: "if( exponent > maxbit + sint(int_size*TTMATH_BITS_PER_UINT) )"
+ // but gcc doesn't understand our types - exponent is Int<>
+
+ for(uint i=0 ; i<man ; ++i)
+ result.table[index+i] = mantissa.table[i];
+ }
- return CheckCarry(c);
- }
+ result.Rcl( how_many_bits % TTMATH_BITS_PER_UINT, 0 );
+ }
+ return 0;
+ }
- /*!
- Logarithm from 'x' with a 'base'
+public:
- we're using the formula:
- Log(x) with 'base' = ln(x) / ln(base)
+ /*!
+ this method converts 'this' into 'result'
- return values:
- 0 - ok
- 1 - overflow
- 2 - incorrect argument (x<=0)
- 3 - incorrect base (a<=0 lub a=1)
- */
- uint Log(const Big<exp,man> & x, const Big<exp,man> & base)
- {
- TTMATH_REFERENCE_ASSERT( base )
- TTMATH_REFERENCE_ASSERT( x )
+ if the value is too big this method returns a carry (1)
+ */
+ template<uint int_size>
+ uint ToUInt(UInt<int_size> & result) const
+ {
+ uint c = ToUIntOrInt(result);
- if( x.IsNan() || base.IsNan() )
- return CheckCarry(1);
+ if( c )
+ return 1;
- if( x.IsSign() || x.IsZero() )
- {
- SetNan();
- return 2;
- }
+ if( IsSign() )
+ return 1;
- Big<exp,man> denominator;;
- denominator.SetOne();
+ return 0;
+ }
- if( base.IsSign() || base.IsZero() || base==denominator )
- {
- SetNan();
- return 3;
- }
- if( x == denominator ) // (this is: if x == 1)
- {
- // log(1) is 0
- SetZero();
- return 0;
- }
+ /*!
+ this method converts 'this' into 'result'
- // another error values we've tested at the beginning
- // there can only be a carry
- uint c = Ln(x);
+ if the value is too big this method returns a carry (1)
+ */
+ template<uint int_size>
+ uint ToInt(UInt<int_size> & result) const
+ {
+ return ToUInt(result);
+ }
- c += denominator.Ln(base);
- c += Div(denominator);
- return CheckCarry(c);
- }
+ /*!
+ this method converts 'this' into 'result'
+ if the value is too big this method returns a carry (1)
+ */
+ template<uint int_size>
+ uint ToInt(Int<int_size> & result) const
+ {
+ uint c = ToUIntOrInt(result);
+ if( c )
+ return 1;
+ uint mask = 0;
- /*!
- *
- * converting methods
- *
- */
+ if( IsSign() )
+ {
+ result.ChangeSign();
+ mask = TTMATH_UINT_MAX_VALUE;
+ }
+ return ((result.table[int_size-1] & TTMATH_UINT_HIGHEST_BIT) == (mask & TTMATH_UINT_HIGHEST_BIT))? 0 : 1;
+ }
- /*!
- converting from another type of a Big object
- */
- template<uint another_exp, uint another_man>
- uint FromBig(const Big<another_exp, another_man> & another)
- {
- info = another.info;
- if( IsNan() )
- return 1;
+ /*!
+ a method for converting 'uint' to this class
+ */
+ uint FromUInt(uint value)
+ {
+ if( value == 0 )
+ {
+ SetZero();
+ return 0;
+ }
- if( exponent.FromInt(another.exponent) )
- {
- SetNan();
- return 1;
- }
+ info = 0;
- uint man_len_min = (man < another_man)? man : another_man;
- uint i;
- uint c = 0;
+ for(uint i=0 ; i<man-1 ; ++i)
+ mantissa.table[i] = 0;
- for( i = 0 ; i<man_len_min ; ++i )
- mantissa.table[man-1-i] = another.mantissa.table[another_man-1-i];
+ mantissa.table[man-1] = value;
+ exponent = -sint(man-1) * sint(TTMATH_BITS_PER_UINT);
- for( ; i<man ; ++i )
- mantissa.table[man-1-i] = 0;
+ // there shouldn't be a carry because 'value' has the 'uint' type
+ Standardizing();
+ return 0;
+ }
- // MS Visual Express 2005 reports a warning (in the lines with 'uint man_diff = ...'):
- // warning C4307: '*' : integral constant overflow
- // but we're using 'if( man > another_man )' and 'if( man < another_man )' and there'll be no such situation here
- #ifdef _MSC_VER
- #pragma warning( disable: 4307 )
- #endif
- if( man > another_man )
- {
- uint man_diff = (man - another_man) * TTMATH_BITS_PER_UINT;
- c += exponent.SubInt(man_diff, 0);
- }
- else
- if( man < another_man )
- {
- uint man_diff = (another_man - man) * TTMATH_BITS_PER_UINT;
- c += exponent.AddInt(man_diff, 0);
- }
+ /*!
+ a method for converting 'uint' to this class
+ */
+ uint FromInt(uint value)
+ {
+ return FromUInt(value);
+ }
- #ifdef _MSC_VER
- #pragma warning( default: 4307 )
- #endif
- // mantissa doesn't have to be standardized (either the highest bit is set or all bits are equal zero)
- CorrectZero();
+ /*!
+ a method for converting 'sint' to this class
+ */
+ uint FromInt(sint value)
+ {
+ bool is_sign = false;
- return CheckCarry(c);
- }
+ if( value < 0 )
+ {
+ value = -value;
+ is_sign = true;
+ }
+ FromUInt(uint(value));
- /*!
- this method converts 'this' into 'result'
+ if( is_sign )
+ SetSign();
- if the value is too big this method returns a carry (1)
- */
- uint ToUInt(uint & result, bool test_sign = true) const
- {
- result = 0;
+ return 0;
+ }
- if( IsZero() )
- return 0;
- if( test_sign && IsSign() )
- // the result should be positive
- return 1;
- sint maxbit = -sint(man*TTMATH_BITS_PER_UINT);
+ /*!
+ this method converts from standard double into this class
- if( exponent > maxbit + sint(TTMATH_BITS_PER_UINT) )
- // if exponent > (maxbit + sint(TTMATH_BITS_PER_UINT)) the value can't be passed
- // into the 'sint' type (it's too big)
- return 1;
+ standard double means IEEE-754 floating point value with 64 bits
+ it is as follows (from http://www.psc.edu/general/software/packages/ieee/ieee.html):
- if( exponent <= maxbit )
- // our value is from the range of (-1,1) and we return zero
- return 0;
+ The IEEE double precision floating point standard representation requires
+ a 64 bit word, which may be represented as numbered from 0 to 63, left to
+ right. The first bit is the sign bit, S, the next eleven bits are the
+ exponent bits, 'E', and the final 52 bits are the fraction 'F':
- UInt<man> mantissa_temp(mantissa);
- // exponent is from a range of (maxbit, maxbit + sint(TTMATH_BITS_PER_UINT) >
- sint how_many_bits = exponent.ToInt();
+ S EEEEEEEEEEE FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+ 0 1 11 12 63
- // how_many_bits is negative, we'll make it positive
- how_many_bits = -how_many_bits;
+ The value V represented by the word may be determined as follows:
- // we're taking into account only the last word in a mantissa table
- mantissa_temp.Rcr( how_many_bits % TTMATH_BITS_PER_UINT, 0 );
- result = mantissa_temp.table[ man-1 ];
+ * If E=2047 and F is nonzero, then V=NaN ("Not a number")
+ * If E=2047 and F is zero and S is 1, then V=-Infinity
+ * If E=2047 and F is zero and S is 0, then V=Infinity
+ * If 0<E<2047 then V=(-1)**S * 2 ** (E-1023) * (1.F) where "1.F" is intended
+ to represent the binary number created by prefixing F with an implicit
+ leading 1 and a binary point.
+ * If E=0 and F is nonzero, then V=(-1)**S * 2 ** (-1022) * (0.F) These are
+ "unnormalized" values.
+ * If E=0 and F is zero and S is 1, then V=-0
+ * If E=0 and F is zero and S is 0, then V=0
+ */
- return 0;
- }
+#ifdef TTMATH_PLATFORM32
+ uint FromDouble(double value)
+ {
+ // I am not sure what will be on a platform which has
+ // a different endianness... but we use this library only
+ // on x86 and amd (intel) 64 bits (as there's a lot of assembler code)
+ union
+ {
+ double d;
+ uint u[2]; // two 32bit words
+ } temp;
+
+ temp.d = value;
+
+ sint e = ( temp.u[1] & 0x7FF00000u) >> 20;
+ uint m1 = ((temp.u[1] & 0xFFFFFu) << 11) | (temp.u[0] >> 21);
+ uint m2 = temp.u[0] << 11;
+
+ if( e == 2047 )
+ {
+ // If E=2047 and F is nonzero, then V=NaN ("Not a number")
+ // If E=2047 and F is zero and S is 1, then V=-Infinity
+ // If E=2047 and F is zero and S is 0, then V=Infinity
+
+ // we do not support -Infinity and +Infinity
+ // we assume that there is always NaN
+
+ SetNan();
+ }
+ else
+ if( e > 0 )
+ {
+ // If 0<E<2047 then
+ // V=(-1)**S * 2 ** (E-1023) * (1.F)
+ // where "1.F" is intended to represent the binary number
+ // created by prefixing F with an implicit leading 1 and a binary point.
+
+ FromDouble_SetExpAndMan((temp.u[1] & 0x80000000u) != 0,
+ e - 1023 - man*TTMATH_BITS_PER_UINT + 1, 0x80000000u,
+ m1, m2);
+
+ // we do not have to call Standardizing() here
+ // because the mantissa will have the highest bit set
+ }
+ else
+ {
+ // e == 0
+
+ if( m1 != 0 || m2 != 0 )
+ {
+ // If E=0 and F is nonzero,
+ // then V=(-1)**S * 2 ** (-1022) * (0.F)
+ // These are "unnormalized" values.
+
+ UInt<2> m;
+ m.table[1] = m1;
+ m.table[0] = m2;
+ uint moved = m.CompensationToLeft();
+
+ FromDouble_SetExpAndMan((temp.u[1] & 0x80000000u) != 0,
+ e - 1022 - man*TTMATH_BITS_PER_UINT + 1 - moved, 0,
+ m.table[1], m.table[2]);
+ }
+ else
+ {
+ // If E=0 and F is zero and S is 1, then V=-0
+ // If E=0 and F is zero and S is 0, then V=0
+
+ // we do not support -0 or 0, only is one 0
+ SetZero();
+ }
+ }
+ return 0; // never be a carry
+ }
- /*!
- this method converts 'this' into 'result'
- if the value is too big this method returns a carry (1)
- */
- uint ToInt(sint & result) const
- {
- result = 0;
- uint result_uint;
+private:
- if( ToUInt(result_uint, false) )
- return 1;
+ void FromDouble_SetExpAndMan(bool is_sign, int e, uint mhighest, uint m1, uint m2)
+ {
+ exponent = e;
+
+ if( man > 1 )
+ {
+ mantissa.table[man-1] = m1 | mhighest;
+ mantissa.table[sint(man-2)] = m2;
+ // although man>1 we're using casting into sint
+ // to get rid from a warning which generates Microsoft Visual:
+ // warning C4307: '*' : integral constant overflow
+
+ for(uint i=0 ; i<man-2 ; ++i)
+ mantissa.table[i] = 0;
+ }
+ else
+ {
+ mantissa.table[0] = m1 | mhighest;
+ }
+
+ info = 0;
+
+ // the value should be different from zero
+ TTMATH_ASSERT( mantissa.IsZero() == false )
+
+ if( is_sign )
+ SetSign();
+ }
- result = static_cast<sint>( result_uint );
- // the exception for the minimal value
- if( IsSign() && result_uint == TTMATH_UINT_HIGHEST_BIT )
- return 0;
+#else
- if( (result_uint & TTMATH_UINT_HIGHEST_BIT) != 0 )
- // the value is too big
- return 1;
+public:
- if( IsSign() )
- result = -result;
+ // 64bit platforms
+ uint FromDouble(double value)
+ {
+ // I am not sure what will be on a plaltform which has
+ // a different endianness... but we use this library only
+ // on x86 and amd (intel) 64 bits (as there's a lot of assembler code)
+ union
+ {
+ double d;
+ uint u; // one 64bit word
+ } temp;
+
+ temp.d = value;
+
+ sint e = (temp.u & 0x7FF0000000000000ul) >> 52;
+ uint m = (temp.u & 0xFFFFFFFFFFFFFul) << 11;
+
+ if( e == 2047 )
+ {
+ // If E=2047 and F is nonzero, then V=NaN ("Not a number")
+ // If E=2047 and F is zero and S is 1, then V=-Infinity
+ // If E=2047 and F is zero and S is 0, then V=Infinity
+
+ // we do not support -Infinity and +Infinity
+ // we assume that there is always NaN
+
+ SetNan();
+ }
+ else
+ if( e > 0 )
+ {
+ // If 0<E<2047 then
+ // V=(-1)**S * 2 ** (E-1023) * (1.F)
+ // where "1.F" is intended to represent the binary number
+ // created by prefixing F with an implicit leading 1 and a binary point.
+
+ FromDouble_SetExpAndMan((temp.u & 0x8000000000000000ul) != 0,
+ e - 1023 - man*TTMATH_BITS_PER_UINT + 1,
+ 0x8000000000000000ul, m);
+
+ // we do not have to call Standardizing() here
+ // because the mantissa will have the highest bit set
+ }
+ else
+ {
+ // e == 0
+
+ if( m != 0 )
+ {
+ // If E=0 and F is nonzero,
+ // then V=(-1)**S * 2 ** (-1022) * (0.F)
+ // These are "unnormalized" values.
+
+ FromDouble_SetExpAndMan(bool(temp.u & 0x8000000000000000ul),
+ e - 1022 - man*TTMATH_BITS_PER_UINT + 1, 0, m);
+ Standardizing();
+ }
+ else
+ {
+ // If E=0 and F is zero and S is 1, then V=-0
+ // If E=0 and F is zero and S is 0, then V=0
+
+ // we do not support -0 or 0, only is one 0
+ SetZero();
+ }
+ }
- return 0;
- }
+ return 0; // never be a carry
+ }
+private:
- /*!
- this method converts 'this' into 'result'
+ void FromDouble_SetExpAndMan(bool is_sign, sint e, uint mhighest, uint m)
+ {
+ exponent = e;
+ mantissa.table[man-1] = m | mhighest;
+
+ for(uint i=0 ; i<man-1 ; ++i)
+ mantissa.table[i] = 0;
+
+ info = 0;
+
+ // the value should be different from zero
+ TTMATH_ASSERT( mantissa.IsZero() == false )
+
+ if( is_sign )
+ SetSign();
+ }
- if the value is too big this method returns a carry (1)
- */
- template<uint int_size>
- uint ToInt(Int<int_size> & result) const
- {
- result.SetZero();
+#endif
- if( IsZero() )
- return 0;
- sint maxbit = -sint(man*TTMATH_BITS_PER_UINT);
+public:
- if( exponent > maxbit + sint(int_size*TTMATH_BITS_PER_UINT) )
- // if exponent > (maxbit + sint(int_size*TTMATH_BITS_PER_UINT)) the value can't be passed
- // into the 'Int<int_size>' type (it's too big)
- return 1;
- if( exponent <= maxbit )
- // our value is from range (-1,1) and we return zero
- return 0;
+ /*!
+ this method converts from float to this class
+ */
+ uint FromFloat(float value)
+ {
+ return FromDouble(double(value));
+ }
+
+
+ /*!
+ this method converts from this class into the 'double'
+
+ if the value is too big:
+ 'result' will be +/-infinity (depending on the sign)
+ if the value is too small:
+ 'result' will be 0
+ */
+ double ToDouble() const
+ {
+ double result;
- sint how_many_bits = exponent.ToInt();
+ ToDouble(result);
- if( how_many_bits < 0 )
- {
- how_many_bits = -how_many_bits;
- uint index = how_many_bits / TTMATH_BITS_PER_UINT;
+ return result;
+ }
- UInt<man> mantissa_temp(mantissa);
- mantissa_temp.Rcr( how_many_bits % TTMATH_BITS_PER_UINT, 0 );
- for(uint i=index, a=0 ; i<man ; ++i,++a)
- result.table[a] = mantissa_temp.table[i];
- }
- else
- {
- uint index = how_many_bits / TTMATH_BITS_PER_UINT;
+private:
- for(uint i=0 ; i<man ; ++i)
- result.table[index+i] = mantissa.table[i];
- result.Rcl( how_many_bits % TTMATH_BITS_PER_UINT, 0 );
- }
+ /*!
+ an auxiliary method to check if the float value is +/-infinity
+ we provide this method because isinf(float) in only in C99 language
+
+ description taken from: http://www.psc.edu/general/software/packages/ieee/ieee.php
+
+ The IEEE single precision floating point standard representation requires a 32 bit word,
+ which may be represented as numbered from 0 to 31, left to right.
+ The first bit is the sign bit, S, the next eight bits are the exponent bits, 'E',
+ and the final 23 bits are the fraction 'F':
+
+ S EEEEEEEE FFFFFFFFFFFFFFFFFFFFFFF
+ 0 1 8 9 31
+
+ The value V represented by the word may be determined as follows:
+
+ * If E=255 and F is nonzero, then V=NaN ("Not a number")
+ * If E=255 and F is zero and S is 1, then V=-Infinity
+ * If E=255 and F is zero and S is 0, then V=Infinity
+ * If 0<E<255 then V=(-1)**S * 2 ** (E-127) * (1.F) where "1.F" is intended to represent
+ the binary number created by prefixing F with an implicit leading 1 and a binary point.
+ * If E=0 and F is nonzero, then V=(-1)**S * 2 ** (-126) * (0.F) These are "unnormalized" values.
+ * If E=0 and F is zero and S is 1, then V=-0
+ * If E=0 and F is zero and S is 0, then V=0
+ */
+ bool IsInf(float value) const
+ {
+ // need testing on a 64 bit machine
+
+ union
+ {
+ float d;
+ uint u;
+ } temp;
+
+ temp.d = value;
+
+ if( ((temp.u >> 23) & 0xff) == 0xff )
+ {
+ if( (temp.u & 0x7FFFFF) == 0 )
+ return true; // +/- infinity
+ }
- // the exception for the minimal value
- if( IsSign() )
- {
- Int<int_size> min;
- min.SetMin();
+ return false;
+ }
- if( result == min )
- return 0;
- }
- if( (result.table[int_size-1] & TTMATH_UINT_HIGHEST_BIT) != 0 )
- // the value is too big
- return 1;
+public:
- if( IsSign() )
- result.ChangeSign();
+ /*!
+ this method converts from this class into the 'float'
- return 0;
- }
+ if the value is too big:
+ 'result' will be +/-infinity (depending on the sign)
+ if the value is too small:
+ 'result' will be 0
+ */
+ float ToFloat() const
+ {
+ float result;
+
+ ToFloat(result);
+
+ return result;
+ }
+
+
+ /*!
+ this method converts from this class into the 'float'
+
+ if the value is too big:
+ 'result' will be +/-infinity (depending on the sign)
+ and the method returns 1
+ if the value is too small:
+ 'result' will be 0
+ and the method returns 1
+ */
+ uint ToFloat(float & result) const
+ {
+ double result_double;
+
+ uint c = ToDouble(result_double);
+ result = float(result_double);
+
+ if( result == -0.0f )
+ result = 0.0f;
+
+ if( c )
+ return 1;
+
+ // although the result_double can have a correct value
+ // but after converting to float there can be infinity
+
+ if( IsInf(result) )
+ return 1;
+
+ if( result == 0.0f && result_double != 0.0 )
+ // result_double was too small for float
+ return 1;
+
+ return 0;
+ }
+
+
+ /*!
+ this method converts from this class into the 'double'
+
+ if the value is too big:
+ 'result' will be +/-infinity (depending on the sign)
+ and the method returns 1
+ if the value is too small:
+ 'result' will be 0
+ and the method returns 1
+ */
+ uint ToDouble(double & result) const
+ {
+ if( IsZero() )
+ {
+ result = 0.0;
+ return 0;
+ }
+
+ if( IsNan() )
+ {
+ result = ToDouble_SetDouble( false, 2047, 0, false, true);
+
+ return 0;
+ }
+
+ sint e_correction = sint(man*TTMATH_BITS_PER_UINT) - 1;
+
+ if( exponent >= 1024 - e_correction )
+ {
+ // +/- infinity
+ result = ToDouble_SetDouble( IsSign(), 2047, 0, true);
+
+ return 1;
+ }
+ else
+ if( exponent <= -1023 - 52 - e_correction )
+ {
+ // too small value - we assume that there'll be a zero
+ result = 0;
+
+ // and return a carry
+ return 1;
+ }
+
+ sint e = exponent.ToInt() + e_correction;
+
+ if( e <= -1023 )
+ {
+ // -1023-52 < e <= -1023 (unnormalized value)
+ result = ToDouble_SetDouble( IsSign(), 0, -(e + 1023));
+ }
+ else
+ {
+ // -1023 < e < 1024
+ result = ToDouble_SetDouble( IsSign(), e + 1023, -1);
+ }
+ return 0;
+ }
- /*!
- a method for converting 'uint' to this class
- */
- void FromUInt(uint value)
- {
- info = 0;
+private:
- for(uint i=0 ; i<man-1 ; ++i)
- mantissa.table[i] = 0;
+#ifdef TTMATH_PLATFORM32
- mantissa.table[man-1] = value;
- exponent = -sint(man-1) * sint(TTMATH_BITS_PER_UINT);
+ // 32bit platforms
+ double ToDouble_SetDouble(bool is_sign, uint e, sint move, bool infinity = false, bool nan = false) const
+ {
+ union
+ {
+ double d;
+ uint u[2]; // two 32bit words
+ } temp;
+
+ temp.u[0] = temp.u[1] = 0;
+
+ if( is_sign )
+ temp.u[1] |= 0x80000000u;
+
+ temp.u[1] |= (e << 20) & 0x7FF00000u;
+
+ if( nan )
+ {
+ temp.u[0] |= 1;
+ return temp.d;
+ }
+
+ if( infinity )
+ return temp.d;
+
+ UInt<2> m;
+ m.table[1] = mantissa.table[man-1];
+ m.table[0] = ( man > 1 ) ? mantissa.table[sint(man-2)] : 0;
+ // although man>1 we're using casting into sint
+ // to get rid from a warning which generates Microsoft Visual:
+ // warning C4307: '*' : integral constant overflow
- // there shouldn't be a carry because 'value' has the 'uint' type
- Standardizing();
- }
+ m.Rcr( 12 + move );
+ m.table[1] &= 0xFFFFFu; // cutting the 20 bit (when 'move' was -1)
+ temp.u[1] |= m.table[1];
+ temp.u[0] |= m.table[0];
- /*!
- a method for converting 'sint' to this class
- */
- void FromInt(sint value)
- {
- bool is_sign = false;
+ return temp.d;
+ }
- if( value < 0 )
- {
- value = -value;
- is_sign = true;
- }
+#else
- FromUInt(uint(value));
+ // 64bit platforms
+ double ToDouble_SetDouble(bool is_sign, uint e, sint move, bool infinity = false, bool nan = false) const
+ {
+ union
+ {
+ double d;
+ uint u; // 64bit word
+ } temp;
+
+ temp.u = 0;
+
+ if( is_sign )
+ temp.u |= 0x8000000000000000ul;
+
+ temp.u |= (e << 52) & 0x7FF0000000000000ul;
+
+ if( nan )
+ {
+ temp.u |= 1;
+ return temp.d;
+ }
+
+ if( infinity )
+ return temp.d;
+
+ uint m = mantissa.table[man-1];
+
+ m >>= ( 12 + move );
+ m &= 0xFFFFFFFFFFFFFul; // cutting the 20 bit (when 'move' was -1)
+ temp.u |= m;
- if( is_sign )
- SetSign();
- }
+ return temp.d;
+ }
+#endif
- /*!
- this method converts from standard double into this class
+public:
- standard double means IEEE-754 floating point value with 64 bits
- it is as follows (from http://www.psc.edu/general/software/packages/ieee/ieee.html):
- The IEEE double precision floating point standard representation requires
- a 64 bit word, which may be represented as numbered from 0 to 63, left to
- right. The first bit is the sign bit, S, the next eleven bits are the
- exponent bits, 'E', and the final 52 bits are the fraction 'F':
+ /*!
+ an operator= for converting 'sint' to this class
+ */
+ Big<exp, man> & operator=(sint value)
+ {
+ FromInt(value);
+
+ return *this;
+ }
+
+
+ /*!
+ an operator= for converting 'uint' to this class
+ */
+ Big<exp, man> & operator=(uint value)
+ {
+ FromUInt(value);
+
+ return *this;
+ }
+
+
+ /*!
+ an operator= for converting 'float' to this class
+ */
+ Big<exp, man> & operator=(float value)
+ {
+ FromFloat(value);
+
+ return *this;
+ }
+
+
+ /*!
+ an operator= for converting 'double' to this class
+ */
+ Big<exp, man> & operator=(double value)
+ {
+ FromDouble(value);
+
+ return *this;
+ }
+
+
+ /*!
+ a constructor for converting 'sint' to this class
+ */
+ Big(sint value)
+ {
+ FromInt(value);
+ }
+
+ /*!
+ a constructor for converting 'uint' to this class
+ */
+ Big(uint value)
+ {
+ FromUInt(value);
+ }
+
+
+ /*!
+ a constructor for converting 'double' to this class
+ */
+ Big(double value)
+ {
+ FromDouble(value);
+ }
+
+
+ /*!
+ a constructor for converting 'float' to this class
+ */
+ Big(float value)
+ {
+ FromFloat(value);
+ }
- S EEEEEEEEEEE FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
- 0 1 11 12 63
- The value V represented by the word may be determined as follows:
+#ifdef TTMATH_PLATFORM32
- * If E=2047 and F is nonzero, then V=NaN ("Not a number")
- * If E=2047 and F is zero and S is 1, then V=-Infinity
- * If E=2047 and F is zero and S is 0, then V=Infinity
- * If 0<E<2047 then V=(-1)**S * 2 ** (E-1023) * (1.F) where "1.F" is intended
- to represent the binary number created by prefixing F with an implicit
- leading 1 and a binary point.
- * If E=0 and F is nonzero, then V=(-1)**S * 2 ** (-1022) * (0.F) These are
- "unnormalized" values.
- * If E=0 and F is zero and S is 1, then V=-0
- * If E=0 and F is zero and S is 0, then V=0
- */
+ /*!
+ this method converts 'this' into 'result' (64 bit unsigned integer)
+ if the value is too big this method returns a carry (1)
+ */
+ uint ToUInt(ulint & result) const
+ {
+ UInt<2> temp; // 64 bits container
+
+ uint c = ToUInt(temp);
+ temp.ToUInt(result);
+
+ return c;
+ }
+
+
+ /*!
+ this method converts 'this' into 'result' (64 bit unsigned integer)
+ if the value is too big this method returns a carry (1)
+ */
+ uint ToInt(ulint & result) const
+ {
+ return ToUInt(result);
+ }
+
+
+ /*!
+ this method converts 'this' into 'result' (64 bit unsigned integer)
+ if the value is too big this method returns a carry (1)
+ */
+ uint ToInt(slint & result) const
+ {
+ Int<2> temp; // 64 bits container
+
+ uint c = ToInt(temp);
+ temp.ToInt(result);
+
+ return c;
+ }
+
+
+ /*!
+ a method for converting 'ulint' (64bit unsigned integer) to this class
+ */
+ uint FromUInt(ulint value)
+ {
+ if( value == 0 )
+ {
+ SetZero();
+ return 0;
+ }
+
+ info = 0;
+
+ if( man == 1 )
+ {
+ sint bit = mantissa.FindLeadingBitInWord(uint(value >> TTMATH_BITS_PER_UINT));
+
+ if( bit != -1 )
+ {
+ // the highest word from value is different from zero
+ bit += 1;
+ value >>= bit;
+ exponent = bit;
+ }
+ else
+ {
+ exponent.SetZero();
+ }
+
+ mantissa.table[0] = uint(value);
+ }
+ else
+ {
+ #ifdef _MSC_VER
+ //warning C4307: '*' : integral constant overflow
+ #pragma warning( disable: 4307 )
+ #endif
+
+ // man >= 2
+ mantissa.table[man-1] = uint(value >> TTMATH_BITS_PER_UINT);
+ mantissa.table[man-2] = uint(value);
+
+ #ifdef _MSC_VER
+ //warning C4307: '*' : integral constant overflow
+ #pragma warning( default: 4307 )
+ #endif
+
+ exponent = -sint(man-2) * sint(TTMATH_BITS_PER_UINT);
+
+ for(uint i=0 ; i<man-2 ; ++i)
+ mantissa.table[i] = 0;
+ }
+
+ // there shouldn't be a carry because 'value' has the 'ulint' type
+ // (we have sufficient exponent)
+ Standardizing();
+
+ return 0;
+ }
+
+
+ /*!
+ a method for converting 'ulint' (64bit unsigned integer) to this class
+ */
+ uint FromInt(ulint value)
+ {
+ return FromUInt(value);
+ }
+
+
+ /*!
+ a method for converting 'slint' (64bit signed integer) to this class
+ */
+ uint FromInt(slint value)
+ {
+ bool is_sign = false;
+
+ if( value < 0 )
+ {
+ value = -value;
+ is_sign = true;
+ }
+
+ FromUInt(ulint(value));
+
+ if( is_sign )
+ SetSign();
+
+ return 0;
+ }
+
+
+ /*!
+ a constructor for converting 'ulint' (64bit unsigned integer) to this class
+ */
+ Big(ulint value)
+ {
+ FromUInt(value);
+ }
+
+
+ /*!
+ an operator for converting 'ulint' (64bit unsigned integer) to this class
+ */
+ Big<exp, man> & operator=(ulint value)
+ {
+ FromUInt(value);
+
+ return *this;
+ }
+
+
+ /*!
+ a constructor for converting 'slint' (64bit signed integer) to this class
+ */
+ Big(slint value)
+ {
+ FromInt(value);
+ }
+
+
+ /*!
+ an operator for converting 'slint' (64bit signed integer) to this class
+ */
+ Big<exp, man> & operator=(slint value)
+ {
+ FromInt(value);
-#ifdef TTMATH_PLATFORM32
+ return *this;
+ }
- void FromDouble(double value)
- {
- // sizeof(double) should be 8 (64 bits), this is actually not a runtime
- // error but I leave it at the moment as is
- TTMATH_ASSERT( sizeof(double) == 8 )
-
- // I am not sure what will be on a platform which has
- // a different endianness... but we use this library only
- // on x86 and amd (intel) 64 bits (as there's a lot of assembler code)
- union
- {
- double d;
- uint u[2]; // two 32bit words
- } temp;
-
- temp.d = value;
-
- sint e = ( temp.u[1] & 0x7FF00000u) >> 20;
- uint m1 = ((temp.u[1] & 0xFFFFFu) << 11) | (temp.u[0] >> 21);
- uint m2 = temp.u[0] << 11;
-
- if( e == 2047 )
- {
- // If E=2047 and F is nonzero, then V=NaN ("Not a number")
- // If E=2047 and F is zero and S is 1, then V=-Infinity
- // If E=2047 and F is zero and S is 0, then V=Infinity
-
- // we do not support -Infinity and +Infinity
- // we assume that there is always NaN
-
- SetNan();
- }
- else
- if( e > 0 )
- {
- // If 0<E<2047 then
- // V=(-1)**S * 2 ** (E-1023) * (1.F)
- // where "1.F" is intended to represent the binary number
- // created by prefixing F with an implicit leading 1 and a binary point.
-
- FromDouble_SetExpAndMan((temp.u[1] & 0x80000000u) != 0,
- e - 1023 - man*TTMATH_BITS_PER_UINT + 1, 0x80000000u,
- m1, m2);
-
- // we do not have to call Standardizing() here
- // because the mantissa will have the highest bit set
- }
- else
- {
- // e == 0
-
- if( m1 != 0 || m2 != 0 )
- {
- // If E=0 and F is nonzero,
- // then V=(-1)**S * 2 ** (-1022) * (0.F)
- // These are "unnormalized" values.
-
- UInt<2> m;
- m.table[1] = m1;
- m.table[0] = m2;
- uint moved = m.CompensationToLeft();
-
- FromDouble_SetExpAndMan((temp.u[1] & 0x80000000u) != 0,
- e - 1022 - man*TTMATH_BITS_PER_UINT + 1 - moved, 0,
- m.table[1], m.table[2]);
- }
- else
- {
- // If E=0 and F is zero and S is 1, then V=-0
- // If E=0 and F is zero and S is 0, then V=0
-
- // we do not support -0 or 0, only is one 0
- SetZero();
- }
- }
- }
+#endif
-private:
- void FromDouble_SetExpAndMan(bool is_sign, int e, uint mhighest, uint m1, uint m2)
- {
- exponent = e;
-
- if( man > 1 )
- {
- mantissa.table[man-1] = m1 | mhighest;
- mantissa.table[sint(man-2)] = m2;
- // although man>1 we're using casting into sint
- // to get rid from a warning which generates Microsoft Visual:
- // warning C4307: '*' : integral constant overflow
-
- for(uint i=0 ; i<man-2 ; ++i)
- mantissa.table[i] = 0;
- }
- else
- {
- mantissa.table[0] = m1 | mhighest;
- }
-
- info = 0;
-
- // the value should be different from zero
- TTMATH_ASSERT( mantissa.IsZero() == false )
-
- if( is_sign )
- SetSign();
- }
+#ifdef TTMATH_PLATFORM64
-#else
+ /*!
+ this method converts 'this' into 'result' (32 bit unsigned integer)
+ ***this method is created only on a 64bit platform***
+ if the value is too big this method returns a carry (1)
+ */
+ uint ToUInt(unsigned int & result) const
+ {
+ uint result_uint;
+
+ uint c = ToUInt(result_uint);
+ result = (unsigned int)result_uint;
+
+ if( c || result_uint != uint(result) )
+ return 1;
+
+ return 0;
+ }
+
+
+ /*!
+ this method converts 'this' into 'result' (32 bit unsigned integer)
+ ***this method is created only on a 64bit platform***
+ if the value is too big this method returns a carry (1)
+ */
+ uint ToInt(unsigned int & result) const
+ {
+ return ToUInt(result);
+ }
+
+
+ /*!
+ this method converts 'this' into 'result' (32 bit signed integer)
+ ***this method is created only on a 64bit platform***
+ if the value is too big this method returns a carry (1)
+ */
+ uint ToInt(signed int & result) const
+ {
+ sint result_sint;
+
+ uint c = ToInt(result_sint);
+ result = (signed int)result_sint;
+
+ if( c || result_sint != sint(result) )
+ return 1;
+
+ return 0;
+ }
+
+
+ /*
+ this method converts 32 bit unsigned int to this class
+ ***this method is created only on a 64bit platform***
+ */
+ uint FromUInt(unsigned int value)
+ {
+ return FromUInt(uint(value));
+ }
+
+
+ /*
+ this method converts 32 bit unsigned int to this class
+ ***this method is created only on a 64bit platform***
+ */
+ uint FromInt(unsigned int value)
+ {
+ return FromUInt(uint(value));
+ }
+
+
+ /*
+ this method converts 32 bit signed int to this class
+ ***this method is created only on a 64bit platform***
+ */
+ uint FromInt(signed int value)
+ {
+ return FromInt(sint(value));
+ }
+
+
+ /*!
+ an operator= for converting 32 bit unsigned int to this class
+ ***this operator is created only on a 64bit platform***
+ */
+ Big<exp, man> & operator=(unsigned int value)
+ {
+ FromUInt(value);
+
+ return *this;
+ }
+
+
+ /*!
+ a constructor for converting 32 bit unsigned int to this class
+ ***this constructor is created only on a 64bit platform***
+ */
+ Big(unsigned int value)
+ {
+ FromUInt(value);
+ }
+
+
+ /*!
+ an operator for converting 32 bit signed int to this class
+ ***this operator is created only on a 64bit platform***
+ */
+ Big<exp, man> & operator=(signed int value)
+ {
+ FromInt(value);
+
+ return *this;
+ }
+
+
+ /*!
+ a constructor for converting 32 bit signed int to this class
+ ***this constructor is created only on a 64bit platform***
+ */
+ Big(signed int value)
+ {
+ FromInt(value);
+ }
-public:
+#endif
- // 64bit platforms
- void FromDouble(double value)
- {
- // sizeof(double) should be 8 (64 bits), this is actually not a runtime
- // error but I leave it at the moment as is
- TTMATH_ASSERT( sizeof(double) == 8 )
-
- // I am not sure what will be on a plaltform which has
- // a different endianness... but we use this library only
- // on x86 and amd (intel) 64 bits (as there's a lot of assembler code)
- union
- {
- double d;
- uint u; // one 64bit word
- } temp;
-
- temp.d = value;
-
- sint e = (temp.u & 0x7FF0000000000000ul) >> 52;
- uint m = (temp.u & 0xFFFFFFFFFFFFFul) << 11;
-
- if( e == 2047 )
- {
- // If E=2047 and F is nonzero, then V=NaN ("Not a number")
- // If E=2047 and F is zero and S is 1, then V=-Infinity
- // If E=2047 and F is zero and S is 0, then V=Infinity
-
- // we do not support -Infinity and +Infinity
- // we assume that there is always NaN
-
- SetNan();
- }
- else
- if( e > 0 )
- {
- // If 0<E<2047 then
- // V=(-1)**S * 2 ** (E-1023) * (1.F)
- // where "1.F" is intended to represent the binary number
- // created by prefixing F with an implicit leading 1 and a binary point.
-
- FromDouble_SetExpAndMan((temp.u & 0x8000000000000000ul) != 0,
- e - 1023 - man*TTMATH_BITS_PER_UINT + 1,
- 0x8000000000000000ul, m);
-
- // we do not have to call Standardizing() here
- // because the mantissa will have the highest bit set
- }
- else
- {
- // e == 0
-
- if( m != 0 )
- {
- // If E=0 and F is nonzero,
- // then V=(-1)**S * 2 ** (-1022) * (0.F)
- // These are "unnormalized" values.
-
- FromDouble_SetExpAndMan(bool(temp.u & 0x8000000000000000ul),
- e - 1022 - man*TTMATH_BITS_PER_UINT + 1, 0, m);
- Standardizing();
- }
- else
- {
- // If E=0 and F is zero and S is 1, then V=-0
- // If E=0 and F is zero and S is 0, then V=0
-
- // we do not support -0 or 0, only is one 0
- SetZero();
- }
- }
- }
private:
- void FromDouble_SetExpAndMan(bool is_sign, sint e, uint mhighest, uint m)
- {
- exponent = e;
- mantissa.table[man-1] = m | mhighest;
-
- for(uint i=0 ; i<man-1 ; ++i)
- mantissa.table[i] = 0;
-
- info = 0;
-
- // the value should be different from zero
- TTMATH_ASSERT( mantissa.IsZero() == false )
-
- if( is_sign )
- SetSign();
- }
+ /*!
+ an auxiliary method for converting from UInt and Int
-#endif
+ we assume that there'll never be a carry here
+ (we have an exponent and the value in Big can be bigger than
+ that one from the UInt)
+ */
+ template<uint int_size>
+ uint FromUIntOrInt(const UInt<int_size> & value, sint compensation)
+ {
+ uint minimum_size = (int_size < man)? int_size : man;
+ exponent = (sint(int_size)-sint(man)) * sint(TTMATH_BITS_PER_UINT) - compensation;
+
+ // copying the highest words
+ uint i;
+ for(i=1 ; i<=minimum_size ; ++i)
+ mantissa.table[man-i] = value.table[int_size-i];
+
+ // setting the rest of mantissa.table into zero (if some has left)
+ for( ; i<=man ; ++i)
+ mantissa.table[man-i] = 0;
+
+ // the highest bit is either one or zero (when the whole mantissa is zero)
+ // we can only call CorrectZero()
+ CorrectZero();
+
+ return 0;
+ }
public:
+ /*!
+ a method for converting from 'UInt<int_size>' to this class
+ */
+ template<uint int_size>
+ uint FromUInt(UInt<int_size> value)
+ {
+ info = 0;
+ sint compensation = (sint)value.CompensationToLeft();
+
+ return FromUIntOrInt(value, compensation);
+ }
+
+
+ /*!
+ a method for converting from 'UInt<int_size>' to this class
+ */
+ template<uint int_size>
+ uint FromInt(const UInt<int_size> & value)
+ {
+ return FromUInt(value);
+ }
+
+
+ /*!
+ a method for converting from 'Int<int_size>' to this class
+ */
+ template<uint int_size>
+ uint FromInt(Int<int_size> value)
+ {
+ info = 0;
+ bool is_sign = false;
+
+ if( value.IsSign() )
+ {
+ value.ChangeSign();
+ is_sign = true;
+ }
+
+ sint compensation = (sint)value.CompensationToLeft();
+ FromUIntOrInt(value, compensation);
+
+ if( is_sign )
+ SetSign();
+
+ return 0;
+ }
+
+
+ /*!
+ an operator= for converting from 'Int<int_size>' to this class
+ */
+ template<uint int_size>
+ Big<exp,man> & operator=(const Int<int_size> & value)
+ {
+ FromInt(value);
+
+ return *this;
+ }
+
+
+ /*!
+ a constructor for converting from 'Int<int_size>' to this class
+ */
+ template<uint int_size>
+ Big(const Int<int_size> & value)
+ {
+ FromInt(value);
+ }
+
+
+ /*!
+ an operator= for converting from 'UInt<int_size>' to this class
+ */
+ template<uint int_size>
+ Big<exp,man> & operator=(const UInt<int_size> & value)
+ {
+ FromUInt(value);
+
+ return *this;
+ }
+
+
+ /*!
+ a constructor for converting from 'UInt<int_size>' to this class
+ */
+ template<uint int_size>
+ Big(const UInt<int_size> & value)
+ {
+ FromUInt(value);
+ }
+
+
+ /*!
+ an operator= for converting from 'Big<another_exp, another_man>' to this class
+ */
+ template<uint another_exp, uint another_man>
+ Big<exp,man> & operator=(const Big<another_exp, another_man> & value)
+ {
+ FromBig(value);
+
+ return *this;
+ }
+
+
+ /*!
+ a constructor for converting from 'Big<another_exp, another_man>' to this class
+ */
+ template<uint another_exp, uint another_man>
+ Big(const Big<another_exp, another_man> & value)
+ {
+ FromBig(value);
+ }
+
+
+ /*!
+ a default constructor
+
+ by default we don't set any of the members to zero
+ only NaN flag is set
+
+ if you want the mantissa and exponent to be set to zero
+ define TTMATH_BIG_DEFAULT_CLEAR macro
+ (useful for debug purposes)
+ */
+ Big()
+ {
+ #ifdef TTMATH_BIG_DEFAULT_CLEAR
+
+ SetZeroNan();
+
+ #else
+
+ info = TTMATH_BIG_NAN;
+ // we're directly setting 'info' (instead of calling SetNan())
+ // in order to get rid of a warning saying that 'info' is uninitialized
+
+ #endif
+ }
+
+
+ /*!
+ a destructor
+ */
+ ~Big()
+ {
+ }
+
+
+ /*!
+ the default assignment operator
+ */
+ Big<exp,man> & operator=(const Big<exp,man> & value)
+ {
+ info = value.info;
+ exponent = value.exponent;
+ mantissa = value.mantissa;
+
+ return *this;
+ }
+
+
+ /*!
+ a constructor for copying from another object of this class
+ */
+
+ Big(const Big<exp,man> & value)
+ {
+ operator=(value);
+ }
+
+
+
+ /*!
+ a method for converting into a string
+ struct Conv is defined in ttmathtypes.h, look there for more information about parameters
+
+ output:
+ return value:
+ 0 - ok and 'result' will be an object of type std::string (or std::wstring) which holds the value
+ 1 - if there is a carry (it shoudn't be in a normal situation - if it is that means there
+ is somewhere an error in the library)
+ */
+ uint ToString( std::string & result,
+ uint base = 10,
+ bool scient = false,
+ sint scient_from = 15,
+ sint round = -1,
+ bool trim_zeroes = true,
+ char comma = '.' ) const
+ {
+ Conv conv;
+
+ conv.base = base;
+ conv.scient = scient;
+ conv.scient_from = scient_from;
+ conv.round = round;
+ conv.trim_zeroes = trim_zeroes;
+ conv.comma = static_cast<uint>(comma);
+
+ return ToStringBase<std::string, char>(result, conv);
+ }
+
+
+ /*!
+ a method for converting into a string
+ struct Conv is defined in ttmathtypes.h, look there for more information about parameters
+ */
+ uint ToString(std::string & result, const Conv & conv) const
+ {
+ return ToStringBase<std::string, char>(result, conv);
+ }
+
+
+ /*!
+ a method for converting into a string
+ struct Conv is defined in ttmathtypes.h, look there for more information about parameters
+ */
+ std::string ToString(const Conv & conv) const
+ {
+ std::string result;
+ ToStringBase<std::string, char>(result, conv);
+
+ return result;
+ }
+
+
+ /*!
+ a method for converting into a string
+ struct Conv is defined in ttmathtypes.h, look there for more information about parameters
+ */
+ std::string ToString(uint base = 10) const
+ {
+ Conv conv;
+ conv.base = base;
+
+ return ToString(conv);
+ }
+
+
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
+
+ /*!
+ a method for converting into a string
+ struct Conv is defined in ttmathtypes.h, look there for more information about parameters
+ */
+ uint ToString( std::wstring & result,
+ uint base = 10,
+ bool scient = false,
+ sint scient_from = 15,
+ sint round = -1,
+ bool trim_zeroes = true,
+ wchar_t comma = '.' ) const
+ {
+ Conv conv;
+
+ conv.base = base;
+ conv.scient = scient;
+ conv.scient_from = scient_from;
+ conv.round = round;
+ conv.trim_zeroes = trim_zeroes;
+ conv.comma = static_cast<uint>(comma);
+
+ return ToStringBase<std::wstring, wchar_t>(result, conv);
+ }
+
+
+ /*!
+ a method for converting into a string
+ struct Conv is defined in ttmathtypes.h, look there for more information about parameters
+ */
+ uint ToString(std::wstring & result, const Conv & conv) const
+ {
+ return ToStringBase<std::wstring, wchar_t>(result, conv);
+ }
+
+
+ /*!
+ a method for converting into a string
+ struct Conv is defined in ttmathtypes.h, look there for more information about parameters
+ */
+ std::wstring ToWString(const Conv & conv) const
+ {
+ std::wstring result;
+ ToStringBase<std::wstring, wchar_t>(result, conv);
+
+ return result;
+ }
+
+
+ /*!
+ a method for converting into a string
+ struct Conv is defined in ttmathtypes.h, look there for more information about parameters
+ */
+ std::wstring ToWString(uint base = 10) const
+ {
+ Conv conv;
+ conv.base = base;
+ return ToWString(conv);
+ }
- /*!
- this method converts from this class into the 'double'
+#endif
- if the value is too big:
- 'result' will be +/-infinity (depending on the sign)
- and the method returns 1
- if the value is too small:
- 'result' will be 0
- and the method returns 1
- */
- uint ToDouble(double & result) const
- {
- // sizeof(double) should be 8 (64 bits), this is actually not a runtime
- // error but I leave it at the moment as is
- TTMATH_ASSERT( sizeof(double) == 8 )
-
- if( IsZero() )
- {
- result = 0.0;
- return 0;
- }
-
- if( IsNan() )
- {
- result = ToDouble_SetDouble( false, 2047, 0, false, true);
-
- return 0;
- }
-
- sint e_correction = sint(man*TTMATH_BITS_PER_UINT) - 1;
-
- if( exponent >= 1024 - e_correction )
- {
- // +/- infinity
- result = ToDouble_SetDouble( 0, 2047, 0, true);
-
- return 1;
- }
- else
- if( exponent <= -1023 - 52 - e_correction )
- {
- // too small value - we assume that there'll be a zero
- result = 0;
-
- // and return a carry
- return 1;
- }
-
- sint e = exponent.ToInt() + e_correction;
-
- if( e <= -1023 )
- {
- // -1023-52 < e <= -1023 (unnormalized value)
- result = ToDouble_SetDouble( IsSign(), 0, -(e + 1023));
- }
- else
- {
- // -1023 < e < 1024
- result = ToDouble_SetDouble( IsSign(), e + 1023, -1);
- }
- return 0;
- }
private:
-#ifdef TTMATH_PLATFORM32
-
- // 32bit platforms
- double ToDouble_SetDouble(bool is_sign, uint e, sint move, bool infinity = false, bool nan = false) const
- {
- union
- {
- double d;
- uint u[2]; // two 32bit words
- } temp;
-
- temp.u[0] = temp.u[1] = 0;
-
- if( is_sign )
- temp.u[1] |= 0x80000000u;
-
- temp.u[1] |= (e << 20) & 0x7FF00000u;
-
- if( nan )
- {
- temp.u[0] |= 1;
- return temp.d;
- }
-
- if( infinity )
- return temp.d;
-
- UInt<2> m;
- m.table[1] = mantissa.table[man-1];
- m.table[0] = ( man > 1 ) ? mantissa.table[sint(man-2)] : 0;
- // although man>1 we're using casting into sint
- // to get rid from a warning which generates Microsoft Visual:
- // warning C4307: '*' : integral constant overflow
- m.Rcr( 12 + move );
- m.table[1] &= 0xFFFFFu; // cutting the 20 bit (when 'move' was -1)
+ /*!
+ an auxiliary method for converting into the string
+ */
+ template<class string_type, class char_type>
+ uint ToStringBase(string_type & result, const Conv & conv) const
+ {
+ static char error_overflow_msg[] = "overflow";
+ static char error_nan_msg[] = "NaN";
+ result.erase();
+
+ if( IsNan() )
+ {
+ Misc::AssignString(result, error_nan_msg);
+ return 0;
+ }
+
+ if( conv.base<2 || conv.base>16 )
+ {
+ Misc::AssignString(result, error_overflow_msg);
+ return 1;
+ }
+
+ if( IsZero() )
+ {
+ result = '0';
+
+ return 0;
+ }
+
+ /*
+ since 'base' is greater or equal 2 that 'new_exp' of type 'Int<exp>' should
+ hold the new value of exponent but we're using 'Int<exp+1>' because
+ if the value for example would be 'max()' then we couldn't show it
+
+ max() -> 11111111 * 2 ^ 11111111111 (bin)(the mantissa and exponent have all bits set)
+ if we were using 'Int<exp>' we couldn't show it in this format:
+ 1,1111111 * 2 ^ 11111111111 (bin)
+ because we have to add something to the mantissa and because
+ mantissa is full we can't do it and it'll be a carry
+ (look at ToString_SetCommaAndExponent(...))
+
+ when the base would be greater than two (for example 10)
+ we could use 'Int<exp>' here
+ */
+ Int<exp+1> new_exp;
+
+ if( ToString_CreateNewMantissaAndExponent<string_type, char_type>(result, conv, new_exp) )
+ {
+ Misc::AssignString(result, error_overflow_msg);
+ return 1;
+ }
+
+
+ if( ToString_SetCommaAndExponent<string_type, char_type>(result, conv, new_exp) )
+ {
+ Misc::AssignString(result, error_overflow_msg);
+ return 1;
+ }
+
+ if( IsSign() )
+ result.insert(result.begin(), '-');
+
+
+ // converted successfully
+ return 0;
+ }
+
+
+
+ /*!
+ in the method 'ToString_CreateNewMantissaAndExponent()' we're using
+ type 'Big<exp+1,man>' and we should have the ability to use some
+ necessary methods from that class (methods which are private here)
+ */
+ friend class Big<exp-1,man>;
+
+
+ /*!
+ an auxiliary method for converting into the string
+
+ input:
+ base - the base in range <2,16>
+
+ output:
+ return values:
+ 0 - ok
+ 1 - if there was a carry
+ new_man - the new mantissa for 'base'
+ new_exp - the new exponent for 'base'
+
+ mathematic part:
+
+ the value is stored as:
+ value = mantissa * 2^exponent
+ we want to show 'value' as:
+ value = new_man * base^new_exp
+
+ then 'new_man' we'll print using the standard method from UInt<> type for printing
+ and 'new_exp' is the offset of the comma operator in a system of a base 'base'
+
+ value = mantissa * 2^exponent
+ value = mantissa * 2^exponent * (base^new_exp / base^new_exp)
+ value = mantissa * (2^exponent / base^new_exp) * base^new_exp
+
+ look at the part (2^exponent / base^new_exp), there'll be good if we take
+ a 'new_exp' equal that value when the (2^exponent / base^new_exp) will be equal one
+
+ on account of the 'base' is not as power of 2 (can be from 2 to 16),
+ this formula will not be true for integer 'new_exp' then in our case we take
+ 'base^new_exp' _greater_ than '2^exponent'
+
+ if 'base^new_exp' were smaller than '2^exponent' the new mantissa could be
+ greater than the max value of the container UInt<man>
+
+ value = mantissa * (2^exponent / base^new_exp) * base^new_exp
+ let M = mantissa * (2^exponent / base^new_exp) then
+ value = M * base^new_exp
+
+ in our calculation we treat M as floating value showing it as:
+ M = mm * 2^ee where ee will be <= 0
+
+ next we'll move all bits of mm into the right when ee is equal zero
+ abs(ee) must not be too big that only few bits from mm we can leave
+
+ then we'll have:
+ M = mmm * 2^0
+ 'mmm' is the new_man which we're looking for
+
+
+ new_exp we calculate in this way:
+ 2^exponent <= base^new_exp
+ new_exp >= log base (2^exponent) <- logarithm with the base 'base' from (2^exponent)
+
+ but we need new_exp as integer then we test:
+ if new_exp is greater than zero and with fraction we add one to new_exp
+ new_exp = new_exp + 1 (if new_exp>0 and with fraction)
+ and at the end we take the integer part:
+ new_exp = int(new_exp)
+ */
+ template<class string_type, class char_type>
+ uint ToString_CreateNewMantissaAndExponent( string_type & new_man, const Conv & conv,
+ Int<exp+1> & new_exp) const
+ {
+ uint c = 0;
+
+ if( conv.base<2 || conv.base>16 )
+ return 1;
+
+ // special method for base equal 2
+ if( conv.base == 2 )
+ return ToString_CreateNewMantissaAndExponent_Base2(new_man, new_exp);
+
+ // special method for base equal 4
+ if( conv.base == 4 )
+ return ToString_CreateNewMantissaAndExponent_BasePow2(new_man, new_exp, 2);
+
+ // special method for base equal 8
+ if( conv.base == 8 )
+ return ToString_CreateNewMantissaAndExponent_BasePow2(new_man, new_exp, 3);
+
+ // special method for base equal 16
+ if( conv.base == 16 )
+ return ToString_CreateNewMantissaAndExponent_BasePow2(new_man, new_exp, 4);
+
+
+ // this = mantissa * 2^exponent
+
+ // temp = +1 * 2^exponent
+ // we're using a bigger type than 'big<exp,man>' (look below)
+ Big<exp+1,man> temp;
+ temp.info = 0;
+ temp.exponent = exponent;
+ temp.mantissa.SetOne();
+ c += temp.Standardizing();
+
+ // new_exp_ = log base (2^exponent)
+ // if new_exp_ is positive and with fraction then we add one
+ Big<exp+1,man> new_exp_;
+ c += new_exp_.ToString_Log(temp, conv.base); // this logarithm isn't very complicated
+
+ // rounding up to the nearest integer
+ if( !new_exp_.IsInteger() )
+ {
+ if( !new_exp_.IsSign() )
+ c += new_exp_.AddOne(); // new_exp_ > 0 and with fraction
+
+ new_exp_.SkipFraction();
+ }
+
+ if( ToString_CreateNewMantissaTryExponent<string_type, char_type>(new_man, conv, new_exp_, new_exp) )
+ {
+ // in very rare cases there can be an overflow from ToString_CreateNewMantissaTryExponent
+ // it means that new_exp_ was too small (the problem comes from floating point numbers precision)
+ // so we increse new_exp_ and try again
+ new_exp_.AddOne();
+ c += ToString_CreateNewMantissaTryExponent<string_type, char_type>(new_man, conv, new_exp_, new_exp);
+ }
+
+ return (c==0)? 0 : 1;
+ }
+
+
+
+ /*!
+ an auxiliary method for converting into the string
+
+ trying to calculate new_man for given exponent (new_exp_)
+ if there is a carry it can mean that new_exp_ is too small
+ */
+ template<class string_type, class char_type>
+ uint ToString_CreateNewMantissaTryExponent( string_type & new_man, const Conv & conv,
+ const Big<exp+1,man> & new_exp_, Int<exp+1> & new_exp) const
+ {
+ uint c = 0;
+
+ // because 'base^new_exp' is >= '2^exponent' then
+ // because base is >= 2 then we've got:
+ // 'new_exp_' must be smaller or equal 'new_exp'
+ // and we can pass it into the Int<exp> type
+ // (in fact we're using a greater type then it'll be ok)
+ c += new_exp_.ToInt(new_exp);
+
+ // base_ = base
+ Big<exp+1,man> base_(conv.base);
+
+ // base_ = base_ ^ new_exp_
+ c += base_.Pow( new_exp_ ); // use new_exp_ so Pow(Big<> &) version will be used
+ // if we hadn't used a bigger type than 'Big<exp,man>' then the result
+ // of this formula 'Pow(...)' would have been with an overflow
+
+ // temp = mantissa * 2^exponent / base_^new_exp_
+ Big<exp+1,man> temp;
+ temp.info = 0;
+ temp.mantissa = mantissa;
+ temp.exponent = exponent;
+ c += temp.Div(base_);
+
+ // moving all bits of the mantissa into the right
+ // (how many times to move depend on the exponent)
+ c += temp.ToString_MoveMantissaIntoRight();
+
+ // because we took 'new_exp' as small as it was
+ // possible ([log base (2^exponent)] + 1) that after the division
+ // (temp.Div( base_ )) the value of exponent should be equal zero or
+ // minimum smaller than zero then we've got the mantissa which has
+ // maximum valid bits
+ temp.mantissa.ToString(new_man, conv.base);
+
+ if( IsInteger() )
+ {
+ // making sure the new mantissa will be without fraction (integer)
+ ToString_CheckMantissaInteger<string_type, char_type>(new_man, new_exp);
+ }
+ else
+ if( conv.base_round )
+ {
+ c += ToString_BaseRound<string_type, char_type>(new_man, conv, new_exp);
+ }
+
+ return (c==0)? 0 : 1;
+ }
+
+
+ /*!
+ this method calculates the logarithm
+ it is used by ToString_CreateNewMantissaAndExponent() method
+
+ it's not too complicated
+ because x=+1*2^exponent (mantissa is one) then during the calculation
+ the Ln(x) will not be making the long formula from LnSurrounding1()
+ and only we have to calculate 'Ln(base)' but it'll be calculated
+ only once, the next time we will get it from the 'history'
- temp.u[1] |= m.table[1];
- temp.u[0] |= m.table[0];
+ x is greater than 0
+ base is in <2,16> range
+ */
+ uint ToString_Log(const Big<exp,man> & x, uint base)
+ {
+ TTMATH_REFERENCE_ASSERT( x )
+ TTMATH_ASSERT( base>=2 && base<=16 )
+
+ Big<exp,man> temp;
+ temp.SetOne();
+
+ if( x == temp )
+ {
+ // log(1) is 0
+ SetZero();
+
+ return 0;
+ }
+
+ // there can be only a carry
+ // because the 'x' is in '1+2*exponent' form then
+ // the long formula from LnSurrounding1() will not be calculated
+ // (LnSurrounding1() will return one immediately)
+ uint c = Ln(x);
+
+ if( base==10 && man<=TTMATH_BUILTIN_VARIABLES_SIZE )
+ {
+ // for the base equal 10 we're using SetLn10() instead of calculating it
+ // (only if we have the constant sufficient big)
+ temp.SetLn10();
+ }
+ else
+ {
+ c += ToString_LogBase(base, temp);
+ }
- return temp.d;
- }
+ c += Div( temp );
-#else
+ return (c==0)? 0 : 1;
+ }
- // 64bit platforms
- double ToDouble_SetDouble(bool is_sign, uint e, sint move, bool infinity = false, bool nan = false) const
- {
- union
- {
- double d;
- uint u; // 64bit word
- } temp;
-
- temp.u = 0;
-
- if( is_sign )
- temp.u |= 0x8000000000000000ul;
-
- temp.u |= (e << 52) & 0x7FF0000000000000ul;
-
- if( nan )
- {
- temp.u |= 1;
- return temp.d;
- }
-
- if( infinity )
- return temp.d;
-
- uint m = mantissa.table[man-1];
-
- m >>= ( 12 + move );
- m &= 0xFFFFFFFFFFFFFul; // cutting the 20 bit (when 'move' was -1)
- temp.u |= m;
- return temp.d;
- }
+#ifndef TTMATH_MULTITHREADS
-#endif
+ /*!
+ this method calculates the logarithm of 'base'
+ it's used in single thread environment
+ */
+ uint ToString_LogBase(uint base, Big<exp,man> & result)
+ {
+ TTMATH_ASSERT( base>=2 && base<=16 )
+
+ // this guardians are initialized before the program runs (static POD types)
+ static int guardians[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ static Big<exp,man> log_history[15];
+ uint index = base - 2;
+ uint c = 0;
+
+ if( guardians[index] == 0 )
+ {
+ Big<exp,man> base_(base);
+ c += log_history[index].Ln(base_);
+ guardians[index] = 1;
+ }
+ result = log_history[index];
-public:
+ return (c==0)? 0 : 1;
+ }
+#else
- /*!
- an operator= for converting 'sint' to this class
- */
- Big<exp, man> & operator=(sint value)
- {
- FromInt(value);
-
- return *this;
- }
-
-
- /*!
- an operator= for converting 'uint' to this class
- */
- Big<exp, man> & operator=(uint value)
- {
- FromUInt(value);
-
- return *this;
- }
-
-
- /*!
- an operator= for converting 'double' to this class
- */
- Big<exp, man> & operator=(double value)
- {
- FromDouble(value);
-
- return *this;
- }
-
-
- /*!
- a constructor for converting 'sint' to this class
- */
- Big(sint value)
- {
- FromInt(value);
- }
-
- /*!
- a constructor for converting 'uint' to this class
- */
- Big(uint value)
- {
- FromUInt(value);
- }
-
-
- /*!
- a constructor for converting 'double' to this class
- */
- Big(double value)
- {
- FromDouble(value);
- }
+ /*!
+ this method calculates the logarithm of 'base'
+ it's used in multi-thread environment
+ */
+ uint ToString_LogBase(uint base, Big<exp,man> & result)
+ {
+ TTMATH_ASSERT( base>=2 && base<=16 )
+
+ // this guardians are initialized before the program runs (static POD types)
+ volatile static sig_atomic_t guardians[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ static Big<exp,man> * plog_history;
+ uint index = base - 2;
+ uint c = 0;
+
+ // double-checked locking
+ if( guardians[index] == 0 )
+ {
+ ThreadLock thread_lock;
+
+ // locking
+ if( thread_lock.Lock() )
+ {
+ static Big<exp,man> log_history[15];
+
+ if( guardians[index] == 0 )
+ {
+ plog_history = log_history;
+
+ Big<exp,man> base_(base);
+ c += log_history[index].Ln(base_);
+ guardians[index] = 1;
+ }
+ }
+ else
+ {
+ // there was a problem with locking, we store the result directly in 'result' object
+ Big<exp,man> base_(base);
+ c += result.Ln(base_);
+
+ return (c==0)? 0 : 1;
+ }
+ // automatically unlocking
+ }
-#ifdef TTMATH_PLATFORM64
+ result = plog_history[index];
- /*!
- in 64bit platforms we must define additional operators and contructors
- in order to allow a user initializing the objects in this way:
- Big<...> type = 20;
- or
- Big<...> type;
- type = 30;
-
- decimal constants such as 20, 30 etc. are integer literal of type int,
- if the value is greater it can even be long int,
- 0 is an octal integer of type int
- (ISO 14882 p2.13.1 Integer literals)
- */
-
- /*!
- an operator= for converting 'signed int' to this class
- ***this operator is created only on a 64bit platform***
- it takes one argument of 32bit
-
-
- */
- Big<exp, man> & operator=(signed int value)
- {
- FromInt(sint(value));
-
- return *this;
- }
-
-
- /*!
- an operator= for converting 'unsigned int' to this class
- ***this operator is created only on a 64bit platform***
- it takes one argument of 32bit
- */
- Big<exp, man> & operator=(unsigned int value)
- {
- FromUInt(uint(value));
-
- return *this;
- }
-
-
- /*!
- a constructor for converting 'signed int' to this class
- ***this constructor is created only on a 64bit platform***
- it takes one argument of 32bit
- */
- Big(signed int value)
- {
- FromInt(sint(value));
- }
-
- /*!
- a constructor for converting 'unsigned int' to this class
- ***this constructor is created only on a 64bit platform***
- it takes one argument of 32bit
- */
- Big(unsigned int value)
- {
- FromUInt(uint(value));
- }
+ return (c==0)? 0 : 1;
+ }
#endif
-private:
+ /*!
+ an auxiliary method for converting into the string (private)
- /*!
- an auxiliary method for converting from UInt and Int
+ this method moving all bits from mantissa into the right side
+ the exponent tell us how many times moving (the exponent is <=0)
+ */
+ uint ToString_MoveMantissaIntoRight()
+ {
+ if( exponent.IsZero() )
+ return 0;
+
+ // exponent can't be greater than zero
+ // because we would cat the highest bits of the mantissa
+ if( !exponent.IsSign() )
+ return 1;
+
+
+ if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) )
+ // if 'exponent' is <= than '-sint(man*TTMATH_BITS_PER_UINT)'
+ // it means that we must cut the whole mantissa
+ // (there'll not be any of the valid bits)
+ return 1;
+
+ // e will be from (-man*TTMATH_BITS_PER_UINT, 0>
+ sint e = -( exponent.ToInt() );
+ mantissa.Rcr(e,0);
+
+ return 0;
+ }
+
+
+ /*!
+ a special method similar to the 'ToString_CreateNewMantissaAndExponent'
+ when the 'base' is equal 2
+
+ we use it because if base is equal 2 we don't have to make those
+ complicated calculations and the output is directly from the source
+ (there will not be any small distortions)
+ */
+ template<class string_type>
+ uint ToString_CreateNewMantissaAndExponent_Base2( string_type & new_man,
+ Int<exp+1> & new_exp ) const
+ {
+ for( sint i=man-1 ; i>=0 ; --i )
+ {
+ uint value = mantissa.table[i];
+
+ for( uint bit=0 ; bit<TTMATH_BITS_PER_UINT ; ++bit )
+ {
+ if( (value & TTMATH_UINT_HIGHEST_BIT) != 0 )
+ new_man += '1';
+ else
+ new_man += '0';
+
+ value <<= 1;
+ }
+ }
+
+ new_exp = exponent;
+
+ return 0;
+ }
+
+
+ /*!
+ a special method used to calculate the new mantissa and exponent
+ when the 'base' is equal 4, 8 or 16
+
+ when base is 4 then bits is 2
+ when base is 8 then bits is 3
+ when base is 16 then bits is 4
+ (and the algorithm can be used with a base greater than 16)
+ */
+ template<class string_type>
+ uint ToString_CreateNewMantissaAndExponent_BasePow2( string_type & new_man,
+ Int<exp+1> & new_exp,
+ uint bits) const
+ {
+ sint move; // how many times move the mantissa
+ UInt<man+1> man_temp(mantissa); // man+1 for moving
+ new_exp = exponent;
+ new_exp.DivInt((sint)bits, move);
+
+ if( move != 0 )
+ {
+ // we're moving the man_temp to left-hand side
+ if( move < 0 )
+ {
+ move = sint(bits) + move;
+ new_exp.SubOne(); // when move is < than 0 then new_exp is < 0 too
+ }
+
+ man_temp.Rcl(move);
+ }
+
+
+ if( bits == 3 )
+ {
+ // base 8
+ // now 'move' is greater than or equal 0
+ uint len = man*TTMATH_BITS_PER_UINT + move;
+ return ToString_CreateNewMantissaAndExponent_Base8(new_man, man_temp, len, bits);
+ }
+ else
+ {
+ // base 4 or 16
+ return ToString_CreateNewMantissaAndExponent_Base4or16(new_man, man_temp, bits);
+ }
+ }
+
+
+ /*!
+ a special method used to calculate the new mantissa
+ when the 'base' is equal 8
+
+ bits is always 3
+
+ we can use this algorithm when the base is 4 or 16 too
+ but we have a faster method ToString_CreateNewMantissaAndExponent_Base4or16()
+ */
+ template<class string_type>
+ uint ToString_CreateNewMantissaAndExponent_Base8( string_type & new_man,
+ UInt<man+1> & man_temp,
+ uint len,
+ uint bits) const
+ {
+ uint shift = TTMATH_BITS_PER_UINT - bits;
+ uint mask = TTMATH_UINT_MAX_VALUE >> shift;
+ uint i;
+
+ for( i=0 ; i<len ; i+=bits )
+ {
+ uint digit = man_temp.table[0] & mask;
+ new_man.insert(new_man.begin(), static_cast<char>(Misc::DigitToChar(digit)));
+
+ man_temp.Rcr(bits);
+ }
+
+ TTMATH_ASSERT( man_temp.IsZero() )
+
+ return 0;
+ }
+
+
+ /*!
+ a special method used to calculate the new mantissa
+ when the 'base' is equal 4 or 16
+
+ when the base is equal 4 or 16 the bits is 2 or 4
+ and because TTMATH_BITS_PER_UINT (32 or 64) is divisible by 2 (or 4)
+ then we can get digits from the end of our mantissa
+ */
+ template<class string_type>
+ uint ToString_CreateNewMantissaAndExponent_Base4or16( string_type & new_man,
+ UInt<man+1> & man_temp,
+ uint bits) const
+ {
+ TTMATH_ASSERT( TTMATH_BITS_PER_UINT % 2 == 0 )
+ TTMATH_ASSERT( TTMATH_BITS_PER_UINT % 4 == 0 )
+
+ uint shift = TTMATH_BITS_PER_UINT - bits;
+ uint mask = TTMATH_UINT_MAX_VALUE << shift;
+ uint digit;
+
+ // table[man] - last word - is different from zero if we moved man_temp
+ digit = man_temp.table[man];
+
+ if( digit != 0 )
+ new_man += static_cast<char>(Misc::DigitToChar(digit));
+
+
+ for( int i=man-1 ; i>=0 ; --i )
+ {
+ uint shift_local = shift;
+ uint mask_local = mask;
+
+ while( mask_local != 0 )
+ {
+ digit = man_temp.table[i] & mask_local;
+
+ if( shift_local != 0 )
+ digit = digit >> shift_local;
+
+ new_man += static_cast<char>(Misc::DigitToChar(digit));
+ mask_local = mask_local >> bits;
+ shift_local = shift_local - bits;
+ }
+ }
+
+ return 0;
+ }
+
+
+ /*!
+ an auxiliary method for converting into the string
+ */
+ template<class string_type, class char_type>
+ bool ToString_RoundMantissaWouldBeInteger(string_type & new_man, const Conv & conv, Int<exp+1> & new_exp) const
+ {
+ // if new_exp is greater or equal to zero then we have an integer value,
+ // if new_exp is equal -1 then we have only one digit after the comma
+ // and after rounding it would be an integer value
+ if( !new_exp.IsSign() || new_exp == -1 )
+ return true;
+
+ if( new_man.size() >= TTMATH_UINT_HIGHEST_BIT || new_man.size() < 2 )
+ return true; // oops, the mantissa is too large for calculating (or too small) - we are not doing the base rounding
+
+ uint i = 0;
+ char_type digit;
+
+ if( new_exp >= -sint(new_man.size()) )
+ {
+ uint new_exp_abs = -new_exp.ToInt();
+ i = new_man.size() - new_exp_abs; // start from the first digit after the comma operator
+ }
+
+ if( Misc::CharToDigit(new_man[new_man.size()-1]) >= conv.base/2 )
+ {
+ if( new_exp < -sint(new_man.size()) )
+ {
+ // there are some zeroes after the comma operator
+ // (between the comma and the first digit from the mantissa)
+ // and the result value will never be an integer
+ return false;
+ }
+
+ digit = static_cast<char_type>( Misc::DigitToChar(conv.base-1) );
+ }
+ else
+ {
+ digit = '0';
+ }
+
+ for( ; i < new_man.size()-1 ; ++i)
+ if( new_man[i] != digit )
+ return false; // it will not be an integer
+
+ return true; // it will be integer after rounding
+ }
+
+
+ /*!
+ an auxiliary method for converting into the string
+ (when this is integer)
+
+ after floating point calculating the new mantissa can consist of some fraction
+ so if our value is integer we should check the new mantissa
+ (after the decimal point there should be only zeroes)
+
+ often this is a last digit different from zero
+ ToString_BaseRound would not get rid of it because the method make a test against
+ an integer value (ToString_RoundMantissaWouldBeInteger) and returns immediately
+ */
+ template<class string_type, class char_type>
+ void ToString_CheckMantissaInteger(string_type & new_man, const Int<exp+1> & new_exp) const
+ {
+ if( !new_exp.IsSign() )
+ return; // return if new_exp >= 0
+
+ uint i = 0;
+ uint man_size = new_man.size();
+
+ if( man_size >= TTMATH_UINT_HIGHEST_BIT )
+ return; // ops, the mantissa is too long
+
+ sint sman_size = -sint(man_size);
+
+ if( new_exp >= sman_size )
+ {
+ sint e = new_exp.ToInt();
+ e = -e;
+ // now e means how many last digits from the mantissa should be equal zero
+
+ i = man_size - uint(e);
+ }
+
+ for( ; i<man_size ; ++i)
+ new_man[i] = '0';
+ }
+
+
+ /*!
+ an auxiliary method for converting into the string
+
+ this method is used for base!=2, base!=4, base!=8 and base!=16
+ we do the rounding when the value has fraction (is not an integer)
+ */
+ template<class string_type, class char_type>
+ uint ToString_BaseRound(string_type & new_man, const Conv & conv, Int<exp+1> & new_exp) const
+ {
+ // we must have minimum two characters
+ if( new_man.size() < 2 )
+ return 0;
+
+ // assert that there will not be an integer after rounding
+ if( ToString_RoundMantissaWouldBeInteger<string_type, char_type>(new_man, conv, new_exp) )
+ return 0;
+
+ typename string_type::size_type i = new_man.length() - 1;
+
+ // we're erasing the last character
+ uint digit = Misc::CharToDigit( new_man[i] );
+ new_man.erase(i, 1);
+ uint c = new_exp.AddOne();
+
+ // if the last character is greater or equal 'base/2'
+ // we are adding one into the new mantissa
+ if( digit >= conv.base / 2 )
+ ToString_RoundMantissa_AddOneIntoMantissa<string_type, char_type>(new_man, conv);
+
+ return c;
+ }
+
+
+ /*!
+ an auxiliary method for converting into the string
+
+ this method addes one into the new mantissa
+ */
+ template<class string_type, class char_type>
+ void ToString_RoundMantissa_AddOneIntoMantissa(string_type & new_man, const Conv & conv) const
+ {
+ if( new_man.empty() )
+ return;
+
+ sint i = sint( new_man.length() ) - 1;
+ bool was_carry = true;
+
+ for( ; i>=0 && was_carry ; --i )
+ {
+ // we can have the comma as well because
+ // we're using this method later in ToString_CorrectDigitsAfterComma_Round()
+ // (we're only ignoring it)
+ if( new_man[i] == static_cast<char_type>(conv.comma) )
+ continue;
+
+ // we're adding one
+ uint digit = Misc::CharToDigit( new_man[i] ) + 1;
+
+ if( digit == conv.base )
+ digit = 0;
+ else
+ was_carry = false;
+
+ new_man[i] = static_cast<char_type>( Misc::DigitToChar(digit) );
+ }
+
+ if( i<0 && was_carry )
+ new_man.insert( new_man.begin() , '1' );
+ }
+
+
+
+ /*!
+ an auxiliary method for converting into the string
+
+ this method sets the comma operator and/or puts the exponent
+ into the string
+ */
+ template<class string_type, class char_type>
+ uint ToString_SetCommaAndExponent(string_type & new_man, const Conv & conv, Int<exp+1> & new_exp) const
+ {
+ uint carry = 0;
+
+ if( new_man.empty() )
+ return carry;
+
+ Int<exp+1> scientific_exp( new_exp );
+
+ // 'new_exp' depends on the 'new_man' which is stored like this e.g:
+ // 32342343234 (the comma is at the end)
+ // we'd like to show it in this way:
+ // 3.2342343234 (the 'scientific_exp' is connected with this example)
+
+ sint offset = sint( new_man.length() ) - 1;
+ carry += scientific_exp.Add( offset );
+ // there shouldn't have been a carry because we're using
+ // a greater type -- 'Int<exp+1>' instead of 'Int<exp>'
+
+ bool print_scientific = conv.scient;
+
+ if( !print_scientific )
+ {
+ if( scientific_exp > conv.scient_from || scientific_exp < -sint(conv.scient_from) )
+ print_scientific = true;
+ }
+
+ if( !print_scientific )
+ ToString_SetCommaAndExponent_Normal<string_type, char_type>(new_man, conv, new_exp);
+ else
+ // we're passing the 'scientific_exp' instead of 'new_exp' here
+ ToString_SetCommaAndExponent_Scientific<string_type, char_type>(new_man, conv, scientific_exp);
+
+ return (carry==0)? 0 : 1;
+ }
+
+
+ /*!
+ an auxiliary method for converting into the string
+ */
+ template<class string_type, class char_type>
+ void ToString_SetCommaAndExponent_Normal(string_type & new_man, const Conv & conv, Int<exp+1> & new_exp ) const
+ {
+ if( !new_exp.IsSign() ) // it means: if( new_exp >= 0 )
+ ToString_SetCommaAndExponent_Normal_AddingZero<string_type, char_type>(new_man, new_exp);
+ else
+ ToString_SetCommaAndExponent_Normal_SetCommaInside<string_type, char_type>(new_man, conv, new_exp);
+
+
+ ToString_Group_man<string_type, char_type>(new_man, conv);
+ }
+
+
+ /*!
+ an auxiliary method for converting into the string
+ */
+ template<class string_type, class char_type>
+ void ToString_SetCommaAndExponent_Normal_AddingZero(string_type & new_man,
+ Int<exp+1> & new_exp) const
+ {
+ // we're adding zero characters at the end
+ // 'i' will be smaller than 'when_scientific' (or equal)
+ uint i = new_exp.ToInt();
+
+ if( new_man.length() + i > new_man.capacity() )
+ // about 6 characters more (we'll need it for the comma or something)
+ new_man.reserve( new_man.length() + i + 6 );
+
+ for( ; i>0 ; --i)
+ new_man += '0';
+ }
+
+
+ /*!
+ an auxiliary method for converting into the string
+ */
+ template<class string_type, class char_type>
+ void ToString_SetCommaAndExponent_Normal_SetCommaInside(
+ string_type & new_man,
+ const Conv & conv,
+ Int<exp+1> & new_exp ) const
+ {
+ // new_exp is < 0
+
+ sint new_man_len = sint(new_man.length()); // 'new_man_len' with a sign
+ sint e = -( new_exp.ToInt() ); // 'e' will be positive
+
+ if( new_exp > -new_man_len )
+ {
+ // we're setting the comma within the mantissa
+
+ sint index = new_man_len - e;
+ new_man.insert( new_man.begin() + index, static_cast<char_type>(conv.comma));
+ }
+ else
+ {
+ // we're adding zero characters before the mantissa
+
+ uint how_many = e - new_man_len;
+ string_type man_temp(how_many+1, '0');
+
+ man_temp.insert( man_temp.begin()+1, static_cast<char_type>(conv.comma));
+ new_man.insert(0, man_temp);
+ }
+
+ ToString_CorrectDigitsAfterComma<string_type, char_type>(new_man, conv);
+ }
+
+
+ /*!
+ an auxiliary method for converting into the string
+ */
+ template<class string_type, class char_type>
+ void ToString_SetCommaAndExponent_Scientific( string_type & new_man,
+ const Conv & conv,
+ Int<exp+1> & scientific_exp ) const
+ {
+ if( new_man.empty() )
+ return;
+
+ if( new_man.size() > 1 )
+ {
+ new_man.insert( new_man.begin()+1, static_cast<char_type>(conv.comma) );
+ ToString_CorrectDigitsAfterComma<string_type, char_type>(new_man, conv);
+ }
+
+ ToString_Group_man<string_type, char_type>(new_man, conv);
+
+ if( conv.base == 10 )
+ {
+ new_man += 'e';
+
+ if( !scientific_exp.IsSign() )
+ new_man += '+';
+ }
+ else
+ {
+ // the 10 here is meant as the base 'base'
+ // (no matter which 'base' we're using there'll always be 10 here)
+ Misc::AddString(new_man, "*10^");
+ }
+
+ string_type temp_exp;
+ scientific_exp.ToString( temp_exp, conv.base );
+
+ new_man += temp_exp;
+ }
+
+
+ /*!
+ an auxiliary method for converting into the string
+ */
+ template<class string_type, class char_type>
+ void ToString_Group_man(string_type & new_man, const Conv & conv) const
+ {
+ typedef typename string_type::size_type StrSize;
+
+ if( conv.group == 0 )
+ return;
+
+ // first we're looking for the comma operator
+ StrSize index = new_man.find(static_cast<char_type>(conv.comma), 0);
+
+ if( index == string_type::npos )
+ index = new_man.size();
+
+ ToString_Group_man_before_comma<string_type, char_type>(new_man, conv, index);
+ ToString_Group_man_after_comma<string_type, char_type>(new_man, conv, index+1);
+ }
+
+
+
+ /*!
+ an auxiliary method for converting into the string
+ */
+ template<class string_type, class char_type>
+ void ToString_Group_man_before_comma( string_type & new_man, const Conv & conv,
+ typename string_type::size_type & index) const
+ {
+ typedef typename string_type::size_type StrSize;
+
+ uint group = 0;
+ StrSize i = index;
+ uint group_digits = conv.group_digits;
+
+ if( group_digits < 1 )
+ group_digits = 1;
+
+ // adding group characters before the comma operator
+ // i>0 because on the first position we don't put any additional grouping characters
+ for( ; i>0 ; --i, ++group)
+ {
+ if( group >= group_digits )
+ {
+ group = 0;
+ new_man.insert(i, 1, static_cast<char_type>(conv.group));
+ ++index;
+ }
+ }
+ }
+
+
+ /*!
+ an auxiliary method for converting into the string
+ */
+ template<class string_type, class char_type>
+ void ToString_Group_man_after_comma(string_type & new_man, const Conv & conv,
+ typename string_type::size_type index) const
+ {
+ uint group = 0;
+ uint group_digits = conv.group_digits;
+
+ if( group_digits < 1 )
+ group_digits = 1;
+
+ for( ; index<new_man.size() ; ++index, ++group)
+ {
+ if( group >= group_digits )
+ {
+ group = 0;
+ new_man.insert(index, 1, static_cast<char_type>(conv.group));
+ ++index;
+ }
+ }
+ }
+
+
+ /*!
+ an auxiliary method for converting into the string
+ */
+ template<class string_type, class char_type>
+ void ToString_CorrectDigitsAfterComma( string_type & new_man,
+ const Conv & conv ) const
+ {
+ if( conv.round >= 0 )
+ ToString_CorrectDigitsAfterComma_Round<string_type, char_type>(new_man, conv);
+
+ if( conv.trim_zeroes )
+ ToString_CorrectDigitsAfterComma_CutOffZeroCharacters<string_type, char_type>(new_man, conv);
+ }
+
+
+ /*!
+ an auxiliary method for converting into the string
+ */
+ template<class string_type, class char_type>
+ void ToString_CorrectDigitsAfterComma_CutOffZeroCharacters(
+ string_type & new_man,
+ const Conv & conv) const
+ {
+ // minimum two characters
+ if( new_man.length() < 2 )
+ return;
+
+ // we're looking for the index of the last character which is not zero
+ uint i = uint( new_man.length() ) - 1;
+ for( ; i>0 && new_man[i]=='0' ; --i );
+
+ // if there is another character than zero at the end
+ // we're finishing
+ if( i == new_man.length() - 1 )
+ return;
+
+ // we must have a comma
+ // (the comma can be removed by ToString_CorrectDigitsAfterComma_Round
+ // which is called before)
+ if( new_man.find_last_of(static_cast<char_type>(conv.comma), i) == string_type::npos )
+ return;
+
+ // if directly before the first zero is the comma operator
+ // we're cutting it as well
+ if( i>0 && new_man[i]==static_cast<char_type>(conv.comma) )
+ --i;
+
+ new_man.erase(i+1, new_man.length()-i-1);
+ }
+
+
+ /*!
+ an auxiliary method for converting into the string
+ */
+ template<class string_type, class char_type>
+ void ToString_CorrectDigitsAfterComma_Round(
+ string_type & new_man,
+ const Conv & conv ) const
+ {
+ typedef typename string_type::size_type StrSize;
+
+ // first we're looking for the comma operator
+ StrSize index = new_man.find(static_cast<char_type>(conv.comma), 0);
+
+ if( index == string_type::npos )
+ // nothing was found (actually there can't be this situation)
+ return;
+
+ // we're calculating how many digits there are at the end (after the comma)
+ // 'after_comma' will be greater than zero because at the end
+ // we have at least one digit
+ StrSize after_comma = new_man.length() - index - 1;
+
+ // if 'max_digit_after_comma' is greater than 'after_comma' (or equal)
+ // we don't have anything for cutting
+ if( static_cast<StrSize>(conv.round) >= after_comma )
+ return;
+
+ uint last_digit = Misc::CharToDigit( new_man[ index + conv.round + 1 ], conv.base );
+
+ // we're cutting the rest of the string
+ new_man.erase(index + conv.round + 1, after_comma - conv.round);
+
+ if( conv.round == 0 )
+ {
+ // we're cutting the comma operator as well
+ // (it's not needed now because we've cut the whole rest after the comma)
+ new_man.erase(index, 1);
+ }
+
+ if( last_digit >= conv.base / 2 )
+ // we must round here
+ ToString_RoundMantissa_AddOneIntoMantissa<string_type, char_type>(new_man, conv);
+ }
- we assume that there'll never be a carry here
- (we have an exponent and the value in Big can be bigger than
- that one from the UInt)
- */
- template<uint int_size>
- void FromUIntOrInt(const UInt<int_size> & value, sint compensation)
- {
- uint minimum_size = (int_size < man)? int_size : man;
- exponent = (sint(int_size)-sint(man)) * sint(TTMATH_BITS_PER_UINT) - compensation;
-
- // copying the highest words
- uint i;
- for(i=1 ; i<=minimum_size ; ++i)
- mantissa.table[man-i] = value.table[int_size-i];
-
- // setting the rest of mantissa.table into zero (if some has left)
- for( ; i<=man ; ++i)
- mantissa.table[man-i] = 0;
-
- // the highest bit is either one or zero (when the whole mantissa is zero)
- // we can only call CorrectZero()
- CorrectZero();
- }
public:
+ /*!
+ a method for converting a string into its value
- /*!
- a method for converting from 'UInt<int_size>' to this class
- */
- template<uint int_size>
- void FromUInt(UInt<int_size> value)
- {
- info = 0;
- sint compensation = (sint)value.CompensationToLeft();
-
- return FromUIntOrInt(value, compensation);
- }
-
-
- /*!
- a method for converting from 'Int<int_size>' to this class
- */
- template<uint int_size>
- void FromInt(Int<int_size> value)
- {
- info = 0;
- bool is_sign = false;
-
- if( value.IsSign() )
- {
- value.ChangeSign();
- is_sign = true;
- }
-
- sint compensation = (sint)value.CompensationToLeft();
- FromUIntOrInt(value, compensation);
-
- if( is_sign )
- SetSign();
- }
-
-
- /*!
- an operator= for converting from 'Int<int_size>' to this class
- */
- template<uint int_size>
- Big<exp,man> & operator=(const Int<int_size> & value)
- {
- FromInt(value);
-
- return *this;
- }
-
-
- /*!
- a constructor for converting from 'Int<int_size>' to this class
- */
- template<uint int_size>
- Big(const Int<int_size> & value)
- {
- FromInt(value);
- }
-
-
- /*!
- an operator= for converting from 'UInt<int_size>' to this class
- */
- template<uint int_size>
- Big<exp,man> & operator=(const UInt<int_size> & value)
- {
- FromUInt(value);
-
- return *this;
- }
-
-
- /*!
- a constructor for converting from 'UInt<int_size>' to this class
- */
- template<uint int_size>
- Big(const UInt<int_size> & value)
- {
- FromUInt(value);
- }
-
-
- /*!
- an operator= for converting from 'Big<another_exp, another_man>' to this class
- */
- template<uint another_exp, uint another_man>
- Big<exp,man> & operator=(const Big<another_exp, another_man> & value)
- {
- FromBig(value);
-
- return *this;
- }
-
-
- /*!
- a constructor for converting from 'Big<another_exp, another_man>' to this class
- */
- template<uint another_exp, uint another_man>
- Big(const Big<another_exp, another_man> & value)
- {
- FromBig(value);
- }
-
-
- /*!
- a default constructor
-
- we don't set any of the members to zero
- only NaN flag is set
- */
- Big()
- {
- info = TTMATH_BIG_NAN;
-
- /*
- we're directly setting 'info' (instead of calling SetNan())
- in order to get rid of a warning saying that 'info' is uninitialized
- */
- }
-
-
- /*!
- a destructor
- */
- ~Big()
- {
- }
-
-
- /*!
- the default assignment operator
- */
- Big<exp,man> & operator=(const Big<exp,man> & value)
- {
- info = value.info;
- exponent = value.exponent;
- mantissa = value.mantissa;
-
- return *this;
- }
-
-
- /*!
- a constructor for copying from another object of this class
- */
-
- Big(const Big<exp,man> & value)
- {
- operator=(value);
- }
-
-
-
- /*!
- a method for converting into a string
- struct Conv is defined in ttmathtypes.h, look there for more information about parameters
-
- output:
- return value:
- 0 - ok and 'result' will be an object of type std::string (or std::wstring) which holds the value
- 1 - if there is a carry (it shoudn't be in a normal situation - if it is that means there
- is somewhere an error in the library)
- */
- uint ToString( std::string & result,
- uint base = 10,
- bool scient = false,
- sint scient_from = 15,
- sint round = -1,
- bool trim_zeroes = true,
- wchar_t comma = '.' ) const
- {
- Conv conv;
-
- conv.base = base;
- conv.scient = scient;
- conv.scient_from = scient_from;
- conv.round = round;
- conv.trim_zeroes = trim_zeroes;
- conv.comma = static_cast<uint>(comma);
-
- return ToStringBase<std::string, char>(result, conv);
- }
-
-
- /*!
- a method for converting into a string
- struct Conv is defined in ttmathtypes.h, look there for more information about parameters
- */
- uint ToString( std::wstring & result,
- uint base = 10,
- bool scient = false,
- sint scient_from = 15,
- sint round = -1,
- bool trim_zeroes = true,
- wchar_t comma = '.' ) const
- {
- Conv conv;
-
- conv.base = base;
- conv.scient = scient;
- conv.scient_from = scient_from;
- conv.round = round;
- conv.trim_zeroes = trim_zeroes;
- conv.comma = static_cast<uint>(comma);
-
- return ToStringBase<std::wstring, wchar_t>(result, conv);
- }
-
-
- /*!
- a method for converting into a string
- struct Conv is defined in ttmathtypes.h, look there for more information about parameters
- */
- uint ToString(std::string & result, const Conv & conv) const
- {
- return ToStringBase<std::string, char>(result, conv);
- }
-
-
- /*!
- a method for converting into a string
- struct Conv is defined in ttmathtypes.h, look there for more information about parameters
- */
- uint ToString(std::wstring & result, const Conv & conv) const
- {
- return ToStringBase<std::wstring, wchar_t>(result, conv);
- }
-
-
- /*!
- a method for converting into a string
- struct Conv is defined in ttmathtypes.h, look there for more information about parameters
- */
- std::string ToString(const Conv & conv) const
- {
- std::string result;
- ToStringBase<std::string, char>(result, conv);
-
- return result;
- }
-
-
- /*!
- a method for converting into a string
- struct Conv is defined in ttmathtypes.h, look there for more information about parameters
- */
- std::string ToString() const
- {
- Conv conv;
-
- return ToString(conv);
- }
-
-
- /*!
- a method for converting into a string
- struct Conv is defined in ttmathtypes.h, look there for more information about parameters
- */
- std::wstring ToWString(const Conv & conv) const
- {
- std::wstring result;
- ToStringBase<std::wstring, wchar_t>(result, conv);
-
- return result;
- }
-
-
- /*!
- a method for converting into a string
- struct Conv is defined in ttmathtypes.h, look there for more information about parameters
- */
- std::wstring ToWString() const
- {
- Conv conv;
+ it returns 1 if the value is too big -- we cannot pass it into the range
+ of our class Big<exp,man> (or if the base is incorrect)
- return ToWString(conv);
- }
+ that means only digits before the comma operator can make this value too big,
+ all digits after the comma we can ignore
+ 'source' - pointer to the string for parsing
+
+ if 'after_source' is set that when this method finishes
+ it sets the pointer to the new first character after parsed value
+
+ 'value_read' - if the pointer is provided that means the value_read will be true
+ only when a value has been actually read, there can be situation where only such
+ a string '-' or '+' will be parsed -- 'after_source' will be different from 'source' but
+ no value has been read (there are no digits)
+ on other words if 'value_read' is true -- there is at least one digit in the string
+ */
+ uint FromString(const char * source, uint base = 10, const char ** after_source = 0, bool * value_read = 0)
+ {
+ Conv conv;
+ conv.base = base;
+
+ return FromStringBase(source, conv, after_source, value_read);
+ }
+
+
+ /*!
+ a method for converting a string into its value
+ */
+ uint FromString(const char * source, const Conv & conv, const char ** after_source = 0, bool * value_read = 0)
+ {
+ return FromStringBase(source, conv, after_source, value_read);
+ }
+
+
+ /*!
+ a method for converting a string into its value
+ */
+ uint FromString(const std::string & string, uint base = 10, const char ** after_source = 0, bool * value_read = 0)
+ {
+ return FromString(string.c_str(), base, after_source, value_read);
+ }
+
+
+ /*!
+ a method for converting a string into its value
+ */
+ uint FromString(const std::string & string, const Conv & conv, const char ** after_source = 0, bool * value_read = 0)
+ {
+ return FromString(string.c_str(), conv, after_source, value_read);
+ }
+
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
+ /*!
+ a method for converting a string into its value
+ */
+ uint FromString(const wchar_t * source, uint base = 10, const wchar_t ** after_source = 0, bool * value_read = 0)
+ {
+ Conv conv;
+ conv.base = base;
+
+ return FromStringBase(source, conv, after_source, value_read);
+ }
+
+
+ /*!
+ a method for converting a string into its value
+ */
+ uint FromString(const wchar_t * source, const Conv & conv, const wchar_t ** after_source = 0, bool * value_read = 0)
+ {
+ return FromStringBase(source, conv, after_source, value_read);
+ }
+
+
+ /*!
+ a method for converting a string into its value
+ */
+ uint FromString(const std::wstring & string, uint base = 10, const wchar_t ** after_source = 0, bool * value_read = 0)
+ {
+ return FromString(string.c_str(), base, after_source, value_read);
+ }
+
+
+ /*!
+ a method for converting a string into its value
+ */
+ uint FromString(const std::wstring & string, const Conv & conv, const wchar_t ** after_source = 0, bool * value_read = 0)
+ {
+ return FromString(string.c_str(), conv, after_source, value_read);
+ }
-private:
-
+#endif
- /*!
- an auxiliary method for converting into the string
- */
- template<class string_type, class char_type>
- uint ToStringBase(string_type & result, const Conv & conv) const
- {
- static char error_overflow_msg[] = "overflow";
- static char error_nan_msg[] = "NaN";
- result.erase();
-
- if( IsNan() )
- {
- Misc::AssignString(result, error_nan_msg);
- return 0;
- }
-
- if( conv.base<2 || conv.base>16 )
- {
- Misc::AssignString(result, error_overflow_msg);
- return 1;
- }
-
- if( IsZero() )
- {
- result = '0';
-
- return 0;
- }
-
- /*
- since 'base' is greater or equal 2 that 'new_exp' of type 'Int<exp>' should
- hold the new value of exponent but we're using 'Int<exp+1>' because
- if the value for example would be 'max()' then we couldn't show it
-
- max() -> 11111111 * 2 ^ 11111111111 (bin)(the mantissa and exponent have all bits set)
- if we were using 'Int<exp>' we couldn't show it in this format:
- 1,1111111 * 2 ^ 11111111111 (bin)
- because we have to add something to the mantissa and because
- mantissa is full we can't do it and it'll be a carry
- (look at ToString_SetCommaAndExponent(...))
-
- when the base would be greater than two (for example 10)
- we could use 'Int<exp>' here
- */
- Int<exp+1> new_exp;
-
- if( ToString_CreateNewMantissaAndExponent<string_type, char_type>(result, conv, new_exp) )
- {
- Misc::AssignString(result, error_overflow_msg);
- return 1;
- }
-
-
- if( ToString_SetCommaAndExponent<string_type, char_type>(result, conv, new_exp) )
- {
- Misc::AssignString(result, error_overflow_msg);
- return 1;
- }
-
- if( IsSign() )
- result.insert(result.begin(), '-');
-
-
- // converted successfully
- return 0;
- }
-
-
-
- /*!
- in the method 'ToString_CreateNewMantissaAndExponent()' we're using
- type 'Big<exp+1,man>' and we should have the ability to use some
- necessary methods from that class (methods which are private here)
- */
- friend class Big<exp-1,man>;
-
-
- /*!
- an auxiliary method for converting into the string
-
- input:
- base - the base in range <2,16>
-
- output:
- return values:
- 0 - ok
- 1 - if there was a carry
- new_man - the new mantissa for 'base'
- new_exp - the new exponent for 'base'
-
- mathematic part:
-
- the value is stored as:
- value = mantissa * 2^exponent
- we want to show 'value' as:
- value = new_man * base^new_exp
-
- then 'new_man' we'll print using the standard method from UInt<> type for printing
- and 'new_exp' is the offset of the comma operator in a system of a base 'base'
-
- value = mantissa * 2^exponent
- value = mantissa * 2^exponent * (base^new_exp / base^new_exp)
- value = mantissa * (2^exponent / base^new_exp) * base^new_exp
-
- look at the part (2^exponent / base^new_exp), there'll be good if we take
- a 'new_exp' equal that value when the (2^exponent / base^new_exp) will be equal one
-
- on account of the 'base' is not as power of 2 (can be from 2 to 16),
- this formula will not be true for integer 'new_exp' then in our case we take
- 'base^new_exp' _greater_ than '2^exponent'
-
- if 'base^new_exp' were smaller than '2^exponent' the new mantissa could be
- greater than the max value of the container UInt<man>
-
- value = mantissa * (2^exponent / base^new_exp) * base^new_exp
- let M = mantissa * (2^exponent / base^new_exp) then
- value = M * base^new_exp
-
- in our calculation we treat M as floating value showing it as:
- M = mm * 2^ee where ee will be <= 0
-
- next we'll move all bits of mm into the right when ee is equal zero
- abs(ee) must not be too big that only few bits from mm we can leave
-
- then we'll have:
- M = mmm * 2^0
- 'mmm' is the new_man which we're looking for
-
-
- new_exp we calculate in this way:
- 2^exponent <= base^new_exp
- new_exp >= log base (2^exponent) <- logarithm with the base 'base' from (2^exponent)
-
- but we need new_exp as integer then we test:
- if new_exp is greater than zero and with fraction we add one to new_exp
- new_exp = new_exp + 1 (if new_exp>0 and with fraction)
- and at the end we take the integer part:
- new_exp = int(new_exp)
- */
- template<class string_type, class char_type>
- uint ToString_CreateNewMantissaAndExponent( string_type & new_man, const Conv & conv,
- Int<exp+1> & new_exp) const
- {
- uint c = 0;
-
- if( conv.base<2 || conv.base>16 )
- return 1;
-
- // the speciality for base equal 2
- if( conv.base == 2 )
- return ToString_CreateNewMantissaAndExponent_Base2(new_man, new_exp);
-
- // the speciality for base equal 4
- if( conv.base == 4 )
- return ToString_CreateNewMantissaAndExponent_BasePow2(new_man, new_exp, 2);
-
- // the speciality for base equal 8
- if( conv.base == 8 )
- return ToString_CreateNewMantissaAndExponent_BasePow2(new_man, new_exp, 3);
-
- // the speciality for base equal 16
- if( conv.base == 16 )
- return ToString_CreateNewMantissaAndExponent_BasePow2(new_man, new_exp, 4);
-
-
- // this = mantissa * 2^exponent
-
- // temp = +1 * 2^exponent
- // we're using a bigger type than 'big<exp,man>' (look below)
- Big<exp+1,man> temp;
- temp.info = 0;
- temp.exponent = exponent;
- temp.mantissa.SetOne();
- c += temp.Standardizing();
-
- // new_exp_ = log base (2^exponent)
- // if new_exp_ is positive and with fraction then we add one
- Big<exp+1,man> new_exp_;
- c += new_exp_.ToString_Log(temp, conv.base); // this logarithm isn't very complicated
-
- // adding some epsilon value (to get rid of some floating point errors)
- temp.Set05();
- temp.exponent.SubOne(); // temp = 0.5/2 = 0.25
- c += new_exp_.Add(temp);
-
- if( !new_exp_.IsSign() && !new_exp_.IsInteger() )
- {
- // new_exp_ > 0 and with fraction
- temp.SetOne();
- c += new_exp_.Add( temp );
- }
-
- // new_exp_ = int(new_exp_)
- new_exp_.SkipFraction();
-
-
- // because 'base^new_exp' is >= '2^exponent' then
- // because base is >= 2 then we've got:
- // 'new_exp_' must be smaller or equal 'new_exp'
- // and we can pass it into the Int<exp> type
- // (in fact we're using a greater type then it'll be ok)
- c += new_exp_.ToInt(new_exp);
-
- // base_ = base
- Big<exp+1,man> base_(conv.base);
-
- // base_ = base_ ^ new_exp_
- c += base_.Pow( new_exp_ );
- // if we hadn't used a bigger type than 'Big<exp,man>' then the result
- // of this formula 'Pow(...)' would have been with an overflow
-
- // temp = mantissa * 2^exponent / base_^new_exp_
- // the sign don't interest us here
- temp.mantissa = mantissa;
- temp.exponent = exponent;
- c += temp.Div(base_, false); // dividing without rounding
-
- // moving all bits of the mantissa into the right
- // (how many times to move depend on the exponent)
- c += temp.ToString_MoveMantissaIntoRight();
-
- // because we took 'new_exp' as small as it was
- // possible ([log base (2^exponent)] + 1) that after the division
- // (temp.Div( base_ )) the value of exponent should be equal zero or
- // minimum smaller than zero then we've got the mantissa which has
- // maximum valid bits
- temp.mantissa.ToString(new_man, conv.base);
-
- // base rounding
- if( conv.base_round )
- c += ToString_BaseRound<string_type, char_type>(new_man, conv, new_exp);
-
- return (c==0)? 0 : 1;
- }
-
-
- /*!
- this method calculates the logarithm
- it is used by ToString_CreateNewMantissaAndExponent() method
-
- it's not too complicated
- because x=+1*2^exponent (mantissa is one) then during the calculation
- the Ln(x) will not be making the long formula from LnSurrounding1()
- and only we have to calculate 'Ln(base)' but it'll be calculated
- only once, the next time we will get it from the 'history'
- x is greater than 0
- base is in <2,16> range
- */
- uint ToString_Log(const Big<exp,man> & x, uint base)
- {
- TTMATH_REFERENCE_ASSERT( x )
- TTMATH_ASSERT( base>=2 && base<=16 )
-
- Big<exp,man> temp;
- temp.SetOne();
-
- if( x == temp )
- {
- // log(1) is 0
- SetZero();
-
- return 0;
- }
-
- // there can be only a carry
- // because the 'x' is in '1+2*exponent' form then
- // the long formula from LnSurrounding1() will not be calculated
- // (LnSurrounding1() will return one immediately)
- uint c = Ln(x);
-
- if( base==10 && man<=TTMATH_BUILTIN_VARIABLES_SIZE )
- {
- // for the base equal 10 we're using SelLn10() instead of calculating it
- // (only if we have the constant sufficient big)
- temp.SetLn10();
- }
- else
- {
- c += ToString_LogBase(base, temp);
- }
+private:
- c += Div( temp );
- return (c==0)? 0 : 1;
- }
+ /*!
+ an auxiliary method for converting from a string
+ */
+ template<class char_type>
+ uint FromStringBase(const char_type * source, const Conv & conv, const char_type ** after_source = 0, bool * value_read = 0)
+ {
+ bool is_sign;
+ bool value_read_temp = false;
+ if( conv.base<2 || conv.base>16 )
+ {
+ SetNan();
-#ifndef TTMATH_MULTITHREADS
+ if( after_source )
+ *after_source = source;
- /*!
- this method calculates the logarithm of 'base'
- it's used in single thread environment
- */
- uint ToString_LogBase(uint base, Big<exp,man> & result)
- {
- TTMATH_ASSERT( base>=2 && base<=16 )
-
- // this guardians are initialized before the program runs (static POD types)
- static int guardians[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
- static Big<exp,man> log_history[15];
- uint index = base - 2;
- uint c = 0;
-
- if( guardians[index] == 0 )
- {
- Big<exp,man> base_(base);
- c += log_history[index].Ln(base_);
- guardians[index] = 1;
- }
+ if( value_read )
+ *value_read = value_read_temp;
- result = log_history[index];
+ return 1;
+ }
- return (c==0)? 0 : 1;
- }
+ SetZero();
+ FromString_TestSign( source, is_sign );
-#else
+ uint c = FromString_ReadPartBeforeComma( source, conv, value_read_temp );
- /*!
- this method calculates the logarithm of 'base'
- it's used in multi-thread environment
- */
- uint ToString_LogBase(uint base, Big<exp,man> & result)
- {
- TTMATH_ASSERT( base>=2 && base<=16 )
-
- // this guardians are initialized before the program runs (static POD types)
- volatile static sig_atomic_t guardians[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
- static Big<exp,man> * plog_history;
- uint index = base - 2;
- uint c = 0;
-
- // double-checked locking
- if( guardians[index] == 0 )
- {
- ThreadLock thread_lock;
-
- // locking
- if( thread_lock.Lock() )
- {
- static Big<exp,man> log_history[15];
-
- if( guardians[index] == 0 )
- {
- plog_history = log_history;
-
- Big<exp,man> base_(base);
- c += log_history[index].Ln(base_);
- guardians[index] = 1;
- }
- }
- else
- {
- // there was a problem with locking, we store the result directly in 'result' object
- Big<exp,man> base_(base);
- c += result.Ln(base_);
-
- return (c==0)? 0 : 1;
- }
+ if( FromString_TestCommaOperator(source, conv) )
+ c += FromString_ReadPartAfterComma( source, conv, value_read_temp );
- // automatically unlocking
- }
+ if( value_read_temp && conv.base == 10 )
+ c += FromString_ReadScientificIfExists( source );
- result = plog_history[index];
+ if( is_sign && !IsZero() )
+ ChangeSign();
- return (c==0)? 0 : 1;
- }
+ if( after_source )
+ *after_source = source;
-#endif
+ if( value_read )
+ *value_read = value_read_temp;
- /*!
- an auxiliary method for converting into the string (private)
+ return CheckCarry(c);
+ }
- this method moving all bits from mantissa into the right side
- the exponent tell us how many times moving (the exponent is <=0)
- */
- uint ToString_MoveMantissaIntoRight()
- {
- if( exponent.IsZero() )
- return 0;
-
- // exponent can't be greater than zero
- // because we would cat the highest bits of the mantissa
- if( !exponent.IsSign() )
- return 1;
-
-
- if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) )
- // if 'exponent' is <= than '-sint(man*TTMATH_BITS_PER_UINT)'
- // it means that we must cut the whole mantissa
- // (there'll not be any of the valid bits)
- return 1;
-
- // e will be from (-man*TTMATH_BITS_PER_UINT, 0>
- sint e = -( exponent.ToInt() );
- mantissa.Rcr(e,0);
-
- return 0;
- }
-
-
- /*!
- a special method similar to the 'ToString_CreateNewMantissaAndExponent'
- when the 'base' is equal 2
-
- we use it because if base is equal 2 we don't have to make those
- complicated calculations and the output is directly from the source
- (there will not be any small distortions)
- */
- template<class string_type>
- uint ToString_CreateNewMantissaAndExponent_Base2( string_type & new_man,
- Int<exp+1> & new_exp ) const
- {
- for( sint i=man-1 ; i>=0 ; --i )
- {
- uint value = mantissa.table[i];
-
- for( uint bit=0 ; bit<TTMATH_BITS_PER_UINT ; ++bit )
- {
- if( (value & TTMATH_UINT_HIGHEST_BIT) != 0 )
- new_man += '1';
- else
- new_man += '0';
-
- value <<= 1;
- }
- }
-
- new_exp = exponent;
-
- return 0;
- }
-
-
- /*!
- a special method used to calculate the new mantissa and exponent
- when the 'base' is equal 4, 8 or 16
-
- when base is 4 then bits is 2
- when base is 8 then bits is 3
- when base is 16 then bits is 4
- (and the algorithm can be used with a base greater than 16)
- */
- template<class string_type>
- uint ToString_CreateNewMantissaAndExponent_BasePow2( string_type & new_man,
- Int<exp+1> & new_exp,
- uint bits) const
- {
- sint move; // how many times move the mantissa
- UInt<man+1> man_temp(mantissa); // man+1 for moving
- new_exp = exponent;
- new_exp.DivInt((sint)bits, move);
-
- if( move != 0 )
- {
- // we're moving the man_temp to left-hand side
- if( move < 0 )
- {
- move = sint(bits) + move;
- new_exp.SubOne(); // when move is < than 0 then new_exp is < 0 too
- }
-
- man_temp.Rcl(move);
- }
-
-
- if( bits == 3 )
- {
- // base 8
- // now 'move' is greater than or equal 0
- uint len = man*TTMATH_BITS_PER_UINT + move;
- return ToString_CreateNewMantissaAndExponent_Base8(new_man, man_temp, len, bits);
- }
- else
- {
- // base 4 or 16
- return ToString_CreateNewMantissaAndExponent_Base4or16(new_man, man_temp, bits);
- }
- }
-
-
- /*!
- a special method used to calculate the new mantissa
- when the 'base' is equal 8
-
- bits is always 3
-
- we can use this algorithm when the base is 4 or 16 too
- but we have a faster method ToString_CreateNewMantissaAndExponent_Base4or16()
- */
- template<class string_type>
- uint ToString_CreateNewMantissaAndExponent_Base8( string_type & new_man,
- UInt<man+1> & man_temp,
- uint len,
- uint bits) const
- {
- uint shift = TTMATH_BITS_PER_UINT - bits;
- uint mask = TTMATH_UINT_MAX_VALUE >> shift;
- uint i;
-
- for( i=0 ; i<len ; i+=bits )
- {
- uint digit = man_temp.table[0] & mask;
- new_man.insert(new_man.begin(), static_cast<char>(Misc::DigitToChar(digit)));
-
- man_temp.Rcr(bits);
- }
-
- TTMATH_ASSERT( man_temp.IsZero() )
-
- return 0;
- }
-
-
- /*!
- a special method used to calculate the new mantissa
- when the 'base' is equal 4 or 16
-
- when the base is equal 4 or 16 the bits is 2 or 4
- and because TTMATH_BITS_PER_UINT (32 or 64) is divisible by 2 (or 4)
- then we can get digits from the end of our mantissa
- */
- template<class string_type>
- uint ToString_CreateNewMantissaAndExponent_Base4or16( string_type & new_man,
- UInt<man+1> & man_temp,
- uint bits) const
- {
- TTMATH_ASSERT( TTMATH_BITS_PER_UINT % 2 == 0 )
- TTMATH_ASSERT( TTMATH_BITS_PER_UINT % 4 == 0 )
-
- uint shift = TTMATH_BITS_PER_UINT - bits;
- uint mask = TTMATH_UINT_MAX_VALUE << shift;
- uint digit;
-
- // table[man] - last word - is different from zero if we moved man_temp
- digit = man_temp.table[man];
-
- if( digit != 0 )
- new_man += static_cast<char>(Misc::DigitToChar(digit));
-
-
- for( int i=man-1 ; i>=0 ; --i )
- {
- uint shift_local = shift;
- uint mask_local = mask;
-
- while( mask_local != 0 )
- {
- digit = man_temp.table[i] & mask_local;
-
- if( shift_local != 0 )
- digit = digit >> shift_local;
-
- new_man += static_cast<char>(Misc::DigitToChar(digit));
- mask_local = mask_local >> bits;
- shift_local = shift_local - bits;
- }
- }
-
- return 0;
- }
-
-
- /*!
- an auxiliary method for converting into the string
- */
- template<class string_type, class char_type>
- bool ToString_RoundMantissaWouldBeInteger(string_type & new_man, const Conv & conv, Int<exp+1> & new_exp) const
- {
- // if new_exp is greater or equal to zero then we have an integer value,
- // if new_exp is equal -1 then we have only one digit after the comma
- // and after rounding it would be an integer value
- if( !new_exp.IsSign() || new_exp == -1 )
- return true;
-
- if( new_man.size() >= TTMATH_UINT_HIGHEST_BIT || new_man.size() < 2 )
- return true; // oops, the mantissa is too large for calculating (or too small) - we are not doing the base rounding
-
- uint i = 0;
- char_type digit;
-
- if( new_exp >= -sint(new_man.size()) )
- {
- uint new_exp_abs = -new_exp.ToInt();
- i = new_man.size() - new_exp_abs; // start from the first digit after the comma operator
- }
-
- if( Misc::CharToDigit(new_man[new_man.size()-1]) >= conv.base/2 )
- {
- if( new_exp < -sint(new_man.size()) )
- {
- // there are some zeroes after the comma operator
- // (between the comma and the first digit from the mantissa)
- // and the result value will never be an integer
- return false;
- }
-
- digit = static_cast<char_type>( Misc::DigitToChar(conv.base-1) );
- }
- else
- {
- digit = '0';
- }
-
- for( ; i < new_man.size()-1 ; ++i)
- if( new_man[i] != digit )
- return false; // it will not be an integer
-
- return true; // it will be integer after rounding
- }
-
-
- /*!
- an auxiliary method for converting into the string
-
- this method is used for base!=2, base!=4, base!=8 and base!=16
- we do the rounding when the value has fraction (is not an integer)
- */
- template<class string_type, class char_type>
- uint ToString_BaseRound(string_type & new_man, const Conv & conv, Int<exp+1> & new_exp) const
- {
- // we must have minimum two characters
- if( new_man.size() < 2 )
- return 0;
-
- // assert that there will not be an integer after rounding
- if( ToString_RoundMantissaWouldBeInteger<string_type, char_type>(new_man, conv, new_exp) )
- return 0;
-
- typename string_type::size_type i = new_man.length() - 1;
-
- // we're erasing the last character
- uint digit = Misc::CharToDigit( new_man[i] );
- new_man.erase(i, 1);
- uint c = new_exp.AddOne();
-
- // if the last character is greater or equal 'base/2'
- // we are adding one into the new mantissa
- if( digit >= conv.base / 2 )
- ToString_RoundMantissa_AddOneIntoMantissa<string_type, char_type>(new_man, conv);
-
- return c;
- }
-
-
- /*!
- an auxiliary method for converting into the string
-
- this method addes one into the new mantissa
- */
- template<class string_type, class char_type>
- void ToString_RoundMantissa_AddOneIntoMantissa(string_type & new_man, const Conv & conv) const
- {
- if( new_man.empty() )
- return;
-
- sint i = sint( new_man.length() ) - 1;
- bool was_carry = true;
-
- for( ; i>=0 && was_carry ; --i )
- {
- // we can have the comma as well because
- // we're using this method later in ToString_CorrectDigitsAfterComma_Round()
- // (we're only ignoring it)
- if( new_man[i] == static_cast<char_type>(conv.comma) )
- continue;
-
- // we're adding one
- uint digit = Misc::CharToDigit( new_man[i] ) + 1;
-
- if( digit == conv.base )
- digit = 0;
- else
- was_carry = false;
-
- new_man[i] = static_cast<char_type>( Misc::DigitToChar(digit) );
- }
-
- if( i<0 && was_carry )
- new_man.insert( new_man.begin() , '1' );
- }
-
-
-
- /*!
- an auxiliary method for converting into the string
-
- this method sets the comma operator and/or puts the exponent
- into the string
- */
- template<class string_type, class char_type>
- uint ToString_SetCommaAndExponent(string_type & new_man, const Conv & conv, Int<exp+1> & new_exp) const
- {
- uint carry = 0;
-
- if( new_man.empty() )
- return carry;
-
- Int<exp+1> scientific_exp( new_exp );
-
- // 'new_exp' depends on the 'new_man' which is stored like this e.g:
- // 32342343234 (the comma is at the end)
- // we'd like to show it in this way:
- // 3.2342343234 (the 'scientific_exp' is connected with this example)
-
- sint offset = sint( new_man.length() ) - 1;
- carry += scientific_exp.Add( offset );
- // there shouldn't have been a carry because we're using
- // a greater type -- 'Int<exp+1>' instead of 'Int<exp>'
-
- bool print_scientific = conv.scient;
-
- if( !print_scientific )
- {
- if( scientific_exp > conv.scient_from || scientific_exp < -sint(conv.scient_from) )
- print_scientific = true;
- }
-
- if( !print_scientific )
- ToString_SetCommaAndExponent_Normal<string_type, char_type>(new_man, conv, new_exp);
- else
- // we're passing the 'scientific_exp' instead of 'new_exp' here
- ToString_SetCommaAndExponent_Scientific<string_type, char_type>(new_man, conv, scientific_exp);
-
- return (carry==0)? 0 : 1;
- }
-
-
- /*!
- an auxiliary method for converting into the string
- */
- template<class string_type, class char_type>
- void ToString_SetCommaAndExponent_Normal(string_type & new_man, const Conv & conv, Int<exp+1> & new_exp ) const
- {
- if( !new_exp.IsSign() ) // it means: if( new_exp >= 0 )
- ToString_SetCommaAndExponent_Normal_AddingZero<string_type, char_type>(new_man, new_exp);
- else
- ToString_SetCommaAndExponent_Normal_SetCommaInside<string_type, char_type>(new_man, conv, new_exp);
-
-
- ToString_Group_man<string_type, char_type>(new_man, conv);
- }
-
-
- /*!
- an auxiliary method for converting into the string
- */
- template<class string_type, class char_type>
- void ToString_SetCommaAndExponent_Normal_AddingZero(string_type & new_man,
- Int<exp+1> & new_exp) const
- {
- // we're adding zero characters at the end
- // 'i' will be smaller than 'when_scientific' (or equal)
- uint i = new_exp.ToInt();
-
- if( new_man.length() + i > new_man.capacity() )
- // about 6 characters more (we'll need it for the comma or something)
- new_man.reserve( new_man.length() + i + 6 );
-
- for( ; i>0 ; --i)
- new_man += '0';
- }
-
-
- /*!
- an auxiliary method for converting into the string
- */
- template<class string_type, class char_type>
- void ToString_SetCommaAndExponent_Normal_SetCommaInside(
- string_type & new_man,
- const Conv & conv,
- Int<exp+1> & new_exp ) const
- {
- // new_exp is < 0
-
- sint new_man_len = sint(new_man.length()); // 'new_man_len' with a sign
- sint e = -( new_exp.ToInt() ); // 'e' will be positive
-
- if( new_exp > -new_man_len )
- {
- // we're setting the comma within the mantissa
-
- sint index = new_man_len - e;
- new_man.insert( new_man.begin() + index, static_cast<char_type>(conv.comma));
- }
- else
- {
- // we're adding zero characters before the mantissa
-
- uint how_many = e - new_man_len;
- string_type man_temp(how_many+1, '0');
-
- man_temp.insert( man_temp.begin()+1, static_cast<char_type>(conv.comma));
- new_man.insert(0, man_temp);
- }
-
- ToString_CorrectDigitsAfterComma<string_type, char_type>(new_man, conv);
- }
-
-
- /*!
- an auxiliary method for converting into the string
- */
- template<class string_type, class char_type>
- void ToString_SetCommaAndExponent_Scientific( string_type & new_man,
- const Conv & conv,
- Int<exp+1> & scientific_exp ) const
- {
- if( new_man.empty() )
- return;
-
- if( new_man.size() > 1 )
- {
- new_man.insert( new_man.begin()+1, static_cast<char_type>(conv.comma) );
- ToString_CorrectDigitsAfterComma<string_type, char_type>(new_man, conv);
- }
-
- ToString_Group_man<string_type, char_type>(new_man, conv);
-
- if( conv.base == 10 )
- {
- new_man += 'e';
-
- if( !scientific_exp.IsSign() )
- new_man += '+';
- }
- else
- {
- // the 10 here is meant as the base 'base'
- // (no matter which 'base' we're using there'll always be 10 here)
- Misc::AddString(new_man, "*10^");
- }
-
- string_type temp_exp;
- scientific_exp.ToString( temp_exp, conv.base );
-
- new_man += temp_exp;
- }
-
-
- /*!
- an auxiliary method for converting into the string
- */
- template<class string_type, class char_type>
- void ToString_Group_man(string_type & new_man, const Conv & conv) const
- {
- typedef typename string_type::size_type StrSize;
-
- if( conv.group == 0 )
- return;
-
- // first we're looking for the comma operator
- StrSize index = new_man.find(static_cast<char_type>(conv.comma), 0);
-
- if( index == string_type::npos )
- index = new_man.size();
-
- ToString_Group_man_before_comma<string_type, char_type>(new_man, conv, index);
- ToString_Group_man_after_comma<string_type, char_type>(new_man, conv, index+1);
- }
-
-
-
- /*!
- an auxiliary method for converting into the string
- */
- template<class string_type, class char_type>
- void ToString_Group_man_before_comma( string_type & new_man, const Conv & conv,
- typename string_type::size_type & index) const
- {
- typedef typename string_type::size_type StrSize;
- uint group = 0;
-
- StrSize i = index;
-
- // adding group characters before the comma operator
- // i>0 because on the first position we don't put any additional grouping characters
- for( ; i>0 ; --i, ++group)
- {
- if( group >= 3 )
- {
- group = 0;
- new_man.insert(i, 1, static_cast<char_type>(conv.group));
- ++index;
- }
- }
- }
-
-
- /*!
- an auxiliary method for converting into the string
- */
- template<class string_type, class char_type>
- void ToString_Group_man_after_comma(string_type & new_man, const Conv & conv,
- typename string_type::size_type index) const
- {
- uint group = 0;
-
- for( ; index<new_man.size() ; ++index, ++group)
- {
- if( group >= 3 )
- {
- group = 0;
- new_man.insert(index, 1, static_cast<char_type>(conv.group));
- ++index;
- }
- }
- }
-
-
- /*!
- an auxiliary method for converting into the string
- */
- template<class string_type, class char_type>
- void ToString_CorrectDigitsAfterComma( string_type & new_man,
- const Conv & conv ) const
- {
- if( conv.round >= 0 )
- ToString_CorrectDigitsAfterComma_Round<string_type, char_type>(new_man, conv);
-
- if( conv.trim_zeroes )
- ToString_CorrectDigitsAfterComma_CutOffZeroCharacters<string_type, char_type>(new_man, conv);
- }
-
-
- /*!
- an auxiliary method for converting into the string
- */
- template<class string_type, class char_type>
- void ToString_CorrectDigitsAfterComma_CutOffZeroCharacters(
- string_type & new_man,
- const Conv & conv) const
- {
- // minimum two characters
- if( new_man.length() < 2 )
- return;
-
- // we're looking for the index of the last character which is not zero
- uint i = uint( new_man.length() ) - 1;
- for( ; i>0 && new_man[i]=='0' ; --i );
-
- // if there is another character than zero at the end
- // we're finishing
- if( i == new_man.length() - 1 )
- return;
-
- // we must have a comma
- // (the comma can be removed by ToString_CorrectDigitsAfterComma_Round
- // which is called before)
- if( new_man.find_last_of(static_cast<char_type>(conv.comma), i) == string_type::npos )
- return;
-
- // if directly before the first zero is the comma operator
- // we're cutting it as well
- if( i>0 && new_man[i]==static_cast<char_type>(conv.comma) )
- --i;
-
- new_man.erase(i+1, new_man.length()-i-1);
- }
-
-
- /*!
- an auxiliary method for converting into the string
- */
- template<class string_type, class char_type>
- void ToString_CorrectDigitsAfterComma_Round(
- string_type & new_man,
- const Conv & conv ) const
- {
- typedef typename string_type::size_type StrSize;
-
- // first we're looking for the comma operator
- StrSize index = new_man.find(static_cast<char_type>(conv.comma), 0);
-
- if( index == string_type::npos )
- // nothing was found (actually there can't be this situation)
- return;
-
- // we're calculating how many digits there are at the end (after the comma)
- // 'after_comma' will be greater than zero because at the end
- // we have at least one digit
- StrSize after_comma = new_man.length() - index - 1;
-
- // if 'max_digit_after_comma' is greater than 'after_comma' (or equal)
- // we don't have anything for cutting
- if( static_cast<StrSize>(conv.round) >= after_comma )
- return;
-
- uint last_digit = Misc::CharToDigit( new_man[ index + conv.round + 1 ], conv.base );
-
- // we're cutting the rest of the string
- new_man.erase(index + conv.round + 1, after_comma - conv.round);
-
- if( conv.round == 0 )
- {
- // we're cutting the comma operator as well
- // (it's not needed now because we've cut the whole rest after the comma)
- new_man.erase(index, 1);
- }
-
- if( last_digit >= conv.base / 2 )
- // we must round here
- ToString_RoundMantissa_AddOneIntoMantissa<string_type, char_type>(new_man, conv);
- }
+ /*!
+ we're testing whether the value is with the sign
+ (this method is used from 'FromString_ReadPartScientific' too)
+ */
+ template<class char_type>
+ void FromString_TestSign( const char_type * & source, bool & is_sign )
+ {
+ Misc::SkipWhiteCharacters(source);
-public:
+ is_sign = false;
- /*!
- a method for converting a string into its value
+ if( *source == '-' )
+ {
+ is_sign = true;
+ ++source;
+ }
+ else
+ if( *source == '+' )
+ {
+ ++source;
+ }
+ }
- it returns 1 if the value is too big -- we cannot pass it into the range
- of our class Big<exp,man> (or if the base is incorrect)
- that means only digits before the comma operator can make this value too big,
- all digits after the comma we can ignore
+ /*!
+ we're testing whether there's a comma operator
+ */
+ template<class char_type>
+ bool FromString_TestCommaOperator(const char_type * & source, const Conv & conv)
+ {
+ if( (*source == static_cast<char_type>(conv.comma)) ||
+ (*source == static_cast<char_type>(conv.comma2) && conv.comma2 != 0 ) )
+ {
+ ++source;
- 'source' - pointer to the string for parsing
-
- if 'after_source' is set that when this method finishes
- it sets the pointer to the new first character after parsed value
-
- 'value_read' - if the pointer is provided that means the value_read will be true
- only when a value has been actually read, there can be situation where only such
- a string '-' or '+' will be parsed -- 'after_source' will be different from 'source' but
- no value has been read (there are no digits)
- on other words if 'value_read' is true -- there is at least one digit in the string
- */
- uint FromString(const char * source, uint base = 10, const char ** after_source = 0, bool * value_read = 0)
- {
- Conv conv;
- conv.base = base;
-
- return FromStringBase(source, conv, after_source, value_read);
- }
-
-
- /*!
- a method for converting a string into its value
- */
- uint FromString(const wchar_t * source, uint base = 10, const wchar_t ** after_source = 0, bool * value_read = 0)
- {
- Conv conv;
- conv.base = base;
-
- return FromStringBase(source, conv, after_source, value_read);
- }
-
-
- /*!
- a method for converting a string into its value
- */
- uint FromString(const char * source, const Conv & conv, const char ** after_source = 0, bool * value_read = 0)
- {
- return FromStringBase(source, conv, after_source, value_read);
- }
-
-
- /*!
- a method for converting a string into its value
- */
- uint FromString(const wchar_t * source, const Conv & conv, const wchar_t ** after_source = 0, bool * value_read = 0)
- {
- return FromStringBase(source, conv, after_source, value_read);
- }
-
-
- /*!
- a method for converting a string into its value
- */
- uint FromString(const std::string & string, uint base = 10, const wchar_t ** after_source = 0, bool * value_read = 0)
- {
- return FromString(string.c_str(), base, after_source, value_read);
- }
-
-
- /*!
- a method for converting a string into its value
- */
- uint FromString(const std::wstring & string, uint base = 10, const wchar_t ** after_source = 0, bool * value_read = 0)
- {
- return FromString(string.c_str(), base, after_source, value_read);
- }
-
-
- /*!
- a method for converting a string into its value
- */
- uint FromString(const std::string & string, const Conv & conv, const wchar_t ** after_source = 0, bool * value_read = 0)
- {
- return FromString(string.c_str(), conv, after_source, value_read);
- }
-
-
- /*!
- a method for converting a string into its value
- */
- uint FromString(const std::wstring & string, const Conv & conv, const wchar_t ** after_source = 0, bool * value_read = 0)
- {
- return FromString(string.c_str(), conv, after_source, value_read);
- }
+ return true;
+ }
-private:
+ return false;
+ }
- /*!
- an auxiliary method for converting from a string
- */
- template<class char_type>
- uint FromStringBase(const char_type * source, const Conv & conv, const char_type ** after_source = 0, bool * value_read = 0)
- {
- bool is_sign;
- bool value_read_temp = false;
+ /*!
+ this method reads the first part of a string
+ (before the comma operator)
+ */
+ template<class char_type>
+ uint FromString_ReadPartBeforeComma( const char_type * & source, const Conv & conv, bool & value_read )
+ {
+ sint character;
+ Big<exp, man> temp;
+ Big<exp, man> base_( conv.base );
+
+ Misc::SkipWhiteCharacters( source );
- if( conv.base<2 || conv.base>16 )
- {
- SetNan();
+ for( ; true ; ++source )
+ {
+ if( conv.group!=0 && *source==static_cast<char>(conv.group) )
+ continue;
- if( after_source )
- *after_source = source;
+ character = Misc::CharToDigit(*source, conv.base);
- if( value_read )
- *value_read = value_read_temp;
+ if( character == -1 )
+ break;
- return 1;
- }
+ value_read = true;
+ temp = character;
- SetZero();
- FromString_TestSign( source, is_sign );
+ if( Mul(base_) )
+ return 1;
- uint c = FromString_ReadPartBeforeComma( source, conv, value_read_temp );
+ if( Add(temp) )
+ return 1;
+ }
- if( FromString_TestCommaOperator(source, conv) )
- c += FromString_ReadPartAfterComma( source, conv, value_read_temp );
+ return 0;
+ }
- if( value_read_temp && conv.base == 10 )
- c += FromString_ReadScientificIfExists( source );
- if( is_sign && !IsZero() )
- ChangeSign();
+ /*!
+ this method reads the second part of a string
+ (after the comma operator)
+ */
+ template<class char_type>
+ uint FromString_ReadPartAfterComma( const char_type * & source, const Conv & conv, bool & value_read )
+ {
+ sint character;
+ uint c = 0, index = 1;
+ Big<exp, man> sum, part, power, old_value, base_( conv.base );
- if( after_source )
- *after_source = source;
+ // we don't remove any white characters here
- if( value_read )
- *value_read = value_read_temp;
+ // this is only to avoid getting a warning about an uninitialized object 'old_value' which GCC reports
+ // (in fact we will initialize it later when the condition 'testing' is fulfilled)
+ old_value.SetZero();
- return CheckCarry(c);
- }
+ power.SetOne();
+ sum.SetZero();
+ for( ; true ; ++source, ++index )
+ {
+ if( conv.group!=0 && *source==static_cast<char>(conv.group) )
+ continue;
+
+ character = Misc::CharToDigit(*source, conv.base);
- /*!
- we're testing whether the value is with the sign
+ if( character == -1 )
+ break;
- (this method is used from 'FromString_ReadPartScientific' too)
- */
- template<class char_type>
- void FromString_TestSign( const char_type * & source, bool & is_sign )
- {
- Misc::SkipWhiteCharacters(source);
+ value_read = true;
- is_sign = false;
+ part = character;
- if( *source == '-' )
- {
- is_sign = true;
- ++source;
- }
- else
- if( *source == '+' )
- {
- ++source;
- }
- }
+ if( power.Mul( base_ ) )
+ // there's no sens to add the next parts, but we can't report this
+ // as an error (this is only inaccuracy)
+ break;
+ if( part.Div( power ) )
+ break;
- /*!
- we're testing whether there's a comma operator
- */
- template<class char_type>
- bool FromString_TestCommaOperator(const char_type * & source, const Conv & conv)
- {
- if( (*source == static_cast<char_type>(conv.comma)) ||
- (*source == static_cast<char_type>(conv.comma2) && conv.comma2 != 0 ) )
- {
- ++source;
+ // every 5 iteration we make a test whether the value will be changed or not
+ // (character must be different from zero to this test)
+ bool testing = (character != 0 && (index % 5) == 0);
- return true;
- }
+ if( testing )
+ old_value = sum;
- return false;
- }
+ // there actually shouldn't be a carry here
+ c += sum.Add( part );
+ if( testing && old_value == sum )
+ // after adding 'part' the value has not been changed
+ // there's no sense to add any next parts
+ break;
+ }
- /*!
- this method reads the first part of a string
- (before the comma operator)
- */
- template<class char_type>
- uint FromString_ReadPartBeforeComma( const char_type * & source, const Conv & conv, bool & value_read )
- {
- sint character;
- Big<exp, man> temp;
- Big<exp, man> base_( conv.base );
+ // we could break the parsing somewhere in the middle of the string,
+ // but the result (value) still can be good
+ // we should set a correct value of 'source' now
+ for( ; Misc::CharToDigit(*source, conv.base) != -1 ; ++source );
- Misc::SkipWhiteCharacters( source );
+ c += Add(sum);
- for( ; true ; ++source )
- {
- if( conv.group!=0 && *source==static_cast<char>(conv.group) )
- continue;
+ return (c==0)? 0 : 1;
+ }
- character = Misc::CharToDigit(*source, conv.base);
- if( character == -1 )
- break;
+ /*!
+ this method checks whether there is a scientific part: [e|E][-|+]value
- value_read = true;
- temp = character;
+ it is called when the base is 10 and some digits were read before
+ */
+ template<class char_type>
+ uint FromString_ReadScientificIfExists(const char_type * & source)
+ {
+ uint c = 0;
- if( Mul(base_) )
- return 1;
+ bool scientific_read = false;
+ const char_type * before_scientific = source;
- if( Add(temp) )
- return 1;
- }
+ if( FromString_TestScientific(source) )
+ c += FromString_ReadPartScientific( source, scientific_read );
- return 0;
- }
+ if( !scientific_read )
+ source = before_scientific;
+ return (c==0)? 0 : 1;
+ }
- /*!
- this method reads the second part of a string
- (after the comma operator)
- */
- template<class char_type>
- uint FromString_ReadPartAfterComma( const char_type * & source, const Conv & conv, bool & value_read )
- {
- sint character;
- uint c = 0, index = 1;
- Big<exp, man> sum, part, power, old_value, base_( conv.base );
- // we don't remove any white characters here
- // this is only to avoid getting a warning about an uninitialized object 'old_value' which GCC reports
- // (in fact we will initialize it later when the condition 'testing' is fulfilled)
- old_value.SetZero();
+ /*!
+ we're testing whether is there the character 'e'
- power.SetOne();
- sum.SetZero();
+ this character is only allowed when we're using the base equals 10
+ */
+ template<class char_type>
+ bool FromString_TestScientific(const char_type * & source)
+ {
+ Misc::SkipWhiteCharacters(source);
- for( ; true ; ++source, ++index )
- {
- if( conv.group!=0 && *source==static_cast<char>(conv.group) )
- continue;
+ if( *source=='e' || *source=='E' )
+ {
+ ++source;
- character = Misc::CharToDigit(*source, conv.base);
+ return true;
+ }
- if( character == -1 )
- break;
+ return false;
+ }
- value_read = true;
- part = character;
+ /*!
+ this method reads the exponent (after 'e' character) when there's a scientific
+ format of value and only when we're using the base equals 10
+ */
+ template<class char_type>
+ uint FromString_ReadPartScientific( const char_type * & source, bool & scientific_read )
+ {
+ uint c = 0;
+ Big<exp, man> new_exponent, temp;
+ bool was_sign = false;
- if( power.Mul( base_ ) )
- // there's no sens to add the next parts, but we can't report this
- // as an error (this is only inaccuracy)
- break;
+ FromString_TestSign( source, was_sign );
+ c += FromString_ReadPartScientific_ReadExponent( source, new_exponent, scientific_read );
- if( part.Div( power ) )
- break;
+ if( scientific_read )
+ {
+ if( was_sign )
+ new_exponent.ChangeSign();
- // every 5 iteration we make a test whether the value will be changed or not
- // (character must be different from zero to this test)
- bool testing = (character != 0 && (index % 5) == 0);
+ temp = 10;
+ c += temp.Pow( new_exponent );
+ c += Mul(temp);
+ }
- if( testing )
- old_value = sum;
+ return (c==0)? 0 : 1;
+ }
- // there actually shouldn't be a carry here
- c += sum.Add( part );
- if( testing && old_value == sum )
- // after adding 'part' the value has not been changed
- // there's no sense to add any next parts
- break;
- }
+ /*!
+ this method reads the value of the extra exponent when scientific format is used
+ (only when base == 10)
+ */
+ template<class char_type>
+ uint FromString_ReadPartScientific_ReadExponent( const char_type * & source, Big<exp, man> & new_exponent, bool & scientific_read )
+ {
+ sint character;
+ Big<exp, man> base, temp;
- // we could break the parsing somewhere in the middle of the string,
- // but the result (value) still can be good
- // we should set a correct value of 'source' now
- for( ; Misc::CharToDigit(*source, conv.base) != -1 ; ++source );
+ Misc::SkipWhiteCharacters(source);
- c += Add(sum);
+ new_exponent.SetZero();
+ base = 10;
- return (c==0)? 0 : 1;
- }
+ for( ; (character=Misc::CharToDigit(*source, 10)) != -1 ; ++source )
+ {
+ scientific_read = true;
+ temp = character;
- /*!
- this method checks whether there is a scientific part: [e|E][-|+]value
+ if( new_exponent.Mul(base) )
+ return 1;
- it is called when the base is 10 and some digits were read before
- */
- template<class char_type>
- uint FromString_ReadScientificIfExists(const char_type * & source)
- {
- uint c = 0;
+ if( new_exponent.Add(temp) )
+ return 1;
+ }
- bool scientific_read = false;
- const char_type * before_scientific = source;
+ return 0;
+ }
- if( FromString_TestScientific(source) )
- c += FromString_ReadPartScientific( source, scientific_read );
- if( !scientific_read )
- source = before_scientific;
-
- return (c==0)? 0 : 1;
- }
+public:
+ /*!
+ a constructor for converting a string into this class
+ */
+ Big(const char * string)
+ {
+ FromString( string );
+ }
+
+
+ /*!
+ a constructor for converting a string into this class
+ */
+ Big(const std::string & string)
+ {
+ FromString( string.c_str() );
+ }
+
+
+ /*!
+ an operator= for converting a string into its value
+ */
+ Big<exp, man> & operator=(const char * string)
+ {
+ FromString( string );
+
+ return *this;
+ }
+
+
+ /*!
+ an operator= for converting a string into its value
+ */
+ Big<exp, man> & operator=(const std::string & string)
+ {
+ FromString( string.c_str() );
+
+ return *this;
+ }
+
+
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
+ /*!
+ a constructor for converting a string into this class
+ */
+ Big(const wchar_t * string)
+ {
+ FromString( string );
+ }
+
+
+ /*!
+ a constructor for converting a string into this class
+ */
+ Big(const std::wstring & string)
+ {
+ FromString( string.c_str() );
+ }
+
+
+ /*!
+ an operator= for converting a string into its value
+ */
+ Big<exp, man> & operator=(const wchar_t * string)
+ {
+ FromString( string );
+
+ return *this;
+ }
+
+
+ /*!
+ an operator= for converting a string into its value
+ */
+ Big<exp, man> & operator=(const std::wstring & string)
+ {
+ FromString( string.c_str() );
- /*!
- we're testing whether is there the character 'e'
+ return *this;
+ }
- this character is only allowed when we're using the base equals 10
- */
- template<class char_type>
- bool FromString_TestScientific(const char_type * & source)
- {
- Misc::SkipWhiteCharacters(source);
- if( *source=='e' || *source=='E' )
- {
- ++source;
+#endif
- return true;
- }
- return false;
- }
+ /*!
+ *
+ * methods for comparing
+ *
+ */
- /*!
- this method reads the exponent (after 'e' character) when there's a scientific
- format of value and only when we're using the base equals 10
- */
- template<class char_type>
- uint FromString_ReadPartScientific( const char_type * & source, bool & scientific_read )
- {
- uint c = 0;
- Big<exp, man> new_exponent, temp;
- bool was_sign = false;
- FromString_TestSign( source, was_sign );
- c += FromString_ReadPartScientific_ReadExponent( source, new_exponent, scientific_read );
+ /*!
+ this method performs the formula 'abs(this) < abs(ss2)'
+ and returns the result
- if( scientific_read )
- {
- if( was_sign )
- new_exponent.ChangeSign();
+ (in other words it treats 'this' and 'ss2' as values without a sign)
+ we don't check the NaN flag
+ */
+ bool SmallerWithoutSignThan(const Big<exp,man> & ss2) const
+ {
+ if( IsZero() )
+ {
+ if( ss2.IsZero() )
+ // we've got two zeroes
+ return false;
+ else
+ // this==0 and ss2!=0
+ return true;
+ }
- temp = 10;
- c += temp.Pow( new_exponent );
- c += Mul(temp);
- }
+ if( ss2.IsZero() )
+ // this!=0 and ss2==0
+ return false;
- return (c==0)? 0 : 1;
- }
+ // we're using the fact that all bits in mantissa are pushed
+ // into the left side -- Standardizing()
+ if( exponent == ss2.exponent )
+ return mantissa < ss2.mantissa;
+ return exponent < ss2.exponent;
+ }
- /*!
- this method reads the value of the extra exponent when scientific format is used
- (only when base == 10)
- */
- template<class char_type>
- uint FromString_ReadPartScientific_ReadExponent( const char_type * & source, Big<exp, man> & new_exponent, bool & scientific_read )
- {
- sint character;
- Big<exp, man> base, temp;
- Misc::SkipWhiteCharacters(source);
+ /*!
+ this method performs the formula 'abs(this) > abs(ss2)'
+ and returns the result
- new_exponent.SetZero();
- base = 10;
+ (in other words it treats 'this' and 'ss2' as values without a sign)
+ we don't check the NaN flag
+ */
+ bool GreaterWithoutSignThan(const Big<exp,man> & ss2) const
+ {
+ if( IsZero() )
+ {
+ if( ss2.IsZero() )
+ // we've got two zeroes
+ return false;
+ else
+ // this==0 and ss2!=0
+ return false;
+ }
- for( ; (character=Misc::CharToDigit(*source, 10)) != -1 ; ++source )
- {
- scientific_read = true;
+ if( ss2.IsZero() )
+ // this!=0 and ss2==0
+ return true;
- temp = character;
+ // we're using the fact that all bits in mantissa are pushed
+ // into the left side -- Standardizing()
+ if( exponent == ss2.exponent )
+ return mantissa > ss2.mantissa;
- if( new_exponent.Mul(base) )
- return 1;
+ return exponent > ss2.exponent;
+ }
- if( new_exponent.Add(temp) )
- return 1;
- }
- return 0;
- }
+ /*!
+ this method performs the formula 'abs(this) == abs(ss2)'
+ and returns the result
+ (in other words it treats 'this' and 'ss2' as values without a sign)
+ we don't check the NaN flag
+ */
+ bool EqualWithoutSign(const Big<exp,man> & ss2) const
+ {
+ if( IsZero() )
+ {
+ if( ss2.IsZero() )
+ // we've got two zeroes
+ return true;
+ else
+ // this==0 and ss2!=0
+ return false;
+ }
-public:
+ if( ss2.IsZero() )
+ // this!=0 and ss2==0
+ return false;
+ if( exponent==ss2.exponent && mantissa==ss2.mantissa )
+ return true;
- /*!
- a constructor for converting a string into this class
- */
- Big(const char * string)
- {
- FromString( string );
- }
+ return false;
+ }
- /*!
- a constructor for converting a string into this class
- */
- Big(const wchar_t * string)
- {
- FromString( string );
- }
+ bool operator<(const Big<exp,man> & ss2) const
+ {
+ if( IsSign() && !ss2.IsSign() )
+ // this<0 and ss2>=0
+ return true;
+ if( !IsSign() && ss2.IsSign() )
+ // this>=0 and ss2<0
+ return false;
- /*!
- a constructor for converting a string into this class
- */
- Big(const std::string & string)
- {
- FromString( string.c_str() );
- }
+ // both signs are the same
+ if( IsSign() )
+ return ss2.SmallerWithoutSignThan( *this );
- /*!
- a constructor for converting a string into this class
- */
- Big(const std::wstring & string)
- {
- FromString( string.c_str() );
- }
+ return SmallerWithoutSignThan( ss2 );
+ }
- /*!
- an operator= for converting a string into its value
- */
- Big<exp, man> & operator=(const char * string)
- {
- FromString( string );
+ bool operator==(const Big<exp,man> & ss2) const
+ {
+ if( IsSign() != ss2.IsSign() )
+ return false;
- return *this;
- }
+ return EqualWithoutSign( ss2 );
+ }
- /*!
- an operator= for converting a string into its value
- */
- Big<exp, man> & operator=(const wchar_t * string)
- {
- FromString( string );
+ bool operator>(const Big<exp,man> & ss2) const
+ {
+ if( IsSign() && !ss2.IsSign() )
+ // this<0 and ss2>=0
+ return false;
- return *this;
- }
+ if( !IsSign() && ss2.IsSign() )
+ // this>=0 and ss2<0
+ return true;
+ // both signs are the same
- /*!
- an operator= for converting a string into its value
- */
- Big<exp, man> & operator=(const std::string & string)
- {
- FromString( string.c_str() );
+ if( IsSign() )
+ return ss2.GreaterWithoutSignThan( *this );
- return *this;
- }
+ return GreaterWithoutSignThan( ss2 );
+ }
- /*!
- an operator= for converting a string into its value
- */
- Big<exp, man> & operator=(const std::wstring & string)
- {
- FromString( string.c_str() );
+ bool operator>=(const Big<exp,man> & ss2) const
+ {
+ return !operator<( ss2 );
+ }
- return *this;
- }
+ bool operator<=(const Big<exp,man> & ss2) const
+ {
+ return !operator>( ss2 );
+ }
- /*!
- *
- * methods for comparing
- *
- */
+ bool operator!=(const Big<exp,man> & ss2) const
+ {
+ return !operator==(ss2);
+ }
- /*!
- this method performs the formula 'abs(this) < abs(ss2)'
- and returns the result
- (in other words it treats 'this' and 'ss2' as values without a sign)
- we don't check the NaN flag
- */
- bool SmallerWithoutSignThan(const Big<exp,man> & ss2) const
- {
- if( IsZero() )
- {
- if( ss2.IsZero() )
- // we've got two zeroes
- return false;
- else
- // this==0 and ss2!=0
- return true;
- }
- if( ss2.IsZero() )
- // this!=0 and ss2==0
- return false;
- // we're using the fact that all bits in mantissa are pushed
- // into the left side -- Standardizing()
- if( exponent == ss2.exponent )
- return mantissa < ss2.mantissa;
+ /*!
+ *
+ * standard mathematical operators
+ *
+ */
- return exponent < ss2.exponent;
- }
+ /*!
+ an operator for changing the sign
- /*!
- this method performs the formula 'abs(this) > abs(ss2)'
- and returns the result
+ this method is not changing 'this' but the changed value is returned
+ */
+ Big<exp,man> operator-() const
+ {
+ Big<exp,man> temp(*this);
- (in other words it treats 'this' and 'ss2' as values without a sign)
- we don't check the NaN flag
- */
- bool GreaterWithoutSignThan(const Big<exp,man> & ss2) const
- {
- if( IsZero() )
- {
- if( ss2.IsZero() )
- // we've got two zeroes
- return false;
- else
- // this==0 and ss2!=0
- return false;
- }
+ temp.ChangeSign();
- if( ss2.IsZero() )
- // this!=0 and ss2==0
- return true;
+ return temp;
+ }
- // we're using the fact that all bits in mantissa are pushed
- // into the left side -- Standardizing()
- if( exponent == ss2.exponent )
- return mantissa > ss2.mantissa;
- return exponent > ss2.exponent;
- }
+ Big<exp,man> operator-(const Big<exp,man> & ss2) const
+ {
+ Big<exp,man> temp(*this);
+ temp.Sub(ss2);
- /*!
- this method performs the formula 'abs(this) == abs(ss2)'
- and returns the result
+ return temp;
+ }
- (in other words it treats 'this' and 'ss2' as values without a sign)
- we don't check the NaN flag
- */
- bool EqualWithoutSign(const Big<exp,man> & ss2) const
- {
- if( IsZero() )
- {
- if( ss2.IsZero() )
- // we've got two zeroes
- return true;
- else
- // this==0 and ss2!=0
- return false;
- }
+ Big<exp,man> & operator-=(const Big<exp,man> & ss2)
+ {
+ Sub(ss2);
- if( ss2.IsZero() )
- // this!=0 and ss2==0
- return false;
+ return *this;
+ }
- if( exponent==ss2.exponent && mantissa==ss2.mantissa )
- return true;
- return false;
- }
+ Big<exp,man> operator+(const Big<exp,man> & ss2) const
+ {
+ Big<exp,man> temp(*this);
+ temp.Add(ss2);
- bool operator<(const Big<exp,man> & ss2) const
- {
- if( IsSign() && !ss2.IsSign() )
- // this<0 and ss2>=0
- return true;
+ return temp;
+ }
- if( !IsSign() && ss2.IsSign() )
- // this>=0 and ss2<0
- return false;
- // both signs are the same
+ Big<exp,man> & operator+=(const Big<exp,man> & ss2)
+ {
+ Add(ss2);
- if( IsSign() )
- return ss2.SmallerWithoutSignThan( *this );
+ return *this;
+ }
- return SmallerWithoutSignThan( ss2 );
- }
+ Big<exp,man> operator*(const Big<exp,man> & ss2) const
+ {
+ Big<exp,man> temp(*this);
- bool operator==(const Big<exp,man> & ss2) const
- {
- if( IsSign() != ss2.IsSign() )
- return false;
+ temp.Mul(ss2);
- return EqualWithoutSign( ss2 );
- }
+ return temp;
+ }
- bool operator>(const Big<exp,man> & ss2) const
- {
- if( IsSign() && !ss2.IsSign() )
- // this<0 and ss2>=0
- return false;
+ Big<exp,man> & operator*=(const Big<exp,man> & ss2)
+ {
+ Mul(ss2);
- if( !IsSign() && ss2.IsSign() )
- // this>=0 and ss2<0
- return true;
+ return *this;
+ }
- // both signs are the same
- if( IsSign() )
- return ss2.GreaterWithoutSignThan( *this );
+ Big<exp,man> operator/(const Big<exp,man> & ss2) const
+ {
+ Big<exp,man> temp(*this);
- return GreaterWithoutSignThan( ss2 );
- }
+ temp.Div(ss2);
+ return temp;
+ }
- bool operator>=(const Big<exp,man> & ss2) const
- {
- return !operator<( ss2 );
- }
+ Big<exp,man> & operator/=(const Big<exp,man> & ss2)
+ {
+ Div(ss2);
- bool operator<=(const Big<exp,man> & ss2) const
- {
- return !operator>( ss2 );
- }
+ return *this;
+ }
- bool operator!=(const Big<exp,man> & ss2) const
- {
- return !operator==(ss2);
- }
+ /*!
+ Prefix operator e.g ++variable
+ */
+ Big<exp,man> & operator++()
+ {
+ AddOne();
+ return *this;
+ }
+ /*!
+ Postfix operator e.g variable++
+ */
+ Big<exp,man> operator++(int)
+ {
+ Big<exp,man> temp( *this );
+ AddOne();
- /*!
- *
- * standard mathematical operators
- *
- */
+ return temp;
+ }
- /*!
- an operator for changing the sign
+ Big<exp,man> & operator--()
+ {
+ SubOne();
- this method is not changing 'this' but the changed value is returned
- */
- Big<exp,man> operator-() const
- {
- Big<exp,man> temp(*this);
+ return *this;
+ }
- temp.ChangeSign();
- return temp;
- }
+ Big<exp,man> operator--(int)
+ {
+ Big<exp,man> temp( *this );
+ SubOne();
- Big<exp,man> operator-(const Big<exp,man> & ss2) const
- {
- Big<exp,man> temp(*this);
+ return temp;
+ }
- temp.Sub(ss2);
- return temp;
- }
- Big<exp,man> & operator-=(const Big<exp,man> & ss2)
- {
- Sub(ss2);
+ /*!
+ *
+ * bitwise operators
+ * (we do not define bitwise not)
+ */
- return *this;
- }
+ Big<exp,man> operator&(const Big<exp,man> & p2) const
+ {
+ Big<exp,man> temp( *this );
- Big<exp,man> operator+(const Big<exp,man> & ss2) const
- {
- Big<exp,man> temp(*this);
+ temp.BitAnd(p2);
- temp.Add(ss2);
+ return temp;
+ }
- return temp;
- }
+ Big<exp,man> & operator&=(const Big<exp,man> & p2)
+ {
+ BitAnd(p2);
- Big<exp,man> & operator+=(const Big<exp,man> & ss2)
- {
- Add(ss2);
+ return *this;
+ }
- return *this;
- }
+ Big<exp,man> operator|(const Big<exp,man> & p2) const
+ {
+ Big<exp,man> temp( *this );
- Big<exp,man> operator*(const Big<exp,man> & ss2) const
- {
- Big<exp,man> temp(*this);
+ temp.BitOr(p2);
- temp.Mul(ss2);
+ return temp;
+ }
- return temp;
- }
+ Big<exp,man> & operator|=(const Big<exp,man> & p2)
+ {
+ BitOr(p2);
- Big<exp,man> & operator*=(const Big<exp,man> & ss2)
- {
- Mul(ss2);
+ return *this;
+ }
- return *this;
- }
+ Big<exp,man> operator^(const Big<exp,man> & p2) const
+ {
+ Big<exp,man> temp( *this );
- Big<exp,man> operator/(const Big<exp,man> & ss2) const
- {
- Big<exp,man> temp(*this);
+ temp.BitXor(p2);
- temp.Div(ss2);
+ return temp;
+ }
- return temp;
- }
+ Big<exp,man> & operator^=(const Big<exp,man> & p2)
+ {
+ BitXor(p2);
- Big<exp,man> & operator/=(const Big<exp,man> & ss2)
- {
- Div(ss2);
+ return *this;
+ }
- return *this;
- }
- /*!
- this method makes an integer value by skipping any fractions
- for example:
- 10.7 will be 10
- 12.1 -- 12
- -20.2 -- 20
- -20.9 -- 20
- -0.7 -- 0
- 0.8 -- 0
- */
- void SkipFraction()
- {
- if( IsNan() || IsZero() )
- return;
- if( !exponent.IsSign() )
- // exponent >=0 -- the value don't have any fractions
- return;
- if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) )
- {
- // the value is from (-1,1), we return zero
- SetZero();
- return;
- }
+ /*!
+ this method makes an integer value by skipping any fractions
- // exponent is in range (-man*TTMATH_BITS_PER_UINT, 0)
- sint e = exponent.ToInt();
+ for example:
+ 10.7 will be 10
+ 12.1 -- 12
+ -20.2 -- 20
+ -20.9 -- 20
+ -0.7 -- 0
+ 0.8 -- 0
+ */
+ void SkipFraction()
+ {
+ if( IsNan() || IsZero() )
+ return;
- mantissa.ClearFirstBits( -e );
+ if( !exponent.IsSign() )
+ // exponent >=0 -- the value don't have any fractions
+ return;
- // we don't have to standardize 'Standardizing()' the value because
- // there's at least one bit in the mantissa
- // (the highest bit which we didn't touch)
- }
+ if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) )
+ {
+ // the value is from (-1,1), we return zero
+ SetZero();
+ return;
+ }
+ // exponent is in range (-man*TTMATH_BITS_PER_UINT, 0)
+ sint e = exponent.ToInt();
+
+ mantissa.ClearFirstBits( -e );
+
+ // we don't have to standardize 'Standardizing()' the value because
+ // there's at least one bit in the mantissa
+ // (the highest bit which we didn't touch)
+ }
- /*!
- this method remains only a fraction from the value
- for example:
- 30.56 will be 0.56
- -12.67 -- -0.67
- */
- void RemainFraction()
- {
- if( IsNan() || IsZero() )
- return;
+ /*!
+ this method remains only a fraction from the value
- if( !exponent.IsSign() )
- {
- // exponent >= 0 -- the value doesn't have any fractions
- // we return zero
- SetZero();
- return;
- }
+ for example:
+ 30.56 will be 0.56
+ -12.67 -- -0.67
+ */
+ void RemainFraction()
+ {
+ if( IsNan() || IsZero() )
+ return;
- if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) )
- {
- // the value is from (-1,1)
- // we don't make anything with the value
- return;
- }
+ if( !exponent.IsSign() )
+ {
+ // exponent >= 0 -- the value doesn't have any fractions
+ // we return zero
+ SetZero();
+ return;
+ }
- // e will be from (-man*TTMATH_BITS_PER_UINT, 0)
- sint e = exponent.ToInt();
+ if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) )
+ {
+ // the value is from (-1,1)
+ // we don't make anything with the value
+ return;
+ }
- sint how_many_bits_leave = sint(man*TTMATH_BITS_PER_UINT) + e; // there'll be a subtraction -- e is negative
- mantissa.Rcl( how_many_bits_leave, 0);
+ // e will be from (-man*TTMATH_BITS_PER_UINT, 0)
+ sint e = exponent.ToInt();
- // there'll not be a carry because the exponent is too small
- exponent.Sub( how_many_bits_leave );
+ sint how_many_bits_leave = sint(man*TTMATH_BITS_PER_UINT) + e; // there'll be a subtraction -- e is negative
+ mantissa.Rcl( how_many_bits_leave, 0);
- // we must call Standardizing() here
- Standardizing();
- }
+ // there'll not be a carry because the exponent is too small
+ exponent.Sub( how_many_bits_leave );
+ // we must call Standardizing() here
+ Standardizing();
+ }
- /*!
- this method returns true if the value is integer
- (there is no a fraction)
- (we don't check nan)
- */
- bool IsInteger() const
- {
- if( IsZero() )
- return true;
+ /*!
+ this method returns true if the value is integer
+ (there is no a fraction)
- if( !exponent.IsSign() )
- // exponent >=0 -- the value don't have any fractions
- return true;
+ (we don't check nan)
+ */
+ bool IsInteger() const
+ {
+ if( IsZero() )
+ return true;
- if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) )
- // the value is from (-1,1)
- return false;
+ if( !exponent.IsSign() )
+ // exponent >=0 -- the value don't have any fractions
+ return true;
- // exponent is in range (-man*TTMATH_BITS_PER_UINT, 0)
- sint e = exponent.ToInt();
- e = -e; // e means how many bits we must check
+ if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) )
+ // the value is from (-1,1)
+ return false;
- uint len = e / TTMATH_BITS_PER_UINT;
- uint rest = e % TTMATH_BITS_PER_UINT;
- uint i = 0;
+ // exponent is in range (-man*TTMATH_BITS_PER_UINT, 0)
+ sint e = exponent.ToInt();
+ e = -e; // e means how many bits we must check
- for( ; i<len ; ++i )
- if( mantissa.table[i] != 0 )
- return false;
+ uint len = e / TTMATH_BITS_PER_UINT;
+ uint rest = e % TTMATH_BITS_PER_UINT;
+ uint i = 0;
- if( rest > 0 )
- {
- uint rest_mask = TTMATH_UINT_MAX_VALUE >> (TTMATH_BITS_PER_UINT - rest);
- if( (mantissa.table[i] & rest_mask) != 0 )
- return false;
- }
+ for( ; i<len ; ++i )
+ if( mantissa.table[i] != 0 )
+ return false;
- return true;
- }
+ if( rest > 0 )
+ {
+ uint rest_mask = TTMATH_UINT_MAX_VALUE >> (TTMATH_BITS_PER_UINT - rest);
+ if( (mantissa.table[i] & rest_mask) != 0 )
+ return false;
+ }
+ return true;
+ }
- /*!
- this method rounds to the nearest integer value
- (it returns a carry if it was)
- for example:
- 2.3 = 2
- 2.8 = 3
+ /*!
+ this method rounds to the nearest integer value
+ (it returns a carry if it was)
- -2.3 = -2
- -2.8 = 3
- */
- uint Round()
- {
- Big<exp,man> half;
- uint c;
+ for example:
+ 2.3 = 2
+ 2.8 = 3
- if( IsNan() )
- return 1;
+ -2.3 = -2
+ -2.8 = 3
+ */
+ uint Round()
+ {
+ Big<exp,man> half;
+ uint c;
- if( IsZero() )
- return 0;
+ if( IsNan() )
+ return 1;
- half.Set05();
+ if( IsZero() )
+ return 0;
- if( IsSign() )
- {
- // 'this' is < 0
- c = Sub( half );
- }
- else
- {
- // 'this' is > 0
- c = Add( half );
- }
+ half.Set05();
- SkipFraction();
+ if( IsSign() )
+ {
+ // 'this' is < 0
+ c = Sub( half );
+ }
+ else
+ {
+ // 'this' is > 0
+ c = Add( half );
+ }
- return CheckCarry(c);
- }
+ SkipFraction();
+ return CheckCarry(c);
+ }
+
- /*!
- *
- * input/output operators for standard streams
- *
- */
+ /*!
+ *
+ * input/output operators for standard streams
+ *
+ */
private:
- /*!
- an auxiliary method for outputing to standard streams
- */
- template<class ostream_type, class string_type>
- static ostream_type & OutputToStream(ostream_type & s, const Big<exp,man> & l)
- {
- string_type ss;
+ /*!
+ an auxiliary method for outputing to standard streams
+ */
+ template<class ostream_type, class string_type>
+ static ostream_type & OutputToStream(ostream_type & s, const Big<exp,man> & l)
+ {
+ string_type ss;
- l.ToString(ss);
- s << ss;
+ l.ToString(ss);
+ s << ss;
- return s;
- }
+ return s;
+ }
public:
- /*!
- output to standard streams
- */
- friend std::ostream & operator<<(std::ostream & s, const Big<exp,man> & l)
- {
- return OutputToStream<std::ostream, std::string>(s, l);
- }
+ /*!
+ output to standard streams
+ */
+ friend std::ostream & operator<<(std::ostream & s, const Big<exp,man> & l)
+ {
+ return OutputToStream<std::ostream, std::string>(s, l);
+ }
+
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
+ /*!
+ output to standard streams
+ */
+ friend std::wostream & operator<<(std::wostream & s, const Big<exp,man> & l)
+ {
+ return OutputToStream<std::wostream, std::wstring>(s, l);
+ }
+#endif
private:
- /*!
- an auxiliary method for converting from a string
- */
- template<class istream_type, class string_type, class char_type>
- static istream_type & InputFromStream(istream_type & s, Big<exp,man> & l)
- {
- string_type ss;
-
- // char or wchar_t for operator>>
- char_type z, old_z;
- bool was_comma = false;
- bool was_e = false;
-
-
- // operator>> omits white characters if they're set for ommiting
- s >> z;
-
- if( z=='-' || z=='+' )
- {
- ss += z;
- s >> z; // we're reading a next character (white characters can be ommited)
- }
-
- old_z = 0;
-
- // we're reading only digits (base=10) and only one comma operator
- for( ; s.good() ; z=static_cast<char_type>(s.get()) )
- {
- if( z=='.' || z==',' )
- {
- if( was_comma || was_e )
- // second comma operator or comma operator after 'e' character
- break;
-
- was_comma = true;
- }
- else
- if( z == 'e' || z == 'E' )
- {
- if( was_e )
- // second 'e' character
- break;
-
- was_e = true;
- }
- else
- if( z == '+' || z == '-' )
- {
- if( old_z != 'e' && old_z != 'E' )
- // '+' or '-' is allowed only after 'e' character
- break;
- }
- else
- if( Misc::CharToDigit(z, 10) < 0 )
- break;
-
-
- ss += z;
- old_z = z;
- }
-
- // we're leaving the last read character
- // (it's not belonging to the value)
- s.unget();
+ /*!
+ an auxiliary method for converting from a string
+ */
+ template<class istream_type, class string_type, class char_type>
+ static istream_type & InputFromStream(istream_type & s, Big<exp,man> & l)
+ {
+ string_type ss;
+
+ // char or wchar_t for operator>>
+ char_type z, old_z;
+ bool was_comma = false;
+ bool was_e = false;
+
+
+ // operator>> omits white characters if they're set for ommiting
+ s >> z;
+
+ if( z=='-' || z=='+' )
+ {
+ ss += z;
+ s >> z; // we're reading a next character (white characters can be ommited)
+ }
+
+ old_z = 0;
+
+ // we're reading only digits (base=10) and only one comma operator
+ for( ; s.good() ; z=static_cast<char_type>(s.get()) )
+ {
+ if( z=='.' || z==',' )
+ {
+ if( was_comma || was_e )
+ // second comma operator or comma operator after 'e' character
+ break;
+
+ was_comma = true;
+ }
+ else
+ if( z == 'e' || z == 'E' )
+ {
+ if( was_e )
+ // second 'e' character
+ break;
+
+ was_e = true;
+ }
+ else
+ if( z == '+' || z == '-' )
+ {
+ if( old_z != 'e' && old_z != 'E' )
+ // '+' or '-' is allowed only after 'e' character
+ break;
+ }
+ else
+ if( Misc::CharToDigit(z, 10) < 0 )
+ break;
+
+
+ ss += z;
+ old_z = z;
+ }
+
+ // we're leaving the last read character
+ // (it's not belonging to the value)
+ s.unget();
- l.FromString( ss );
+ l.FromString( ss );
- return s;
- }
+ return s;
+ }
public:
- /*!
- input from standard streams
- */
- friend std::istream & operator>>(std::istream & s, Big<exp,man> & l)
- {
- return InputFromStream<std::istream, std::string, char>(s, l);
- }
-
+ /*!
+ input from standard streams
+ */
+ friend std::istream & operator>>(std::istream & s, Big<exp,man> & l)
+ {
+ return InputFromStream<std::istream, std::string, char>(s, l);
+ }
+
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
+ /*!
+ input from standard streams
+ */
+ friend std::wistream & operator>>(std::wistream & s, Big<exp,man> & l)
+ {
+ return InputFromStream<std::wistream, std::wstring, wchar_t>(s, l);
+ }
+#endif
};
Modified: trunk/boost/geometry/extensions/contrib/ttmath/ttmathint.h
==============================================================================
--- trunk/boost/geometry/extensions/contrib/ttmath/ttmathint.h (original)
+++ trunk/boost/geometry/extensions/contrib/ttmath/ttmathint.h 2011-02-19 08:33:14 EST (Sat, 19 Feb 2011)
@@ -4,20 +4,20 @@
* Author: Tomasz Sowa <t.sowa_at_[hidden]>
*/
-/*
- * Copyright (c) 2006-2009, Tomasz Sowa
+/*
+ * Copyright (c) 2006-2011, Tomasz Sowa
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
- *
+ *
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
- *
+ *
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* * Neither the name Tomasz Sowa nor the names of contributors to this
* project may be used to endorse or promote products derived
* from this software without specific prior written permission.
@@ -41,7 +41,7 @@
#define headerfilettmathint
/*!
- \file ttmathint.h
+ \file ttmathint.h
\brief template class Int<uint>
*/
@@ -52,1478 +52,1867 @@
/*!
- \brief Int implements a big integer value with a sign
+ \brief Int implements a big integer value with a sign
- value_size - how many bytes specify our value
- on 32bit platforms: value_size=1 -> 4 bytes -> 32 bits
- on 64bit platforms: value_size=1 -> 8 bytes -> 64 bits
- value_size = 1,2,3,4,5,6....
+ value_size - how many bytes specify our value
+ on 32bit platforms: value_size=1 -> 4 bytes -> 32 bits
+ on 64bit platforms: value_size=1 -> 8 bytes -> 64 bits
+ value_size = 1,2,3,4,5,6....
*/
template<uint value_size>
class Int : public UInt<value_size>
{
public:
- /*!
- this method sets the max value which this class can hold
- (all bits will be one besides the last one)
- */
- void SetMax()
- {
- UInt<value_size>::SetMax();
- UInt<value_size>::table[value_size-1] = ~ TTMATH_UINT_HIGHEST_BIT;
- }
-
-
- /*!
- this method sets the min value which this class can hold
- (all bits will be zero besides the last one which is one)
- */
- void SetMin()
- {
- UInt<value_size>::SetZero();
- UInt<value_size>::table[value_size-1] = TTMATH_UINT_HIGHEST_BIT;
- }
-
-
- /*!
- this method sets -1 as the value
- (-1 is equal the max value in an unsigned type)
- */
- void SetSignOne()
- {
- UInt<value_size>::SetMax();
- }
-
-
- /*!
- we change the sign of the value
+ /*!
+ this method sets the max value which this class can hold
+ (all bits will be one besides the last one)
+ */
+ void SetMax()
+ {
+ UInt<value_size>::SetMax();
+ UInt<value_size>::table[value_size-1] = ~ TTMATH_UINT_HIGHEST_BIT;
+ }
+
+
+ /*!
+ this method sets the min value which this class can hold
+ (all bits will be zero besides the last one which is one)
+ */
+ void SetMin()
+ {
+ UInt<value_size>::SetZero();
+ UInt<value_size>::table[value_size-1] = TTMATH_UINT_HIGHEST_BIT;
+ }
+
+
+ /*!
+ this method sets -1 as the value
+ (-1 is equal the max value in an unsigned type)
+ */
+ void SetSignOne()
+ {
+ UInt<value_size>::SetMax();
+ }
+
+
+ /*!
+ we change the sign of the value
+
+ if it isn't possible to change the sign this method returns 1
+ else return 0 and changing the sign
+ */
+ uint ChangeSign()
+ {
+ /*
+ if the value is equal that one which has been returned from SetMin
+ (only the highest bit is set) that means we can't change sign
+ because the value is too big (bigger about one)
+
+ e.g. when value_size = 1 and value is -2147483648 we can't change it to the
+ 2147483648 because the max value which can be held is 2147483647
+
+ we don't change the value and we're using this fact somewhere in some methods
+ (if we look on our value without the sign we get the correct value
+ eg. -2147483648 in Int<1> will be 2147483648 on the UInt<1> type)
+ */
+ if( UInt<value_size>::IsOnlyTheHighestBitSet() )
+ return 1;
+
+ UInt<value_size> temp(*this);
+ UInt<value_size>::SetZero();
+ UInt<value_size>::Sub(temp);
+
+ return 0;
+ }
+
+
+
+ /*!
+ this method sets the sign
+
+ e.g. 1 -> -1
+ -2 -> -2
+
+ from a positive value we make a negative value,
+ if the value is negative we do nothing
+ */
+ void SetSign()
+ {
+ if( IsSign() )
+ return;
+
+ ChangeSign();
+ }
+
+
+
+ /*!
+ this method returns true if there's the sign
+
+ (the highest bit will be converted to the bool)
+ */
+ bool IsSign() const
+ {
+ return UInt<value_size>::IsTheHighestBitSet();
+ }
+
+
+
+ /*!
+ it sets an absolute value
+
+ it can return carry (1) (look on ChangeSign() for details)
+ */
+ uint Abs()
+ {
+ if( !IsSign() )
+ return 0;
+
+ return ChangeSign();
+ }
+
+
+
+
+ /*!
+ *
+ * basic mathematic functions
+ *
+ */
- if it isn't possible to change the sign this method returns 1
- else return 0 and changing the sign
- */
- uint ChangeSign()
- {
- Int<value_size> temp;
-
- temp.SetMin();
-
- /*
- if the value is equal that one which has been returned from SetMin
- that means we can't change sign because the value is too big (bigger about one)
-
- e.g. when value_size = 1 and value is -2147483648 we can't change it to the
- 2147483648 because the max value which can be held is 2147483647
-
- we don't change the value and we're using this fact somewhere in some methods
- (if we look on our value without the sign we get the correct value
- eg. -2147483648 in Int<1> will be 2147483648 on the UInt<1> type)
- */
- if( operator==(temp) )
- return 1;
-
- temp.SetZero();
- temp.UInt<value_size>::Sub(*this);
+private:
- operator=(temp);
+ uint CorrectCarryAfterAdding(bool p1_is_sign, bool p2_is_sign)
+ {
+ if( !p1_is_sign && !p2_is_sign )
+ {
+ if( UInt<value_size>::IsTheHighestBitSet() )
+ return 1;
+ }
+
+ if( p1_is_sign && p2_is_sign )
+ {
+ if( ! UInt<value_size>::IsTheHighestBitSet() )
+ return 1;
+ }
- return 0;
- }
+ return 0;
+ }
+public:
- /*!
- this method sets the sign
+ /*!
+ this method adds two value with a sign and returns a carry
- e.g. 1 -> -1
- -2 -> -2
+ we're using methods from the base class because values are stored with U2
+ we must only make the carry correction
- from a positive value we make a negative value,
- if the value is negative we do nothing
- */
- void SetSign()
- {
- if( IsSign() )
- return;
+ this = p1(=this) + p2
- ChangeSign();
- }
+ when p1>=0 i p2>=0 carry is set when the highest bit of value is set
+ when p1<0 i p2<0 carry is set when the highest bit of value is clear
+ when p1>=0 i p2<0 carry will never be set
+ when p1<0 i p2>=0 carry will never be set
+ */
+ uint Add(const Int<value_size> & ss2)
+ {
+ bool p1_is_sign = IsSign();
+ bool p2_is_sign = ss2.IsSign();
+ UInt<value_size>::Add(ss2);
+ return CorrectCarryAfterAdding(p1_is_sign, p2_is_sign);
+ }
- /*!
- this method returns true if there's the sign
- (the highest bit will be converted to the bool)
- */
- bool IsSign() const
- {
- return UInt<value_size>::IsTheHighestBitSet();
- }
+ /*!
+ this method adds one *unsigned* word (at a specific position)
+ and returns a carry (if it was)
+ look at a description in UInt<>::AddInt(...)
+ */
+ uint AddInt(uint value, uint index = 0)
+ {
+ bool p1_is_sign = IsSign();
+ UInt<value_size>::AddInt(value, index);
- /*!
- it sets an absolute value
+ return CorrectCarryAfterAdding(p1_is_sign, false);
+ }
- it can return carry (1) (look on ChangeSign() for details)
- */
- uint Abs()
- {
- if( !IsSign() )
- return 0;
- return ChangeSign();
- }
+ /*!
+ this method adds two *unsigned* words to the existing value
+ and these words begin on the 'index' position
+ index should be equal or smaller than value_size-2 (index <= value_size-2)
+ x1 - lower word, x2 - higher word
+ look at a description in UInt<>::AddTwoInts(...)
+ */
+ uint AddTwoInts(uint x2, uint x1, uint index)
+ {
+ bool p1_is_sign = IsSign();
+ UInt<value_size>::AddTwoInts(x2, x1, index);
- /*!
- *
- * basic mathematic functions
- *
- */
+ return CorrectCarryAfterAdding(p1_is_sign, false);
+ }
private:
- uint CorrectCarryAfterAdding(bool p1_is_sign, bool p2_is_sign)
- {
- if( !p1_is_sign && !p2_is_sign )
- {
- if( UInt<value_size>::IsTheHighestBitSet() )
- return 1;
- }
-
- if( p1_is_sign && p2_is_sign )
- {
- if( ! UInt<value_size>::IsTheHighestBitSet() )
- return 1;
- }
-
- return 0;
- }
+ uint CorrectCarryAfterSubtracting(bool p1_is_sign, bool p2_is_sign)
+ {
+ if( !p1_is_sign && p2_is_sign )
+ {
+ if( UInt<value_size>::IsTheHighestBitSet() )
+ return 1;
+ }
+
+ if( p1_is_sign && !p2_is_sign )
+ {
+ if( ! UInt<value_size>::IsTheHighestBitSet() )
+ return 1;
+ }
+ return 0;
+ }
public:
- /*!
- this method adds two value with a sign and returns a carry
-
- we're using methods from the base class because values are stored with U2
- we must only make the carry correction
-
- this = p1(=this) + p2
+ /*!
+ this method subtracts two values with a sign
- when p1>=0 i p2>=0 carry is set when the highest bit of value is set
- when p1<0 i p2<0 carry is set when the highest bit of value is clear
- when p1>=0 i p2<0 carry will never be set
- when p1<0 i p2>=0 carry will never be set
- */
- uint Add(const Int<value_size> & ss2)
- {
- bool p1_is_sign = IsSign();
- bool p2_is_sign = ss2.IsSign();
+ we don't use the previous Add because the method ChangeSign can
+ sometimes return carry
- UInt<value_size>::Add(ss2);
+ this = p1(=this) - p2
- return CorrectCarryAfterAdding(p1_is_sign, p2_is_sign);
- }
+ when p1>=0 i p2>=0 carry will never be set
+ when p1<0 i p2<0 carry will never be set
+ when p1>=0 i p2<0 carry is set when the highest bit of value is set
+ when p1<0 i p2>=0 carry is set when the highest bit of value is clear
+ */
+ uint Sub(const Int<value_size> & ss2)
+ {
+ bool p1_is_sign = IsSign();
+ bool p2_is_sign = ss2.IsSign();
+ UInt<value_size>::Sub(ss2);
- /*!
- this method adds one *unsigned* word (at a specific position)
- and returns a carry (if it was)
+ return CorrectCarryAfterSubtracting(p1_is_sign, p2_is_sign);
+ }
- look at a description in UInt<>::AddInt(...)
- */
- uint AddInt(uint value, uint index = 0)
- {
- bool p1_is_sign = IsSign();
- UInt<value_size>::AddInt(value, index);
+ /*!
+ this method subtracts one *unsigned* word (at a specific position)
+ and returns a carry (if it was)
+ */
+ uint SubInt(uint value, uint index = 0)
+ {
+ bool p1_is_sign = IsSign();
- return CorrectCarryAfterAdding(p1_is_sign, false);
- }
+ UInt<value_size>::SubInt(value, index);
+ return CorrectCarryAfterSubtracting(p1_is_sign, false);
+ }
- /*!
- this method adds two *unsigned* words to the existing value
- and these words begin on the 'index' position
- index should be equal or smaller than value_size-2 (index <= value_size-2)
- x1 - lower word, x2 - higher word
+ /*!
+ this method adds one to the value and returns carry
+ */
+ uint AddOne()
+ {
+ bool p1_is_sign = IsSign();
- look at a description in UInt<>::AddTwoInts(...)
- */
- uint AddTwoInts(uint x2, uint x1, uint index)
- {
- bool p1_is_sign = IsSign();
+ UInt<value_size>::AddOne();
- UInt<value_size>::AddTwoInts(x2, x1, index);
+ return CorrectCarryAfterAdding(p1_is_sign, false);
+ }
- return CorrectCarryAfterAdding(p1_is_sign, false);
- }
-private:
-
- uint CorrectCarryAfterSubtracting(bool p1_is_sign, bool p2_is_sign)
- {
- if( !p1_is_sign && p2_is_sign )
- {
- if( UInt<value_size>::IsTheHighestBitSet() )
- return 1;
- }
-
- if( p1_is_sign && !p2_is_sign )
- {
- if( ! UInt<value_size>::IsTheHighestBitSet() )
- return 1;
- }
-
- return 0;
- }
-
-public:
+ /*!
+ this method subtracts one from the value and returns carry
+ */
+ uint SubOne()
+ {
+ bool p1_is_sign = IsSign();
- /*!
- this method subtracts two values with a sign
+ UInt<value_size>::SubOne();
- we don't use the previous Add because the method ChangeSign can
- sometimes return carry
-
- this = p1(=this) - p2
-
- when p1>=0 i p2>=0 carry will never be set
- when p1<0 i p2<0 carry will never be set
- when p1>=0 i p2<0 carry is set when the highest bit of value is set
- when p1<0 i p2>=0 carry is set when the highest bit of value is clear
- */
- uint Sub(const Int<value_size> & ss2)
- {
- bool p1_is_sign = IsSign();
- bool p2_is_sign = ss2.IsSign();
-
- UInt<value_size>::Sub(ss2);
-
- return CorrectCarryAfterSubtracting(p1_is_sign, p2_is_sign);
- }
-
-
- /*!
- this method subtracts one *unsigned* word (at a specific position)
- and returns a carry (if it was)
- */
- uint SubInt(uint value, uint index = 0)
- {
- bool p1_is_sign = IsSign();
-
- UInt<value_size>::SubInt(value, index);
-
- return CorrectCarryAfterSubtracting(p1_is_sign, false);
- }
-
-
- /*!
- this method adds one to the value and returns carry
- */
- uint AddOne()
- {
- bool p1_is_sign = IsSign();
-
- UInt<value_size>::AddOne();
-
- return CorrectCarryAfterAdding(p1_is_sign, false);
- }
-
-
- /*!
- this method subtracts one from the value and returns carry
- */
- uint SubOne()
- {
- bool p1_is_sign = IsSign();
-
- UInt<value_size>::SubOne();
-
- return CorrectCarryAfterSubtracting(p1_is_sign, false);
- }
-
-
-
- /*!
- multiplication this = this * ss2
-
- it returns carry if the result is too big
- (we're using the method from the base class but we have to make
- one correction in account of signs)
- */
- uint Mul(Int<value_size> ss2)
- {
- bool ss1_is_sign, ss2_is_sign;
-
- ss1_is_sign = IsSign();
- ss2_is_sign = ss2.IsSign();
-
- /*
- we don't have to check the carry from Abs (values will be correct
- because next we're using the method Mul from the base class UInt
- which is without a sign)
- */
- Abs();
- ss2.Abs();
-
- if( UInt<value_size>::Mul(ss2) )
- return 1;
-
-
- /*
- we have to examine the sign of the result now
- but if the result is with the sign then:
- 1. if the signs were the same that means the result is too big
- (the result must be without a sign)
- 2. if the signs were different that means if the result
- is different from that one which has been returned from SetMin()
- that is carry (result too big) but if the result is equal SetMin()
- there'll be ok (and the next SetSign will has no effect because
- the value is actually negative -- look at description of that case
- in ChangeSign())
- */
- if( IsSign() )
- {
- /*
- there can be one case where signs are different and
- the result will be equal the value from SetMin()
- (this situation is ok)
- */
- if( ss1_is_sign != ss2_is_sign )
- {
- Int<value_size> temp;
- temp.SetMin();
-
- if( operator!=(temp) )
- /*
- the result is too big
- */
- return 1;
- }
- else
- {
- /*
- the result is too big
- */
- return 1;
- }
- }
-
- if( ss1_is_sign != ss2_is_sign )
- SetSign();
-
-
- return 0;
- }
-
-
- /*!
- division this = this / ss2
- returned values:
- 0 - ok
- 1 - division by zero
-
- for example: (result means 'this')
- 20 / 3 --> result: 6 remainder: 2
- -20 / 3 --> result: -6 remainder: -2
- 20 / -3 --> result: -6 remainder: 2
- -20 / -3 --> result: 6 remainder: -2
-
- in other words: this(old) = ss2 * this(new)(result) + remainder
- */
- uint Div(Int<value_size> ss2, Int<value_size> * remainder = 0)
- {
- bool ss1_is_sign, ss2_is_sign;
-
- ss1_is_sign = IsSign();
- ss2_is_sign = ss2.IsSign();
-
- /*
- we don't have to test the carry from Abs as well as in Mul
- */
- Abs();
- ss2.Abs();
-
- uint c = UInt<value_size>::Div(ss2, remainder);
-
- if( ss1_is_sign != ss2_is_sign )
- SetSign();
-
- if( ss1_is_sign && remainder )
- remainder->SetSign();
-
- return c;
- }
-
- uint Div(const Int<value_size> & ss2, Int<value_size> & remainder)
- {
- return Div(ss2, &remainder);
- }
-
-
- /*!
- division this = this / ss2 (ss2 is int)
- returned values:
- 0 - ok
- 1 - division by zero
-
- for example: (result means 'this')
- 20 / 3 --> result: 6 remainder: 2
- -20 / 3 --> result: -6 remainder: -2
- 20 / -3 --> result: -6 remainder: 2
- -20 / -3 --> result: 6 remainder: -2
-
- in other words: this(old) = ss2 * this(new)(result) + remainder
- */
- uint DivInt(sint ss2, sint * remainder = 0)
- {
- bool ss1_is_sign, ss2_is_sign;
-
- ss1_is_sign = IsSign();
-
- /*
- we don't have to test the carry from Abs as well as in Mul
- */
- Abs();
-
- if( ss2 < 0 )
- {
- ss2 = -ss2;
- ss2_is_sign = true;
- }
- else
- {
- ss2_is_sign = false;
- }
-
- uint rem;
- uint c = UInt<value_size>::DivInt((uint)ss2, &rem);
-
- if( ss1_is_sign != ss2_is_sign )
- SetSign();
-
- if( remainder )
- {
- if( ss1_is_sign )
- *remainder = -sint(rem);
- else
- *remainder = sint(rem);
- }
-
- return c;
- }
-
-
- uint DivInt(sint ss2, sint & remainder)
- {
- return DivInt(ss2, &remainder);
- }
+ return CorrectCarryAfterSubtracting(p1_is_sign, false);
+ }
private:
- /*!
- power this = this ^ pow
- this can be negative
- pow is >= 0
- */
- uint Pow2(const Int<value_size> & pow)
- {
- bool was_sign = IsSign();
- uint c = 0;
-
- if( was_sign )
- c += Abs();
-
- uint c_temp = UInt<value_size>::Pow(pow);
- if( c_temp > 0 )
- return c_temp; // c_temp can be: 0, 1 or 2
-
- if( was_sign && (pow.table[0] & 1) == 1 )
- // negative value to the power of odd number is negative
- c += ChangeSign();
+ uint CheckMinCarry(bool ss1_is_sign, bool ss2_is_sign)
+ {
+ /*
+ we have to examine the sign of the result now
+ but if the result is with the sign then:
+ 1. if the signs were the same that means the result is too big
+ (the result must be without a sign)
+ 2. if the signs were different that means if the result
+ is different from that one which has been returned from SetMin()
+ that is carry (result too big) but if the result is equal SetMin()
+ there'll be ok (and the next SetSign will has no effect because
+ the value is actually negative -- look at description of that case
+ in ChangeSign())
+ */
+ if( IsSign() )
+ {
+ if( ss1_is_sign != ss2_is_sign )
+ {
+ /*
+ there can be one case where signs are different and
+ the result will be equal the value from SetMin() (only the highest bit is set)
+ (this situation is ok)
+ */
+ if( !UInt<value_size>::IsOnlyTheHighestBitSet() )
+ return 1;
+ }
+ else
+ {
+ // signs were the same
+ return 1;
+ }
+ }
- return (c==0)? 0 : 1;
- }
+ return 0;
+ }
public:
- /*!
- power this = this ^ pow
-
- return values:
- 0 - ok
- 1 - carry
- 2 - incorrect arguments 0^0 or 0^(-something)
- */
- uint Pow(Int<value_size> pow)
- {
- if( !pow.IsSign() )
- return Pow2(pow);
-
- if( UInt<value_size>::IsZero() )
- // if 'pow' is negative then
- // 'this' must be different from zero
- return 2;
-
- if( pow.ChangeSign() )
- return 1;
-
- Int<value_size> t(*this);
- uint c_temp = t.Pow2(pow);
- if( c_temp > 0 )
- return c_temp;
-
- UInt<value_size>::SetOne();
- if( Div(t) )
- return 1;
-
- return 0;
- }
+ /*!
+ multiplication: this = this * ss2
+ it can return a carry
+ */
+ uint MulInt(sint ss2)
+ {
+ bool ss1_is_sign, ss2_is_sign;
+ uint c;
+
+ ss1_is_sign = IsSign();
+
+ /*
+ we don't have to check the carry from Abs (values will be correct
+ because next we're using the method MulInt from the base class UInt
+ which is without a sign)
+ */
+ Abs();
+
+ if( ss2 < 0 )
+ {
+ ss2 = -ss2;
+ ss2_is_sign = true;
+ }
+ else
+ {
+ ss2_is_sign = false;
+ }
+
+ c = UInt<value_size>::MulInt((uint)ss2);
+ c += CheckMinCarry(ss1_is_sign, ss2_is_sign);
+
+ if( ss1_is_sign != ss2_is_sign )
+ SetSign();
+
+ return c;
+ }
+
+
+
+ /*!
+ multiplication this = this * ss2
+
+ it returns carry if the result is too big
+ (we're using the method from the base class but we have to make
+ one correction in account of signs)
+ */
+ uint Mul(Int<value_size> ss2)
+ {
+ bool ss1_is_sign, ss2_is_sign;
+ uint c;
+
+ ss1_is_sign = IsSign();
+ ss2_is_sign = ss2.IsSign();
+
+ /*
+ we don't have to check the carry from Abs (values will be correct
+ because next we're using the method Mul from the base class UInt
+ which is without a sign)
+ */
+ Abs();
+ ss2.Abs();
+
+ c = UInt<value_size>::Mul(ss2);
+ c += CheckMinCarry(ss1_is_sign, ss2_is_sign);
+
+ if( ss1_is_sign != ss2_is_sign )
+ SetSign();
+
+ return c;
+ }
+
+
+ /*!
+ division this = this / ss2
+ returned values:
+ 0 - ok
+ 1 - division by zero
+
+ for example: (result means 'this')
+ 20 / 3 --> result: 6 remainder: 2
+ -20 / 3 --> result: -6 remainder: -2
+ 20 / -3 --> result: -6 remainder: 2
+ -20 / -3 --> result: 6 remainder: -2
+
+ in other words: this(old) = ss2 * this(new)(result) + remainder
+ */
+ uint Div(Int<value_size> ss2, Int<value_size> * remainder = 0)
+ {
+ bool ss1_is_sign, ss2_is_sign;
+
+ ss1_is_sign = IsSign();
+ ss2_is_sign = ss2.IsSign();
+
+ /*
+ we don't have to test the carry from Abs as well as in Mul
+ */
+ Abs();
+ ss2.Abs();
+
+ uint c = UInt<value_size>::Div(ss2, remainder);
+
+ if( ss1_is_sign != ss2_is_sign )
+ SetSign();
+
+ if( ss1_is_sign && remainder )
+ remainder->SetSign();
+
+ return c;
+ }
+
+ uint Div(const Int<value_size> & ss2, Int<value_size> & remainder)
+ {
+ return Div(ss2, &remainder);
+ }
+
+
+ /*!
+ division this = this / ss2 (ss2 is int)
+ returned values:
+ 0 - ok
+ 1 - division by zero
+
+ for example: (result means 'this')
+ 20 / 3 --> result: 6 remainder: 2
+ -20 / 3 --> result: -6 remainder: -2
+ 20 / -3 --> result: -6 remainder: 2
+ -20 / -3 --> result: 6 remainder: -2
+
+ in other words: this(old) = ss2 * this(new)(result) + remainder
+ */
+ uint DivInt(sint ss2, sint * remainder = 0)
+ {
+ bool ss1_is_sign, ss2_is_sign;
+
+ ss1_is_sign = IsSign();
+
+ /*
+ we don't have to test the carry from Abs as well as in Mul
+ */
+ Abs();
+
+ if( ss2 < 0 )
+ {
+ ss2 = -ss2;
+ ss2_is_sign = true;
+ }
+ else
+ {
+ ss2_is_sign = false;
+ }
+
+ uint rem;
+ uint c = UInt<value_size>::DivInt((uint)ss2, &rem);
+
+ if( ss1_is_sign != ss2_is_sign )
+ SetSign();
+
+ if( remainder )
+ {
+ if( ss1_is_sign )
+ *remainder = -sint(rem);
+ else
+ *remainder = sint(rem);
+ }
+
+ return c;
+ }
+
+
+ uint DivInt(sint ss2, sint & remainder)
+ {
+ return DivInt(ss2, &remainder);
+ }
- /*!
- *
- * convertion methods
- *
- */
private:
- /*!
- an auxiliary method for converting both from UInt and Int
- */
- template<uint argument_size>
- uint FromUIntOrInt(const UInt<argument_size> & p, bool UInt_type)
- {
- uint min_size = (value_size < argument_size)? value_size : argument_size;
- uint i;
-
- for(i=0 ; i<min_size ; ++i)
- UInt<value_size>::table[i] = p.table[i];
-
-
- if( value_size > argument_size )
- {
- uint fill;
-
- if( UInt_type )
- fill = 0;
- else
- fill = (p.table[argument_size-1] & TTMATH_UINT_HIGHEST_BIT)?
- TTMATH_UINT_MAX_VALUE : 0;
-
- // 'this' is longer than 'p'
- for( ; i<value_size ; ++i)
- UInt<value_size>::table[i] = fill;
- }
- else
- {
- uint test = (UInt<value_size>::table[value_size-1] & TTMATH_UINT_HIGHEST_BIT)?
- TTMATH_UINT_MAX_VALUE : 0;
-
- if( UInt_type && test!=0 )
- return 1;
-
- for( ; i<argument_size ; ++i)
- if( p.table[i] != test )
- return 1;
- }
-
- return 0;
- }
-
-public:
-
- /*!
- this method converts an Int<another_size> type into this class
-
- this operation has mainly sense if the value from p
- can be held in this type
-
- it returns a carry if the value 'p' is too big
- */
- template<uint argument_size>
- uint FromInt(const Int<argument_size> & p)
- {
- return FromUIntOrInt(p, false);
- }
-
-
- /*!
- this method converts the sint type into this class
- */
- uint FromInt(sint value)
- {
- uint fill = ( value<0 ) ? TTMATH_UINT_MAX_VALUE : 0;
-
- for(uint i=1 ; i<value_size ; ++i)
- UInt<value_size>::table[i] = fill;
-
- UInt<value_size>::table[0] = uint(value);
-
- // there'll never be a carry here
- return 0;
- }
-
+ /*!
+ power this = this ^ pow
+ this can be negative
+ pow is >= 0
+ */
+ uint Pow2(const Int<value_size> & pow)
+ {
+ bool was_sign = IsSign();
+ uint c = 0;
+
+ if( was_sign )
+ c += Abs();
+
+ uint c_temp = UInt<value_size>::Pow(pow);
+ if( c_temp > 0 )
+ return c_temp; // c_temp can be: 0, 1 or 2
+
+ if( was_sign && (pow.table[0] & 1) == 1 )
+ // negative value to the power of odd number is negative
+ c += ChangeSign();
- /*!
- this method converts UInt<another_size> into this class
- */
- template<uint argument_size>
- uint FromUInt(const UInt<argument_size> & p)
- {
- return FromUIntOrInt(p, true);
- }
+ return (c==0)? 0 : 1;
+ }
- /*!
- this method converts the uint type into this class
- */
- uint FromUInt(uint value)
- {
- for(uint i=1 ; i<value_size ; ++i)
- UInt<value_size>::table[i] = 0;
-
- UInt<value_size>::table[0] = value;
-
- // there can be a carry here when the size of this value is equal one word
- // and the 'value' has the highest bit set
- if( value_size==1 && (value & TTMATH_UINT_HIGHEST_BIT)!=0 )
- return 1;
-
- return 0;
- }
-
+public:
- /*!
- the default assignment operator
- */
- Int<value_size> & operator=(const Int<value_size> & p)
- {
- FromInt(p);
+ /*!
+ power this = this ^ pow
- return *this;
- }
+ return values:
+ 0 - ok
+ 1 - carry
+ 2 - incorrect arguments 0^0 or 0^(-something)
+ */
+ uint Pow(Int<value_size> pow)
+ {
+ if( !pow.IsSign() )
+ return Pow2(pow);
+
+ if( UInt<value_size>::IsZero() )
+ // if 'pow' is negative then
+ // 'this' must be different from zero
+ return 2;
+
+ if( pow.ChangeSign() )
+ return 1;
+
+ Int<value_size> t(*this);
+ uint c_temp = t.Pow2(pow);
+ if( c_temp > 0 )
+ return c_temp;
+
+ UInt<value_size>::SetOne();
+ if( Div(t) )
+ return 1;
+
+ return 0;
+ }
- /*!
- this operator converts an Int<another_size> type to this class
- it doesn't return a carry
- */
- template<uint argument_size>
- Int<value_size> & operator=(const Int<argument_size> & p)
- {
- FromInt(p);
+ /*!
+ *
+ * convertion methods
+ *
+ */
+private:
- return *this;
- }
+ /*!
+ an auxiliary method for converting both from UInt and Int
+ */
+ template<uint argument_size>
+ uint FromUIntOrInt(const UInt<argument_size> & p, bool UInt_type)
+ {
+ uint min_size = (value_size < argument_size)? value_size : argument_size;
+ uint i;
+
+ for(i=0 ; i<min_size ; ++i)
+ UInt<value_size>::table[i] = p.table[i];
+
+
+ if( value_size > argument_size )
+ {
+ uint fill;
+
+ if( UInt_type )
+ fill = 0;
+ else
+ fill = (p.table[argument_size-1] & TTMATH_UINT_HIGHEST_BIT)?
+ TTMATH_UINT_MAX_VALUE : 0;
+
+ // 'this' is longer than 'p'
+ for( ; i<value_size ; ++i)
+ UInt<value_size>::table[i] = fill;
+ }
+ else
+ {
+ uint test = (UInt<value_size>::table[value_size-1] & TTMATH_UINT_HIGHEST_BIT)?
+ TTMATH_UINT_MAX_VALUE : 0;
+
+ if( UInt_type && test!=0 )
+ return 1;
+
+ for( ; i<argument_size ; ++i)
+ if( p.table[i] != test )
+ return 1;
+ }
- /*!
- this method converts the sint type to this class
- */
- Int<value_size> & operator=(sint i)
- {
- FromInt(i);
+ return 0;
+ }
- return *this;
- }
+public:
+ /*!
+ this method converts an Int<another_size> type into this class
- /*!
- a constructor for converting the uint to this class
- */
- Int(sint i)
- {
- FromInt(i);
- }
+ this operation has mainly sense if the value from p
+ can be held in this type
+ it returns a carry if the value 'p' is too big
+ */
+ template<uint argument_size>
+ uint FromInt(const Int<argument_size> & p)
+ {
+ return FromUIntOrInt(p, false);
+ }
+
+
+ /*!
+ this method converts the sint type into this class
+ */
+ uint FromInt(sint value)
+ {
+ uint fill = ( value<0 ) ? TTMATH_UINT_MAX_VALUE : 0;
+
+ for(uint i=1 ; i<value_size ; ++i)
+ UInt<value_size>::table[i] = fill;
+
+ UInt<value_size>::table[0] = uint(value);
+
+ // there'll never be a carry here
+ return 0;
+ }
+
+
+ /*!
+ this method converts UInt<another_size> into this class
+ */
+ template<uint argument_size>
+ uint FromUInt(const UInt<argument_size> & p)
+ {
+ return FromUIntOrInt(p, true);
+ }
+
+
+ /*!
+ this method converts UInt<another_size> into this class
+ */
+ template<uint argument_size>
+ uint FromInt(const UInt<argument_size> & p)
+ {
+ return FromUIntOrInt(p, true);
+ }
+
+
+ /*!
+ this method converts the uint type into this class
+ */
+ uint FromUInt(uint value)
+ {
+ for(uint i=1 ; i<value_size ; ++i)
+ UInt<value_size>::table[i] = 0;
+
+ UInt<value_size>::table[0] = value;
+
+ // there can be a carry here when the size of this value is equal one word
+ // and the 'value' has the highest bit set
+ if( value_size==1 && (value & TTMATH_UINT_HIGHEST_BIT)!=0 )
+ return 1;
+
+ return 0;
+ }
+
+
+ /*!
+ this method converts the uint type into this class
+ */
+ uint FromInt(uint value)
+ {
+ return FromUInt(value);
+ }
+
+
+ /*!
+ the default assignment operator
+ */
+ Int<value_size> & operator=(const Int<value_size> & p)
+ {
+ FromInt(p);
+
+ return *this;
+ }
+
+
+ /*!
+ this operator converts an Int<another_size> type to this class
+
+ it doesn't return a carry
+ */
+ template<uint argument_size>
+ Int<value_size> & operator=(const Int<argument_size> & p)
+ {
+ FromInt(p);
+
+ return *this;
+ }
+
+
+ /*!
+ this method converts the sint type to this class
+ */
+ Int<value_size> & operator=(sint i)
+ {
+ FromInt(i);
+
+ return *this;
+ }
+
+
+ /*!
+ a constructor for converting the uint to this class
+ */
+ Int(sint i)
+ {
+ FromInt(i);
+ }
+
+
+ /*!
+ a copy constructor
+ */
+ Int(const Int<value_size> & u)
+ {
+ FromInt(u);
+ }
+
+
+ /*!
+ a constructor for copying from another types
+ */
+ template<uint argument_size>
+ Int(const Int<argument_size> & u)
+ {
+ // look that 'size' we still set as 'value_size' and not as u.value_size
+ FromInt(u);
+ }
+
+
+
+ /*!
+ this operator converts an UInt<another_size> type to this class
+
+ it doesn't return a carry
+ */
+ template<uint argument_size>
+ Int<value_size> & operator=(const UInt<argument_size> & p)
+ {
+ FromUInt(p);
+
+ return *this;
+ }
+
+
+ /*!
+ this method converts the Uint type to this class
+ */
+ Int<value_size> & operator=(uint i)
+ {
+ FromUInt(i);
+
+ return *this;
+ }
+
+
+ /*!
+ a constructor for converting the uint to this class
+ */
+ Int(uint i)
+ {
+ FromUInt(i);
+ }
+
+
+ /*!
+ a constructor for copying from another types
+ */
+ template<uint argument_size>
+ Int(const UInt<argument_size> & u)
+ {
+ // look that 'size' we still set as 'value_size' and not as u.value_size
+ FromUInt(u);
+ }
+
+
+
+#ifdef TTMATH_PLATFORM32
+
+
+ /*!
+ this method converts unsigned 64 bit int type to this class
+ ***this method is created only on a 32bit platform***
+ */
+ uint FromUInt(ulint n)
+ {
+ uint c = UInt<value_size>::FromUInt(n);
+
+ if( c )
+ return 1;
+
+ if( value_size == 1 )
+ return ((UInt<value_size>::table[0] & TTMATH_UINT_HIGHEST_BIT) == 0) ? 0 : 1;
+
+ if( value_size == 2 )
+ return ((UInt<value_size>::table[1] & TTMATH_UINT_HIGHEST_BIT) == 0) ? 0 : 1;
+
+ return 0;
+ }
+
+
+ /*!
+ this method converts unsigned 64 bit int type to this class
+ ***this method is created only on a 32bit platform***
+ */
+ uint FromInt(ulint n)
+ {
+ return FromUInt(n);
+ }
+
+
+ /*!
+ this method converts signed 64 bit int type to this class
+ ***this method is created only on a 32bit platform***
+ */
+ uint FromInt(slint n)
+ {
+ uint mask = (n < 0) ? TTMATH_UINT_MAX_VALUE : 0;
+
+ UInt<value_size>::table[0] = (uint)(ulint)n;
+
+ if( value_size == 1 )
+ {
+ if( uint(ulint(n) >> 32) != mask )
+ return 1;
+
+ return ((UInt<value_size>::table[0] & TTMATH_UINT_HIGHEST_BIT) == (mask & TTMATH_UINT_HIGHEST_BIT)) ? 0 : 1;
+ }
+
+ UInt<value_size>::table[1] = (uint)(ulint(n) >> 32);
+
+ for(uint i=2 ; i<value_size ; ++i)
+ UInt<value_size>::table[i] = mask;
+
+ return 0;
+ }
+
+
+ /*!
+ this operator converts unsigned 64 bit int type to this class
+ ***this operator is created only on a 32bit platform***
+ */
+ Int<value_size> & operator=(ulint n)
+ {
+ FromUInt(n);
+
+ return *this;
+ }
+
+
+ /*!
+ a constructor for converting unsigned 64 bit int to this class
+ ***this constructor is created only on a 32bit platform***
+ */
+ Int(ulint n)
+ {
+ FromUInt(n);
+ }
+
+
+ /*!
+ this operator converts signed 64 bit int type to this class
+ ***this operator is created only on a 32bit platform***
+ */
+ Int<value_size> & operator=(slint n)
+ {
+ FromInt(n);
+
+ return *this;
+ }
+
+
+ /*!
+ a constructor for converting signed 64 bit int to this class
+ ***this constructor is created only on a 32bit platform***
+ */
+ Int(slint n)
+ {
+ FromInt(n);
+ }
- /*!
- a copy constructor
- */
- Int(const Int<value_size> & u)
- {
- FromInt(u);
- }
+#endif
- /*!
- a constructor for copying from another types
- */
- template<uint argument_size>
- Int(const Int<argument_size> & u)
- {
- // look that 'size' we still set as 'value_size' and not as u.value_size
- FromInt(u);
- }
+#ifdef TTMATH_PLATFORM64
- /*!
- this operator converts an UInt<another_size> type to this class
+ /*!
+ this method converts 32 bit unsigned int type to this class
+ ***this operator is created only on a 64bit platform***
+ */
+ uint FromUInt(unsigned int i)
+ {
+ return FromUInt(uint(i));
+ }
+
+
+ /*!
+ this method converts 32 bit unsigned int type to this class
+ ***this operator is created only on a 64bit platform***
+ */
+ uint FromInt(unsigned int i)
+ {
+ return FromUInt(i);
+ }
+
+
+ /*!
+ this method converts 32 bit signed int type to this class
+ ***this operator is created only on a 64bit platform***
+ */
+ uint FromInt(signed int i)
+ {
+ return FromInt(sint(i));
+ }
+
+
+ /*!
+ this method converts 32 bit unsigned int type to this class
+ ***this operator is created only on a 64bit platform***
+ */
+ Int<value_size> & operator=(unsigned int i)
+ {
+ FromUInt(i);
+
+ return *this;
+ }
+
+
+ /*!
+ a constructor for converting 32 bit unsigned int to this class
+ ***this constructor is created only on a 64bit platform***
+ */
+ Int(unsigned int i)
+ {
+ FromUInt(i);
+ }
+
+
+ /*!
+ this operator converts 32 bit signed int type to this class
+ ***this operator is created only on a 64bit platform***
+ */
+ Int<value_size> & operator=(signed int i)
+ {
+ FromInt(i);
+
+ return *this;
+ }
+
+
+ /*!
+ a constructor for converting 32 bit signed int to this class
+ ***this constructor is created only on a 64bit platform***
+ */
+ Int(signed int i)
+ {
+ FromInt(i);
+ }
- it doesn't return a carry
- */
- template<uint argument_size>
- Int<value_size> & operator=(const UInt<argument_size> & p)
- {
- FromUInt(p);
+#endif
- return *this;
- }
- /*!
- this method converts the Uint type to this class
- */
- Int<value_size> & operator=(uint i)
- {
- FromUInt(i);
+ /*!
+ a constructor for converting string to this class (with the base=10)
+ */
+ Int(const char * s)
+ {
+ FromString(s);
+ }
+
+
+ /*!
+ a constructor for converting a string to this class (with the base=10)
+ */
+ Int(const std::string & s)
+ {
+ FromString( s.c_str() );
+ }
+
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
+ /*!
+ a constructor for converting string to this class (with the base=10)
+ */
+ Int(const wchar_t * s)
+ {
+ FromString(s);
+ }
+
+
+ /*!
+ a constructor for converting a string to this class (with the base=10)
+ */
+ Int(const std::wstring & s)
+ {
+ FromString( s.c_str() );
+ }
- return *this;
- }
+#endif
- /*!
- a constructor for converting the uint to this class
- */
- Int(uint i)
- {
- FromUInt(i);
- }
+ /*!
+ a default constructor
+ we don't clear table etc.
+ */
+ Int()
+ {
+ }
+
+
+ /*!
+ the destructor
+ */
+ ~Int()
+ {
+ }
+
+
+ /*!
+ this method returns the lowest value from table with a sign
+
+ we must be sure when we using this method whether the value
+ will hold in an sint type or not (the rest value from table must be zero or -1)
+ */
+ sint ToInt() const
+ {
+ return sint( UInt<value_size>::table[0] );
+ }
+
+
+ /*!
+ this method converts the value to uint type
+ can return a carry if the value is too long to store it in uint type
+ */
+ uint ToUInt(uint & result) const
+ {
+ uint c = UInt<value_size>::ToUInt(result);
+
+ if( value_size == 1 )
+ return (result & TTMATH_UINT_HIGHEST_BIT) == 0 ? 0 : 1;
+
+ return c;
+ }
+
+
+ /*!
+ this method converts the value to uint type
+ can return a carry if the value is too long to store it in uint type
+ */
+ uint ToInt(uint & result) const
+ {
+ return ToUInt(result);
+ }
+
+
+ /*!
+ this method converts the value to sint type
+ can return a carry if the value is too long to store it in sint type
+ */
+ uint ToInt(sint & result) const
+ {
+ result = sint( UInt<value_size>::table[0] );
+ uint mask = IsSign() ? TTMATH_UINT_MAX_VALUE : 0;
+
+ if( (result & TTMATH_UINT_HIGHEST_BIT) != (mask & TTMATH_UINT_HIGHEST_BIT) )
+ return 1;
+
+ for(uint i=1 ; i<value_size ; ++i)
+ if( UInt<value_size>::table[i] != mask )
+ return 1;
+
+ return 0;
+ }
+
+
+#ifdef TTMATH_PLATFORM32
+
+ /*!
+ this method converts the value to ulint type (64 bit unsigned integer)
+ can return a carry if the value is too long to store it in ulint type
+ *** this method is created only on a 32 bit platform ***
+ */
+ uint ToUInt(ulint & result) const
+ {
+ uint c = UInt<value_size>::ToUInt(result);
+
+ if( value_size == 1 )
+ return (UInt<value_size>::table[0] & TTMATH_UINT_HIGHEST_BIT) == 0 ? 0 : 1;
+
+ if( value_size == 2 )
+ return (UInt<value_size>::table[1] & TTMATH_UINT_HIGHEST_BIT) == 0 ? 0 : 1;
+
+ return c;
+ }
+
+
+ /*!
+ this method converts the value to ulint type (64 bit unsigned integer)
+ can return a carry if the value is too long to store it in ulint type
+ *** this method is created only on a 32 bit platform ***
+ */
+ uint ToInt(ulint & result) const
+ {
+ return ToUInt(result);
+ }
+
+
+ /*!
+ this method converts the value to slint type (64 bit signed integer)
+ can return a carry if the value is too long to store it in slint type
+ *** this method is created only on a 32 bit platform ***
+ */
+ uint ToInt(slint & result) const
+ {
+ if( value_size == 1 )
+ {
+ result = slint(sint(UInt<value_size>::table[0]));
+ }
+ else
+ {
+ uint low = UInt<value_size>::table[0];
+ uint high = UInt<value_size>::table[1];
+
+ result = low;
+ result |= (ulint(high) << TTMATH_BITS_PER_UINT);
+
+ uint mask = IsSign() ? TTMATH_UINT_MAX_VALUE : 0;
+
+ if( (high & TTMATH_UINT_HIGHEST_BIT) != (mask & TTMATH_UINT_HIGHEST_BIT) )
+ return 1;
+
+ for(uint i=2 ; i<value_size ; ++i)
+ if( UInt<value_size>::table[i] != mask )
+ return 1;
+ }
- /*!
- a constructor for copying from another types
- */
- template<uint argument_size>
- Int(const UInt<argument_size> & u)
- {
- // look that 'size' we still set as 'value_size' and not as u.value_size
- FromUInt(u);
- }
+ return 0;
+ }
+#endif
#ifdef TTMATH_PLATFORM64
- /*!
- this method converts the signed int type to this class
+ /*!
+ this method converts the value to a 32 bit unsigned integer
+ can return a carry if the value is too long to store it in this type
+ *** this method is created only on a 64 bit platform ***
+ */
+ uint ToUInt(unsigned int & result) const
+ {
+ uint c = UInt<value_size>::ToUInt(result);
+
+ if( c || IsSign() )
+ return 1;
+
+ return 0;
+ }
+
+
+ /*!
+ this method converts the value to a 32 bit unsigned integer
+ can return a carry if the value is too long to store it in this type
+ *** this method is created only on a 64 bit platform ***
+ */
+ uint ToInt(unsigned int & result) const
+ {
+ return ToUInt(result);
+ }
+
+
+ /*!
+ this method converts the value to a 32 bit signed integer
+ can return a carry if the value is too long to store it in this type
+ *** this method is created only on a 64 bit platform ***
+ */
+ uint ToInt(int & result) const
+ {
+ uint first = UInt<value_size>::table[0];
+
+ result = int(first);
+ uint mask = IsSign() ? TTMATH_UINT_MAX_VALUE : 0;
+
+ if( (first >> 31) != (mask >> 31) )
+ return 1;
+
+ for(uint i=1 ; i<value_size ; ++i)
+ if( UInt<value_size>::table[i] != mask )
+ return 1;
- ***this operator is created only on a 64bit platform***
- it takes one argument of 32bit
- */
- Int<value_size> & operator=(signed int i)
- {
- FromInt(sint(i));
-
- return *this;
- }
-
-
- /*!
- a constructor for converting the signed int to this class
-
- ***this constructor is created only on a 64bit platform***
- it takes one argument of 32bit
- */
- Int(signed int i)
- {
- FromInt(sint(i));
- }
-
-
- /*!
- this method converts the unsigned int type to this class
-
- ***this operator is created only on a 64bit platform***
- it takes one argument of 32bit
- */
- Int<value_size> & operator=(unsigned int i)
- {
- FromUInt(uint(i));
-
- return *this;
- }
-
-
- /*!
- a constructor for converting the unsigned int to this class
-
- ***this constructor is created only on a 64bit platform***
- it takes one argument of 32bit
- */
- Int(unsigned int i)
- {
- FromUInt(uint(i));
- }
+ return 0;
+ }
#endif
- /*!
- a constructor for converting string to this class (with the base=10)
- */
- Int(const char * s)
- {
- FromString(s);
- }
-
-
- /*!
- a constructor for converting string to this class (with the base=10)
- */
- Int(const wchar_t * s)
- {
- FromString(s);
- }
-
-
- /*!
- a constructor for converting a string to this class (with the base=10)
- */
- Int(const std::string & s)
- {
- FromString( s.c_str() );
- }
-
-
- /*!
- a constructor for converting a string to this class (with the base=10)
- */
- Int(const std::wstring & s)
- {
- FromString( s.c_str() );
- }
-
-
- /*!
- a default constructor
-
- we don't clear table etc.
- */
- Int()
- {
- }
-
-
- /*!
- the destructor
- */
- ~Int()
- {
- }
-
-
- /*!
- this method returns the lowest value from table with a sign
-
- we must be sure when we using this method whether the value
- will hold in an sint type or not (the rest value from table must be zero or -1)
- */
- sint ToInt() const
- {
- return sint( UInt<value_size>::table[0] );
- }
-
-
-private:
-
- /*!
- an auxiliary method for converting to a string
- */
- template<class string_type>
- void ToStringBase(string_type & result, uint b = 10) const
- {
- if( IsSign() )
- {
- Int<value_size> temp(*this);
- temp.Abs();
-
- temp.UInt<value_size>::ToString(result, b);
- result.insert(result.begin(), '-');
- }
- else
- {
- UInt<value_size>::ToString(result, b);
- }
- }
-
-public:
-
- /*!
- this method converts the value to a string with a base equal 'b'
- */
- void ToString(std::string & result, uint b = 10) const
- {
- return ToStringBase(result, b);
- }
-
-
- /*!
- this method converts the value to a string with a base equal 'b'
- */
- void ToString(std::wstring & result, uint b = 10) const
- {
- return ToStringBase(result, b);
- }
-
-
- /*!
- this method converts the value to a string with a base equal 'b'
- */
- std::string ToString(uint b = 10) const
- {
- std::string result;
- ToStringBase(result, b);
-
- return result;
- }
-
-
- /*!
- this method converts the value to a string with a base equal 'b'
- */
- std::wstring ToWString(uint b = 10) const
- {
- std::wstring result;
- ToStringBase(result, b);
-
- return result;
- }
private:
- /*!
- an auxiliary method for converting from a string
- */
- template<class char_type>
- uint FromStringBase(const char_type * s, uint b = 10, const char_type ** after_source = 0, bool * value_read = 0)
- {
- bool is_sign = false;
-
- Misc::SkipWhiteCharacters(s);
-
- if( *s == '-' )
- {
- is_sign = true;
- Misc::SkipWhiteCharacters(++s);
- }
- else
- if( *s == '+' )
- {
- Misc::SkipWhiteCharacters(++s);
- }
-
- if( UInt<value_size>::FromString(s,b,after_source,value_read) )
- return 1;
-
- if( is_sign )
- {
- Int<value_size> mmin;
-
- mmin.SetMin();
-
- /*
- the reference to mmin will be automatically converted to the reference
- to UInt type
- (this value can be equal mmin -- look at a description in ChangeSign())
- */
- if( UInt<value_size>::operator>( mmin ) )
- return 1;
-
- /*
- if the value is equal mmin the method ChangeSign() does nothing (only returns 1 but we ignore it)
- */
- ChangeSign();
- }
- else
- {
- Int<value_size> mmax;
-
- mmax.SetMax();
-
- if( UInt<value_size>::operator>( mmax ) )
- return 1;
- }
-
- return 0;
- }
-
+ /*!
+ an auxiliary method for converting to a string
+ */
+ template<class string_type>
+ void ToStringBase(string_type & result, uint b = 10) const
+ {
+ if( IsSign() )
+ {
+ Int<value_size> temp(*this);
+ temp.Abs();
+ temp.UInt<value_size>::ToStringBase(result, b, true);
+ }
+ else
+ {
+ UInt<value_size>::ToStringBase(result, b, false);
+ }
+ }
public:
- /*!
- this method converts a string into its value
- it returns carry=1 if the value will be too big or an incorrect base 'b' is given
-
- string is ended with a non-digit value, for example:
- "-12" will be translated to -12
- as well as:
- "- 12foo" will be translated to -12 too
-
- existing first white characters will be ommited
- (between '-' and a first digit can be white characters too)
-
- after_source (if exists) is pointing at the end of the parsed string
-
- value_read (if exists) tells whether something has actually been read (at least one digit)
- */
- uint FromString(const char * s, uint b = 10, const char ** after_source = 0, bool * value_read = 0)
- {
- return FromStringBase(s, b, after_source, value_read);
- }
-
-
- /*!
- this method converts a string into its value
- */
- uint FromString(const wchar_t * s, uint b = 10, const wchar_t ** after_source = 0, bool * value_read = 0)
- {
- return FromStringBase(s, b, after_source, value_read);
- }
-
-
- /*!
- this method converts a string into its value
- it returns carry=1 if the value will be too big or an incorrect base 'b' is given
- */
- uint FromString(const std::string & s, uint b = 10)
- {
- return FromString( s.c_str(), b );
- }
+ /*!
+ this method converts the value to a string with a base equal 'b'
+ */
+ void ToString(std::string & result, uint b = 10) const
+ {
+ return ToStringBase(result, b);
+ }
+
+
+ /*!
+ this method converts the value to a string with a base equal 'b'
+ */
+ std::string ToString(uint b = 10) const
+ {
+ std::string result;
+ ToStringBase(result, b);
+
+ return result;
+ }
+
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
+ /*!
+ this method converts the value to a string with a base equal 'b'
+ */
+ void ToString(std::wstring & result, uint b = 10) const
+ {
+ return ToStringBase(result, b);
+ }
+
+
+ /*!
+ this method converts the value to a string with a base equal 'b'
+ */
+ std::wstring ToWString(uint b = 10) const
+ {
+ std::wstring result;
+ ToStringBase(result, b);
+ return result;
+ }
- /*!
- this method converts a string into its value
- it returns carry=1 if the value will be too big or an incorrect base 'b' is given
- */
- uint FromString(const std::wstring & s, uint b = 10)
- {
- return FromString( s.c_str(), b );
- }
-
-
- /*!
- this operator converts a string into its value (with base = 10)
- */
- Int<value_size> & operator=(const char * s)
- {
- FromString(s);
+#endif
- return *this;
- }
- /*!
- this operator converts a string into its value (with base = 10)
- */
- Int<value_size> & operator=(const wchar_t * s)
- {
- FromString(s);
+private:
- return *this;
- }
+ /*!
+ an auxiliary method for converting from a string
+ */
+ template<class char_type>
+ uint FromStringBase(const char_type * s, uint b = 10, const char_type ** after_source = 0, bool * value_read = 0)
+ {
+ bool is_sign = false;
+
+ Misc::SkipWhiteCharacters(s);
+
+ if( *s == '-' )
+ {
+ is_sign = true;
+ Misc::SkipWhiteCharacters(++s);
+ }
+ else
+ if( *s == '+' )
+ {
+ Misc::SkipWhiteCharacters(++s);
+ }
+
+ if( UInt<value_size>::FromString(s,b,after_source,value_read) )
+ return 1;
+
+ if( is_sign )
+ {
+ Int<value_size> mmin;
+
+ mmin.SetMin();
+
+ /*
+ the reference to mmin will be automatically converted to the reference
+ to UInt type
+ (this value can be equal mmin -- look at a description in ChangeSign())
+ */
+ if( UInt<value_size>::operator>( mmin ) )
+ return 1;
+
+ /*
+ if the value is equal mmin the method ChangeSign() does nothing (only returns 1 but we ignore it)
+ */
+ ChangeSign();
+ }
+ else
+ {
+ Int<value_size> mmax;
+
+ mmax.SetMax();
+
+ if( UInt<value_size>::operator>( mmax ) )
+ return 1;
+ }
+ return 0;
+ }
- /*!
- this operator converts a string into its value (with base = 10)
- */
- Int<value_size> & operator=(const std::string & s)
- {
- FromString( s.c_str() );
- return *this;
- }
+public:
+ /*!
+ this method converts a string into its value
+ it returns carry=1 if the value will be too big or an incorrect base 'b' is given
+
+ string is ended with a non-digit value, for example:
+ "-12" will be translated to -12
+ as well as:
+ "- 12foo" will be translated to -12 too
+
+ existing first white characters will be ommited
+ (between '-' and a first digit can be white characters too)
+
+ after_source (if exists) is pointing at the end of the parsed string
+
+ value_read (if exists) tells whether something has actually been read (at least one digit)
+ */
+ uint FromString(const char * s, uint b = 10, const char ** after_source = 0, bool * value_read = 0)
+ {
+ return FromStringBase(s, b, after_source, value_read);
+ }
+
+
+ /*!
+ this method converts a string into its value
+ */
+ uint FromString(const wchar_t * s, uint b = 10, const wchar_t ** after_source = 0, bool * value_read = 0)
+ {
+ return FromStringBase(s, b, after_source, value_read);
+ }
+
+
+ /*!
+ this method converts a string into its value
+ it returns carry=1 if the value will be too big or an incorrect base 'b' is given
+ */
+ uint FromString(const std::string & s, uint b = 10)
+ {
+ return FromString( s.c_str(), b );
+ }
+
+
+ /*!
+ this operator converts a string into its value (with base = 10)
+ */
+ Int<value_size> & operator=(const char * s)
+ {
+ FromString(s);
+
+ return *this;
+ }
+
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
+
+ /*!
+ this method converts a string into its value
+ it returns carry=1 if the value will be too big or an incorrect base 'b' is given
+ */
+ uint FromString(const std::wstring & s, uint b = 10)
+ {
+ return FromString( s.c_str(), b );
+ }
+
+
+ /*!
+ this operator converts a string into its value (with base = 10)
+ */
+ Int<value_size> & operator=(const wchar_t * s)
+ {
+ FromString(s);
+
+ return *this;
+ }
+
+
+ /*!
+ this operator converts a string into its value (with base = 10)
+ */
+ Int<value_size> & operator=(const std::wstring & s)
+ {
+ FromString( s.c_str() );
- /*!
- this operator converts a string into its value (with base = 10)
- */
- Int<value_size> & operator=(const std::wstring & s)
- {
- FromString( s.c_str() );
+ return *this;
+ }
- return *this;
- }
+#endif
- /*!
- *
- * methods for comparing
- *
- *
- */
+ /*!
+ this operator converts a string into its value (with base = 10)
+ */
+ Int<value_size> & operator=(const std::string & s)
+ {
+ FromString( s.c_str() );
- bool operator==(const Int<value_size> & l) const
- {
- return UInt<value_size>::operator==(l);
- }
+ return *this;
+ }
- bool operator!=(const Int<value_size> & l) const
- {
- return UInt<value_size>::operator!=(l);
- }
- bool operator<(const Int<value_size> & l) const
- {
- sint i=value_size-1;
- sint a1 = sint(UInt<value_size>::table[i]);
- sint a2 = sint(l.table[i]);
+ /*!
+ *
+ * methods for comparing
+ *
+ *
+ */
- if( a1 != a2 )
- return a1 < a2;
+ bool operator==(const Int<value_size> & l) const
+ {
+ return UInt<value_size>::operator==(l);
+ }
+ bool operator!=(const Int<value_size> & l) const
+ {
+ return UInt<value_size>::operator!=(l);
+ }
- for(--i ; i>=0 ; --i)
- {
- if( UInt<value_size>::table[i] != l.table[i] )
- // comparison as unsigned int
- return UInt<value_size>::table[i] < l.table[i];
- }
+ bool operator<(const Int<value_size> & l) const
+ {
+ sint i=value_size-1;
- // they're equal
- return false;
- }
+ sint a1 = sint(UInt<value_size>::table[i]);
+ sint a2 = sint(l.table[i]);
+ if( a1 != a2 )
+ return a1 < a2;
- bool operator>(const Int<value_size> & l) const
- {
- sint i=value_size-1;
- sint a1 = sint(UInt<value_size>::table[i]);
- sint a2 = sint(l.table[i]);
+ for(--i ; i>=0 ; --i)
+ {
+ if( UInt<value_size>::table[i] != l.table[i] )
+ // comparison as unsigned int
+ return UInt<value_size>::table[i] < l.table[i];
+ }
- if( a1 != a2 )
- return a1 > a2;
+ // they're equal
+ return false;
+ }
- for(--i ; i>=0 ; --i)
- {
- if( UInt<value_size>::table[i] != l.table[i] )
- // comparison as unsigned int
- return UInt<value_size>::table[i] > l.table[i];
- }
+ bool operator>(const Int<value_size> & l) const
+ {
+ sint i=value_size-1;
- // they're equal
- return false;
- }
+ sint a1 = sint(UInt<value_size>::table[i]);
+ sint a2 = sint(l.table[i]);
+ if( a1 != a2 )
+ return a1 > a2;
- bool operator<=(const Int<value_size> & l) const
- {
- sint i=value_size-1;
- sint a1 = sint(UInt<value_size>::table[i]);
- sint a2 = sint(l.table[i]);
+ for(--i ; i>=0 ; --i)
+ {
+ if( UInt<value_size>::table[i] != l.table[i] )
+ // comparison as unsigned int
+ return UInt<value_size>::table[i] > l.table[i];
+ }
- if( a1 != a2 )
- return a1 < a2;
+ // they're equal
+ return false;
+ }
- for(--i ; i>=0 ; --i)
- {
- if( UInt<value_size>::table[i] != l.table[i] )
- // comparison as unsigned int
- return UInt<value_size>::table[i] < l.table[i];
- }
+ bool operator<=(const Int<value_size> & l) const
+ {
+ sint i=value_size-1;
- // they're equal
- return true;
- }
+ sint a1 = sint(UInt<value_size>::table[i]);
+ sint a2 = sint(l.table[i]);
+ if( a1 != a2 )
+ return a1 < a2;
- bool operator>=(const Int<value_size> & l) const
- {
- sint i=value_size-1;
- sint a1 = sint(UInt<value_size>::table[i]);
- sint a2 = sint(l.table[i]);
+ for(--i ; i>=0 ; --i)
+ {
+ if( UInt<value_size>::table[i] != l.table[i] )
+ // comparison as unsigned int
+ return UInt<value_size>::table[i] < l.table[i];
+ }
- if( a1 != a2 )
- return a1 > a2;
+ // they're equal
+ return true;
+ }
- for(--i ; i>=0 ; --i)
- {
- if( UInt<value_size>::table[i] != l.table[i] )
- // comparison as unsigned int
- return UInt<value_size>::table[i] > l.table[i];
- }
+ bool operator>=(const Int<value_size> & l) const
+ {
+ sint i=value_size-1;
- // they're equal
- return true;
- }
+ sint a1 = sint(UInt<value_size>::table[i]);
+ sint a2 = sint(l.table[i]);
+ if( a1 != a2 )
+ return a1 > a2;
- /*!
- *
- * standard mathematical operators
- *
- */
+ for(--i ; i>=0 ; --i)
+ {
+ if( UInt<value_size>::table[i] != l.table[i] )
+ // comparison as unsigned int
+ return UInt<value_size>::table[i] > l.table[i];
+ }
+ // they're equal
+ return true;
+ }
- /*!
- an operator for changing the sign
- it's not changing 'this' but the changed value will be returned
- */
- Int<value_size> operator-() const
- {
- Int<value_size> temp(*this);
- temp.ChangeSign();
+ /*!
+ *
+ * standard mathematical operators
+ *
+ */
- return temp;
- }
+ /*!
+ an operator for changing the sign
- Int<value_size> operator-(const Int<value_size> & p2) const
- {
- Int<value_size> temp(*this);
+ it's not changing 'this' but the changed value will be returned
+ */
+ Int<value_size> operator-() const
+ {
+ Int<value_size> temp(*this);
- temp.Sub(p2);
+ temp.ChangeSign();
+
+ return temp;
+ }
- return temp;
- }
+ Int<value_size> operator-(const Int<value_size> & p2) const
+ {
+ Int<value_size> temp(*this);
- Int<value_size> & operator-=(const Int<value_size> & p2)
- {
- Sub(p2);
+ temp.Sub(p2);
- return *this;
- }
+ return temp;
+ }
- Int<value_size> operator+(const Int<value_size> & p2) const
- {
- Int<value_size> temp(*this);
+ Int<value_size> & operator-=(const Int<value_size> & p2)
+ {
+ Sub(p2);
- temp.Add(p2);
+ return *this;
+ }
- return temp;
- }
+ Int<value_size> operator+(const Int<value_size> & p2) const
+ {
+ Int<value_size> temp(*this);
- Int<value_size> & operator+=(const Int<value_size> & p2)
- {
- Add(p2);
+ temp.Add(p2);
- return *this;
- }
+ return temp;
+ }
- Int<value_size> operator*(const Int<value_size> & p2) const
- {
- Int<value_size> temp(*this);
+ Int<value_size> & operator+=(const Int<value_size> & p2)
+ {
+ Add(p2);
- temp.Mul(p2);
+ return *this;
+ }
- return temp;
- }
+ Int<value_size> operator*(const Int<value_size> & p2) const
+ {
+ Int<value_size> temp(*this);
- Int<value_size> & operator*=(const Int<value_size> & p2)
- {
- Mul(p2);
+ temp.Mul(p2);
- return *this;
- }
+ return temp;
+ }
- Int<value_size> operator/(const Int<value_size> & p2) const
- {
- Int<value_size> temp(*this);
+ Int<value_size> & operator*=(const Int<value_size> & p2)
+ {
+ Mul(p2);
- temp.Div(p2);
+ return *this;
+ }
- return temp;
- }
+ Int<value_size> operator/(const Int<value_size> & p2) const
+ {
+ Int<value_size> temp(*this);
- Int<value_size> & operator/=(const Int<value_size> & p2)
- {
- Div(p2);
+ temp.Div(p2);
- return *this;
- }
+ return temp;
+ }
- Int<value_size> operator%(const Int<value_size> & p2) const
- {
- Int<value_size> temp(*this);
- Int<value_size> remainder;
+ Int<value_size> & operator/=(const Int<value_size> & p2)
+ {
+ Div(p2);
- temp.Div(p2, remainder);
+ return *this;
+ }
- return remainder;
- }
+ Int<value_size> operator%(const Int<value_size> & p2) const
+ {
+ Int<value_size> temp(*this);
+ Int<value_size> remainder;
+
+ temp.Div(p2, remainder);
- Int<value_size> & operator%=(const Int<value_size> & p2)
- {
- Int<value_size> temp(*this);
- Int<value_size> remainder;
+ return remainder;
+ }
- temp.Div(p2, remainder);
- operator=(remainder);
+ Int<value_size> & operator%=(const Int<value_size> & p2)
+ {
+ Int<value_size> remainder;
+
+ Div(p2, remainder);
+ operator=(remainder);
- return *this;
- }
+ return *this;
+ }
- /*!
- Prefix operator e.g. ++variable
- */
- UInt<value_size> & operator++()
- {
- AddOne();
+ /*!
+ Prefix operator e.g. ++variable
+ */
+ UInt<value_size> & operator++()
+ {
+ AddOne();
- return *this;
- }
+ return *this;
+ }
- /*!
- Postfix operator e.g. variable++
- */
- UInt<value_size> operator++(int)
- {
- UInt<value_size> temp( *this );
+ /*!
+ Postfix operator e.g. variable++
+ */
+ UInt<value_size> operator++(int)
+ {
+ UInt<value_size> temp( *this );
- AddOne();
+ AddOne();
- return temp;
- }
+ return temp;
+ }
- UInt<value_size> & operator--()
- {
- SubOne();
+ UInt<value_size> & operator--()
+ {
+ SubOne();
- return *this;
- }
+ return *this;
+ }
- UInt<value_size> operator--(int)
- {
- UInt<value_size> temp( *this );
+ UInt<value_size> operator--(int)
+ {
+ UInt<value_size> temp( *this );
- SubOne();
+ SubOne();
- return temp;
- }
+ return temp;
+ }
- /*!
- *
- * input/output operators for standard streams
- *
- */
+ /*!
+ *
+ * input/output operators for standard streams
+ *
+ */
private:
- /*!
- an auxiliary method for outputing to standard streams
- */
- template<class ostream_type, class string_type>
- static ostream_type & OutputToStream(ostream_type & s, const Int<value_size> & l)
- {
- string_type ss;
+ /*!
+ an auxiliary method for outputing to standard streams
+ */
+ template<class ostream_type, class string_type>
+ static ostream_type & OutputToStream(ostream_type & s, const Int<value_size> & l)
+ {
+ string_type ss;
- l.ToString(ss);
- s << ss;
+ l.ToString(ss);
+ s << ss;
- return s;
- }
+ return s;
+ }
public:
- /*!
- output to standard streams
- */
- friend std::ostream & operator<<(std::ostream & s, const Int<value_size> & l)
- {
- return OutputToStream<std::ostream, std::string>(s, l);
- }
-
+ /*!
+ output to standard streams
+ */
+ friend std::ostream & operator<<(std::ostream & s, const Int<value_size> & l)
+ {
+ return OutputToStream<std::ostream, std::string>(s, l);
+ }
+
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
+ /*!
+ output to standard streams
+ */
+ friend std::wostream & operator<<(std::wostream & s, const Int<value_size> & l)
+ {
+ return OutputToStream<std::wostream, std::wstring>(s, l);
+ }
+#endif
private:
- /*!
- an auxiliary method for converting from a string
- */
- template<class istream_type, class string_type, class char_type>
- static istream_type & InputFromStream(istream_type & s, Int<value_size> & l)
- {
- string_type ss;
-
- // char or wchar_t for operator>>
- char_type z;
-
- // operator>> omits white characters if they're set for ommiting
- s >> z;
-
- if( z=='-' || z=='+' )
- {
- ss += z;
- s >> z; // we're reading a next character (white characters can be ommited)
- }
-
- // we're reading only digits (base=10)
- while( s.good() && Misc::CharToDigit(z, 10)>=0 )
- {
- ss += z;
- z = static_cast<char_type>(s.get());
- }
-
- // we're leaving the last readed character
- // (it's not belonging to the value)
- s.unget();
+ /*!
+ an auxiliary method for converting from a string
+ */
+ template<class istream_type, class string_type, class char_type>
+ static istream_type & InputFromStream(istream_type & s, Int<value_size> & l)
+ {
+ string_type ss;
+
+ // char or wchar_t for operator>>
+ char_type z;
+
+ // operator>> omits white characters if they're set for ommiting
+ s >> z;
+
+ if( z=='-' || z=='+' )
+ {
+ ss += z;
+ s >> z; // we're reading a next character (white characters can be ommited)
+ }
+
+ // we're reading only digits (base=10)
+ while( s.good() && Misc::CharToDigit(z, 10)>=0 )
+ {
+ ss += z;
+ z = static_cast<char_type>(s.get());
+ }
+
+ // we're leaving the last readed character
+ // (it's not belonging to the value)
+ s.unget();
- l.FromString(ss);
+ l.FromString(ss);
- return s;
- }
+ return s;
+ }
public:
- /*!
- input from standard streams
- */
- friend std::istream & operator>>(std::istream & s, Int<value_size> & l)
- {
- return InputFromStream<std::istream, std::string, char>(s, l);
- }
-
+ /*!
+ input from standard streams
+ */
+ friend std::istream & operator>>(std::istream & s, Int<value_size> & l)
+ {
+ return InputFromStream<std::istream, std::string, char>(s, l);
+ }
+
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
+ /*!
+ input from standard streams
+ */
+ friend std::wistream & operator>>(std::wistream & s, Int<value_size> & l)
+ {
+ return InputFromStream<std::wistream, std::wstring, wchar_t>(s, l);
+ }
+#endif
};
Modified: trunk/boost/geometry/extensions/contrib/ttmath/ttmathmisc.h
==============================================================================
--- trunk/boost/geometry/extensions/contrib/ttmath/ttmathmisc.h (original)
+++ trunk/boost/geometry/extensions/contrib/ttmath/ttmathmisc.h 2011-02-19 08:33:14 EST (Sat, 19 Feb 2011)
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (c) 2006-2009, Tomasz Sowa
+ * Copyright (c) 2006-2010, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -75,6 +75,8 @@
}
+#ifndef TTMATH_DONT_USE_WCHAR
+
/*!
result = str
*/
@@ -116,6 +118,8 @@
return AssignString(result, str.c_str());
}
+#endif
+
/*
*
@@ -134,6 +138,8 @@
}
+#ifndef TTMATH_DONT_USE_WCHAR
+
/*!
result += str
*/
@@ -143,6 +149,7 @@
result += *str;
}
+#endif
/*
Modified: trunk/boost/geometry/extensions/contrib/ttmath/ttmathobjects.h
==============================================================================
--- trunk/boost/geometry/extensions/contrib/ttmath/ttmathobjects.h (original)
+++ trunk/boost/geometry/extensions/contrib/ttmath/ttmathobjects.h 2011-02-19 08:33:14 EST (Sat, 19 Feb 2011)
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (c) 2006-2009, Tomasz Sowa
+ * Copyright (c) 2006-2010, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -99,7 +99,7 @@
if 'can_be_digit' is true that means when the 'c' is a digit this
method returns true otherwise it returns false
*/
- static bool CorrectCharacter(wchar_t c, bool can_be_digit)
+ static bool CorrectCharacter(int c, bool can_be_digit)
{
if( (c>='a' && c<='z') || (c>='A' && c<='Z') )
return true;
@@ -148,6 +148,9 @@
}
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
/*!
this method returns true if such an object is defined (name exists)
*/
@@ -163,6 +166,8 @@
return IsDefined(str_tmp1);
}
+#endif
+
/*!
this method adds one object (variable of function) into the table
@@ -184,6 +189,8 @@
}
+#ifndef TTMATH_DONT_USE_WCHAR
+
/*!
this method adds one object (variable of function) into the table
*/
@@ -200,6 +207,8 @@
return Add(str_tmp1, str_tmp2, param);
}
+#endif
+
/*!
this method returns 'true' if the table is empty
@@ -258,6 +267,9 @@
}
+#ifndef TTMATH_DONT_USE_WCHAR
+
+
/*!
this method changes the value and the number of parameters for a specific object
*/
@@ -274,6 +286,8 @@
return EditValue(str_tmp1, str_tmp2, param);
}
+#endif
+
/*!
this method changes the name of a specific object
@@ -306,6 +320,10 @@
}
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
+
/*!
this method changes the name of a specific object
*/
@@ -322,6 +340,8 @@
return EditName(str_tmp1, str_tmp2);
}
+#endif
+
/*!
this method deletes an object
@@ -342,6 +362,9 @@
}
+#ifndef TTMATH_DONT_USE_WCHAR
+
+
/*!
this method deletes an object
*/
@@ -357,7 +380,9 @@
return Delete(str_tmp1);
}
-
+#endif
+
+
/*!
this method gets the value of a specific object
*/
@@ -380,6 +405,8 @@
}
+#ifndef TTMATH_DONT_USE_WCHAR
+
/*!
this method gets the value of a specific object
*/
@@ -397,6 +424,8 @@
return err;
}
+#endif
+
/*!
this method gets the value of a specific object
@@ -421,6 +450,8 @@
}
+#ifndef TTMATH_DONT_USE_WCHAR
+
/*!
this method gets the value of a specific object
(this version is used for not copying the whole string)
@@ -437,6 +468,8 @@
return GetValue(str_tmp1, value);
}
+#endif
+
/*!
this method gets the value and the number of parameters
@@ -463,6 +496,8 @@
}
+#ifndef TTMATH_DONT_USE_WCHAR
+
/*!
this method gets the value and the number of parameters
of a specific object
@@ -481,6 +516,8 @@
return err;
}
+#endif
+
/*!
this method sets the value and the number of parameters
@@ -508,6 +545,9 @@
}
+#ifndef TTMATH_DONT_USE_WCHAR
+
+
/*!
this method sets the value and the number of parameters
of a specific object
@@ -527,6 +567,9 @@
}
+#endif
+
+
/*!
this method returns a pointer into the table
*/
Modified: trunk/boost/geometry/extensions/contrib/ttmath/ttmathparser.h
==============================================================================
--- trunk/boost/geometry/extensions/contrib/ttmath/ttmathparser.h (original)
+++ trunk/boost/geometry/extensions/contrib/ttmath/ttmathparser.h 2011-02-19 08:33:14 EST (Sat, 19 Feb 2011)
@@ -131,8 +131,8 @@
for example:
"1+2;4+5"
the result will be on the stack as follows:
- "3"
- "9"
+ stack[0].value=3
+ stack[1].value=9
*/
template<class ValueType>
class Parser
@@ -282,9 +282,16 @@
/*!
stack on which we're keeping the Items
- at the end of parsing we'll have the result on its
- the result don't have to be one value, it can be a list
- of values separated by the 'semicolon item'
+ at the end of parsing we'll have the result here
+ the result don't have to be one value, it can be
+ more than one if we have used a semicolon in the global space
+ e.g. such input string "1+2;3+4" will generate a result:
+ stack[0].value=3
+ stack[1].value=7
+
+ you should check if the stack is not empty, because if there was
+ a syntax error in the input string then we do not have any results
+ on the stack
*/
std::vector<Item> stack;
@@ -317,8 +324,6 @@
/*!
pointer to the currently reading char
- it's either char* or wchar_t*
-
when an error has occured it may be used to count the index of the wrong character
*/
const char * pstring;
@@ -1416,7 +1421,7 @@
*/
void Sprintf(char * buffer, int par)
{
-char buf[30]; // char, not wchar_t etc.
+char buf[30]; // char, not wchar_t
int i;
#ifdef _MSC_VER
@@ -2708,6 +2713,8 @@
}
+#ifndef TTMATH_DONT_USE_WCHAR
+
/*!
the main method using for parsing string
*/
@@ -2715,7 +2722,9 @@
{
Misc::AssignString(wide_to_ansi, str);
-return Parse(wide_to_ansi.c_str());
+return Parse(wide_to_ansi.c_str());
+
+ // !! wide_to_ansi clearing can be added here
}
@@ -2727,6 +2736,8 @@
return Parse(str.c_str());
}
+#endif
+
/*!
this method returns true is something was calculated
@@ -2744,6 +2755,18 @@
}
+/*!
+ initializing coefficients used when calculating the gamma (or factorial) function
+ this speed up the next calculations
+ you don't have to call this method explicitly
+ these coefficients will be calculated when needed
+*/
+void InitCGamma()
+{
+ cgamma.InitAll();
+}
+
+
};
Modified: trunk/boost/geometry/extensions/contrib/ttmath/ttmathtypes.h
==============================================================================
--- trunk/boost/geometry/extensions/contrib/ttmath/ttmathtypes.h (original)
+++ trunk/boost/geometry/extensions/contrib/ttmath/ttmathtypes.h 2011-02-19 08:33:14 EST (Sat, 19 Feb 2011)
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (c) 2006-2010, Tomasz Sowa
+ * Copyright (c) 2006-2011, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -56,70 +56,95 @@
#include <sstream>
#include <vector>
+#ifndef _MSC_VER
+#include <stdint.h>
+// for uint64_t and int64_t on a 32 bit platform
+#endif
+
+
+
/*!
the version of the library
TTMATH_PRERELEASE_VER is either zero or one
- if zero that means this is the release version of the library
+ zero means that this is the release version of the library
+ (one means something like beta)
*/
#define TTMATH_MAJOR_VER 0
#define TTMATH_MINOR_VER 9
-#define TTMATH_REVISION_VER 1
-#define TTMATH_PRERELEASE_VER 0
+#define TTMATH_REVISION_VER 3
+#define TTMATH_PRERELEASE_VER 1
-/*!
- TTMATH_DEBUG
- this macro enables further testing during writing your code
- you don't have to define it in a release mode
-
- if this macro is set then macros TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT
- are set as well and these macros can throw an exception if a condition in it
- is not fulfilled (look at the definition of TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT)
-
- TTMATH_RELEASE
- if you are confident that your code is perfect you can define TTMATH_RELEASE
- macro for example by using -D option in gcc
- gcc -DTTMATH_RELEASE -o myprogram myprogram.cpp
- or by defining this macro in your code before using any header files of this library
- if TTMATH_RELEASE is not set then TTMATH_DEBUG is set automatically
-*/
-#ifndef TTMATH_RELEASE
- #define TTMATH_DEBUG
-#endif
+/*!
+ you can define a platform explicitly by defining either
+ TTMATH_PLATFORM32 or TTMATH_PLATFORM64 macro
+*/
+#if !defined TTMATH_PLATFORM32 && !defined TTMATH_PLATFORM64
+ #if !defined _M_X64 && !defined __x86_64__
-namespace ttmath
-{
+ /*
+ other platforms than x86 and amd64 are not recognized at the moment
+ so you should set TTMATH_PLATFORMxx manually
+ */
-#if !defined _M_X64 && !defined __x86_64__
+ // we're using a 32bit platform
+ #define TTMATH_PLATFORM32
- /*!
- we're using a 32bit platform
- */
- #define TTMATH_PLATFORM32
+ #else
-#else
+ // we're using a 64bit platform
+ #define TTMATH_PLATFORM64
- /*!
- we're using a 64bit platform
- */
- #define TTMATH_PLATFORM64
+ #endif
#endif
-
/*!
- another compilers than MS VC or GCC by default use no asm version (TTMATH_NOASM)
+ asm version of the library is available by default only for:
+ x86 and amd64 platforms and for Microsoft Visual and GCC compilers
+
+ but you can force using asm version (the same asm as for Microsoft Visual)
+ by defining TTMATH_FORCEASM macro
+ you have to be sure that your compiler accept such an asm format
*/
-#if !defined _MSC_VER && !defined __GNUC__
- #define TTMATH_NOASM
+#ifndef TTMATH_FORCEASM
+
+ #if !defined __i386__ && !defined _X86_ && !defined _M_IX86 && !defined __x86_64__ && !defined _M_X64
+ /*!
+ x86 architecture:
+ __i386__ defined by GNU C
+ _X86_ defined by MinGW32
+ _M_IX86 defined by Visual Studio, Intel C/C++, Digital Mars and Watcom C/C++
+
+ amd64 architecture:
+ __x86_64__ defined by GNU C and Sun Studio
+ _M_X64 defined by Visual Studio
+
+ asm version is available only for x86 or amd64 platforms
+ */
+ #define TTMATH_NOASM
+ #endif
+
+
+
+ #if !defined _MSC_VER && !defined __GNUC__
+ /*!
+ another compilers than MS VC or GCC by default use no asm version
+ */
+ #define TTMATH_NOASM
+ #endif
+
#endif
+namespace ttmath
+{
+
#ifdef TTMATH_PLATFORM32
@@ -130,17 +155,18 @@
typedef signed int sint;
/*!
- this type is twice bigger than uint
- (64bit on a 32bit platforms)
-
- although C++ Standard - ANSI ISO IEC 14882:2003 doesn't define such a type (long long)
- but it is defined in C99 and in upcoming C++0x /3.9.1 (2)/ and many compilers support it
-
- this type is used in UInt::MulTwoWords and UInt::DivTwoWords when macro TTMATH_NOASM is defined
- but only on a 32bit platform
+ on 32 bit platform ulint and slint will be equal 64 bits
*/
- #ifdef TTMATH_NOASM
+ #ifdef _MSC_VER
+ // long long on MS Windows (Visual and GCC mingw compilers) have 64 bits
+ // stdint.h is not available on Visual Studio prior to VS 2010 version
typedef unsigned long long int ulint;
+ typedef signed long long int slint;
+ #else
+ // we do not use 'long' here because there is a difference in unix and windows
+ // environments: in unix 'long' has 64 bits but in windows it has only 32 bits
+ typedef uint64_t ulint;
+ typedef int64_t slint;
#endif
/*!
@@ -188,13 +214,8 @@
#endif
/*!
- on 64bit platform we do not define ulint
- sizeof(long long) is 8 (64bit) but we need 128bit
-
- on 64 bit platform (when there is defined TTMATH_NOASM macro)
- methods UInt::MulTwoWords and UInt::DivTwoWords are using other algorithms than those on 32 bit
+ on 64bit platforms we do not define ulint and slint
*/
- //typedef unsigned long long int ulint;
/*!
how many bits there are in the uint type
@@ -371,7 +392,7 @@
/*!
used only in Big::ToString()
- if scient is false then the value will be print in the scientific mode
+ if scient is false then the value will be printed in the scientific mode
only if the exponent is greater than scien_from
default: 15
*/
@@ -445,6 +466,13 @@
/*!
+ how many digits should be grouped (it is used if 'group' is non zero)
+ default: 3
+ */
+ uint group_digits;
+
+
+ /*!
*/
uint group_exp; // not implemented yet
@@ -463,6 +491,7 @@
comma = '.';
comma2 = ',';
group = 0;
+ group_digits = 3;
group_exp = 0;
}
};
@@ -521,26 +550,13 @@
In the library is used macro TTMATH_REFERENCE_ASSERT which
can throw an exception of this type
+ ** from version 0.9.2 this macro is removed from all methods
+ in public interface so you don't have to worry about it **
+
If you compile with gcc you can get a small benefit
from using method Where() (it returns std::string) with
the name and the line of a file where the macro TTMATH_REFERENCE_ASSERT
was used)
-
- What is the 'reference' error?
- Some kind of methods use a reference as their argument to another object,
- and the another object not always can be the same which is calling, e.g.
- Big<1,2> foo(10);
- foo.Mul(foo); // this is incorrect
- above method Mul is making something more with 'this' object and
- 'this' cannot be passed as the argument because the result will be undefined
-
- macro TTMATH_REFERENCE_ASSERT helps us to solve the above problem
-
- note! some methods can use 'this' object as the argument
- for example this code is correct:
- UInt<2> foo(10);
- foo.Add(foo);
- but there are only few methods which can do that
*/
class ReferenceError : public std::logic_error, public ExceptionInfo
{
@@ -596,8 +612,21 @@
/*!
- look at the description of macros TTMATH_RELEASE and TTMATH_DEBUG
+ TTMATH_DEBUG
+ this macro enables further testing during writing your code
+ you don't have to define it in a release mode
+
+ if this macro is set then macros TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT
+ are set as well and these macros can throw an exception if a condition in it
+ is not fulfilled (look at the definition of TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT)
+
+ TTMATH_DEBUG is set automatically if DEBUG or _DEBUG are defined
*/
+ #if defined DEBUG || defined _DEBUG
+ #define TTMATH_DEBUG
+ #endif
+
+
#ifdef TTMATH_DEBUG
#if defined(__FILE__) && defined(__LINE__)
Modified: trunk/boost/geometry/extensions/contrib/ttmath/ttmathuint.h
==============================================================================
--- trunk/boost/geometry/extensions/contrib/ttmath/ttmathuint.h (original)
+++ trunk/boost/geometry/extensions/contrib/ttmath/ttmathuint.h 2011-02-19 08:33:14 EST (Sat, 19 Feb 2011)
@@ -4,20 +4,20 @@
* Author: Tomasz Sowa <t.sowa_at_[hidden]>
*/
-/*
- * Copyright (c) 2006-2009, Tomasz Sowa
+/*
+ * Copyright (c) 2006-2011, Tomasz Sowa
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
- *
+ *
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
- *
+ *
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* * Neither the name Tomasz Sowa nor the names of contributors to this
* project may be used to endorse or promote products derived
* from this software without specific prior written permission.
@@ -42,7 +42,7 @@
/*!
- \file ttmathuint.h
+ \file ttmathuint.h
\brief template class UInt<uint>
*/
@@ -61,296 +61,309 @@
namespace ttmath
{
-/*!
- \brief UInt implements a big integer value without a sign
+/*!
+ \brief UInt implements a big integer value without a sign
- value_size - how many bytes specify our value
- on 32bit platforms: value_size=1 -> 4 bytes -> 32 bits
- on 64bit platforms: value_size=1 -> 8 bytes -> 64 bits
- value_size = 1,2,3,4,5,6....
+ value_size - how many bytes specify our value
+ on 32bit platforms: value_size=1 -> 4 bytes -> 32 bits
+ on 64bit platforms: value_size=1 -> 8 bytes -> 64 bits
+ value_size = 1,2,3,4,5,6....
*/
template<uint value_size>
class UInt
{
public:
- /*!
- buffer for the integer value
- table[0] - the lowest word of the value
- */
- uint table[value_size];
-
-
-
- /*!
- some methods used for debugging purposes
- */
-
-
- /*!
- this method is only for debugging purposes or when we want to make
- a table of a variable (constant) in ttmathbig.h
-
- it prints the table in a nice form of several columns
- */
- template<class ostream_type>
- void PrintTable(ostream_type & output) const
- {
- // how many columns there'll be
- const int columns = 8;
-
- int c = 1;
- for(int i=value_size-1 ; i>=0 ; --i)
- {
- output << "0x" << std::setfill('0');
-
- #ifdef TTMATH_PLATFORM32
- output << std::setw(8);
- #else
- output << std::setw(16);
- #endif
-
- output << std::hex << table[i];
-
- if( i>0 )
- {
- output << ", ";
-
- if( ++c > columns )
- {
- output << std::endl;
- c = 1;
- }
- }
- }
-
- output << std::dec << std::endl;
- }
-
-
- /*!
- this method is used when macro TTMATH_DEBUG_LOG is defined
- */
- template<class char_type, class ostream_type>
- static void PrintVectorLog(const char_type * msg, ostream_type & output, const uint * vector, uint vector_len)
- {
- output << msg << std::endl;
-
- for(uint i=0 ; i<vector_len ; ++i)
- output << " table[" << i << "]: " << vector[i] << std::endl;
- }
-
-
- /*!
- this method is used when macro TTMATH_DEBUG_LOG is defined
- */
- template<class char_type, class ostream_type>
- static void PrintVectorLog(const char_type * msg, uint carry, ostream_type & output, const uint * vector, uint vector_len)
- {
- PrintVectorLog(msg, output, vector, vector_len);
- output << " carry: " << carry << std::endl;
- }
-
-
- /*!
- this method is used when macro TTMATH_DEBUG_LOG is defined
- */
- template<class char_type, class ostream_type>
- void PrintLog(const char_type * msg, ostream_type & output) const
- {
- PrintVectorLog(msg, output, table, value_size);
- }
-
-
- /*!
- this method is used when macro TTMATH_DEBUG_LOG is defined
- */
- template<class char_type, class ostream_type>
- void PrintLog(const char_type * msg, uint carry, ostream_type & output) const
- {
- PrintVectorLog(msg, output, table, value_size);
- output << " carry: " << carry << std::endl;
- }
-
-
- /*!
- this method returns the size of the table
- */
- uint Size() const
- {
- return value_size;
- }
-
-
- /*!
- this method sets zero
- */
- void SetZero()
- {
- // in the future here can be 'memset'
-
- for(uint i=0 ; i<value_size ; ++i)
- table[i] = 0;
-
- TTMATH_LOG("UInt::SetZero")
- }
-
-
- /*!
- this method sets one
- */
- void SetOne()
- {
- SetZero();
- table[0] = 1;
-
- TTMATH_LOG("UInt::SetOne")
- }
-
-
- /*!
- this method sets the max value which this class can hold
- (all bits will be one)
- */
- void SetMax()
- {
- for(uint i=0 ; i<value_size ; ++i)
- table[i] = TTMATH_UINT_MAX_VALUE;
-
- TTMATH_LOG("UInt::SetMax")
- }
-
-
- /*!
- this method sets the min value which this class can hold
- (for an unsigned integer value the zero is the smallest value)
- */
- void SetMin()
- {
- SetZero();
-
- TTMATH_LOG("UInt::SetMin")
- }
-
+ /*!
+ buffer for the integer value
+ table[0] - the lowest word of the value
+ */
+ uint table[value_size];
+
+
+
+ /*!
+ some methods used for debugging purposes
+ */
+
+
+ /*!
+ this method is only for debugging purposes or when we want to make
+ a table of a variable (constant) in ttmathbig.h
+
+ it prints the table in a nice form of several columns
+ */
+ template<class ostream_type>
+ void PrintTable(ostream_type & output) const
+ {
+ // how many columns there'll be
+ const int columns = 8;
+
+ int c = 1;
+ for(int i=value_size-1 ; i>=0 ; --i)
+ {
+ output << "0x" << std::setfill('0');
+
+ #ifdef TTMATH_PLATFORM32
+ output << std::setw(8);
+ #else
+ output << std::setw(16);
+ #endif
+
+ output << std::hex << table[i];
+
+ if( i>0 )
+ {
+ output << ", ";
+
+ if( ++c > columns )
+ {
+ output << std::endl;
+ c = 1;
+ }
+ }
+ }
+
+ output << std::dec << std::endl;
+ }
+
+
+ /*!
+ this method is used when macro TTMATH_DEBUG_LOG is defined
+ */
+ template<class char_type, class ostream_type>
+ static void PrintVectorLog(const char_type * msg, ostream_type & output, const uint * vector, uint vector_len)
+ {
+ output << msg << std::endl;
+
+ for(uint i=0 ; i<vector_len ; ++i)
+ output << " table[" << i << "]: " << vector[i] << std::endl;
+ }
+
+
+ /*!
+ this method is used when macro TTMATH_DEBUG_LOG is defined
+ */
+ template<class char_type, class ostream_type>
+ static void PrintVectorLog(const char_type * msg, uint carry, ostream_type & output, const uint * vector, uint vector_len)
+ {
+ PrintVectorLog(msg, output, vector, vector_len);
+ output << " carry: " << carry << std::endl;
+ }
+
+
+ /*!
+ this method is used when macro TTMATH_DEBUG_LOG is defined
+ */
+ template<class char_type, class ostream_type>
+ void PrintLog(const char_type * msg, ostream_type & output) const
+ {
+ PrintVectorLog(msg, output, table, value_size);
+ }
+
+
+ /*!
+ this method is used when macro TTMATH_DEBUG_LOG is defined
+ */
+ template<class char_type, class ostream_type>
+ void PrintLog(const char_type * msg, uint carry, ostream_type & output) const
+ {
+ PrintVectorLog(msg, output, table, value_size);
+ output << " carry: " << carry << std::endl;
+ }
+
+
+ /*!
+ this method returns the size of the table
+ */
+ uint Size() const
+ {
+ return value_size;
+ }
+
+
+ /*!
+ this method sets zero
+ */
+ void SetZero()
+ {
+ // in the future here can be 'memset'
+
+ for(uint i=0 ; i<value_size ; ++i)
+ table[i] = 0;
+
+ TTMATH_LOG("UInt::SetZero")
+ }
+
+
+ /*!
+ this method sets one
+ */
+ void SetOne()
+ {
+ SetZero();
+ table[0] = 1;
+
+ TTMATH_LOG("UInt::SetOne")
+ }
+
+
+ /*!
+ this method sets the max value which this class can hold
+ (all bits will be one)
+ */
+ void SetMax()
+ {
+ for(uint i=0 ; i<value_size ; ++i)
+ table[i] = TTMATH_UINT_MAX_VALUE;
+
+ TTMATH_LOG("UInt::SetMax")
+ }
+
+
+ /*!
+ this method sets the min value which this class can hold
+ (for an unsigned integer value the zero is the smallest value)
+ */
+ void SetMin()
+ {
+ SetZero();
+
+ TTMATH_LOG("UInt::SetMin")
+ }
+
+
+ /*!
+ this method swappes this for an argument
+ */
+ void Swap(UInt<value_size> & ss2)
+ {
+ for(uint i=0 ; i<value_size ; ++i)
+ {
+ uint temp = table[i];
+ table[i] = ss2.table[i];
+ ss2.table[i] = temp;
+ }
+ }
#ifdef TTMATH_PLATFORM32
- /*!
- this method copies the value stored in an another table
- (warning: first values in temp_table are the highest words -- it's different
- from our table)
-
- we copy as many words as it is possible
-
- if temp_table_len is bigger than value_size we'll try to round
- the lowest word from table depending on the last not used bit in temp_table
- (this rounding isn't a perfect rounding -- look at the description below)
-
- and if temp_table_len is smaller than value_size we'll clear the rest words
- in the table
- */
- void SetFromTable(const uint * temp_table, uint temp_table_len)
- {
- uint temp_table_index = 0;
- sint i; // 'i' with a sign
-
- for(i=value_size-1 ; i>=0 && temp_table_index<temp_table_len; --i, ++temp_table_index)
- table[i] = temp_table[ temp_table_index ];
-
-
- // rounding mantissa
- if( temp_table_index < temp_table_len )
- {
- if( (temp_table[temp_table_index] & TTMATH_UINT_HIGHEST_BIT) != 0 )
- {
- /*
- very simply rounding
- if the bit from not used last word from temp_table is set to one
- we're rouding the lowest word in the table
-
- in fact there should be a normal addition but
- we don't use Add() or AddTwoInts() because these methods
- can set a carry and then there'll be a small problem
- for optimization
- */
- if( table[0] != TTMATH_UINT_MAX_VALUE )
- ++table[0];
- }
- }
-
- // cleaning the rest of the mantissa
- for( ; i>=0 ; --i)
- table[i] = 0;
+ /*!
+ this method copies the value stored in an another table
+ (warning: first values in temp_table are the highest words -- it's different
+ from our table)
+
+ we copy as many words as it is possible
+
+ if temp_table_len is bigger than value_size we'll try to round
+ the lowest word from table depending on the last not used bit in temp_table
+ (this rounding isn't a perfect rounding -- look at the description below)
+
+ and if temp_table_len is smaller than value_size we'll clear the rest words
+ in the table
+ */
+ void SetFromTable(const uint * temp_table, uint temp_table_len)
+ {
+ uint temp_table_index = 0;
+ sint i; // 'i' with a sign
+
+ for(i=value_size-1 ; i>=0 && temp_table_index<temp_table_len; --i, ++temp_table_index)
+ table[i] = temp_table[ temp_table_index ];
+
+
+ // rounding mantissa
+ if( temp_table_index < temp_table_len )
+ {
+ if( (temp_table[temp_table_index] & TTMATH_UINT_HIGHEST_BIT) != 0 )
+ {
+ /*
+ very simply rounding
+ if the bit from not used last word from temp_table is set to one
+ we're rouding the lowest word in the table
+
+ in fact there should be a normal addition but
+ we don't use Add() or AddTwoInts() because these methods
+ can set a carry and then there'll be a small problem
+ for optimization
+ */
+ if( table[0] != TTMATH_UINT_MAX_VALUE )
+ ++table[0];
+ }
+ }
+
+ // cleaning the rest of the mantissa
+ for( ; i>=0 ; --i)
+ table[i] = 0;
- TTMATH_LOG("UInt::SetFromTable")
- }
+ TTMATH_LOG("UInt::SetFromTable")
+ }
#endif
#ifdef TTMATH_PLATFORM64
- /*!
- this method copies the value stored in an another table
- (warning: first values in temp_table are the highest words -- it's different
- from our table)
-
- ***this method is created only on a 64bit platform***
-
- we copy as many words as it is possible
-
- if temp_table_len is bigger than value_size we'll try to round
- the lowest word from table depending on the last not used bit in temp_table
- (this rounding isn't a perfect rounding -- look at the description below)
-
- and if temp_table_len is smaller than value_size we'll clear the rest words
- in the table
-
- warning: we're using 'temp_table' as a pointer at 32bit words
- */
- void SetFromTable(const unsigned int * temp_table, uint temp_table_len)
- {
- uint temp_table_index = 0;
- sint i; // 'i' with a sign
-
- for(i=value_size-1 ; i>=0 && temp_table_index<temp_table_len; --i, ++temp_table_index)
- {
- table[i] = uint(temp_table[ temp_table_index ]) << 32;
-
- ++temp_table_index;
-
- if( temp_table_index<temp_table_len )
- table[i] |= temp_table[ temp_table_index ];
- }
-
-
- // rounding mantissa
- if( temp_table_index < temp_table_len )
- {
- if( (temp_table[temp_table_index] & TTMATH_UINT_HIGHEST_BIT) != 0 )
- {
- /*
- very simply rounding
- if the bit from not used last word from temp_table is set to one
- we're rouding the lowest word in the table
-
- in fact there should be a normal addition but
- we don't use Add() or AddTwoInts() because these methods
- can set a carry and then there'll be a small problem
- for optimization
- */
- if( table[0] != TTMATH_UINT_MAX_VALUE )
- ++table[0];
- }
- }
-
- // cleaning the rest of the mantissa
- for( ; i >= 0 ; --i)
- table[i] = 0;
+ /*!
+ this method copies the value stored in an another table
+ (warning: first values in temp_table are the highest words -- it's different
+ from our table)
+
+ ***this method is created only on a 64bit platform***
+
+ we copy as many words as it is possible
+
+ if temp_table_len is bigger than value_size we'll try to round
+ the lowest word from table depending on the last not used bit in temp_table
+ (this rounding isn't a perfect rounding -- look at the description below)
+
+ and if temp_table_len is smaller than value_size we'll clear the rest words
+ in the table
+
+ warning: we're using 'temp_table' as a pointer at 32bit words
+ */
+ void SetFromTable(const unsigned int * temp_table, uint temp_table_len)
+ {
+ uint temp_table_index = 0;
+ sint i; // 'i' with a sign
+
+ for(i=value_size-1 ; i>=0 && temp_table_index<temp_table_len; --i, ++temp_table_index)
+ {
+ table[i] = uint(temp_table[ temp_table_index ]) << 32;
+
+ ++temp_table_index;
+
+ if( temp_table_index<temp_table_len )
+ table[i] |= temp_table[ temp_table_index ];
+ }
+
+
+ // rounding mantissa
+ if( temp_table_index < temp_table_len )
+ {
+ if( (temp_table[temp_table_index] & TTMATH_UINT_HIGHEST_BIT) != 0 )
+ {
+ /*
+ very simply rounding
+ if the bit from not used last word from temp_table is set to one
+ we're rouding the lowest word in the table
+
+ in fact there should be a normal addition but
+ we don't use Add() or AddTwoInts() because these methods
+ can set a carry and then there'll be a small problem
+ for optimization
+ */
+ if( table[0] != TTMATH_UINT_MAX_VALUE )
+ ++table[0];
+ }
+ }
+
+ // cleaning the rest of the mantissa
+ for( ; i >= 0 ; --i)
+ table[i] = 0;
- TTMATH_LOG("UInt::SetFromTable")
- }
+ TTMATH_LOG("UInt::SetFromTable")
+ }
#endif
@@ -358,908 +371,930 @@
- /*!
- *
- * basic mathematic functions
- *
- */
+ /*!
+ *
+ * basic mathematic functions
+ *
+ */
- /*!
- this method adds one to the existing value
- */
- uint AddOne()
- {
- return AddInt(1);
- }
-
-
- /*!
- this method subtracts one from the existing value
- */
- uint SubOne()
- {
- return SubInt(1);
- }
+ /*!
+ this method adds one to the existing value
+ */
+ uint AddOne()
+ {
+ return AddInt(1);
+ }
+
+
+ /*!
+ this method subtracts one from the existing value
+ */
+ uint SubOne()
+ {
+ return SubInt(1);
+ }
private:
- /*!
- an auxiliary method for moving bits into the left hand side
-
- this method moves only words
- */
- void RclMoveAllWords(uint & rest_bits, uint & last_c, uint bits, uint c)
- {
- rest_bits = bits % TTMATH_BITS_PER_UINT;
- uint all_words = bits / TTMATH_BITS_PER_UINT;
- uint mask = ( c ) ? TTMATH_UINT_MAX_VALUE : 0;
-
-
- if( all_words >= value_size )
- {
- if( all_words == value_size && rest_bits == 0 )
- last_c = table[0] & 1;
- // else: last_c is default set to 0
-
- // clearing
- for(uint i = 0 ; i<value_size ; ++i)
- table[i] = mask;
-
- rest_bits = 0;
- }
- else
- if( all_words > 0 )
- {
- // 0 < all_words < value_size
-
- sint first, second;
- last_c = table[value_size - all_words] & 1; // all_words is greater than 0
-
- // copying the first part of the value
- for(first = value_size-1, second=first-all_words ; second>=0 ; --first, --second)
- table[first] = table[second];
-
- // setting the rest to 'c'
- for( ; first>=0 ; --first )
- table[first] = mask;
- }
-
- TTMATH_LOG("UInt::RclMoveAllWords")
- }
+ /*!
+ an auxiliary method for moving bits into the left hand side
+ this method moves only words
+ */
+ void RclMoveAllWords(uint & rest_bits, uint & last_c, uint bits, uint c)
+ {
+ rest_bits = bits % TTMATH_BITS_PER_UINT;
+ uint all_words = bits / TTMATH_BITS_PER_UINT;
+ uint mask = ( c ) ? TTMATH_UINT_MAX_VALUE : 0;
+
+
+ if( all_words >= value_size )
+ {
+ if( all_words == value_size && rest_bits == 0 )
+ last_c = table[0] & 1;
+ // else: last_c is default set to 0
+
+ // clearing
+ for(uint i = 0 ; i<value_size ; ++i)
+ table[i] = mask;
+
+ rest_bits = 0;
+ }
+ else
+ if( all_words > 0 )
+ {
+ // 0 < all_words < value_size
+
+ sint first, second;
+ last_c = table[value_size - all_words] & 1; // all_words is greater than 0
+
+ // copying the first part of the value
+ for(first = value_size-1, second=first-all_words ; second>=0 ; --first, --second)
+ table[first] = table[second];
+
+ // setting the rest to 'c'
+ for( ; first>=0 ; --first )
+ table[first] = mask;
+ }
+
+ TTMATH_LOG("UInt::RclMoveAllWords")
+ }
+
public:
- /*!
- moving all bits into the left side 'bits' times
- return value <- this <- C
-
- bits is from a range of <0, man * TTMATH_BITS_PER_UINT>
- or it can be even bigger then all bits will be set to 'c'
-
- the value c will be set into the lowest bits
- and the method returns state of the last moved bit
- */
- uint Rcl(uint bits, uint c=0)
- {
- uint last_c = 0;
- uint rest_bits = bits;
-
- if( bits == 0 )
- return 0;
-
- if( bits >= TTMATH_BITS_PER_UINT )
- RclMoveAllWords(rest_bits, last_c, bits, c);
-
- if( rest_bits == 0 )
- {
- TTMATH_LOG("UInt::Rcl")
- return last_c;
- }
-
- // rest_bits is from 1 to TTMATH_BITS_PER_UINT-1 now
- if( rest_bits == 1 )
- {
- last_c = Rcl2_one(c);
- }
- else if( rest_bits == 2 )
- {
- // performance tests showed that for rest_bits==2 it's better to use Rcl2_one twice instead of Rcl2(2,c)
- Rcl2_one(c);
- last_c = Rcl2_one(c);
- }
- else
- {
- last_c = Rcl2(rest_bits, c);
- }
+ /*!
+ moving all bits into the left side 'bits' times
+ return value <- this <- C
+
+ bits is from a range of <0, man * TTMATH_BITS_PER_UINT>
+ or it can be even bigger then all bits will be set to 'c'
+
+ the value c will be set into the lowest bits
+ and the method returns state of the last moved bit
+ */
+ uint Rcl(uint bits, uint c=0)
+ {
+ uint last_c = 0;
+ uint rest_bits = bits;
+
+ if( bits == 0 )
+ return 0;
+
+ if( bits >= TTMATH_BITS_PER_UINT )
+ RclMoveAllWords(rest_bits, last_c, bits, c);
+
+ if( rest_bits == 0 )
+ {
+ TTMATH_LOG("UInt::Rcl")
+ return last_c;
+ }
+
+ // rest_bits is from 1 to TTMATH_BITS_PER_UINT-1 now
+ if( rest_bits == 1 )
+ {
+ last_c = Rcl2_one(c);
+ }
+ else if( rest_bits == 2 )
+ {
+ // performance tests showed that for rest_bits==2 it's better to use Rcl2_one twice instead of Rcl2(2,c)
+ Rcl2_one(c);
+ last_c = Rcl2_one(c);
+ }
+ else
+ {
+ last_c = Rcl2(rest_bits, c);
+ }
- TTMATH_LOGC("UInt::Rcl", last_c)
+ TTMATH_LOGC("UInt::Rcl", last_c)
- return last_c;
- }
+ return last_c;
+ }
private:
- /*!
- an auxiliary method for moving bits into the right hand side
+ /*!
+ an auxiliary method for moving bits into the right hand side
- this method moves only words
- */
- void RcrMoveAllWords(uint & rest_bits, uint & last_c, uint bits, uint c)
- {
- rest_bits = bits % TTMATH_BITS_PER_UINT;
- uint all_words = bits / TTMATH_BITS_PER_UINT;
- uint mask = ( c ) ? TTMATH_UINT_MAX_VALUE : 0;
-
-
- if( all_words >= value_size )
- {
- if( all_words == value_size && rest_bits == 0 )
- last_c = (table[value_size-1] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0;
- // else: last_c is default set to 0
-
- // clearing
- for(uint i = 0 ; i<value_size ; ++i)
- table[i] = mask;
-
- rest_bits = 0;
- }
- else if( all_words > 0 )
- {
- // 0 < all_words < value_size
-
- uint first, second;
- last_c = (table[all_words - 1] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0; // all_words is > 0
-
- // copying the first part of the value
- for(first=0, second=all_words ; second<value_size ; ++first, ++second)
- table[first] = table[second];
-
- // setting the rest to 'c'
- for( ; first<value_size ; ++first )
- table[first] = mask;
- }
+ this method moves only words
+ */
+ void RcrMoveAllWords(uint & rest_bits, uint & last_c, uint bits, uint c)
+ {
+ rest_bits = bits % TTMATH_BITS_PER_UINT;
+ uint all_words = bits / TTMATH_BITS_PER_UINT;
+ uint mask = ( c ) ? TTMATH_UINT_MAX_VALUE : 0;
+
+
+ if( all_words >= value_size )
+ {
+ if( all_words == value_size && rest_bits == 0 )
+ last_c = (table[value_size-1] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0;
+ // else: last_c is default set to 0
+
+ // clearing
+ for(uint i = 0 ; i<value_size ; ++i)
+ table[i] = mask;
+
+ rest_bits = 0;
+ }
+ else if( all_words > 0 )
+ {
+ // 0 < all_words < value_size
+
+ uint first, second;
+ last_c = (table[all_words - 1] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0; // all_words is > 0
+
+ // copying the first part of the value
+ for(first=0, second=all_words ; second<value_size ; ++first, ++second)
+ table[first] = table[second];
+
+ // setting the rest to 'c'
+ for( ; first<value_size ; ++first )
+ table[first] = mask;
+ }
- TTMATH_LOG("UInt::RcrMoveAllWords")
- }
+ TTMATH_LOG("UInt::RcrMoveAllWords")
+ }
public:
- /*!
- moving all bits into the right side 'bits' times
- c -> this -> return value
-
- bits is from a range of <0, man * TTMATH_BITS_PER_UINT>
- or it can be even bigger then all bits will be set to 'c'
-
- the value c will be set into the highest bits
- and the method returns state of the last moved bit
- */
- uint Rcr(uint bits, uint c=0)
- {
- uint last_c = 0;
- uint rest_bits = bits;
-
- if( bits == 0 )
- return 0;
-
- if( bits >= TTMATH_BITS_PER_UINT )
- RcrMoveAllWords(rest_bits, last_c, bits, c);
-
- if( rest_bits == 0 )
- {
- TTMATH_LOG("UInt::Rcr")
- return last_c;
- }
-
- // rest_bits is from 1 to TTMATH_BITS_PER_UINT-1 now
- if( rest_bits == 1 )
- {
- last_c = Rcr2_one(c);
- }
- else if( rest_bits == 2 )
- {
- // performance tests showed that for rest_bits==2 it's better to use Rcr2_one twice instead of Rcr2(2,c)
- Rcr2_one(c);
- last_c = Rcr2_one(c);
- }
- else
- {
- last_c = Rcr2(rest_bits, c);
- }
-
- TTMATH_LOGC("UInt::Rcr", last_c)
-
- return last_c;
- }
-
-
- /*!
- this method moves all bits into the left side
- (it returns value how many bits have been moved)
- */
- uint CompensationToLeft()
- {
- uint moving = 0;
-
- // a - index a last word which is different from zero
- sint a;
- for(a=value_size-1 ; a>=0 && table[a]==0 ; --a);
-
- if( a < 0 )
- return moving; // all words in table have zero
+ /*!
+ moving all bits into the right side 'bits' times
+ c -> this -> return value
+
+ bits is from a range of <0, man * TTMATH_BITS_PER_UINT>
+ or it can be even bigger then all bits will be set to 'c'
+
+ the value c will be set into the highest bits
+ and the method returns state of the last moved bit
+ */
+ uint Rcr(uint bits, uint c=0)
+ {
+ uint last_c = 0;
+ uint rest_bits = bits;
+
+ if( bits == 0 )
+ return 0;
+
+ if( bits >= TTMATH_BITS_PER_UINT )
+ RcrMoveAllWords(rest_bits, last_c, bits, c);
+
+ if( rest_bits == 0 )
+ {
+ TTMATH_LOG("UInt::Rcr")
+ return last_c;
+ }
+
+ // rest_bits is from 1 to TTMATH_BITS_PER_UINT-1 now
+ if( rest_bits == 1 )
+ {
+ last_c = Rcr2_one(c);
+ }
+ else if( rest_bits == 2 )
+ {
+ // performance tests showed that for rest_bits==2 it's better to use Rcr2_one twice instead of Rcr2(2,c)
+ Rcr2_one(c);
+ last_c = Rcr2_one(c);
+ }
+ else
+ {
+ last_c = Rcr2(rest_bits, c);
+ }
+
+ TTMATH_LOGC("UInt::Rcr", last_c)
+
+ return last_c;
+ }
+
+
+ /*!
+ this method moves all bits into the left side
+ (it returns value how many bits have been moved)
+ */
+ uint CompensationToLeft()
+ {
+ uint moving = 0;
+
+ // a - index a last word which is different from zero
+ sint a;
+ for(a=value_size-1 ; a>=0 && table[a]==0 ; --a);
+
+ if( a < 0 )
+ return moving; // all words in table have zero
+
+ if( a != value_size-1 )
+ {
+ moving += ( value_size-1 - a ) * TTMATH_BITS_PER_UINT;
+
+ // moving all words
+ sint i;
+ for(i=value_size-1 ; a>=0 ; --i, --a)
+ table[i] = table[a];
+
+ // setting the rest word to zero
+ for(; i>=0 ; --i)
+ table[i] = 0;
+ }
+
+ uint moving2 = FindLeadingBitInWord( table[value_size-1] );
+ // moving2 is different from -1 because the value table[value_size-1]
+ // is not zero
+
+ moving2 = TTMATH_BITS_PER_UINT - moving2 - 1;
+ Rcl(moving2);
+
+ TTMATH_LOG("UInt::CompensationToLeft")
+
+ return moving + moving2;
+ }
+
+
+ /*!
+ this method looks for the highest set bit
+
+ result:
+ if 'this' is not zero:
+ return value - true
+ 'table_id' - the index of a word <0..value_size-1>
+ 'index' - the index of this set bit in the word <0..TTMATH_BITS_PER_UINT)
+
+ if 'this' is zero:
+ return value - false
+ both 'table_id' and 'index' are zero
+ */
+ bool FindLeadingBit(uint & table_id, uint & index) const
+ {
+ for(table_id=value_size-1 ; table_id!=0 && table[table_id]==0 ; --table_id);
+
+ if( table_id==0 && table[table_id]==0 )
+ {
+ // is zero
+ index = 0;
+
+ return false;
+ }
+
+ // table[table_id] is different from 0
+ index = FindLeadingBitInWord( table[table_id] );
+
+ return true;
+ }
+
+
+ /*!
+ this method looks for the smallest set bit
+
+ result:
+ if 'this' is not zero:
+ return value - true
+ 'table_id' - the index of a word <0..value_size-1>
+ 'index' - the index of this set bit in the word <0..TTMATH_BITS_PER_UINT)
+
+ if 'this' is zero:
+ return value - false
+ both 'table_id' and 'index' are zero
+ */
+ bool FindLowestBit(uint & table_id, uint & index) const
+ {
+ for(table_id=0 ; table_id<value_size && table[table_id]==0 ; ++table_id);
+
+ if( table_id >= value_size )
+ {
+ // is zero
+ index = 0;
+ table_id = 0;
+
+ return false;
+ }
+
+ // table[table_id] is different from 0
+ index = FindLowestBitInWord( table[table_id] );
+
+ return true;
+ }
+
+
+ /*!
+ getting the 'bit_index' bit
+
+ bit_index bigger or equal zero
+ */
+ uint GetBit(uint bit_index) const
+ {
+ TTMATH_ASSERT( bit_index < value_size * TTMATH_BITS_PER_UINT )
+
+ uint index = bit_index / TTMATH_BITS_PER_UINT;
+ uint bit = bit_index % TTMATH_BITS_PER_UINT;
+
+ uint temp = table[index];
+ uint res = SetBitInWord(temp, bit);
+
+ return res;
+ }
+
+
+ /*!
+ setting the 'bit_index' bit
+ and returning the last state of the bit
+
+ bit_index bigger or equal zero
+ */
+ uint SetBit(uint bit_index)
+ {
+ TTMATH_ASSERT( bit_index < value_size * TTMATH_BITS_PER_UINT )
+
+ uint index = bit_index / TTMATH_BITS_PER_UINT;
+ uint bit = bit_index % TTMATH_BITS_PER_UINT;
+ uint res = SetBitInWord(table[index], bit);
+
+ TTMATH_LOG("UInt::SetBit")
+
+ return res;
+ }
+
+
+ /*!
+ this method performs a bitwise operation AND
+ */
+ void BitAnd(const UInt<value_size> & ss2)
+ {
+ for(uint x=0 ; x<value_size ; ++x)
+ table[x] &= ss2.table[x];
+
+ TTMATH_LOG("UInt::BitAnd")
+ }
+
+
+ /*!
+ this method performs a bitwise operation OR
+ */
+ void BitOr(const UInt<value_size> & ss2)
+ {
+ for(uint x=0 ; x<value_size ; ++x)
+ table[x] |= ss2.table[x];
+
+ TTMATH_LOG("UInt::BitOr")
+ }
+
+
+ /*!
+ this method performs a bitwise operation XOR
+ */
+ void BitXor(const UInt<value_size> & ss2)
+ {
+ for(uint x=0 ; x<value_size ; ++x)
+ table[x] ^= ss2.table[x];
+
+ TTMATH_LOG("UInt::BitXor")
+ }
+
+
+ /*!
+ this method performs a bitwise operation NOT
+ */
+ void BitNot()
+ {
+ for(uint x=0 ; x<value_size ; ++x)
+ table[x] = ~table[x];
+
+ TTMATH_LOG("UInt::BitNot")
+ }
+
+
+ /*!
+ this method performs a bitwise operation NOT but only
+ on the range of <0, leading_bit>
+
+ for example:
+ BitNot2(8) = BitNot2( 1000(bin) ) = 111(bin) = 7
+ */
+ void BitNot2()
+ {
+ uint table_id, index;
+
+ if( FindLeadingBit(table_id, index) )
+ {
+ for(uint x=0 ; x<table_id ; ++x)
+ table[x] = ~table[x];
+
+ uint mask = TTMATH_UINT_MAX_VALUE;
+ uint shift = TTMATH_BITS_PER_UINT - index - 1;
+
+ if(shift)
+ mask >>= shift;
+
+ table[table_id] ^= mask;
+ }
+ else
+ table[0] = 1;
+
+
+ TTMATH_LOG("UInt::BitNot2")
+ }
+
+
+
+ /*!
+ *
+ * Multiplication
+ *
+ *
+ */
- if( a != value_size-1 )
- {
- moving += ( value_size-1 - a ) * TTMATH_BITS_PER_UINT;
-
- // moving all words
- sint i;
- for(i=value_size-1 ; a>=0 ; --i, --a)
- table[i] = table[a];
-
- // setting the rest word to zero
- for(; i>=0 ; --i)
- table[i] = 0;
- }
-
- uint moving2 = FindLeadingBitInWord( table[value_size-1] );
- // moving2 is different from -1 because the value table[value_size-1]
- // is not zero
-
- moving2 = TTMATH_BITS_PER_UINT - moving2 - 1;
- Rcl(moving2);
-
- TTMATH_LOG("UInt::CompensationToLeft")
-
- return moving + moving2;
- }
-
-
- /*!
- this method looks for the highest set bit
-
- result:
- if 'this' is not zero:
- return value - true
- 'table_id' - the index of a word <0..value_size-1>
- 'index' - the index of this set bit in the word <0..TTMATH_BITS_PER_UINT)
-
- if 'this' is zero:
- return value - false
- both 'table_id' and 'index' are zero
- */
- bool FindLeadingBit(uint & table_id, uint & index) const
- {
- for(table_id=value_size-1 ; table_id!=0 && table[table_id]==0 ; --table_id);
-
- if( table_id==0 && table[table_id]==0 )
- {
- // is zero
- index = 0;
-
- return false;
- }
-
- // table[table_id] is different from 0
- index = FindLeadingBitInWord( table[table_id] );
-
- return true;
- }
+public:
+ /*!
+ multiplication: this = this * ss2
- /*!
- this method looks for the smallest set bit
+ it can return a carry
+ */
+ uint MulInt(uint ss2)
+ {
+ uint r1, r2, x1;
+ uint c = 0;
- result:
- if 'this' is not zero:
- return value - true
- 'table_id' - the index of a word <0..value_size-1>
- 'index' - the index of this set bit in the word <0..TTMATH_BITS_PER_UINT)
+ UInt<value_size> u(*this);
+ SetZero();
- if 'this' is zero:
- return value - false
- both 'table_id' and 'index' are zero
- */
- bool FindLowestBit(uint & table_id, uint & index) const
- {
- for(table_id=0 ; table_id<value_size && table[table_id]==0 ; ++table_id);
+ if( ss2 == 0 )
+ {
+ TTMATH_LOGC("UInt::MulInt(uint)", 0)
+ return 0;
+ }
- if( table_id >= value_size )
- {
- // is zero
- index = 0;
- table_id = 0;
+ for(x1=0 ; x1<value_size-1 ; ++x1)
+ {
+ MulTwoWords(u.table[x1], ss2, &r2, &r1);
+ c += AddTwoInts(r2,r1,x1);
+ }
- return false;
- }
+ // x1 = value_size-1 (last word)
+ MulTwoWords(u.table[x1], ss2, &r2, &r1);
+ c += (r2!=0) ? 1 : 0;
+ c += AddInt(r1, x1);
- // table[table_id] is different from 0
- index = FindLowestBitInWord( table[table_id] );
+ TTMATH_LOGC("UInt::MulInt(uint)", c)
- return true;
- }
+ return (c==0)? 0 : 1;
+ }
- /*!
- getting the 'bit_index' bit
+ /*!
+ multiplication: result = this * ss2
- bit_index bigger or equal zero
- */
- uint GetBit(uint bit_index) const
- {
- TTMATH_ASSERT( bit_index < value_size * TTMATH_BITS_PER_UINT )
+ we're using this method only when result_size is greater than value_size
+ if so there will not be a carry
+ */
+ template<uint result_size>
+ void MulInt(uint ss2, UInt<result_size> & result) const
+ {
+ TTMATH_ASSERT( result_size > value_size )
- uint index = bit_index / TTMATH_BITS_PER_UINT;
- uint bit = bit_index % TTMATH_BITS_PER_UINT;
+ uint r2,r1;
+ uint x1size=value_size;
+ uint x1start=0;
- uint temp = table[index];
- uint res = SetBitInWord(temp, bit);
+ result.SetZero();
- return res;
- }
+ if( ss2 == 0 )
+ {
+ TTMATH_VECTOR_LOG("UInt::MulInt(uint, UInt<>)", result.table, result_size)
+ return;
+ }
+ if( value_size > 2 )
+ {
+ // if the value_size is smaller than or equal to 2
+ // there is no sense to set x1size and x1start to another values
- /*!
- setting the 'bit_index' bit
- and returning the last state of the bit
+ for(x1size=value_size ; x1size>0 && table[x1size-1]==0 ; --x1size);
- bit_index bigger or equal zero
- */
- uint SetBit(uint bit_index)
- {
- TTMATH_ASSERT( bit_index < value_size * TTMATH_BITS_PER_UINT )
+ if( x1size == 0 )
+ {
+ TTMATH_VECTOR_LOG("UInt::MulInt(uint, UInt<>)", result.table, result_size)
+ return;
+ }
- uint index = bit_index / TTMATH_BITS_PER_UINT;
- uint bit = bit_index % TTMATH_BITS_PER_UINT;
- uint res = SetBitInWord(table[index], bit);
+ for(x1start=0 ; x1start<x1size && table[x1start]==0 ; ++x1start);
+ }
- TTMATH_LOG("UInt::SetBit")
+ for(uint x1=x1start ; x1<x1size ; ++x1)
+ {
+ MulTwoWords(table[x1], ss2, &r2, &r1 );
+ result.AddTwoInts(r2,r1,x1);
+ }
- return res;
- }
+ TTMATH_VECTOR_LOG("UInt::MulInt(uint, UInt<>)", result.table, result_size)
+ return;
+ }
- /*!
- this method performs a bitwise operation AND
- */
- void BitAnd(const UInt<value_size> & ss2)
- {
- for(uint x=0 ; x<value_size ; ++x)
- table[x] &= ss2.table[x];
- TTMATH_LOG("UInt::BitAnd")
- }
+ /*!
+ the multiplication 'this' = 'this' * ss2
- /*!
- this method performs a bitwise operation OR
- */
- void BitOr(const UInt<value_size> & ss2)
- {
- for(uint x=0 ; x<value_size ; ++x)
- table[x] |= ss2.table[x];
+ algorithm: 100 - means automatically choose the fastest algorithm
+ */
+ uint Mul(const UInt<value_size> & ss2, uint algorithm = 100)
+ {
+ switch( algorithm )
+ {
+ case 1:
+ return Mul1(ss2);
- TTMATH_LOG("UInt::BitOr")
- }
+ case 2:
+ return Mul2(ss2);
+ case 3:
+ return Mul3(ss2);
- /*!
- this method performs a bitwise operation XOR
- */
- void BitXor(const UInt<value_size> & ss2)
- {
- for(uint x=0 ; x<value_size ; ++x)
- table[x] ^= ss2.table[x];
+ case 100:
+ default:
+ return MulFastest(ss2);
+ }
+ }
- TTMATH_LOG("UInt::BitXor")
- }
+ /*!
+ the multiplication 'result' = 'this' * ss2
- /*!
- this method performs a bitwise operation NOT
- */
- void BitNot()
- {
- for(uint x=0 ; x<value_size ; ++x)
- table[x] = ~table[x];
+ since the 'result' is twice bigger than 'this' and 'ss2'
+ this method never returns a carry
- TTMATH_LOG("UInt::BitNot")
- }
+ algorithm: 100 - means automatically choose the fastest algorithm
+ */
+ void MulBig(const UInt<value_size> & ss2,
+ UInt<value_size*2> & result,
+ uint algorithm = 100)
+ {
+ switch( algorithm )
+ {
+ case 1:
+ return Mul1Big(ss2, result);
+ case 2:
+ return Mul2Big(ss2, result);
- /*!
- this method performs a bitwise operation NOT but only
- on the range of <0, leading_bit>
+ case 3:
+ return Mul3Big(ss2, result);
- for example:
- BitNot2(8) = BitNot2( 1000(bin) ) = 111(bin) = 7
- */
- void BitNot2()
- {
- uint table_id, index;
+ case 100:
+ default:
+ return MulFastestBig(ss2, result);
+ }
+ }
- if( FindLeadingBit(table_id, index) )
- {
- for(uint x=0 ; x<table_id ; ++x)
- table[x] = ~table[x];
- uint mask = TTMATH_UINT_MAX_VALUE;
- uint shift = TTMATH_BITS_PER_UINT - index - 1;
- if(shift)
- mask >>= shift;
+ /*!
+ the first version of the multiplication algorithm
+ */
- table[table_id] ^= mask;
- }
- else
- table[0] = 1;
+private:
+ /*!
+ multiplication: this = this * ss2
- TTMATH_LOG("UInt::BitNot2")
- }
+ it returns carry if it has been
+ */
+ uint Mul1Ref(const UInt<value_size> & ss2)
+ {
+ TTMATH_REFERENCE_ASSERT( ss2 )
+
+ UInt<value_size> ss1( *this );
+ SetZero();
+
+ for(uint i=0; i < value_size*TTMATH_BITS_PER_UINT ; ++i)
+ {
+ if( Add(*this) )
+ {
+ TTMATH_LOGC("UInt::Mul1", 1)
+ return 1;
+ }
+
+ if( ss1.Rcl(1) )
+ if( Add(ss2) )
+ {
+ TTMATH_LOGC("UInt::Mul1", 1)
+ return 1;
+ }
+ }
+ TTMATH_LOGC("UInt::Mul1", 0)
+ return 0;
+ }
- /*!
- *
- * Multiplication
- *
- *
- */
public:
- /*!
- multiplication: this = this * ss2
+ /*!
+ multiplication: this = this * ss2
+ can return carry
+ */
+ uint Mul1(const UInt<value_size> & ss2)
+ {
+ if( this == &ss2 )
+ {
+ UInt<value_size> copy_ss2(ss2);
+ return Mul1Ref(copy_ss2);
+ }
+ else
+ {
+ return Mul1Ref(ss2);
+ }
+ }
+
+
+ /*!
+ multiplication: result = this * ss2
+
+ result is twice bigger than 'this' and 'ss2'
+ this method never returns carry
+ */
+ void Mul1Big(const UInt<value_size> & ss2_, UInt<value_size*2> & result)
+ {
+ UInt<value_size*2> ss2;
+ uint i;
+
+ // copying *this into result and ss2_ into ss2
+ for(i=0 ; i<value_size ; ++i)
+ {
+ result.table[i] = table[i];
+ ss2.table[i] = ss2_.table[i];
+ }
+
+ // cleaning the highest bytes in result and ss2
+ for( ; i < value_size*2 ; ++i)
+ {
+ result.table[i] = 0;
+ ss2.table[i] = 0;
+ }
+
+ // multiply
+ // (there will not be a carry)
+ result.Mul1( ss2 );
+
+ TTMATH_LOG("UInt::Mul1Big")
+ }
+
+
+
+ /*!
+ the second version of the multiplication algorithm
+
+ this algorithm is similar to the 'schoolbook method' which is done by hand
+ */
+
+ /*!
+ multiplication: this = this * ss2
+
+ it returns carry if it has been
+ */
+ uint Mul2(const UInt<value_size> & ss2)
+ {
+ UInt<value_size*2> result;
+ uint i, c = 0;
+
+ Mul2Big(ss2, result);
+
+ // copying result
+ for(i=0 ; i<value_size ; ++i)
+ table[i] = result.table[i];
+
+ // testing carry
+ for( ; i<value_size*2 ; ++i)
+ if( result.table[i] != 0 )
+ {
+ c = 1;
+ break;
+ }
+
+ TTMATH_LOGC("UInt::Mul2", c)
+
+ return c;
+ }
+
+
+ /*!
+ multiplication: result = this * ss2
+
+ result is twice bigger than this and ss2
+ this method never returns carry
+ */
+ void Mul2Big(const UInt<value_size> & ss2, UInt<value_size*2> & result)
+ {
+ Mul2Big2<value_size>(table, ss2.table, result);
- it can return a carry
- */
- uint MulInt(uint ss2)
- {
- uint r1, r2, x1;
- uint c = 0;
-
- UInt<value_size> u(*this);
- SetZero();
-
- if( ss2 == 0 )
- {
- TTMATH_LOGC("UInt::MulInt(uint)", 0)
- return 0;
- }
-
- for(x1=0 ; x1<value_size-1 ; ++x1)
- {
- MulTwoWords(u.table[x1], ss2, &r2, &r1);
- c += AddTwoInts(r2,r1,x1);
- }
-
- // x1 = value_size-1 (last word)
- MulTwoWords(u.table[x1], ss2, &r2, &r1);
- c += (r2!=0) ? 1 : 0;
- c += AddInt(r1, x1);
-
- TTMATH_LOGC("UInt::MulInt(uint)", c)
-
- return (c==0)? 0 : 1;
- }
-
-
- /*!
- multiplication: result = this * ss2
-
- we're using this method only when result_size is greater than value_size
- if so there will not be a carry
- */
- template<uint result_size>
- void MulInt(uint ss2, UInt<result_size> & result) const
- {
- TTMATH_ASSERT( result_size > value_size )
-
- uint r2,r1;
- uint x1size=value_size;
- uint x1start=0;
-
- result.SetZero();
-
- if( ss2 == 0 )
- {
- TTMATH_VECTOR_LOG("UInt::MulInt(uint, UInt<>)", result.table, result_size)
- return;
- }
-
- if( value_size > 2 )
- {
- // if the value_size is smaller than or equal to 2
- // there is no sense to set x1size and x1start to another values
-
- for(x1size=value_size ; x1size>0 && table[x1size-1]==0 ; --x1size);
-
- if( x1size == 0 )
- {
- TTMATH_VECTOR_LOG("UInt::MulInt(uint, UInt<>)", result.table, result_size)
- return;
- }
-
- for(x1start=0 ; x1start<x1size && table[x1start]==0 ; ++x1start);
- }
-
- for(uint x1=x1start ; x1<x1size ; ++x1)
- {
- MulTwoWords(table[x1], ss2, &r2, &r1 );
- result.AddTwoInts(r2,r1,x1);
- }
-
- TTMATH_VECTOR_LOG("UInt::MulInt(uint, UInt<>)", result.table, result_size)
-
- return;
- }
-
-
-
- /*!
- the multiplication 'this' = 'this' * ss2
-
- algorithm: 100 - means automatically choose the fastest algorithm
- */
- uint Mul(const UInt<value_size> & ss2, uint algorithm = 100)
- {
- switch( algorithm )
- {
- case 1:
- return Mul1(ss2);
-
- case 2:
- return Mul2(ss2);
-
- case 3:
- return Mul3(ss2);
-
- case 100:
- default:
- return MulFastest(ss2);
- }
- }
-
-
- /*!
- the multiplication 'result' = 'this' * ss2
-
- since the 'result' is twice bigger than 'this' and 'ss2'
- this method never returns a carry
-
- algorithm: 100 - means automatically choose the fastest algorithm
- */
- void MulBig(const UInt<value_size> & ss2,
- UInt<value_size*2> & result,
- uint algorithm = 100)
- {
- switch( algorithm )
- {
- case 1:
- return Mul1Big(ss2, result);
-
- case 2:
- return Mul2Big(ss2, result);
-
- case 3:
- return Mul3Big(ss2, result);
-
- case 100:
- default:
- return MulFastestBig(ss2, result);
- }
- }
-
-
-
- /*!
- the first version of the multiplication algorithm
- */
-
- /*!
- multiplication: this = this * ss2
-
- it returns carry if it has been
- */
- uint Mul1(const UInt<value_size> & ss2)
- {
- TTMATH_REFERENCE_ASSERT( ss2 )
-
- UInt<value_size> ss1( *this );
- SetZero();
-
- for(uint i=0; i < value_size*TTMATH_BITS_PER_UINT ; ++i)
- {
- if( Add(*this) )
- {
- TTMATH_LOGC("UInt::Mul1", 1)
- return 1;
- }
-
- if( ss1.Rcl(1) )
- if( Add(ss2) )
- {
- TTMATH_LOGC("UInt::Mul1", 1)
- return 1;
- }
- }
-
- TTMATH_LOGC("UInt::Mul1", 0)
-
- return 0;
- }
-
-
- /*!
- multiplication: result = this * ss2
-
- result is twice bigger than 'this' and 'ss2'
- this method never returns carry
- */
- void Mul1Big(const UInt<value_size> & ss2_, UInt<value_size*2> & result)
- {
- UInt<value_size*2> ss2;
- uint i;
-
- // copying *this into result and ss2_ into ss2
- for(i=0 ; i<value_size ; ++i)
- {
- result.table[i] = table[i];
- ss2.table[i] = ss2_.table[i];
- }
-
- // cleaning the highest bytes in result and ss2
- for( ; i < value_size*2 ; ++i)
- {
- result.table[i] = 0;
- ss2.table[i] = 0;
- }
-
- // multiply
- // (there will not be a carry)
- result.Mul1( ss2 );
-
- TTMATH_LOG("UInt::Mul1Big")
- }
-
-
-
- /*!
- the second version of the multiplication algorithm
-
- this algorithm is similar to the 'schoolbook method' which is done by hand
- */
-
- /*!
- multiplication: this = this * ss2
-
- it returns carry if it has been
- */
- uint Mul2(const UInt<value_size> & ss2)
- {
- UInt<value_size*2> result;
- uint i, c = 0;
-
- Mul2Big(ss2, result);
-
- // copying result
- for(i=0 ; i<value_size ; ++i)
- table[i] = result.table[i];
-
- // testing carry
- for( ; i<value_size*2 ; ++i)
- if( result.table[i] != 0 )
- {
- c = 1;
- break;
- }
-
- TTMATH_LOGC("UInt::Mul2", c)
-
- return c;
- }
-
-
- /*!
- multiplication: result = this * ss2
-
- result is twice bigger than this and ss2
- this method never returns carry
- */
- void Mul2Big(const UInt<value_size> & ss2, UInt<value_size*2> & result)
- {
- Mul2Big2<value_size>(table, ss2.table, result);
-
- TTMATH_LOG("UInt::Mul2Big")
- }
+ TTMATH_LOG("UInt::Mul2Big")
+ }
private:
- /*!
- an auxiliary method for calculating the multiplication
+ /*!
+ an auxiliary method for calculating the multiplication
- arguments we're taking as pointers (this is to improve the Mul3Big2()- avoiding
- unnecessary copying objects), the result should be taken as a pointer too,
- but at the moment there is no method AddTwoInts() which can operate on pointers
- */
- template<uint ss_size>
- void Mul2Big2(const uint * ss1, const uint * ss2, UInt<ss_size*2> & result)
- {
- uint x1size = ss_size, x2size = ss_size;
- uint x1start = 0, x2start = 0;
-
- if( ss_size > 2 )
- {
- // if the ss_size is smaller than or equal to 2
- // there is no sense to set x1size (and others) to another values
-
- for(x1size=ss_size ; x1size>0 && ss1[x1size-1]==0 ; --x1size);
- for(x2size=ss_size ; x2size>0 && ss2[x2size-1]==0 ; --x2size);
-
- for(x1start=0 ; x1start<x1size && ss1[x1start]==0 ; ++x1start);
- for(x2start=0 ; x2start<x2size && ss2[x2start]==0 ; ++x2start);
- }
-
- Mul2Big3<ss_size>(ss1, ss2, result, x1start, x1size, x2start, x2size);
- }
+ arguments we're taking as pointers (this is to improve the Mul3Big2()- avoiding
+ unnecessary copying objects), the result should be taken as a pointer too,
+ but at the moment there is no method AddTwoInts() which can operate on pointers
+ */
+ template<uint ss_size>
+ void Mul2Big2(const uint * ss1, const uint * ss2, UInt<ss_size*2> & result)
+ {
+ uint x1size = ss_size, x2size = ss_size;
+ uint x1start = 0, x2start = 0;
+
+ if( ss_size > 2 )
+ {
+ // if the ss_size is smaller than or equal to 2
+ // there is no sense to set x1size (and others) to another values
+
+ for(x1size=ss_size ; x1size>0 && ss1[x1size-1]==0 ; --x1size);
+ for(x2size=ss_size ; x2size>0 && ss2[x2size-1]==0 ; --x2size);
+
+ for(x1start=0 ; x1start<x1size && ss1[x1start]==0 ; ++x1start);
+ for(x2start=0 ; x2start<x2size && ss2[x2start]==0 ; ++x2start);
+ }
+
+ Mul2Big3<ss_size>(ss1, ss2, result, x1start, x1size, x2start, x2size);
+ }
- /*!
- an auxiliary method for calculating the multiplication
- */
- template<uint ss_size>
- void Mul2Big3(const uint * ss1, const uint * ss2, UInt<ss_size*2> & result, uint x1start, uint x1size, uint x2start, uint x2size)
- {
- uint r2, r1;
-
- result.SetZero();
-
- if( x1size==0 || x2size==0 )
- return;
-
- for(uint x1=x1start ; x1<x1size ; ++x1)
- {
- for(uint x2=x2start ; x2<x2size ; ++x2)
- {
- MulTwoWords(ss1[x1], ss2[x2], &r2, &r1);
- result.AddTwoInts(r2, r1, x2+x1);
- // here will never be a carry
- }
- }
- }
+ /*!
+ an auxiliary method for calculating the multiplication
+ */
+ template<uint ss_size>
+ void Mul2Big3(const uint * ss1, const uint * ss2, UInt<ss_size*2> & result, uint x1start, uint x1size, uint x2start, uint x2size)
+ {
+ uint r2, r1;
+
+ result.SetZero();
+
+ if( x1size==0 || x2size==0 )
+ return;
+
+ for(uint x1=x1start ; x1<x1size ; ++x1)
+ {
+ for(uint x2=x2start ; x2<x2size ; ++x2)
+ {
+ MulTwoWords(ss1[x1], ss2[x2], &r2, &r1);
+ result.AddTwoInts(r2, r1, x2+x1);
+ // here will never be a carry
+ }
+ }
+ }
public:
- /*!
- multiplication: this = this * ss2
+ /*!
+ multiplication: this = this * ss2
- This is Karatsuba Multiplication algorithm, we're using it when value_size is greater than
- or equal to TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE macro (defined in ttmathuint.h).
- If value_size is smaller then we're using Mul2Big() instead.
-
- Karatsuba multiplication:
- Assume we have:
- this = x = x1*B^m + x0
- ss2 = y = y1*B^m + y0
- where x0 and y0 are less than B^m
- the product from multiplication we can show as:
- x*y = (x1*B^m + x0)(y1*B^m + y0) = z2*B^(2m) + z1*B^m + z0
- where
- z2 = x1*y1
- z1 = x1*y0 + x0*y1
- z0 = x0*y0
- this is standard schoolbook algorithm with O(n^2), Karatsuba observed that z1 can be given in other form:
- z1 = (x1 + x0)*(y1 + y0) - z2 - z0 / z1 = (x1*y1 + x1*y0 + x0*y1 + x0*y0) - x1*y1 - x0*y0 = x1*y0 + x0*y1 /
- and to calculate the multiplication we need only three multiplications (with some additions and subtractions)
-
- Our objects 'this' and 'ss2' we divide into two parts and by using recurrence we calculate the multiplication.
- Karatsuba multiplication has O( n^(ln(3)/ln(2)) )
- */
- uint Mul3(const UInt<value_size> & ss2)
- {
- UInt<value_size*2> result;
- uint i, c = 0;
-
- Mul3Big(ss2, result);
-
- // copying result
- for(i=0 ; i<value_size ; ++i)
- table[i] = result.table[i];
-
- // testing carry
- for( ; i<value_size*2 ; ++i)
- if( result.table[i] != 0 )
- {
- c = 1;
- break;
- }
-
- TTMATH_LOGC("UInt::Mul3", c)
-
- return c;
- }
-
-
-
- /*!
- multiplication: result = this * ss2
-
- result is twice bigger than this and ss2,
- this method never returns carry,
- (Karatsuba multiplication)
- */
- void Mul3Big(const UInt<value_size> & ss2, UInt<value_size*2> & result)
- {
- Mul3Big2<value_size>(table, ss2.table, result.table);
+ This is Karatsuba Multiplication algorithm, we're using it when value_size is greater than
+ or equal to TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE macro (defined in ttmathuint.h).
+ If value_size is smaller then we're using Mul2Big() instead.
+
+ Karatsuba multiplication:
+ Assume we have:
+ this = x = x1*B^m + x0
+ ss2 = y = y1*B^m + y0
+ where x0 and y0 are less than B^m
+ the product from multiplication we can show as:
+ x*y = (x1*B^m + x0)(y1*B^m + y0) = z2*B^(2m) + z1*B^m + z0
+ where
+ z2 = x1*y1
+ z1 = x1*y0 + x0*y1
+ z0 = x0*y0
+ this is standard schoolbook algorithm with O(n^2), Karatsuba observed that z1 can be given in other form:
+ z1 = (x1 + x0)*(y1 + y0) - z2 - z0 / z1 = (x1*y1 + x1*y0 + x0*y1 + x0*y0) - x1*y1 - x0*y0 = x1*y0 + x0*y1 /
+ and to calculate the multiplication we need only three multiplications (with some additions and subtractions)
+
+ Our objects 'this' and 'ss2' we divide into two parts and by using recurrence we calculate the multiplication.
+ Karatsuba multiplication has O( n^(ln(3)/ln(2)) )
+ */
+ uint Mul3(const UInt<value_size> & ss2)
+ {
+ UInt<value_size*2> result;
+ uint i, c = 0;
+
+ Mul3Big(ss2, result);
+
+ // copying result
+ for(i=0 ; i<value_size ; ++i)
+ table[i] = result.table[i];
+
+ // testing carry
+ for( ; i<value_size*2 ; ++i)
+ if( result.table[i] != 0 )
+ {
+ c = 1;
+ break;
+ }
+
+ TTMATH_LOGC("UInt::Mul3", c)
+
+ return c;
+ }
+
+
+
+ /*!
+ multiplication: result = this * ss2
+
+ result is twice bigger than this and ss2,
+ this method never returns carry,
+ (Karatsuba multiplication)
+ */
+ void Mul3Big(const UInt<value_size> & ss2, UInt<value_size*2> & result)
+ {
+ Mul3Big2<value_size>(table, ss2.table, result.table);
- TTMATH_LOG("UInt::Mul3Big")
- }
+ TTMATH_LOG("UInt::Mul3Big")
+ }
private:
- /*!
- an auxiliary method for calculating the Karatsuba multiplication
+ /*!
+ an auxiliary method for calculating the Karatsuba multiplication
- result_size is equal ss_size*2
- */
- template<uint ss_size>
- void Mul3Big2(const uint * ss1, const uint * ss2, uint * result)
- {
- const uint * x1, * x0, * y1, * y0;
-
-
- if( ss_size>1 && ss_size<TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE )
- {
- UInt<ss_size*2> res;
- Mul2Big2<ss_size>(ss1, ss2, res);
-
- for(uint i=0 ; i<ss_size*2 ; ++i)
- result[i] = res.table[i];
-
- return;
- }
- else
- if( ss_size == 1 )
- {
- return MulTwoWords(*ss1, *ss2, &result[1], &result[0]);
- }
-
-
- if( (ss_size & 1) == 1 )
- {
- // ss_size is odd
- x0 = ss1;
- y0 = ss2;
- x1 = ss1 + ss_size / 2 + 1;
- y1 = ss2 + ss_size / 2 + 1;
-
- // the second vectors (x1 and y1) are smaller about one from the first ones (x0 and y0)
- Mul3Big3<ss_size/2 + 1, ss_size/2, ss_size*2>(x1, x0, y1, y0, result);
- }
- else
- {
- // ss_size is even
- x0 = ss1;
- y0 = ss2;
- x1 = ss1 + ss_size / 2;
- y1 = ss2 + ss_size / 2;
-
- // all four vectors (x0 x1 y0 y1) are equal in size
- Mul3Big3<ss_size/2, ss_size/2, ss_size*2>(x1, x0, y1, y0, result);
- }
- }
+ result_size is equal ss_size*2
+ */
+ template<uint ss_size>
+ void Mul3Big2(const uint * ss1, const uint * ss2, uint * result)
+ {
+ const uint * x1, * x0, * y1, * y0;
+
+
+ if( ss_size>1 && ss_size<TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE )
+ {
+ UInt<ss_size*2> res;
+ Mul2Big2<ss_size>(ss1, ss2, res);
+
+ for(uint i=0 ; i<ss_size*2 ; ++i)
+ result[i] = res.table[i];
+
+ return;
+ }
+ else
+ if( ss_size == 1 )
+ {
+ return MulTwoWords(*ss1, *ss2, &result[1], &result[0]);
+ }
+
+
+ if( (ss_size & 1) == 1 )
+ {
+ // ss_size is odd
+ x0 = ss1;
+ y0 = ss2;
+ x1 = ss1 + ss_size / 2 + 1;
+ y1 = ss2 + ss_size / 2 + 1;
+
+ // the second vectors (x1 and y1) are smaller about one from the first ones (x0 and y0)
+ Mul3Big3<ss_size/2 + 1, ss_size/2, ss_size*2>(x1, x0, y1, y0, result);
+ }
+ else
+ {
+ // ss_size is even
+ x0 = ss1;
+ y0 = ss2;
+ x1 = ss1 + ss_size / 2;
+ y1 = ss2 + ss_size / 2;
+
+ // all four vectors (x0 x1 y0 y1) are equal in size
+ Mul3Big3<ss_size/2, ss_size/2, ss_size*2>(x1, x0, y1, y0, result);
+ }
+ }
@@ -1270,110 +1305,112 @@
#endif
- /*!
- an auxiliary method for calculating the Karatsuba multiplication
+ /*!
+ an auxiliary method for calculating the Karatsuba multiplication
+
+ x = x1*B^m + x0
+ y = y1*B^m + y0
- x = x1*B^m + x0
- y = y1*B^m + y0
+ first_size - is the size of vectors: x0 and y0
+ second_size - is the size of vectors: x1 and y1 (can be either equal first_size or smaller about one from first_size)
- first_size - is the size of vectors: x0 and y0
- second_size - is the size of vectors: x1 and y1 (can be either equal first_size or smaller about one from first_size)
+ x*y = (x1*B^m + x0)(y1*B^m + y0) = z2*B^(2m) + z1*B^m + z0
+ where
+ z0 = x0*y0
+ z2 = x1*y1
+ z1 = (x1 + x0)*(y1 + y0) - z2 - z0
+ */
+ template<uint first_size, uint second_size, uint result_size>
+ void Mul3Big3(const uint * x1, const uint * x0, const uint * y1, const uint * y0, uint * result)
+ {
+ uint i, c, xc, yc;
+
+ UInt<first_size> temp, temp2;
+ UInt<first_size*3> z1;
+
+ // z0 and z2 we store directly in the result (we don't use any temporary variables)
+ Mul3Big2<first_size>(x0, y0, result); // z0
+ Mul3Big2<second_size>(x1, y1, result+first_size*2); // z2
+
+ // now we calculate z1
+ // temp = (x0 + x1)
+ // temp2 = (y0 + y1)
+ // we're using temp and temp2 with UInt<first_size>, although there can be a carry but
+ // we simple remember it in xc and yc (xc and yc can be either 0 or 1),
+ // and (x0 + x1)*(y0 + y1) we calculate in this way (schoolbook algorithm):
+ //
+ // xc | temp
+ // yc | temp2
+ // --------------------
+ // (temp * temp2)
+ // xc*temp2 |
+ // yc*temp |
+ // xc*yc |
+ // ---------- z1 --------
+ //
+ // and the result is never larger in size than 3*first_size
+
+ xc = AddVector(x0, x1, first_size, second_size, temp.table);
+ yc = AddVector(y0, y1, first_size, second_size, temp2.table);
+
+ Mul3Big2<first_size>(temp.table, temp2.table, z1.table);
+
+ // clearing the rest of z1
+ for(i=first_size*2 ; i<first_size*3 ; ++i)
+ z1.table[i] = 0;
+
+
+ if( xc )
+ {
+ c = AddVector(z1.table+first_size, temp2.table, first_size*3-first_size, first_size, z1.table+first_size);
+ TTMATH_ASSERT( c==0 )
+ }
+
+ if( yc )
+ {
+ c = AddVector(z1.table+first_size, temp.table, first_size*3-first_size, first_size, z1.table+first_size);
+ TTMATH_ASSERT( c==0 )
+ }
+
+
+ if( xc && yc )
+ {
+ for( i=first_size*2 ; i<first_size*3 ; ++i )
+ if( ++z1.table[i] != 0 )
+ break; // break if there was no carry
+ }
+
+ // z1 = z1 - z2
+ c = SubVector(z1.table, result+first_size*2, first_size*3, second_size*2, z1.table);
+ TTMATH_ASSERT(c==0)
+
+ // z1 = z1 - z0
+ c = SubVector(z1.table, result, first_size*3, first_size*2, z1.table);
+ TTMATH_ASSERT(c==0)
+
+ // here we've calculated the z1
+ // now we're adding it to the result
+
+ if( first_size > second_size )
+ {
+ uint z1_size = result_size - first_size;
+ TTMATH_ASSERT( z1_size <= first_size*3 )
+
+ for(i=z1_size ; i<first_size*3 ; ++i)
+ {
+ TTMATH_ASSERT( z1.table[i] == 0 )
+ }
+
+ c = AddVector(result+first_size, z1.table, result_size-first_size, z1_size, result+first_size);
+ TTMATH_ASSERT(c==0)
+ }
+ else
+ {
+ c = AddVector(result+first_size, z1.table, result_size-first_size, first_size*3, result+first_size);
+ TTMATH_ASSERT(c==0)
+ }
+ }
- x*y = (x1*B^m + x0)(y1*B^m + y0) = z2*B^(2m) + z1*B^m + z0
- where
- z0 = x0*y0
- z2 = x1*y1
- z1 = (x1 + x0)*(y1 + y0) - z2 - z0
- */
- template<uint first_size, uint second_size, uint result_size>
- void Mul3Big3(const uint * x1, const uint * x0, const uint * y1, const uint * y0, uint * result)
- {
- uint i, c, xc, yc;
-
- UInt<first_size> temp, temp2;
- UInt<first_size*3> z1;
-
- // z0 and z2 we store directly in the result (we don't use any temporary variables)
- Mul3Big2<first_size>(x0, y0, result); // z0
- Mul3Big2<second_size>(x1, y1, result+first_size*2); // z2
-
- // now we calculate z1
- // temp = (x0 + x1)
- // temp2 = (y0 + y1)
- // we're using temp and temp2 with UInt<first_size>, although there can be a carry but
- // we simple remember it in xc and yc (xc and yc can be either 0 or 1),
- // and (x0 + x1)*(y0 + y1) we calculate in this way (schoolbook algorithm):
- //
- // xc | temp
- // yc | temp2
- // --------------------
- // (temp * temp2)
- // xc*temp2 |
- // yc*temp |
- // xc*yc |
- // ---------- z1 --------
- //
- // and the result is never larger in size than 3*first_size
-
- xc = AddVector(x0, x1, first_size, second_size, temp.table);
- yc = AddVector(y0, y1, first_size, second_size, temp2.table);
-
- Mul3Big2<first_size>(temp.table, temp2.table, z1.table);
-
- // clearing the rest of z1
- for(i=first_size*2 ; i<first_size*3 ; ++i)
- z1.table[i] = 0;
-
-
- if( xc )
- {
- c = AddVector(z1.table+first_size, temp2.table, first_size*3-first_size, first_size, z1.table+first_size);
- TTMATH_ASSERT( c==0 )
- }
-
- if( yc )
- {
- c = AddVector(z1.table+first_size, temp.table, first_size*3-first_size, first_size, z1.table+first_size);
- TTMATH_ASSERT( c==0 )
- }
-
-
- if( xc && yc )
- {
- for( i=first_size*2 ; i<first_size*3 ; ++i )
- if( ++z1.table[i] != 0 )
- break; // break if there was no carry
- }
-
- // z1 = z1 - z2
- c = SubVector(z1.table, result+first_size*2, first_size*3, second_size*2, z1.table);
- TTMATH_ASSERT(c==0)
-
- // z1 = z1 - z0
- c = SubVector(z1.table, result, first_size*3, first_size*2, z1.table);
- TTMATH_ASSERT(c==0)
-
- // here we've calculated the z1
- // now we're adding it to the result
-
- if( first_size > second_size )
- {
- uint z1_size = result_size - first_size;
- TTMATH_ASSERT( z1_size <= first_size*3 )
-
- for(i=z1_size ; i<first_size*3 ; ++i)
- TTMATH_ASSERT( z1.table[i] == 0 )
- ;
-
- c = AddVector(result+first_size, z1.table, result_size-first_size, z1_size, result+first_size);
- TTMATH_ASSERT(c==0)
- }
- else
- {
- c = AddVector(result+first_size, z1.table, result_size-first_size, first_size*3, result+first_size);
- TTMATH_ASSERT(c==0)
- }
- }
#ifdef _MSC_VER
@@ -1384,2115 +1421,2693 @@
public:
- /*!
- multiplication this = this * ss2
- */
- uint MulFastest(const UInt<value_size> & ss2)
- {
- UInt<value_size*2> result;
- uint i, c = 0;
-
- MulFastestBig(ss2, result);
-
- // copying result
- for(i=0 ; i<value_size ; ++i)
- table[i] = result.table[i];
-
- // testing carry
- for( ; i<value_size*2 ; ++i)
- if( result.table[i] != 0 )
- {
- c = 1;
- break;
- }
-
- TTMATH_LOGC("UInt::MulFastest", c)
-
- return c;
- }
-
-
- /*!
- multiplication result = this * ss2
-
- this method is trying to select the fastest algorithm
- (in the future this method can be improved)
- */
- void MulFastestBig(const UInt<value_size> & ss2, UInt<value_size*2> & result)
- {
- if( value_size < TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE )
- return Mul2Big(ss2, result);
-
- uint x1size = value_size, x2size = value_size;
- uint x1start = 0, x2start = 0;
-
- for(x1size=value_size ; x1size>0 && table[x1size-1]==0 ; --x1size);
- for(x2size=value_size ; x2size>0 && ss2.table[x2size-1]==0 ; --x2size);
-
- if( x1size==0 || x2size==0 )
- {
- // either 'this' or 'ss2' is equal zero - the result is zero too
- result.SetZero();
- return;
- }
-
- for(x1start=0 ; x1start<x1size && table[x1start]==0 ; ++x1start);
- for(x2start=0 ; x2start<x2size && ss2.table[x2start]==0 ; ++x2start);
-
- uint distancex1 = x1size - x1start;
- uint distancex2 = x2size - x2start;
-
- if( distancex1 < 3 || distancex2 < 3 )
- // either 'this' or 'ss2' have only 2 (or 1) items different from zero (side by side)
- // (this condition in the future can be improved)
- return Mul2Big3<value_size>(table, ss2.table, result, x1start, x1size, x2start, x2size);
-
-
- // Karatsuba multiplication
- Mul3Big(ss2, result);
-
- TTMATH_LOG("UInt::MulFastestBig")
- }
-
-
- /*!
- *
- * Division
- *
- *
- */
-
+ /*!
+ multiplication this = this * ss2
+ */
+ uint MulFastest(const UInt<value_size> & ss2)
+ {
+ UInt<value_size*2> result;
+ uint i, c = 0;
+
+ MulFastestBig(ss2, result);
+
+ // copying result
+ for(i=0 ; i<value_size ; ++i)
+ table[i] = result.table[i];
+
+ // testing carry
+ for( ; i<value_size*2 ; ++i)
+ if( result.table[i] != 0 )
+ {
+ c = 1;
+ break;
+ }
+
+ TTMATH_LOGC("UInt::MulFastest", c)
+
+ return c;
+ }
+
+
+ /*!
+ multiplication result = this * ss2
+
+ this method is trying to select the fastest algorithm
+ (in the future this method can be improved)
+ */
+ void MulFastestBig(const UInt<value_size> & ss2, UInt<value_size*2> & result)
+ {
+ if( value_size < TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE )
+ return Mul2Big(ss2, result);
+
+ uint x1size = value_size, x2size = value_size;
+ uint x1start = 0, x2start = 0;
+
+ for(x1size=value_size ; x1size>0 && table[x1size-1]==0 ; --x1size);
+ for(x2size=value_size ; x2size>0 && ss2.table[x2size-1]==0 ; --x2size);
+
+ if( x1size==0 || x2size==0 )
+ {
+ // either 'this' or 'ss2' is equal zero - the result is zero too
+ result.SetZero();
+ return;
+ }
+
+ for(x1start=0 ; x1start<x1size && table[x1start]==0 ; ++x1start);
+ for(x2start=0 ; x2start<x2size && ss2.table[x2start]==0 ; ++x2start);
+
+ uint distancex1 = x1size - x1start;
+ uint distancex2 = x2size - x2start;
+
+ if( distancex1 < 3 || distancex2 < 3 )
+ // either 'this' or 'ss2' have only 2 (or 1) items different from zero (side by side)
+ // (this condition in the future can be improved)
+ return Mul2Big3<value_size>(table, ss2.table, result, x1start, x1size, x2start, x2size);
+
+
+ // Karatsuba multiplication
+ Mul3Big(ss2, result);
+
+ TTMATH_LOG("UInt::MulFastestBig")
+ }
+
+
+ /*!
+ *
+ * Division
+ *
+ *
+ */
+
public:
- /*!
- division by one unsigned word
+ /*!
+ division by one unsigned word
- returns 1 when divisor is zero
- */
- uint DivInt(uint divisor, uint * remainder = 0)
- {
- if( divisor == 0 )
- {
- if( remainder )
- *remainder = 0; // this is for convenience, without it the compiler can report that 'remainder' is uninitialized
-
- TTMATH_LOG("UInt::DivInt")
-
- return 1;
- }
-
- if( divisor == 1 )
- {
- if( remainder )
- *remainder = 0;
-
- TTMATH_LOG("UInt::DivInt")
-
- return 0;
- }
-
- UInt<value_size> dividend(*this);
- SetZero();
-
- sint i; // i must be with a sign
- uint r = 0;
-
- // we're looking for the last word in ss1
- for(i=value_size-1 ; i>0 && dividend.table[i]==0 ; --i);
-
- for( ; i>=0 ; --i)
- DivTwoWords(r, dividend.table[i], divisor, &table[i], &r);
-
- if( remainder )
- *remainder = r;
-
- TTMATH_LOG("UInt::DivInt")
-
- return 0;
- }
-
- uint DivInt(uint divisor, uint & remainder)
- {
- return DivInt(divisor, &remainder);
- }
-
-
-
- /*!
- division this = this / ss2
-
- return values:
- 0 - ok
- 1 - division by zero
- 'this' will be the quotient
- 'remainder' - remainder
- */
- uint Div( const UInt<value_size> & divisor,
- UInt<value_size> * remainder = 0,
- uint algorithm = 3)
- {
- switch( algorithm )
- {
- case 1:
- return Div1(divisor, remainder);
-
- case 2:
- return Div2(divisor, remainder);
-
- case 3:
- default:
- return Div3(divisor, remainder);
- }
- }
-
- uint Div(const UInt<value_size> & divisor, UInt<value_size> & remainder, uint algorithm = 3)
- {
- return Div(divisor, &remainder, algorithm);
- }
+ returns 1 when divisor is zero
+ */
+ uint DivInt(uint divisor, uint * remainder = 0)
+ {
+ if( divisor == 0 )
+ {
+ if( remainder )
+ *remainder = 0; // this is for convenience, without it the compiler can report that 'remainder' is uninitialized
+
+ TTMATH_LOG("UInt::DivInt")
+
+ return 1;
+ }
+
+ if( divisor == 1 )
+ {
+ if( remainder )
+ *remainder = 0;
+
+ TTMATH_LOG("UInt::DivInt")
+
+ return 0;
+ }
+
+ UInt<value_size> dividend(*this);
+ SetZero();
+
+ sint i; // i must be with a sign
+ uint r = 0;
+
+ // we're looking for the last word in ss1
+ for(i=value_size-1 ; i>0 && dividend.table[i]==0 ; --i);
+
+ for( ; i>=0 ; --i)
+ DivTwoWords(r, dividend.table[i], divisor, &table[i], &r);
+
+ if( remainder )
+ *remainder = r;
+
+ TTMATH_LOG("UInt::DivInt")
+
+ return 0;
+ }
+
+ uint DivInt(uint divisor, uint & remainder)
+ {
+ return DivInt(divisor, &remainder);
+ }
+
+
+
+ /*!
+ division this = this / ss2
+
+ return values:
+ 0 - ok
+ 1 - division by zero
+ 'this' will be the quotient
+ 'remainder' - remainder
+ */
+ uint Div( const UInt<value_size> & divisor,
+ UInt<value_size> * remainder = 0,
+ uint algorithm = 3)
+ {
+ switch( algorithm )
+ {
+ case 1:
+ return Div1(divisor, remainder);
+
+ case 2:
+ return Div2(divisor, remainder);
+
+ case 3:
+ default:
+ return Div3(divisor, remainder);
+ }
+ }
+
+ uint Div(const UInt<value_size> & divisor, UInt<value_size> & remainder, uint algorithm = 3)
+ {
+ return Div(divisor, &remainder, algorithm);
+ }
private:
- /*!
- return values:
- 0 - none has to be done
- 1 - division by zero
- 2 - division should be made
- */
- uint Div_StandardTest( const UInt<value_size> & v,
- uint & m, uint & n,
- UInt<value_size> * remainder = 0)
- {
- switch( Div_CalculatingSize(v, m, n) )
- {
- case 4: // 'this' is equal v
- if( remainder )
- remainder->SetZero();
-
- SetOne();
- TTMATH_LOG("UInt::Div_StandardTest")
- return 0;
-
- case 3: // 'this' is smaller than v
- if( remainder )
- *remainder = *this;
-
- SetZero();
- TTMATH_LOG("UInt::Div_StandardTest")
- return 0;
-
- case 2: // 'this' is zero
- if( remainder )
- remainder->SetZero();
-
- SetZero();
- TTMATH_LOG("UInt::Div_StandardTest")
- return 0;
-
- case 1: // v is zero
- TTMATH_LOG("UInt::Div_StandardTest")
- return 1;
- }
-
- TTMATH_LOG("UInt::Div_StandardTest")
-
- return 2;
- }
-
-
-
- /*!
- return values:
- 0 - ok
- 'm' - is the index (from 0) of last non-zero word in table ('this')
- 'n' - is the index (from 0) of last non-zero word in v.table
- 1 - v is zero
- 2 - 'this' is zero
- 3 - 'this' is smaller than v
- 4 - 'this' is equal v
-
- if the return value is different than zero the 'm' and 'n' are undefined
- */
- uint Div_CalculatingSize(const UInt<value_size> & v, uint & m, uint & n)
- {
- m = n = value_size-1;
-
- for( ; n!=0 && v.table[n]==0 ; --n);
-
- if( n==0 && v.table[n]==0 )
- return 1;
-
- for( ; m!=0 && table[m]==0 ; --m);
-
- if( m==0 && table[m]==0 )
- return 2;
-
- if( m < n )
- return 3;
- else
- if( m == n )
- {
- uint i;
- for(i = n ; i!=0 && table[i]==v.table[i] ; --i);
-
- if( table[i] < v.table[i] )
- return 3;
- else
- if (table[i] == v.table[i] )
- return 4;
- }
+ /*!
+ return values:
+ 0 - none has to be done
+ 1 - division by zero
+ 2 - division should be made
+ */
+ uint Div_StandardTest( const UInt<value_size> & v,
+ uint & m, uint & n,
+ UInt<value_size> * remainder = 0)
+ {
+ switch( Div_CalculatingSize(v, m, n) )
+ {
+ case 4: // 'this' is equal v
+ if( remainder )
+ remainder->SetZero();
+
+ SetOne();
+ TTMATH_LOG("UInt::Div_StandardTest")
+ return 0;
+
+ case 3: // 'this' is smaller than v
+ if( remainder )
+ *remainder = *this;
+
+ SetZero();
+ TTMATH_LOG("UInt::Div_StandardTest")
+ return 0;
+
+ case 2: // 'this' is zero
+ if( remainder )
+ remainder->SetZero();
+
+ SetZero();
+ TTMATH_LOG("UInt::Div_StandardTest")
+ return 0;
+
+ case 1: // v is zero
+ TTMATH_LOG("UInt::Div_StandardTest")
+ return 1;
+ }
+
+ TTMATH_LOG("UInt::Div_StandardTest")
+
+ return 2;
+ }
+
+
+
+ /*!
+ return values:
+ 0 - ok
+ 'm' - is the index (from 0) of last non-zero word in table ('this')
+ 'n' - is the index (from 0) of last non-zero word in v.table
+ 1 - v is zero
+ 2 - 'this' is zero
+ 3 - 'this' is smaller than v
+ 4 - 'this' is equal v
+
+ if the return value is different than zero the 'm' and 'n' are undefined
+ */
+ uint Div_CalculatingSize(const UInt<value_size> & v, uint & m, uint & n)
+ {
+ m = n = value_size-1;
+
+ for( ; n!=0 && v.table[n]==0 ; --n);
+
+ if( n==0 && v.table[n]==0 )
+ return 1;
+
+ for( ; m!=0 && table[m]==0 ; --m);
+
+ if( m==0 && table[m]==0 )
+ return 2;
+
+ if( m < n )
+ return 3;
+ else
+ if( m == n )
+ {
+ uint i;
+ for(i = n ; i!=0 && table[i]==v.table[i] ; --i);
+
+ if( table[i] < v.table[i] )
+ return 3;
+ else
+ if (table[i] == v.table[i] )
+ return 4;
+ }
- return 0;
- }
+ return 0;
+ }
public:
- /*!
- the first division algorithm
- radix 2
- */
- uint Div1(const UInt<value_size> & divisor, UInt<value_size> * remainder = 0)
- {
- uint m,n, test;
-
- test = Div_StandardTest(divisor, m, n, remainder);
- if( test < 2 )
- return test;
-
- if( !remainder )
- {
- UInt<value_size> rem;
+ /*!
+ the first division algorithm
+ radix 2
+ */
+ uint Div1(const UInt<value_size> & divisor, UInt<value_size> * remainder = 0)
+ {
+ uint m,n, test;
+
+ test = Div_StandardTest(divisor, m, n, remainder);
+ if( test < 2 )
+ return test;
+
+ if( !remainder )
+ {
+ UInt<value_size> rem;
+
+ return Div1_Calculate(divisor, rem);
+ }
+
+ return Div1_Calculate(divisor, *remainder);
+ }
+
+
+ /*!
+ the first division algorithm
+ radix 2
+ */
+ uint Div1(const UInt<value_size> & divisor, UInt<value_size> & remainder)
+ {
+ return Div1(divisor, &remainder);
+ }
+
+
+private:
+
+ uint Div1_Calculate(const UInt<value_size> & divisor, UInt<value_size> & rest)
+ {
+ if( this == &divisor )
+ {
+ UInt<value_size> divisor_copy(divisor);
+ return Div1_CalculateRef(divisor_copy, rest);
+ }
+ else
+ {
+ return Div1_CalculateRef(divisor, rest);
+ }
+ }
+
+
+ uint Div1_CalculateRef(const UInt<value_size> & divisor, UInt<value_size> & rest)
+ {
+ TTMATH_REFERENCE_ASSERT( divisor )
+
+ sint loop;
+ sint c;
+
+ rest.SetZero();
+ loop = value_size * TTMATH_BITS_PER_UINT;
+ c = 0;
+
+
+ div_a:
+ c = Rcl(1, c);
+ c = rest.Add(rest,c);
+ c = rest.Sub(divisor,c);
+
+ c = !c;
+
+ if(!c)
+ goto div_d;
+
+
+ div_b:
+ --loop;
+ if(loop)
+ goto div_a;
+
+ c = Rcl(1, c);
+ TTMATH_LOG("UInt::Div1_Calculate")
+ return 0;
+
+
+ div_c:
+ c = Rcl(1, c);
+ c = rest.Add(rest,c);
+ c = rest.Add(divisor);
+
+ if(c)
+ goto div_b;
+
+
+ div_d:
+ --loop;
+ if(loop)
+ goto div_c;
+
+ c = Rcl(1, c);
+ c = rest.Add(divisor);
+
+ TTMATH_LOG("UInt::Div1_Calculate")
+
+ return 0;
+ }
+
+
+public:
- return Div1_Calculate(divisor, rem);
- }
+ /*!
+ the second division algorithm
- return Div1_Calculate(divisor, *remainder);
- }
+ return values:
+ 0 - ok
+ 1 - division by zero
+ */
+ uint Div2(const UInt<value_size> & divisor, UInt<value_size> * remainder = 0)
+ {
+ if( this == &divisor )
+ {
+ UInt<value_size> divisor_copy(divisor);
+ return Div2Ref(divisor_copy, remainder);
+ }
+ else
+ {
+ return Div2Ref(divisor, remainder);
+ }
+ }
+
+
+ /*!
+ the second division algorithm
+
+ return values:
+ 0 - ok
+ 1 - division by zero
+ */
+ uint Div2(const UInt<value_size> & divisor, UInt<value_size> & remainder)
+ {
+ return Div2(divisor, &remainder);
+ }
private:
+ /*!
+ the second division algorithm
- uint Div1_Calculate(const UInt<value_size> & divisor, UInt<value_size> & rest)
- {
- TTMATH_REFERENCE_ASSERT( divisor )
+ return values:
+ 0 - ok
+ 1 - division by zero
+ */
+ uint Div2Ref(const UInt<value_size> & divisor, UInt<value_size> * remainder = 0)
+ {
+ uint bits_diff;
+ uint status = Div2_Calculate(divisor, remainder, bits_diff);
+ if( status < 2 )
+ return status;
+
+ if( CmpBiggerEqual(divisor) )
+ {
+ Div2(divisor, remainder);
+ SetBit(bits_diff);
+ }
+ else
+ {
+ if( remainder )
+ *remainder = *this;
+
+ SetZero();
+ SetBit(bits_diff);
+ }
+
+ TTMATH_LOG("UInt::Div2")
+
+ return 0;
+ }
+
+
+ /*!
+ return values:
+ 0 - we've calculated the division
+ 1 - division by zero
+ 2 - we have to still calculate
+
+ */
+ uint Div2_Calculate(const UInt<value_size> & divisor, UInt<value_size> * remainder,
+ uint & bits_diff)
+ {
+ uint table_id, index;
+ uint divisor_table_id, divisor_index;
+
+ uint status = Div2_FindLeadingBitsAndCheck( divisor, remainder,
+ table_id, index,
+ divisor_table_id, divisor_index);
+
+ if( status < 2 )
+ {
+ TTMATH_LOG("UInt::Div2_Calculate")
+ return status;
+ }
+
+ // here we know that 'this' is greater than divisor
+ // then 'index' is greater or equal 'divisor_index'
+ bits_diff = index - divisor_index;
+
+ UInt<value_size> divisor_copy(divisor);
+ divisor_copy.Rcl(bits_diff, 0);
+
+ if( CmpSmaller(divisor_copy, table_id) )
+ {
+ divisor_copy.Rcr(1);
+ --bits_diff;
+ }
+
+ Sub(divisor_copy, 0);
+
+ TTMATH_LOG("UInt::Div2_Calculate")
+
+ return 2;
+ }
+
+
+ /*!
+ return values:
+ 0 - we've calculated the division
+ 1 - division by zero
+ 2 - we have to still calculate
+ */
+ uint Div2_FindLeadingBitsAndCheck( const UInt<value_size> & divisor,
+ UInt<value_size> * remainder,
+ uint & table_id, uint & index,
+ uint & divisor_table_id, uint & divisor_index)
+ {
+ if( !divisor.FindLeadingBit(divisor_table_id, divisor_index) )
+ {
+ // division by zero
+ TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck")
+ return 1;
+ }
+
+ if( !FindLeadingBit(table_id, index) )
+ {
+ // zero is divided by something
+
+ SetZero();
+
+ if( remainder )
+ remainder->SetZero();
+
+ TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck")
+
+ return 0;
+ }
+
+ divisor_index += divisor_table_id * TTMATH_BITS_PER_UINT;
+ index += table_id * TTMATH_BITS_PER_UINT;
+
+ if( divisor_table_id == 0 )
+ {
+ // dividor has only one 32-bit word
+
+ uint r;
+ DivInt(divisor.table[0], &r);
+
+ if( remainder )
+ {
+ remainder->SetZero();
+ remainder->table[0] = r;
+ }
+
+ TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck")
+
+ return 0;
+ }
+
+
+ if( Div2_DivisorGreaterOrEqual( divisor, remainder,
+ table_id, index,
+ divisor_index) )
+ {
+ TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck")
+ return 0;
+ }
+
+
+ TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck")
+
+ return 2;
+ }
+
+
+ /*!
+ return values:
+ true if divisor is equal or greater than 'this'
+ */
+ bool Div2_DivisorGreaterOrEqual( const UInt<value_size> & divisor,
+ UInt<value_size> * remainder,
+ uint table_id, uint index,
+ uint divisor_index )
+ {
+ if( divisor_index > index )
+ {
+ // divisor is greater than this
+
+ if( remainder )
+ *remainder = *this;
+
+ SetZero();
+
+ TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual")
+
+ return true;
+ }
+
+ if( divisor_index == index )
+ {
+ // table_id == divisor_table_id as well
+
+ uint i;
+ for(i = table_id ; i!=0 && table[i]==divisor.table[i] ; --i);
+
+ if( table[i] < divisor.table[i] )
+ {
+ // divisor is greater than 'this'
+
+ if( remainder )
+ *remainder = *this;
+
+ SetZero();
+
+ TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual")
+
+ return true;
+ }
+ else
+ if( table[i] == divisor.table[i] )
+ {
+ // divisor is equal 'this'
+
+ if( remainder )
+ remainder->SetZero();
+
+ SetOne();
+
+ TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual")
+
+ return true;
+ }
+ }
- sint loop;
- sint c;
+ TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual")
- rest.SetZero();
- loop = value_size * TTMATH_BITS_PER_UINT;
- c = 0;
+ return false;
+ }
- div_a:
- c = Rcl(1, c);
- c = rest.Add(rest,c);
- c = rest.Sub(divisor,c);
+public:
- c = !c;
+ /*!
+ the third division algorithm
+ */
+ uint Div3(const UInt<value_size> & ss2, UInt<value_size> * remainder = 0)
+ {
+ if( this == &ss2 )
+ {
+ UInt<value_size> copy_ss2(ss2);
+ return Div3Ref(copy_ss2, remainder);
+ }
+ else
+ {
+ return Div3Ref(ss2, remainder);
+ }
+ }
+
+
+ /*!
+ the third division algorithm
+ */
+ uint Div3(const UInt<value_size> & ss2, UInt<value_size> & remainder)
+ {
+ return Div3(ss2, &remainder);
+ }
- if(!c)
- goto div_d;
+private:
- div_b:
- --loop;
- if(loop)
- goto div_a;
+ /*!
+ the third division algorithm
- c = Rcl(1, c);
- TTMATH_LOG("UInt::Div1_Calculate")
- return 0;
+ this algorithm is described in the following book:
+ "The art of computer programming 2" (4.3.1 page 272)
+ Donald E. Knuth
+ !! give the description here (from the book)
+ */
+ uint Div3Ref(const UInt<value_size> & v, UInt<value_size> * remainder = 0)
+ {
+ uint m,n, test;
+
+ test = Div_StandardTest(v, m, n, remainder);
+ if( test < 2 )
+ return test;
+
+ if( n == 0 )
+ {
+ uint r;
+ DivInt( v.table[0], &r );
+
+ if( remainder )
+ {
+ remainder->SetZero();
+ remainder->table[0] = r;
+ }
+
+ TTMATH_LOG("UInt::Div3")
+
+ return 0;
+ }
+
+
+ // we can only use the third division algorithm when
+ // the divisor is greater or equal 2^32 (has more than one 32-bit word)
+ ++m;
+ ++n;
+ m = m - n;
+ Div3_Division(v, remainder, m, n);
+ TTMATH_LOG("UInt::Div3")
- div_c:
- c = Rcl(1, c);
- c = rest.Add(rest,c);
- c = rest.Add(divisor);
+ return 0;
+ }
- if(c)
- goto div_b;
- div_d:
- --loop;
- if(loop)
- goto div_c;
+private:
- c = Rcl(1, c);
- c = rest.Add(divisor);
- TTMATH_LOG("UInt::Div1_Calculate")
+ void Div3_Division(UInt<value_size> v, UInt<value_size> * remainder, uint m, uint n)
+ {
+ TTMATH_ASSERT( n>=2 )
- return 0;
- }
+ UInt<value_size+1> uu, vv;
+ UInt<value_size> q;
+ uint d, u_value_size, u0, u1, u2, v1, v0, j=m;
+
+ u_value_size = Div3_Normalize(v, n, d);
+ if( j+n == value_size )
+ u2 = u_value_size;
+ else
+ u2 = table[j+n];
-public:
+ Div3_MakeBiggerV(v, vv);
+ for(uint i = j+1 ; i<value_size ; ++i)
+ q.table[i] = 0;
- /*!
- the second division algorithm
+ while( true )
+ {
+ u1 = table[j+n-1];
+ u0 = table[j+n-2];
+ v1 = v.table[n-1];
+ v0 = v.table[n-2];
- return values:
- 0 - ok
- 1 - division by zero
- */
- uint Div2(const UInt<value_size> & divisor, UInt<value_size> * remainder = 0)
- {
- TTMATH_REFERENCE_ASSERT( divisor )
-
- uint bits_diff;
- uint status = Div2_Calculate(divisor, remainder, bits_diff);
- if( status < 2 )
- return status;
-
- if( CmpBiggerEqual(divisor) )
- {
- Div2(divisor, remainder);
- SetBit(bits_diff);
- }
- else
- {
- if( remainder )
- *remainder = *this;
-
- SetZero();
- SetBit(bits_diff);
- }
-
- TTMATH_LOG("UInt::Div2")
-
- return 0;
- }
-
-
- uint Div2(const UInt<value_size> & divisor, UInt<value_size> & remainder)
- {
- return Div2(divisor, &remainder);
- }
+ uint qp = Div3_Calculate(u2,u1,u0, v1,v0);
+ Div3_MakeNewU(uu, j, n, u2);
+ Div3_MultiplySubtract(uu, vv, qp);
+ Div3_CopyNewU(uu, j, n);
-private:
+ q.table[j] = qp;
- /*!
- return values:
- 0 - we've calculated the division
- 1 - division by zero
- 2 - we have to still calculate
+ // the next loop
+ if( j-- == 0 )
+ break;
- */
- uint Div2_Calculate(const UInt<value_size> & divisor, UInt<value_size> * remainder,
- uint & bits_diff)
- {
- uint table_id, index;
- uint divisor_table_id, divisor_index;
+ u2 = table[j+n];
+ }
- uint status = Div2_FindLeadingBitsAndCheck( divisor, remainder,
- table_id, index,
- divisor_table_id, divisor_index);
+ if( remainder )
+ Div3_Unnormalize(remainder, n, d);
- if( status < 2 )
- {
- TTMATH_LOG("UInt::Div2_Calculate")
- return status;
- }
+ *this = q;
- // here we know that 'this' is greater than divisor
- // then 'index' is greater or equal 'divisor_index'
- bits_diff = index - divisor_index;
+ TTMATH_LOG("UInt::Div3_Division")
+ }
- UInt<value_size> divisor_copy(divisor);
- divisor_copy.Rcl(bits_diff, 0);
- if( CmpSmaller(divisor_copy, table_id) )
- {
- divisor_copy.Rcr(1);
- --bits_diff;
- }
+ void Div3_MakeNewU(UInt<value_size+1> & uu, uint j, uint n, uint u_max)
+ {
+ uint i;
- Sub(divisor_copy, 0);
+ for(i=0 ; i<n ; ++i, ++j)
+ uu.table[i] = table[j];
- TTMATH_LOG("UInt::Div2_Calculate")
+ // 'n' is from <1..value_size> so and 'i' is from <0..value_size>
+ // then table[i] is always correct (look at the declaration of 'uu')
+ uu.table[i] = u_max;
- return 2;
- }
+ for( ++i ; i<value_size+1 ; ++i)
+ uu.table[i] = 0;
+ TTMATH_LOG("UInt::Div3_MakeNewU")
+ }
- /*!
- return values:
- 0 - we've calculated the division
- 1 - division by zero
- 2 - we have to still calculate
- */
- uint Div2_FindLeadingBitsAndCheck( const UInt<value_size> & divisor,
- UInt<value_size> * remainder,
- uint & table_id, uint & index,
- uint & divisor_table_id, uint & divisor_index)
- {
- if( !divisor.FindLeadingBit(divisor_table_id, divisor_index) )
- {
- // division by zero
- TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck")
- return 1;
- }
- if( !FindLeadingBit(table_id, index) )
- {
- // zero is divided by something
+ void Div3_CopyNewU(const UInt<value_size+1> & uu, uint j, uint n)
+ {
+ uint i;
- SetZero();
+ for(i=0 ; i<n ; ++i)
+ table[i+j] = uu.table[i];
- if( remainder )
- remainder->SetZero();
+ if( i+j < value_size )
+ table[i+j] = uu.table[i];
- TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck")
+ TTMATH_LOG("UInt::Div3_CopyNewU")
+ }
- return 0;
- }
- divisor_index += divisor_table_id * TTMATH_BITS_PER_UINT;
- index += table_id * TTMATH_BITS_PER_UINT;
+ /*!
+ we're making the new 'vv'
+ the value is actually the same but the 'table' is bigger (value_size+1)
+ */
+ void Div3_MakeBiggerV(const UInt<value_size> & v, UInt<value_size+1> & vv)
+ {
+ for(uint i=0 ; i<value_size ; ++i)
+ vv.table[i] = v.table[i];
- if( divisor_table_id == 0 )
- {
- // dividor has only one 32-bit word
+ vv.table[value_size] = 0;
- uint r;
- DivInt(divisor.table[0], &r);
+ TTMATH_LOG("UInt::Div3_MakeBiggerV")
+ }
+
- if( remainder )
- {
- remainder->SetZero();
- remainder->table[0] = r;
- }
+ /*!
+ we're moving all bits from 'v' into the left side of the n-1 word
+ (the highest bit at v.table[n-1] will be equal one,
+ the bits from 'this' we're moving the same times as 'v')
- TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck")
+ return values:
+ d - how many times we've moved
+ return - the next-left value from 'this' (that after table[value_size-1])
+ */
+ uint Div3_Normalize(UInt<value_size> & v, uint n, uint & d)
+ {
+ // v.table[n-1] is != 0
- return 0;
- }
+ uint bit = (uint)FindLeadingBitInWord(v.table[n-1]);
+ uint move = (TTMATH_BITS_PER_UINT - bit - 1);
+ uint res = table[value_size-1];
+ d = move;
+ if( move > 0 )
+ {
+ v.Rcl(move, 0);
+ Rcl(move, 0);
+ res = res >> (bit + 1);
+ }
+ else
+ {
+ res = 0;
+ }
- if( Div2_DivisorGreaterOrEqual( divisor, remainder,
- table_id, index,
- divisor_index) )
- {
- TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck")
- return 0;
- }
+ TTMATH_LOG("UInt::Div3_Normalize")
+ return res;
+ }
- TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck")
- return 2;
- }
+ void Div3_Unnormalize(UInt<value_size> * remainder, uint n, uint d)
+ {
+ for(uint i=n ; i<value_size ; ++i)
+ table[i] = 0;
+ Rcr(d,0);
- /*!
- return values:
- true if divisor is equal or greater than 'this'
- */
- bool Div2_DivisorGreaterOrEqual( const UInt<value_size> & divisor,
- UInt<value_size> * remainder,
- uint table_id, uint index,
- uint divisor_index )
- {
- if( divisor_index > index )
- {
- // divisor is greater than this
+ *remainder = *this;
- if( remainder )
- *remainder = *this;
+ TTMATH_LOG("UInt::Div3_Unnormalize")
+ }
- SetZero();
- TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual")
+ uint Div3_Calculate(uint u2, uint u1, uint u0, uint v1, uint v0)
+ {
+ UInt<2> u_temp;
+ uint rp;
+ bool next_test;
- return true;
- }
+ TTMATH_ASSERT( v1 != 0 )
- if( divisor_index == index )
- {
- // table_id == divisor_table_id as well
+ u_temp.table[1] = u2;
+ u_temp.table[0] = u1;
+ u_temp.DivInt(v1, &rp);
- uint i;
- for(i = table_id ; i!=0 && table[i]==divisor.table[i] ; --i);
+ TTMATH_ASSERT( u_temp.table[1]==0 || u_temp.table[1]==1 )
- if( table[i] < divisor.table[i] )
- {
- // divisor is greater than 'this'
+ do
+ {
+ bool decrease = false;
- if( remainder )
- *remainder = *this;
+ if( u_temp.table[1] == 1 )
+ decrease = true;
+ else
+ {
+ UInt<2> temp1, temp2;
- SetZero();
+ UInt<2>::MulTwoWords(u_temp.table[0], v0, temp1.table+1, temp1.table);
+ temp2.table[1] = rp;
+ temp2.table[0] = u0;
- TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual")
+ if( temp1 > temp2 )
+ decrease = true;
+ }
- return true;
- }
- else
- if( table[i] == divisor.table[i] )
- {
- // divisor is equal 'this'
+ next_test = false;
- if( remainder )
- remainder->SetZero();
+ if( decrease )
+ {
+ u_temp.SubOne();
- SetOne();
+ rp += v1;
- TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual")
+ if( rp >= v1 ) // it means that there wasn't a carry (r<b from the book)
+ next_test = true;
+ }
+ }
+ while( next_test );
- return true;
- }
- }
+ TTMATH_LOG("UInt::Div3_Calculate")
- TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual")
+ return u_temp.table[0];
+ }
- return false;
- }
-public:
+ void Div3_MultiplySubtract( UInt<value_size+1> & uu,
+ const UInt<value_size+1> & vv, uint & qp)
+ {
+ // D4 (in the book)
- /*!
- the third division algorithm
+ UInt<value_size+1> vv_temp(vv);
+ vv_temp.MulInt(qp);
- this algorithm is described in the following book:
- "The art of computer programming 2" (4.3.1 page 272)
- Donald E. Knuth
- */
- uint Div3(const UInt<value_size> & v, UInt<value_size> * remainder = 0)
- {
- TTMATH_REFERENCE_ASSERT( v )
-
- uint m,n, test;
-
- test = Div_StandardTest(v, m, n, remainder);
- if( test < 2 )
- return test;
-
- if( n == 0 )
- {
- uint r;
- DivInt( v.table[0], &r );
-
- if( remainder )
- {
- remainder->SetZero();
- remainder->table[0] = r;
- }
-
- TTMATH_LOG("UInt::Div3")
-
- return 0;
- }
-
-
- // we can only use the third division algorithm when
- // the divisor is greater or equal 2^32 (has more than one 32-bit word)
- ++m;
- ++n;
- m = m - n;
- Div3_Division(v, remainder, m, n);
+ if( uu.Sub(vv_temp) )
+ {
+ // there was a carry
+
+ //
+ // !!! this part of code was not tested
+ //
- TTMATH_LOG("UInt::Div3")
+ --qp;
+ uu.Add(vv);
- return 0;
- }
+ // can be a carry from this additions but it should be ignored
+ // because it cancels with the borrow from uu.Sub(vv_temp)
+ }
+ TTMATH_LOG("UInt::Div3_MultiplySubtract")
+ }
-private:
- void Div3_Division(UInt<value_size> v, UInt<value_size> * remainder, uint m, uint n)
- {
- TTMATH_ASSERT( n>=2 )
- UInt<value_size+1> uu, vv;
- UInt<value_size> q;
- uint d, u_value_size, u0, u1, u2, v1, v0, j=m;
- u_value_size = Div3_Normalize(v, n, d);
+public:
- if( j+n == value_size )
- u2 = u_value_size;
- else
- u2 = table[j+n];
- Div3_MakeBiggerV(v, vv);
+ /*!
+ power this = this ^ pow
+ binary algorithm (r-to-l)
- for(uint i = j+1 ; i<value_size ; ++i)
- q.table[i] = 0;
+ return values:
+ 0 - ok
+ 1 - carry
+ 2 - incorrect argument (0^0)
+ */
+ uint Pow(UInt<value_size> pow)
+ {
+ if(pow.IsZero() && IsZero())
+ // we don't define zero^zero
+ return 2;
- while( true )
- {
- u1 = table[j+n-1];
- u0 = table[j+n-2];
- v1 = v.table[n-1];
- v0 = v.table[n-2];
+ UInt<value_size> start(*this);
+ UInt<value_size> result;
+ result.SetOne();
+ uint c = 0;
- uint qp = Div3_Calculate(u2,u1,u0, v1,v0);
+ while( !c )
+ {
+ if( pow.table[0] & 1 )
+ c += result.Mul(start);
- Div3_MakeNewU(uu, j, n, u2);
- Div3_MultiplySubtract(uu, vv, qp);
- Div3_CopyNewU(uu, j, n);
+ pow.Rcr2_one(0);
+ if( pow.IsZero() )
+ break;
- q.table[j] = qp;
+ c += start.Mul(start);
+ }
- // the next loop
- if( j-- == 0 )
- break;
+ *this = result;
- u2 = table[j+n];
- }
+ TTMATH_LOGC("UInt::Pow(UInt<>)", c)
- if( remainder )
- Div3_Unnormalize(remainder, n, d);
+ return (c==0)? 0 : 1;
+ }
- *this = q;
- TTMATH_LOG("UInt::Div3_Division")
- }
+ /*!
+ square root
+ e.g. Sqrt(9) = 3
+ ('digit-by-digit' algorithm)
+ */
+ void Sqrt()
+ {
+ UInt<value_size> bit, temp;
+ if( IsZero() )
+ return;
- void Div3_MakeNewU(UInt<value_size+1> & uu, uint j, uint n, uint u_max)
- {
- uint i;
+ UInt<value_size> value(*this);
- for(i=0 ; i<n ; ++i, ++j)
- uu.table[i] = table[j];
+ SetZero();
+ bit.SetZero();
+ bit.table[value_size-1] = (TTMATH_UINT_HIGHEST_BIT >> 1);
+
+ while( bit > value )
+ bit.Rcr(2);
- // 'n' is from <1..value_size> so and 'i' is from <0..value_size>
- // then table[i] is always correct (look at the declaration of 'uu')
- uu.table[i] = u_max;
+ while( !bit.IsZero() )
+ {
+ temp = *this;
+ temp.Add(bit);
- for( ++i ; i<value_size+1 ; ++i)
- uu.table[i] = 0;
+ if( value >= temp )
+ {
+ value.Sub(temp);
+ Rcr(1);
+ Add(bit);
+ }
+ else
+ {
+ Rcr(1);
+ }
- TTMATH_LOG("UInt::Div3_MakeNewU")
- }
+ bit.Rcr(2);
+ }
+ TTMATH_LOG("UInt::Sqrt")
+ }
- void Div3_CopyNewU(const UInt<value_size+1> & uu, uint j, uint n)
- {
- uint i;
- for(i=0 ; i<n ; ++i)
- table[i+j] = uu.table[i];
- if( i+j < value_size )
- table[i+j] = uu.table[i];
+ /*!
+ this method sets n first bits to value zero
- TTMATH_LOG("UInt::Div3_CopyNewU")
- }
+ For example:
+ let n=2 then if there's a value 111 (bin) there'll be '100' (bin)
+ */
+ void ClearFirstBits(uint n)
+ {
+ if( n >= value_size*TTMATH_BITS_PER_UINT )
+ {
+ SetZero();
+ TTMATH_LOG("UInt::ClearFirstBits")
+ return;
+ }
+ uint * p = table;
- /*!
- we're making the new 'vv'
- the value is actually the same but the 'table' is bigger (value_size+1)
- */
- void Div3_MakeBiggerV(const UInt<value_size> & v, UInt<value_size+1> & vv)
- {
- for(uint i=0 ; i<value_size ; ++i)
- vv.table[i] = v.table[i];
+ // first we're clearing the whole words
+ while( n >= TTMATH_BITS_PER_UINT )
+ {
+ *p++ = 0;
+ n -= TTMATH_BITS_PER_UINT;
+ }
- vv.table[value_size] = 0;
+ if( n == 0 )
+ {
+ TTMATH_LOG("UInt::ClearFirstBits")
+ return;
+ }
- TTMATH_LOG("UInt::Div3_MakeBiggerV")
- }
+ // and then we're clearing one word which has left
+ // mask -- all bits are set to one
+ uint mask = TTMATH_UINT_MAX_VALUE;
+ mask = mask << n;
- /*!
- we're moving all bits from 'v' into the left side of the n-1 word
- (the highest bit at v.table[n-1] will be equal one,
- the bits from 'this' we're moving the same times as 'v')
+ (*p) &= mask;
- return values:
- d - how many times we've moved
- return - the next-left value from 'this' (that after table[value_size-1])
- */
- uint Div3_Normalize(UInt<value_size> & v, uint n, uint & d)
- {
- // v.table[n-1] is != 0
+ TTMATH_LOG("UInt::ClearFirstBits")
+ }
- uint bit = (uint)FindLeadingBitInWord(v.table[n-1]);
- uint move = (TTMATH_BITS_PER_UINT - bit - 1);
- uint res = table[value_size-1];
- d = move;
- if( move > 0 )
- {
- v.Rcl(move, 0);
- Rcl(move, 0);
- res = res >> (bit + 1);
- }
- else
- {
- res = 0;
- }
+ /*!
+ this method returns true if the highest bit of the value is set
+ */
+ bool IsTheHighestBitSet() const
+ {
+ return (table[value_size-1] & TTMATH_UINT_HIGHEST_BIT) != 0;
+ }
- TTMATH_LOG("UInt::Div3_Normalize")
- return res;
- }
+ /*!
+ this method returns true if the lowest bit of the value is set
+ */
+ bool IsTheLowestBitSet() const
+ {
+ return (*table & 1) != 0;
+ }
- void Div3_Unnormalize(UInt<value_size> * remainder, uint n, uint d)
- {
- for(uint i=n ; i<value_size ; ++i)
- table[i] = 0;
+ /*!
+ returning true if only the highest bit is set
+ */
+ bool IsOnlyTheHighestBitSet() const
+ {
+ for(uint i=0 ; i<value_size-1 ; ++i)
+ if( table[i] != 0 )
+ return false;
- Rcr(d,0);
+ if( table[value_size-1] != TTMATH_UINT_HIGHEST_BIT )
+ return false;
- *remainder = *this;
+ return true;
+ }
- TTMATH_LOG("UInt::Div3_Unnormalize")
- }
+ /*!
+ returning true if only the lowest bit is set
+ */
+ bool IsOnlyTheLowestBitSet() const
+ {
+ if( table[0] != 1 )
+ return false;
- uint Div3_Calculate(uint u2, uint u1, uint u0, uint v1, uint v0)
- {
- UInt<2> u_temp;
- uint rp;
- bool next_test;
+ for(uint i=1 ; i<value_size ; ++i)
+ if( table[i] != 0 )
+ return false;
- TTMATH_ASSERT( v1 != 0 )
+ return true;
+ }
- u_temp.table[1] = u2;
- u_temp.table[0] = u1;
- u_temp.DivInt(v1, &rp);
- TTMATH_ASSERT( u_temp.table[1]==0 || u_temp.table[1]==1 )
+ /*!
+ this method returns true if the value is equal zero
+ */
+ bool IsZero() const
+ {
+ for(uint i=0 ; i<value_size ; ++i)
+ if(table[i] != 0)
+ return false;
- do
- {
- bool decrease = false;
+ return true;
+ }
- if( u_temp.table[1] == 1 )
- decrease = true;
- else
- {
- UInt<2> temp1, temp2;
- UInt<2>::MulTwoWords(u_temp.table[0], v0, temp1.table+1, temp1.table);
- temp2.table[1] = rp;
- temp2.table[0] = u0;
+ /*!
+ returning true if first 'bits' bits are equal zero
+ */
+ bool AreFirstBitsZero(uint bits) const
+ {
+ TTMATH_ASSERT( bits <= value_size * TTMATH_BITS_PER_UINT )
- if( temp1 > temp2 )
- decrease = true;
- }
+ uint index = bits / TTMATH_BITS_PER_UINT;
+ uint rest = bits % TTMATH_BITS_PER_UINT;
+ uint i;
- next_test = false;
+ for(i=0 ; i<index ; ++i)
+ if(table[i] != 0 )
+ return false;
- if( decrease )
- {
- u_temp.SubOne();
+ if( rest == 0 )
+ return true;
- rp += v1;
+ uint mask = TTMATH_UINT_MAX_VALUE >> (TTMATH_BITS_PER_UINT - rest);
- if( rp >= v1 ) // it means that there wasn't a carry (r<b from the book)
- next_test = true;
- }
- }
- while( next_test );
+ return (table[i] & mask) == 0;
+ }
- TTMATH_LOG("UInt::Div3_Calculate")
- return u_temp.table[0];
- }
+ /*!
+ *
+ * conversion methods
+ *
+ */
- void Div3_MultiplySubtract( UInt<value_size+1> & uu,
- const UInt<value_size+1> & vv, uint & qp)
- {
- // D4 (in the book)
- UInt<value_size+1> vv_temp(vv);
- vv_temp.MulInt(qp);
+ /*!
+ this method converts an UInt<another_size> type to this class
- if( uu.Sub(vv_temp) )
- {
- // there was a carry
+ this operation has mainly sense if the value from p is
+ equal or smaller than that one which is returned from UInt<value_size>::SetMax()
- //
- // !!! this part of code was not tested
- //
+ it returns a carry if the value 'p' is too big
+ */
+ template<uint argument_size>
+ uint FromUInt(const UInt<argument_size> & p)
+ {
+ uint min_size = (value_size < argument_size)? value_size : argument_size;
+ uint i;
- --qp;
- uu.Add(vv);
+ for(i=0 ; i<min_size ; ++i)
+ table[i] = p.table[i];
- // can be a carry from this additions but it should be ignored
- // because it cancels with the borrow from uu.Sub(vv_temp)
- }
- TTMATH_LOG("UInt::Div3_MultiplySubtract")
- }
+ if( value_size > argument_size )
+ {
+ // 'this' is longer than 'p'
+ for( ; i<value_size ; ++i)
+ table[i] = 0;
+ }
+ else
+ {
+ for( ; i<argument_size ; ++i)
+ if( p.table[i] != 0 )
+ {
+ TTMATH_LOGC("UInt::FromUInt(UInt<>)", 1)
+ return 1;
+ }
+ }
+ TTMATH_LOGC("UInt::FromUInt(UInt<>)", 0)
+ return 0;
+ }
+ /*!
+ this method converts an UInt<another_size> type to this class
-public:
+ this operation has mainly sense if the value from p is
+ equal or smaller than that one which is returned from UInt<value_size>::SetMax()
+
+ it returns a carry if the value 'p' is too big
+ */
+ template<uint argument_size>
+ uint FromInt(const UInt<argument_size> & p)
+ {
+ return FromUInt(p);
+ }
+
+
+ /*!
+ this method converts the uint type to this class
+ */
+ uint FromUInt(uint value)
+ {
+ for(uint i=1 ; i<value_size ; ++i)
+ table[i] = 0;
+ table[0] = value;
- /*!
- power this = this ^ pow
- binary algorithm (r-to-l)
+ TTMATH_LOG("UInt::FromUInt(uint)")
- return values:
- 0 - ok
- 1 - carry
- 2 - incorrect argument (0^0)
- */
- uint Pow(UInt<value_size> pow)
- {
- if(pow.IsZero() && IsZero())
- // we don't define zero^zero
- return 2;
+ // there'll never be a carry here
+ return 0;
+ }
- UInt<value_size> start(*this), start_temp;
- UInt<value_size> result;
- result.SetOne();
- uint c = 0;
- while( !c )
- {
- if( pow.table[0] & 1 )
- c += result.Mul(start);
+ /*!
+ this method converts the uint type to this class
+ */
+ uint FromInt(uint value)
+ {
+ return FromUInt(value);
+ }
- pow.Rcr2_one(0);
- if( pow.IsZero() )
- break;
- start_temp = start;
- // in the second Mul algorithm we can use start.Mul(start) directly (there is no TTMATH_ASSERT_REFERENCE there)
- c += start.Mul(start_temp);
- }
+ /*!
+ this method converts the sint type to this class
+ */
+ uint FromInt(sint value)
+ {
+ uint c = FromUInt(uint(value));
- *this = result;
+ if( c || value < 0 )
+ return 1;
- TTMATH_LOGC("UInt::Pow(UInt<>)", c)
+ return 0;
+ }
- return (c==0)? 0 : 1;
- }
+ /*!
+ this operator converts an UInt<another_size> type to this class
- /*!
- square root
- e.g. Sqrt(9) = 3
- ('digit-by-digit' algorithm)
- */
- void Sqrt()
- {
- UInt<value_size> bit, temp;
+ it doesn't return a carry
+ */
+ template<uint argument_size>
+ UInt<value_size> & operator=(const UInt<argument_size> & p)
+ {
+ FromUInt(p);
- if( IsZero() )
- return;
+ return *this;
+ }
- UInt<value_size> value(*this);
- SetZero();
- bit.SetZero();
- bit.table[value_size-1] = (TTMATH_UINT_HIGHEST_BIT >> 1);
+ /*!
+ the assignment operator
+ */
+ UInt<value_size> & operator=(const UInt<value_size> & p)
+ {
+ for(uint i=0 ; i<value_size ; ++i)
+ table[i] = p.table[i];
- while( bit > value )
- bit.Rcr(2);
+ TTMATH_LOG("UInt::operator=(UInt<>)")
- while( !bit.IsZero() )
- {
- temp = *this;
- temp.Add(bit);
+ return *this;
+ }
- if( value >= temp )
- {
- value.Sub(temp);
- Rcr(1);
- Add(bit);
- }
- else
- {
- Rcr(1);
- }
- bit.Rcr(2);
- }
+ /*!
+ this method converts the uint type to this class
+ */
+ UInt<value_size> & operator=(uint i)
+ {
+ FromUInt(i);
- TTMATH_LOG("UInt::Sqrt")
- }
+ return *this;
+ }
+ /*!
+ a constructor for converting the uint to this class
+ */
+ UInt(uint i)
+ {
+ FromUInt(i);
+ }
- /*!
- this method sets n first bits to value zero
- For example:
- let n=2 then if there's a value 111 (bin) there'll be '100' (bin)
- */
- void ClearFirstBits(uint n)
- {
- if( n >= value_size*TTMATH_BITS_PER_UINT )
- {
- SetZero();
- TTMATH_LOG("UInt::ClearFirstBits")
- return;
- }
+ /*!
+ this method converts the sint type to this class
+ */
+ UInt<value_size> & operator=(sint i)
+ {
+ FromInt(i);
- uint * p = table;
+ return *this;
+ }
- // first we're clearing the whole words
- while( n >= TTMATH_BITS_PER_UINT )
- {
- *p++ = 0;
- n -= TTMATH_BITS_PER_UINT;
- }
- if( n == 0 )
- {
- TTMATH_LOG("UInt::ClearFirstBits")
- return;
- }
+ /*!
+ a constructor for converting the sint to this class
- // and then we're clearing one word which has left
- // mask -- all bits are set to one
- uint mask = TTMATH_UINT_MAX_VALUE;
+ look at the description of UInt::operator=(sint)
+ */
+ UInt(sint i)
+ {
+ FromInt(i);
+ }
- mask = mask << n;
- (*p) &= mask;
+#ifdef TTMATH_PLATFORM32
+
+
+ /*!
+ this method converts unsigned 64 bit int type to this class
+ ***this method is created only on a 32bit platform***
+ */
+ uint FromUInt(ulint n)
+ {
+ table[0] = (uint)n;
+
+ if( value_size == 1 )
+ {
+ uint c = ((n >> TTMATH_BITS_PER_UINT) == 0) ? 0 : 1;
+
+ TTMATH_LOGC("UInt::FromUInt(ulint)", c)
+ return c;
+ }
+
+ table[1] = (uint)(n >> TTMATH_BITS_PER_UINT);
+
+ for(uint i=2 ; i<value_size ; ++i)
+ table[i] = 0;
+
+ TTMATH_LOG("UInt::FromUInt(ulint)")
+
+ return 0;
+ }
+
+
+ /*!
+ this method converts unsigned 64 bit int type to this class
+ ***this method is created only on a 32bit platform***
+ */
+ uint FromInt(ulint n)
+ {
+ return FromUInt(n);
+ }
+
+
+ /*!
+ this method converts signed 64 bit int type to this class
+ ***this method is created only on a 32bit platform***
+ */
+ uint FromInt(slint n)
+ {
+ uint c = FromUInt(ulint(n));
+
+ if( c || n < 0 )
+ return 1;
+
+ return 0;
+ }
+
+
+ /*!
+ this operator converts unsigned 64 bit int type to this class
+ ***this operator is created only on a 32bit platform***
+ */
+ UInt<value_size> & operator=(ulint n)
+ {
+ FromUInt(n);
+
+ return *this;
+ }
+
+
+ /*!
+ a constructor for converting unsigned 64 bit int to this class
+ ***this constructor is created only on a 32bit platform***
+ */
+ UInt(ulint n)
+ {
+ FromUInt(n);
+ }
+
+
+ /*!
+ this operator converts signed 64 bit int type to this class
+ ***this operator is created only on a 32bit platform***
+ */
+ UInt<value_size> & operator=(slint n)
+ {
+ FromInt(n);
+
+ return *this;
+ }
+
+
+ /*!
+ a constructor for converting signed 64 bit int to this class
+ ***this constructor is created only on a 32bit platform***
+ */
+ UInt(slint n)
+ {
+ FromInt(n);
+ }
+
+#endif
- TTMATH_LOG("UInt::ClearFirstBits")
- }
- /*!
- this method returns true if the highest bit of the value is set
- */
- bool IsTheHighestBitSet() const
- {
- return (table[value_size-1] & TTMATH_UINT_HIGHEST_BIT) != 0;
- }
+#ifdef TTMATH_PLATFORM64
- /*!
- this method returns true if the lowest bit of the value is set
- */
- bool IsTheLowestBitSet() const
- {
- return (*table & 1) != 0;
- }
+ /*!
+ this method converts 32 bit unsigned int type to this class
+ ***this operator is created only on a 64bit platform***
+ */
+ uint FromUInt(unsigned int i)
+ {
+ return FromUInt(uint(i));
+ }
+
+ /*!
+ this method converts 32 bit unsigned int type to this class
+ ***this operator is created only on a 64bit platform***
+ */
+ uint FromInt(unsigned int i)
+ {
+ return FromUInt(uint(i));
+ }
+
+
+ /*!
+ this method converts 32 bit signed int type to this class
+ ***this operator is created only on a 64bit platform***
+ */
+ uint FromInt(signed int i)
+ {
+ return FromInt(sint(i));
+ }
+
+
+ /*!
+ this operator converts 32 bit unsigned int type to this class
+ ***this operator is created only on a 64bit platform***
+ */
+ UInt<value_size> & operator=(unsigned int i)
+ {
+ FromUInt(i);
+
+ return *this;
+ }
+
+
+ /*!
+ a constructor for converting 32 bit unsigned int to this class
+ ***this constructor is created only on a 64bit platform***
+ */
+ UInt(unsigned int i)
+ {
+ FromUInt(i);
+ }
+
+
+ /*!
+ an operator for converting 32 bit signed int to this class
+ ***this constructor is created only on a 64bit platform***
+ */
+ UInt<value_size> & operator=(signed int i)
+ {
+ FromInt(i);
+
+ return *this;
+ }
+
+
+ /*!
+ a constructor for converting 32 bit signed int to this class
+ ***this constructor is created only on a 64bit platform***
+ */
+ UInt(signed int i)
+ {
+ FromInt(i);
+ }
- /*!
- this method returns true if the value is equal zero
- */
- bool IsZero() const
- {
- for(uint i=0 ; i<value_size ; ++i)
- if(table[i] != 0)
- return false;
+#endif
- return true;
- }
- /*!
- returning true if first 'bits' bits are equal zero
- */
- bool AreFirstBitsZero(uint bits) const
- {
- TTMATH_ASSERT( bits <= value_size * TTMATH_BITS_PER_UINT )
- uint index = bits / TTMATH_BITS_PER_UINT;
- uint rest = bits % TTMATH_BITS_PER_UINT;
- uint i;
- for(i=0 ; i<index ; ++i)
- if(table[i] != 0 )
- return false;
+ /*!
+ a constructor for converting a string to this class (with the base=10)
+ */
+ UInt(const char * s)
+ {
+ FromString(s);
+ }
+
+
+ /*!
+ a constructor for converting a string to this class (with the base=10)
+ */
+ UInt(const std::string & s)
+ {
+ FromString( s.c_str() );
+ }
+
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
+ /*!
+ a constructor for converting a string to this class (with the base=10)
+ */
+ UInt(const wchar_t * s)
+ {
+ FromString(s);
+ }
+
+
+ /*!
+ a constructor for converting a string to this class (with the base=10)
+ */
+ UInt(const std::wstring & s)
+ {
+ FromString( s.c_str() );
+ }
- if( rest == 0 )
- return true;
+#endif
- uint mask = TTMATH_UINT_MAX_VALUE >> (TTMATH_BITS_PER_UINT - rest);
- return (table[i] & mask) == 0;
- }
+ /*!
+ a default constructor
- /*!
- *
- * conversion methods
- *
- */
+ we don't clear the table
+ */
+ UInt()
+ {
+ // when macro TTMATH_DEBUG_LOG is defined
+ // we set special values to the table
+ // in order to be everywhere the same value of the UInt object
+ // without this it would be difficult to analyse the log file
+ #ifdef TTMATH_DEBUG_LOG
+ #ifdef TTMATH_PLATFORM32
+ for(uint i=0 ; i<value_size ; ++i)
+ table[i] = 0xc1c1c1c1;
+ #else
+ for(uint i=0 ; i<value_size ; ++i)
+ table[i] = 0xc1c1c1c1c1c1c1c1;
+ #endif
+ #endif
+ }
+
+
+ /*!
+ a copy constructor
+ */
+ UInt(const UInt<value_size> & u)
+ {
+ for(uint i=0 ; i<value_size ; ++i)
+ table[i] = u.table[i];
+
+ TTMATH_LOG("UInt::UInt(UInt<>)")
+ }
+
+
+
+ /*!
+ a template for producting constructors for copying from another types
+ */
+ template<uint argument_size>
+ UInt(const UInt<argument_size> & u)
+ {
+ // look that 'size' we still set as 'value_size' and not as u.value_size
+ FromUInt(u);
+ }
+
+
+
+
+ /*!
+ a destructor
+ */
+ ~UInt()
+ {
+ }
+
+
+ /*!
+ this method returns the lowest value from table
+
+ we must be sure when we using this method whether the value
+ will hold in an uint type or not (the rest value from the table must be zero)
+ */
+ uint ToUInt() const
+ {
+ return table[0];
+ }
+
+
+ /*!
+ this method converts the value to uint type
+ can return a carry if the value is too long to store it in uint type
+ */
+ uint ToUInt(uint & result) const
+ {
+ result = table[0];
+
+ for(uint i=1 ; i<value_size ; ++i)
+ if( table[i] != 0 )
+ return 1;
+
+ return 0;
+ }
+
+
+ /*!
+ this method converts the value to uint type
+ can return a carry if the value is too long to store it in uint type
+ */
+ uint ToInt(uint & result) const
+ {
+ return ToUInt(result);
+ }
+
+
+ /*!
+ this method converts the value to sint type (signed integer)
+ can return a carry if the value is too long to store it in sint type
+ */
+ uint ToInt(sint & result) const
+ {
+ result = sint(table[0]);
+
+ if( (result & TTMATH_UINT_HIGHEST_BIT) != 0 )
+ return 1;
+
+ for(uint i=1 ; i<value_size ; ++i)
+ if( table[i] != 0 )
+ return 1;
+ return 0;
+ }
- /*!
- this method converts an UInt<another_size> type to this class
+#ifdef TTMATH_PLATFORM32
- this operation has mainly sense if the value from p is
- equal or smaller than that one which is returned from UInt<value_size>::SetMax()
+ /*!
+ this method converts the value to ulint type (64 bit unsigned integer)
+ can return a carry if the value is too long to store it in ulint type
+ *** this method is created only on a 32 bit platform ***
+ */
+ uint ToUInt(ulint & result) const
+ {
+ if( value_size == 1 )
+ {
+ result = table[0];
+ }
+ else
+ {
+ uint low = table[0];
+ uint high = table[1];
+
+ result = low;
+ result |= (ulint(high) << TTMATH_BITS_PER_UINT);
+
+ for(uint i=2 ; i<value_size ; ++i)
+ if( table[i] != 0 )
+ return 1;
+ }
+
+ return 0;
+ }
+
+
+ /*!
+ this method converts the value to ulint type (64 bit unsigned integer)
+ can return a carry if the value is too long to store it in ulint type
+ *** this method is created only on a 32 bit platform ***
+ */
+ uint ToInt(ulint & result) const
+ {
+ return ToUInt(result);
+ }
+
+
+ /*!
+ this method converts the value to slint type (64 bit signed integer)
+ can return a carry if the value is too long to store it in slint type
+ *** this method is created only on a 32 bit platform ***
+ */
+ uint ToInt(slint & result) const
+ {
+ ulint temp;
- it returns a carry if the value 'p' is too big
- */
- template<uint argument_size>
- uint FromUInt(const UInt<argument_size> & p)
- {
- uint min_size = (value_size < argument_size)? value_size : argument_size;
- uint i;
+ uint c = ToUInt(temp);
+ result = slint(temp);
- for(i=0 ; i<min_size ; ++i)
- table[i] = p.table[i];
+ if( c || result < 0 )
+ return 1;
+ return 0;
+ }
- if( value_size > argument_size )
- {
- // 'this' is longer than 'p'
+#endif
- for( ; i<value_size ; ++i)
- table[i] = 0;
- }
- else
- {
- for( ; i<argument_size ; ++i)
- if( p.table[i] != 0 )
- {
- TTMATH_LOGC("UInt::FromUInt(UInt<>)", 1)
- return 1;
- }
- }
- TTMATH_LOGC("UInt::FromUInt(UInt<>)", 0)
- return 0;
- }
+#ifdef TTMATH_PLATFORM64
+ /*!
+ this method converts the value to a 32 unsigned integer
+ can return a carry if the value is too long to store it in this type
+ *** this method is created only on a 64 bit platform ***
+ */
+ uint ToUInt(unsigned int & result) const
+ {
+ result = (unsigned int)table[0];
+
+ if( (table[0] >> 32) != 0 )
+ return 1;
+
+ for(uint i=1 ; i<value_size ; ++i)
+ if( table[i] != 0 )
+ return 1;
+
+ return 0;
+ }
+
+
+ /*!
+ this method converts the value to a 32 unsigned integer
+ can return a carry if the value is too long to store it in this type
+ *** this method is created only on a 64 bit platform ***
+ */
+ uint ToInt(unsigned int & result) const
+ {
+ return ToUInt(result);
+ }
+
+
+ /*!
+ this method converts the value to a 32 signed integer
+ can return a carry if the value is too long to store it in this type
+ *** this method is created only on a 64 bit platform ***
+ */
+ uint ToInt(int & result) const
+ {
+ unsigned int temp;
- /*!
- this method converts the uint type to this class
- */
- void FromUInt(uint value)
- {
- for(uint i=1 ; i<value_size ; ++i)
- table[i] = 0;
+ uint c = ToUInt(temp);
+ result = int(temp);
- table[0] = value;
+ if( c || result < 0 )
+ return 1;
- TTMATH_LOG("UInt::FromUInt(uint)")
- }
+ return 0;
+ }
- /*!
- this operator converts an UInt<another_size> type to this class
+#endif
- it doesn't return a carry
- */
- template<uint argument_size>
- UInt<value_size> & operator=(const UInt<argument_size> & p)
- {
- FromUInt(p);
- return *this;
- }
- /*!
- the assignment operator
- */
- UInt<value_size> & operator=(const UInt<value_size> & p)
- {
- for(uint i=0 ; i<value_size ; ++i)
- table[i] = p.table[i];
+protected:
- TTMATH_LOG("UInt::operator=(UInt<>)")
+ /*!
+ an auxiliary method for converting into the string
+ it returns the log (with the base 2) from x
+ where x is in <2;16>
+ */
+ double ToStringLog2(uint x) const
+ {
+ static double log_tab[] = {
+ 1.000000000000000000,
+ 0.630929753571457437,
+ 0.500000000000000000,
+ 0.430676558073393050,
+ 0.386852807234541586,
+ 0.356207187108022176,
+ 0.333333333333333333,
+ 0.315464876785728718,
+ 0.301029995663981195,
+ 0.289064826317887859,
+ 0.278942945651129843,
+ 0.270238154427319741,
+ 0.262649535037193547,
+ 0.255958024809815489,
+ 0.250000000000000000
+ };
+
+ if( x<2 || x>16 )
+ return 0;
+
+ return log_tab[x-2];
+ }
+
+
+ /*!
+ an auxiliary method for converting to a string
+ it's used from Int::ToString() too (negative is set true then)
+ */
+ template<class string_type>
+ void ToStringBase(string_type & result, uint b = 10, bool negative = false) const
+ {
+ UInt<value_size> temp(*this);
+ uint rest, table_id, index, digits;
+ double digits_d;
+ char character;
+
+ result.clear();
+
+ if( b<2 || b>16 )
+ return;
+
+ if( !FindLeadingBit(table_id, index) )
+ {
+ result = '0';
+ return;
+ }
+
+ if( negative )
+ result = '-';
+
+ digits_d = table_id; // for not making an overflow in uint type
+ digits_d *= TTMATH_BITS_PER_UINT;
+ digits_d += index + 1;
+ digits_d *= ToStringLog2(b);
+ digits = static_cast<uint>(digits_d) + 3; // plus some epsilon
+
+ if( result.capacity() < digits )
+ result.reserve(digits);
+
+ do
+ {
+ temp.DivInt(b, &rest);
+ character = static_cast<char>(Misc::DigitToChar(rest));
+ result.insert(result.end(), character);
+ }
+ while( !temp.IsZero() );
+
+ size_t i1 = negative ? 1 : 0; // the first is a hyphen (when negative is true)
+ size_t i2 = result.size() - 1;
+
+ for( ; i1 < i2 ; ++i1, --i2 )
+ {
+ char tempc = static_cast<char>(result[i1]);
+ result[i1] = result[i2];
+ result[i2] = tempc;
+ }
+ }
- return *this;
- }
- /*!
- this method converts the uint type to this class
- */
- UInt<value_size> & operator=(uint i)
- {
- FromUInt(i);
+public:
- return *this;
- }
+ /*!
+ this method converts the value to a string with a base equal 'b'
+ */
+ void ToString(std::string & result, uint b = 10) const
+ {
+ return ToStringBase(result, b);
+ }
+
+
+ std::string ToString(uint b = 10) const
+ {
+ std::string result;
+ ToStringBase(result, b);
+
+ return result;
+ }
+
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
+ void ToString(std::wstring & result, uint b = 10) const
+ {
+ return ToStringBase(result, b);
+ }
+
+ std::wstring ToWString(uint b = 10) const
+ {
+ std::wstring result;
+ ToStringBase(result, b);
+
+ return result;
+ }
+#endif
- /*!
- a constructor for converting the uint to this class
- */
- UInt(uint i)
- {
- FromUInt(i);
- }
- /*!
- this method converts the sint type to this class
+private:
- we provide operator(sint) and the constructor(sint) in order to allow
- the programmer do that:
- UInt<..> type = 10;
+ /*!
+ an auxiliary method for converting from a string
+ */
+ template<class char_type>
+ uint FromStringBase(const char_type * s, uint b = 10, const char_type ** after_source = 0, bool * value_read = 0)
+ {
+ UInt<value_size> base( b );
+ UInt<value_size> temp;
+ sint z;
+ uint c = 0;
+
+ SetZero();
+ temp.SetZero();
+ Misc::SkipWhiteCharacters(s);
+
+ if( after_source )
+ *after_source = s;
+
+ if( value_read )
+ *value_read = false;
+
+ if( b<2 || b>16 )
+ return 1;
+
+
+ for( ; (z=Misc::CharToDigit(*s, b)) != -1 ; ++s)
+ {
+ if( value_read )
+ *value_read = true;
+
+ if( c == 0 )
+ {
+ temp.table[0] = z;
+
+ c += Mul(base);
+ c += Add(temp);
+ }
+ }
- above "10" constant has the int type (signed int), if we don't give such
- operators and constructors the compiler will not compile the program,
- because it has to make a conversion and doesn't know into which type
- (the UInt class has operator=(const char*), operator=(uint) etc.)
- */
- UInt<value_size> & operator=(sint i)
- {
- FromUInt(uint(i));
+ if( after_source )
+ *after_source = s;
- return *this;
- }
+ TTMATH_LOGC("UInt::FromString", c)
+ return (c==0)? 0 : 1;
+ }
- /*!
- a constructor for converting the sint to this class
- look at the description of UInt::operator=(sint)
- */
- UInt(sint i)
- {
- FromUInt(uint(i));
- }
+public:
+ /*!
+ this method converts a string into its value
+ it returns carry=1 if the value will be too big or an incorrect base 'b' is given
-#ifdef TTMATH_PLATFORM64
+ string is ended with a non-digit value, for example:
+ "12" will be translated to 12
+ as well as:
+ "12foo" will be translated to 12 too
- /*!
- in 64bit platforms we must define additional operators and contructors
- in order to allow a user initializing the objects in this way:
- UInt<...> type = 20;
- or
- UInt<...> type;
- type = 30;
-
- decimal constants such as 20, 30 etc. are integer literal of type int,
- if the value is greater it can even be long int,
- 0 is an octal integer of type int
- (ISO 14882 p2.13.1 Integer literals)
- */
-
- /*!
- this operator converts the unsigned int type to this class
-
- ***this operator is created only on a 64bit platform***
- it takes one argument of 32bit
- */
- UInt<value_size> & operator=(unsigned int i)
- {
- FromUInt(uint(i));
-
- return *this;
- }
-
-
- /*!
- a constructor for converting the unsigned int to this class
-
- ***this constructor is created only on a 64bit platform***
- it takes one argument of 32bit
- */
- UInt(unsigned int i)
- {
- FromUInt(uint(i));
- }
-
-
- /*!
- an operator for converting the signed int to this class
-
- ***this constructor is created only on a 64bit platform***
- it takes one argument of 32bit
-
- look at the description of UInt::operator=(sint)
- */
- UInt<value_size> & operator=(signed int i)
- {
- FromUInt(uint(i));
-
- return *this;
- }
-
-
- /*!
- a constructor for converting the signed int to this class
-
- ***this constructor is created only on a 64bit platform***
- it takes one argument of 32bit
-
- look at the description of UInt::operator=(sint)
- */
- UInt(signed int i)
- {
- FromUInt(uint(i));
- }
+ existing first white characters will be ommited
+ if the value from s is too large the rest digits will be skipped
-#endif
+ after_source (if exists) is pointing at the end of the parsed string
+ value_read (if exists) tells whether something has actually been read (at least one digit)
+ */
+ uint FromString(const char * s, uint b = 10, const char ** after_source = 0, bool * value_read = 0)
+ {
+ return FromStringBase(s, b, after_source, value_read);
+ }
+ /*!
+ this method converts a string into its value
+ (it returns carry=1 if the value will be too big or an incorrect base 'b' is given)
+ */
+ uint FromString(const std::string & s, uint b = 10)
+ {
+ return FromString( s.c_str(), b );
+ }
- /*!
- a constructor for converting a string to this class (with the base=10)
- */
- UInt(const char * s)
- {
- FromString(s);
- }
-
-
- /*!
- a constructor for converting a string to this class (with the base=10)
- */
- UInt(const wchar_t * s)
- {
- FromString(s);
- }
-
-
- /*!
- a constructor for converting a string to this class (with the base=10)
- */
- UInt(const std::string & s)
- {
- FromString( s.c_str() );
- }
-
-
- /*!
- a constructor for converting a string to this class (with the base=10)
- */
- UInt(const std::wstring & s)
- {
- FromString( s.c_str() );
- }
-
-
- /*!
- a default constructor
-
- we don't clear the table
- */
- UInt()
- {
- // when macro TTMATH_DEBUG_LOG is defined
- // we set special values to the table
- // in order to be everywhere the same value of the UInt object
- // without this it would be difficult to analyse the log file
- #ifdef TTMATH_DEBUG_LOG
- #ifdef TTMATH_PLATFORM32
- for(uint i=0 ; i<value_size ; ++i)
- table[i] = 0xc1c1c1c1;
- #else
- for(uint i=0 ; i<value_size ; ++i)
- table[i] = 0xc1c1c1c1c1c1c1c1;
- #endif
- #endif
- }
-
-
- /*!
- a copy constructor
- */
- UInt(const UInt<value_size> & u)
- {
- for(uint i=0 ; i<value_size ; ++i)
- table[i] = u.table[i];
-
- TTMATH_LOG("UInt::UInt(UInt<>)")
- }
-
-
-
- /*!
- a template for producting constructors for copying from another types
- */
- template<uint argument_size>
- UInt(const UInt<argument_size> & u)
- {
- // look that 'size' we still set as 'value_size' and not as u.value_size
- FromUInt(u);
- }
-
-
-
-
- /*!
- a destructor
- */
- ~UInt()
- {
- }
-
-
- /*!
- this method returns the lowest value from table
-
- we must be sure when we using this method whether the value
- will hold in an uint type or not (the rest value from the table must be zero)
- */
- uint ToUInt() const
- {
- return table[0];
- }
+ /*!
+ this operator converts a string into its value (with base = 10)
+ */
+ UInt<value_size> & operator=(const char * s)
+ {
+ FromString(s);
-private:
+ return *this;
+ }
- /*!
- an auxiliary method for converting to a string
- */
- template<class string_type>
- void ToStringBase(string_type & result, uint b = 10) const
- {
- UInt<value_size> temp( *this );
- char character;
- uint rem;
-
- result.clear();
-
- if( b<2 || b>16 )
- return;
-
- do
- {
- temp.DivInt(b, &rem);
- character = static_cast<char>( Misc::DigitToChar(rem) );
- result.insert(result.begin(), character);
- }
- while( !temp.IsZero() );
- return;
- }
+ /*!
+ this operator converts a string into its value (with base = 10)
+ */
+ UInt<value_size> & operator=(const std::string & s)
+ {
+ FromString( s.c_str() );
+ return *this;
+ }
-public:
- /*!
- this method converts the value to a string with a base equal 'b'
- */
- void ToString(std::string & result, uint b = 10) const
- {
- return ToStringBase(result, b);
- }
-
- void ToString(std::wstring & result, uint b = 10) const
- {
- return ToStringBase(result, b);
- }
-
- std::string ToString(uint b = 10) const
- {
- std::string result;
- ToStringBase(result, b);
-
- return result;
- }
-
- std::wstring ToWString(uint b = 10) const
- {
- std::wstring result;
- ToStringBase(result, b);
- return result;
- }
+#ifndef TTMATH_DONT_USE_WCHAR
+ /*!
+ this method converts a string into its value
+ */
+ uint FromString(const wchar_t * s, uint b = 10, const wchar_t ** after_source = 0, bool * value_read = 0)
+ {
+ return FromStringBase(s, b, after_source, value_read);
+ }
-private:
- /*!
- an auxiliary method for converting from a string
- */
- template<class char_type>
- uint FromStringBase(const char_type * s, uint b = 10, const char_type ** after_source = 0, bool * value_read = 0)
- {
- UInt<value_size> base( b );
- UInt<value_size> temp;
- sint z;
- uint c = 0;
-
- SetZero();
- temp.SetZero();
- Misc::SkipWhiteCharacters(s);
-
- if( after_source )
- *after_source = s;
-
- if( value_read )
- *value_read = false;
-
- if( b<2 || b>16 )
- return 1;
-
-
- for( ; (z=Misc::CharToDigit(*s, b)) != -1 ; ++s)
- {
- if( value_read )
- *value_read = true;
-
- if( c == 0 )
- {
- temp.table[0] = z;
-
- c += Mul(base);
- c += Add(temp);
- }
- }
+ /*!
+ this method converts a string into its value
- if( after_source )
- *after_source = s;
+ (it returns carry=1 if the value will be too big or an incorrect base 'b' is given)
+ */
+ uint FromString(const std::wstring & s, uint b = 10)
+ {
+ return FromString( s.c_str(), b );
+ }
- TTMATH_LOGC("UInt::FromString", c)
- return (c==0)? 0 : 1;
- }
+ /*!
+ this operator converts a string into its value (with base = 10)
+ */
+ UInt<value_size> & operator=(const wchar_t * s)
+ {
+ FromString(s);
+ return *this;
+ }
-public:
+ /*!
+ this operator converts a string into its value (with base = 10)
+ */
+ UInt<value_size> & operator=(const std::wstring & s)
+ {
+ FromString( s.c_str() );
- /*!
- this method converts a string into its value
- it returns carry=1 if the value will be too big or an incorrect base 'b' is given
+ return *this;
+ }
- string is ended with a non-digit value, for example:
- "12" will be translated to 12
- as well as:
- "12foo" will be translated to 12 too
+#endif
- existing first white characters will be ommited
- if the value from s is too large the rest digits will be skipped
+ /*!
+ *
+ * methods for comparing
+ *
+ */
- after_source (if exists) is pointing at the end of the parsed string
- value_read (if exists) tells whether something has actually been read (at least one digit)
- */
- uint FromString(const char * s, uint b = 10, const char ** after_source = 0, bool * value_read = 0)
- {
- return FromStringBase(s, b, after_source, value_read);
- }
+ /*!
+ this method returns true if 'this' is smaller than 'l'
+ 'index' is an index of the first word from will be the comparison performed
+ (note: we start the comparison from back - from the last word, when index is -1 /default/
+ it is automatically set into the last word)
+ I introduced it for some kind of optimization made in the second division algorithm (Div2)
+ */
+ bool CmpSmaller(const UInt<value_size> & l, sint index = -1) const
+ {
+ sint i;
- /*!
- this method converts a string into its value
- */
- uint FromString(const wchar_t * s, uint b = 10, const wchar_t ** after_source = 0, bool * value_read = 0)
- {
- return FromStringBase(s, b, after_source, value_read);
- }
+ if( index==-1 || index>=sint(value_size) )
+ i = value_size - 1;
+ else
+ i = index;
- /*!
- this method converts a string into its value
+ for( ; i>=0 ; --i)
+ {
+ if( table[i] != l.table[i] )
+ return table[i] < l.table[i];
+ }
- (it returns carry=1 if the value will be too big or an incorrect base 'b' is given)
- */
- uint FromString(const std::string & s, uint b = 10)
- {
- return FromString( s.c_str(), b );
- }
+ // they're equal
+ return false;
+ }
- /*!
- this method converts a string into its value
- (it returns carry=1 if the value will be too big or an incorrect base 'b' is given)
- */
- uint FromString(const std::wstring & s, uint b = 10)
- {
- return FromString( s.c_str(), b );
- }
+ /*!
+ this method returns true if 'this' is bigger than 'l'
+ 'index' is an index of the first word from will be the comparison performed
+ (note: we start the comparison from back - from the last word, when index is -1 /default/
+ it is automatically set into the last word)
- /*!
- this operator converts a string into its value (with base = 10)
- */
- UInt<value_size> & operator=(const char * s)
- {
- FromString(s);
+ I introduced it for some kind of optimization made in the second division algorithm (Div2)
+ */
+ bool CmpBigger(const UInt<value_size> & l, sint index = -1) const
+ {
+ sint i;
- return *this;
- }
+ if( index==-1 || index>=sint(value_size) )
+ i = value_size - 1;
+ else
+ i = index;
- /*!
- this operator converts a string into its value (with base = 10)
- */
- UInt<value_size> & operator=(const wchar_t * s)
- {
- FromString(s);
+ for( ; i>=0 ; --i)
+ {
+ if( table[i] != l.table[i] )
+ return table[i] > l.table[i];
+ }
- return *this;
- }
+ // they're equal
+ return false;
+ }
- /*!
- this operator converts a string into its value (with base = 10)
- */
- UInt<value_size> & operator=(const std::string & s)
- {
- FromString( s.c_str() );
+ /*!
+ this method returns true if 'this' is equal 'l'
- return *this;
- }
+ 'index' is an index of the first word from will be the comparison performed
+ (note: we start the comparison from back - from the last word, when index is -1 /default/
+ it is automatically set into the last word)
+ */
+ bool CmpEqual(const UInt<value_size> & l, sint index = -1) const
+ {
+ sint i;
+ if( index==-1 || index>=sint(value_size) )
+ i = value_size - 1;
+ else
+ i = index;
- /*!
- this operator converts a string into its value (with base = 10)
- */
- UInt<value_size> & operator=(const std::wstring & s)
- {
- FromString( s.c_str() );
- return *this;
- }
+ for( ; i>=0 ; --i)
+ if( table[i] != l.table[i] )
+ return false;
+ return true;
+ }
- /*!
- *
- * methods for comparing
- *
- */
- /*!
- this method returns true if 'this' is smaller than 'l'
+ /*!
+ this method returns true if 'this' is smaller than or equal 'l'
- 'index' is an index of the first word from will be the comparison performed
- (note: we start the comparison from back - from the last word, when index is -1 /default/
- it is automatically set into the last word)
- I introduced it for some kind of optimization made in the second division algorithm (Div2)
- */
- bool CmpSmaller(const UInt<value_size> & l, sint index = -1) const
- {
- sint i;
+ 'index' is an index of the first word from will be the comparison performed
+ (note: we start the comparison from back - from the last word, when index is -1 /default/
+ it is automatically set into the last word)
+ */
+ bool CmpSmallerEqual(const UInt<value_size> & l, sint index=-1) const
+ {
+ sint i;
- if( index==-1 || index>=sint(value_size) )
- i = value_size - 1;
- else
- i = index;
+ if( index==-1 || index>=sint(value_size) )
+ i = value_size - 1;
+ else
+ i = index;
- for( ; i>=0 ; --i)
- {
- if( table[i] != l.table[i] )
- return table[i] < l.table[i];
- }
+ for( ; i>=0 ; --i)
+ {
+ if( table[i] != l.table[i] )
+ return table[i] < l.table[i];
+ }
- // they're equal
- return false;
- }
+ // they're equal
+ return true;
+ }
- /*!
- this method returns true if 'this' is bigger than 'l'
+ /*!
+ this method returns true if 'this' is bigger than or equal 'l'
- 'index' is an index of the first word from will be the comparison performed
- (note: we start the comparison from back - from the last word, when index is -1 /default/
- it is automatically set into the last word)
+ 'index' is an index of the first word from will be the comparison performed
+ (note: we start the comparison from back - from the last word, when index is -1 /default/
+ it is automatically set into the last word)
+ */
+ bool CmpBiggerEqual(const UInt<value_size> & l, sint index=-1) const
+ {
+ sint i;
- I introduced it for some kind of optimization made in the second division algorithm (Div2)
- */
- bool CmpBigger(const UInt<value_size> & l, sint index = -1) const
- {
- sint i;
+ if( index==-1 || index>=sint(value_size) )
+ i = value_size - 1;
+ else
+ i = index;
- if( index==-1 || index>=sint(value_size) )
- i = value_size - 1;
- else
- i = index;
+ for( ; i>=0 ; --i)
+ {
+ if( table[i] != l.table[i] )
+ return table[i] > l.table[i];
+ }
- for( ; i>=0 ; --i)
- {
- if( table[i] != l.table[i] )
- return table[i] > l.table[i];
- }
+ // they're equal
+ return true;
+ }
- // they're equal
- return false;
- }
+ /*
+ operators for comparising
+ */
- /*!
- this method returns true if 'this' is equal 'l'
+ bool operator<(const UInt<value_size> & l) const
+ {
+ return CmpSmaller(l);
+ }
- 'index' is an index of the first word from will be the comparison performed
- (note: we start the comparison from back - from the last word, when index is -1 /default/
- it is automatically set into the last word)
- */
- bool CmpEqual(const UInt<value_size> & l, sint index = -1) const
- {
- sint i;
- if( index==-1 || index>=sint(value_size) )
- i = value_size - 1;
- else
- i = index;
+ bool operator>(const UInt<value_size> & l) const
+ {
+ return CmpBigger(l);
+ }
- for( ; i>=0 ; --i)
- if( table[i] != l.table[i] )
- return false;
+ bool operator==(const UInt<value_size> & l) const
+ {
+ return CmpEqual(l);
+ }
- return true;
- }
+ bool operator!=(const UInt<value_size> & l) const
+ {
+ return !operator==(l);
+ }
- /*!
- this method returns true if 'this' is smaller than or equal 'l'
+ bool operator<=(const UInt<value_size> & l) const
+ {
+ return CmpSmallerEqual(l);
+ }
- 'index' is an index of the first word from will be the comparison performed
- (note: we start the comparison from back - from the last word, when index is -1 /default/
- it is automatically set into the last word)
- */
- bool CmpSmallerEqual(const UInt<value_size> & l, sint index=-1) const
- {
- sint i;
+ bool operator>=(const UInt<value_size> & l) const
+ {
+ return CmpBiggerEqual(l);
+ }
- if( index==-1 || index>=sint(value_size) )
- i = value_size - 1;
- else
- i = index;
+ /*!
+ *
+ * standard mathematical operators
+ *
+ */
- for( ; i>=0 ; --i)
- {
- if( table[i] != l.table[i] )
- return table[i] < l.table[i];
- }
+ UInt<value_size> operator-(const UInt<value_size> & p2) const
+ {
+ UInt<value_size> temp(*this);
- // they're equal
- return true;
- }
+ temp.Sub(p2);
+ return temp;
+ }
+ UInt<value_size> & operator-=(const UInt<value_size> & p2)
+ {
+ Sub(p2);
- /*!
- this method returns true if 'this' is bigger than or equal 'l'
+ return *this;
+ }
- 'index' is an index of the first word from will be the comparison performed
- (note: we start the comparison from back - from the last word, when index is -1 /default/
- it is automatically set into the last word)
- */
- bool CmpBiggerEqual(const UInt<value_size> & l, sint index=-1) const
- {
- sint i;
+ UInt<value_size> operator+(const UInt<value_size> & p2) const
+ {
+ UInt<value_size> temp(*this);
- if( index==-1 || index>=sint(value_size) )
- i = value_size - 1;
- else
- i = index;
+ temp.Add(p2);
+ return temp;
+ }
- for( ; i>=0 ; --i)
- {
- if( table[i] != l.table[i] )
- return table[i] > l.table[i];
- }
+ UInt<value_size> & operator+=(const UInt<value_size> & p2)
+ {
+ Add(p2);
- // they're equal
- return true;
- }
+ return *this;
+ }
- /*
- operators for comparising
- */
+ UInt<value_size> operator*(const UInt<value_size> & p2) const
+ {
+ UInt<value_size> temp(*this);
- bool operator<(const UInt<value_size> & l) const
- {
- return CmpSmaller(l);
- }
+ temp.Mul(p2);
+ return temp;
+ }
- bool operator>(const UInt<value_size> & l) const
- {
- return CmpBigger(l);
- }
+ UInt<value_size> & operator*=(const UInt<value_size> & p2)
+ {
+ Mul(p2);
- bool operator==(const UInt<value_size> & l) const
- {
- return CmpEqual(l);
- }
+ return *this;
+ }
- bool operator!=(const UInt<value_size> & l) const
- {
- return !operator==(l);
- }
+ UInt<value_size> operator/(const UInt<value_size> & p2) const
+ {
+ UInt<value_size> temp(*this);
+ temp.Div(p2);
- bool operator<=(const UInt<value_size> & l) const
- {
- return CmpSmallerEqual(l);
- }
+ return temp;
+ }
- bool operator>=(const UInt<value_size> & l) const
- {
- return CmpBiggerEqual(l);
- }
+ UInt<value_size> & operator/=(const UInt<value_size> & p2)
+ {
+ Div(p2);
- /*!
- *
- * standard mathematical operators
- *
- */
+ return *this;
+ }
- UInt<value_size> operator-(const UInt<value_size> & p2) const
- {
- UInt<value_size> temp(*this);
- temp.Sub(p2);
+ UInt<value_size> operator%(const UInt<value_size> & p2) const
+ {
+ UInt<value_size> temp(*this);
+ UInt<value_size> remainder;
+
+ temp.Div( p2, remainder );
- return temp;
- }
+ return remainder;
+ }
- UInt<value_size> & operator-=(const UInt<value_size> & p2)
- {
- Sub(p2);
- return *this;
- }
+ UInt<value_size> & operator%=(const UInt<value_size> & p2)
+ {
+ UInt<value_size> remainder;
+
+ Div( p2, remainder );
+ operator=(remainder);
- UInt<value_size> operator+(const UInt<value_size> & p2) const
- {
- UInt<value_size> temp(*this);
+ return *this;
+ }
- temp.Add(p2);
- return temp;
- }
+ /*!
+ Prefix operator e.g ++variable
+ */
+ UInt<value_size> & operator++()
+ {
+ AddOne();
- UInt<value_size> & operator+=(const UInt<value_size> & p2)
- {
- Add(p2);
+ return *this;
+ }
- return *this;
- }
+ /*!
+ Postfix operator e.g variable++
+ */
+ UInt<value_size> operator++(int)
+ {
+ UInt<value_size> temp( *this );
- UInt<value_size> operator*(const UInt<value_size> & p2) const
- {
- UInt<value_size> temp(*this);
+ AddOne();
- temp.Mul(p2);
+ return temp;
+ }
- return temp;
- }
+ UInt<value_size> & operator--()
+ {
+ SubOne();
- UInt<value_size> & operator*=(const UInt<value_size> & p2)
- {
- Mul(p2);
+ return *this;
+ }
- return *this;
- }
+ UInt<value_size> operator--(int)
+ {
+ UInt<value_size> temp( *this );
- UInt<value_size> operator/(const UInt<value_size> & p2) const
- {
- UInt<value_size> temp(*this);
+ SubOne();
- temp.Div(p2);
+ return temp;
+ }
- return temp;
- }
- UInt<value_size> & operator/=(const UInt<value_size> & p2)
- {
- Div(p2);
+ /*!
+ *
+ * bitwise operators
+ *
+ */
- return *this;
- }
+ UInt<value_size> operator~() const
+ {
+ UInt<value_size> temp( *this );
+ temp.BitNot();
- UInt<value_size> operator%(const UInt<value_size> & p2) const
- {
- UInt<value_size> temp(*this);
- UInt<value_size> remainder;
+ return temp;
+ }
- temp.Div( p2, remainder );
- return remainder;
- }
+ UInt<value_size> operator&(const UInt<value_size> & p2) const
+ {
+ UInt<value_size> temp( *this );
+ temp.BitAnd(p2);
- UInt<value_size> & operator%=(const UInt<value_size> & p2)
- {
- UInt<value_size> temp(*this);
- UInt<value_size> remainder;
+ return temp;
+ }
- temp.Div( p2, remainder );
- operator=(remainder);
+ UInt<value_size> & operator&=(const UInt<value_size> & p2)
+ {
+ BitAnd(p2);
- return *this;
- }
+ return *this;
+ }
- /*!
- Prefix operator e.g ++variable
- */
- UInt<value_size> & operator++()
- {
- AddOne();
+ UInt<value_size> operator|(const UInt<value_size> & p2) const
+ {
+ UInt<value_size> temp( *this );
- return *this;
- }
+ temp.BitOr(p2);
+ return temp;
+ }
- /*!
- Postfix operator e.g variable++
- */
- UInt<value_size> operator++(int)
- {
- UInt<value_size> temp( *this );
- AddOne();
+ UInt<value_size> & operator|=(const UInt<value_size> & p2)
+ {
+ BitOr(p2);
- return temp;
- }
+ return *this;
+ }
- UInt<value_size> & operator--()
- {
- SubOne();
+ UInt<value_size> operator^(const UInt<value_size> & p2) const
+ {
+ UInt<value_size> temp( *this );
- return *this;
- }
+ temp.BitXor(p2);
+ return temp;
+ }
- UInt<value_size> operator--(int)
- {
- UInt<value_size> temp( *this );
- SubOne();
+ UInt<value_size> & operator^=(const UInt<value_size> & p2)
+ {
+ BitXor(p2);
- return temp;
- }
+ return *this;
+ }
- UInt<value_size> operator>>(int move)
- {
- UInt<value_size> temp( *this );
+ UInt<value_size> operator>>(int move) const
+ {
+ UInt<value_size> temp( *this );
- temp.Rcr(move);
+ temp.Rcr(move);
- return temp;
- }
+ return temp;
+ }
- UInt<value_size> & operator>>=(int move)
- {
- Rcr(move);
+ UInt<value_size> & operator>>=(int move)
+ {
+ Rcr(move);
- return *this;
- }
+ return *this;
+ }
- UInt<value_size> operator<<(int move)
- {
- UInt<value_size> temp( *this );
+ UInt<value_size> operator<<(int move) const
+ {
+ UInt<value_size> temp( *this );
- temp.Rcl(move);
+ temp.Rcl(move);
- return temp;
- }
+ return temp;
+ }
- UInt<value_size> & operator<<=(int move)
- {
- Rcl(move);
+ UInt<value_size> & operator<<=(int move)
+ {
+ Rcl(move);
- return *this;
- }
+ return *this;
+ }
- /*!
- *
- * input/output operators for standard streams
- *
- * (they are very simple, in the future they should be changed)
- *
- */
+ /*!
+ *
+ * input/output operators for standard streams
+ *
+ * (they are very simple, in the future they should be changed)
+ *
+ */
private:
- /*!
- an auxiliary method for outputing to standard streams
- */
- template<class ostream_type, class string_type>
- static ostream_type & OutputToStream(ostream_type & s, const UInt<value_size> & l)
- {
- string_type ss;
+ /*!
+ an auxiliary method for outputing to standard streams
+ */
+ template<class ostream_type, class string_type>
+ static ostream_type & OutputToStream(ostream_type & s, const UInt<value_size> & l)
+ {
+ string_type ss;
- l.ToString(ss);
- s << ss;
+ l.ToString(ss);
+ s << ss;
- return s;
- }
+ return s;
+ }
public:
- /*!
- output to standard streams
- */
- friend std::ostream & operator<<(std::ostream & s, const UInt<value_size> & l)
- {
- return OutputToStream<std::ostream, std::string>(s, l);
- }
+ /*!
+ output to standard streams
+ */
+ friend std::ostream & operator<<(std::ostream & s, const UInt<value_size> & l)
+ {
+ return OutputToStream<std::ostream, std::string>(s, l);
+ }
+
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
+ /*!
+ output to standard streams
+ */
+ friend std::wostream & operator<<(std::wostream & s, const UInt<value_size> & l)
+ {
+ return OutputToStream<std::wostream, std::wstring>(s, l);
+ }
+#endif
private:
- /*!
- an auxiliary method for reading from standard streams
- */
- template<class istream_type, class string_type, class char_type>
- static istream_type & InputFromStream(istream_type & s, UInt<value_size> & l)
- {
- string_type ss;
-
- // char or wchar_t for operator>>
- char_type z;
-
- // operator>> omits white characters if they're set for ommiting
- s >> z;
-
- // we're reading only digits (base=10)
- while( s.good() && Misc::CharToDigit(z, 10)>=0 )
- {
- ss += z;
- z = static_cast<char_type>(s.get());
- }
-
- // we're leaving the last read character
- // (it's not belonging to the value)
- s.unget();
+ /*!
+ an auxiliary method for reading from standard streams
+ */
+ template<class istream_type, class string_type, class char_type>
+ static istream_type & InputFromStream(istream_type & s, UInt<value_size> & l)
+ {
+ string_type ss;
+
+ // char or wchar_t for operator>>
+ char_type z;
+
+ // operator>> omits white characters if they're set for ommiting
+ s >> z;
+
+ // we're reading only digits (base=10)
+ while( s.good() && Misc::CharToDigit(z, 10)>=0 )
+ {
+ ss += z;
+ z = static_cast<char_type>(s.get());
+ }
+
+ // we're leaving the last read character
+ // (it's not belonging to the value)
+ s.unget();
- l.FromString(ss);
+ l.FromString(ss);
- return s;
- }
+ return s;
+ }
public:
- /*!
- input from standard streams
- */
- friend std::istream & operator>>(std::istream & s, UInt<value_size> & l)
- {
- return InputFromStream<std::istream, std::string, char>(s, l);
- }
-
+ /*!
+ input from standard streams
+ */
+ friend std::istream & operator>>(std::istream & s, UInt<value_size> & l)
+ {
+ return InputFromStream<std::istream, std::string, char>(s, l);
+ }
+
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
+ /*!
+ input from standard streams
+ */
+ friend std::wistream & operator>>(std::wistream & s, UInt<value_size> & l)
+ {
+ return InputFromStream<std::wistream, std::wstring, wchar_t>(s, l);
+ }
+#endif
- /*
- following methods are defined in:
- ttmathuint_x86.h
- ttmathuint_x86_64.h
- ttmathuint_noasm.h
- */
+ /*
+ following methods are defined in:
+ ttmathuint_x86.h
+ ttmathuint_x86_64.h
+ ttmathuint_noasm.h
+ */
#ifdef TTMATH_NOASM
- static uint AddTwoWords(uint a, uint b, uint carry, uint * result);
- static uint SubTwoWords(uint a, uint b, uint carry, uint * result);
+ static uint AddTwoWords(uint a, uint b, uint carry, uint * result);
+ static uint SubTwoWords(uint a, uint b, uint carry, uint * result);
#ifdef TTMATH_PLATFORM64
- union uint_
- {
- struct
- {
- unsigned int low; // 32 bit
- unsigned int high; // 32 bit
- } u_;
-
- uint u; // 64 bit
- };
-
-
- static void DivTwoWords2(uint a,uint b, uint c, uint * r, uint * rest);
- static uint DivTwoWordsNormalize(uint_ & a_, uint_ & b_, uint_ & c_);
- static uint DivTwoWordsUnnormalize(uint u, uint d);
- static unsigned int DivTwoWordsCalculate(uint_ u_, unsigned int u3, uint_ v_);
- static void MultiplySubtract(uint_ & u_, unsigned int & u3, unsigned int & q, uint_ v_);
+ union uint_
+ {
+ struct
+ {
+ unsigned int low; // 32 bit
+ unsigned int high; // 32 bit
+ } u_;
+
+ uint u; // 64 bit
+ };
+
+
+ static void DivTwoWords2(uint a,uint b, uint c, uint * r, uint * rest);
+ static uint DivTwoWordsNormalize(uint_ & a_, uint_ & b_, uint_ & c_);
+ static uint DivTwoWordsUnnormalize(uint u, uint d);
+ static unsigned int DivTwoWordsCalculate(uint_ u_, unsigned int u3, uint_ v_);
+ static void MultiplySubtract(uint_ & u_, unsigned int & u3, unsigned int & q, uint_ v_);
#endif // TTMATH_PLATFORM64
#endif // TTMATH_NOASM
private:
- uint Rcl2_one(uint c);
- uint Rcr2_one(uint c);
- uint Rcl2(uint bits, uint c);
- uint Rcr2(uint bits, uint c);
+ uint Rcl2_one(uint c);
+ uint Rcr2_one(uint c);
+ uint Rcl2(uint bits, uint c);
+ uint Rcr2(uint bits, uint c);
public:
- static const char * LibTypeStr();
- static LibTypeCode LibType();
- uint Add(const UInt<value_size> & ss2, uint c=0);
- uint AddInt(uint value, uint index = 0);
- uint AddTwoInts(uint x2, uint x1, uint index);
- static uint AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result);
- uint Sub(const UInt<value_size> & ss2, uint c=0);
- uint SubInt(uint value, uint index = 0);
- static uint SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result);
- static sint FindLeadingBitInWord(uint x);
- static sint FindLowestBitInWord(uint x);
- static uint SetBitInWord(uint & value, uint bit);
- static void MulTwoWords(uint a, uint b, uint * result_high, uint * result_low);
- static void DivTwoWords(uint a,uint b, uint c, uint * r, uint * rest);
+ static const char * LibTypeStr();
+ static LibTypeCode LibType();
+ uint Add(const UInt<value_size> & ss2, uint c=0);
+ uint AddInt(uint value, uint index = 0);
+ uint AddTwoInts(uint x2, uint x1, uint index);
+ static uint AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result);
+ uint Sub(const UInt<value_size> & ss2, uint c=0);
+ uint SubInt(uint value, uint index = 0);
+ static uint SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result);
+ static sint FindLeadingBitInWord(uint x);
+ static sint FindLowestBitInWord(uint x);
+ static uint SetBitInWord(uint & value, uint bit);
+ static void MulTwoWords(uint a, uint b, uint * result_high, uint * result_low);
+ static void DivTwoWords(uint a,uint b, uint c, uint * r, uint * rest);
};
/*!
- this specialization is needed in order to not confused the compiler "error: ISO C++ forbids zero-size array"
- when compiling Mul3Big2() method
+ this specialization is needed in order to not confused the compiler "error: ISO C++ forbids zero-size array"
+ when compiling Mul3Big2() method
*/
template<>
class UInt<0>
{
public:
- uint table[1];
+ uint table[1];
- void Mul2Big(const UInt<0> &, UInt<0> &) { TTMATH_ASSERT(false) };
- void SetZero() { TTMATH_ASSERT(false) };
- uint AddTwoInts(uint, uint, uint) { TTMATH_ASSERT(false) return 0; };
+ void Mul2Big(const UInt<0> &, UInt<0> &) { TTMATH_ASSERT(false) };
+ void SetZero() { TTMATH_ASSERT(false) };
+ uint AddTwoInts(uint, uint, uint) { TTMATH_ASSERT(false) return 0; };
};
Modified: trunk/boost/geometry/extensions/contrib/ttmath/ttmathuint_noasm.h
==============================================================================
--- trunk/boost/geometry/extensions/contrib/ttmath/ttmathuint_noasm.h (original)
+++ trunk/boost/geometry/extensions/contrib/ttmath/ttmathuint_noasm.h 2011-02-19 08:33:14 EST (Sat, 19 Feb 2011)
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (c) 2006-2009, Tomasz Sowa
+ * Copyright (c) 2006-2010, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -480,6 +480,8 @@
c = new_c;
}
+ c = (c != 0)? 1 : 0;
+
TTMATH_LOGC("UInt::Rcr2_one", c)
return c;
@@ -518,7 +520,7 @@
c = new_c;
}
- TTMATH_LOGC("UInt::Rcl2", c)
+ TTMATH_LOGC("UInt::Rcl2", (c & 1))
return (c & 1);
}
@@ -557,9 +559,11 @@
c = new_c;
}
+ c = (c & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0;
+
TTMATH_LOGC("UInt::Rcr2", c)
- return (c & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0;
+ return c;
}
Modified: trunk/boost/geometry/extensions/contrib/ttmath/ttmathuint_x86_64.h
==============================================================================
--- trunk/boost/geometry/extensions/contrib/ttmath/ttmathuint_x86_64.h (original)
+++ trunk/boost/geometry/extensions/contrib/ttmath/ttmathuint_x86_64.h 2011-02-19 08:33:14 EST (Sat, 19 Feb 2011)
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (c) 2006-2009, Tomasz Sowa
+ * Copyright (c) 2006-2010, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -51,7 +51,7 @@
this file is included at the end of ttmathuint.h
*/
-#ifdef _MSC_VER
+#ifndef __GNUC__
#include <intrin.h>
#endif
@@ -59,7 +59,7 @@
namespace ttmath
{
- #ifdef _MSC_VER
+ #ifndef __GNUC__
extern "C"
{
@@ -92,7 +92,7 @@
template<uint value_size>
const char * UInt<value_size>::LibTypeStr()
{
- #ifdef _MSC_VER
+ #ifndef __GNUC__
static const char info[] = "asm_vc_64";
#endif
@@ -110,7 +110,7 @@
template<uint value_size>
LibTypeCode UInt<value_size>::LibType()
{
- #ifdef _MSC_VER
+ #ifndef __GNUC__
LibTypeCode info = asm_vc_64;
#endif
@@ -149,11 +149,7 @@
// we don't have to use TTMATH_REFERENCE_ASSERT here
// this algorithm doesn't require it
- #if !defined(__GNUC__) && !defined(_MSC_VER)
- #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro"
- #endif
-
- #ifdef _MSC_VER
+ #ifndef __GNUC__
c = ttmath_adc_x64(p1,p2,b,c);
#endif
@@ -220,12 +216,7 @@
TTMATH_ASSERT( index < value_size )
- #if !defined(__GNUC__) && !defined(_MSC_VER)
- #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro"
- #endif
-
-
- #ifdef _MSC_VER
+ #ifndef __GNUC__
c = ttmath_addindexed_x64(p1,b,index,value);
#endif
@@ -304,12 +295,7 @@
TTMATH_ASSERT( index < value_size - 1 )
- #if !defined(__GNUC__) && !defined(_MSC_VER)
- #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro"
- #endif
-
-
- #ifdef _MSC_VER
+ #ifndef __GNUC__
c = ttmath_addindexed2_x64(p1,b,index,x1,x2);
#endif
@@ -378,12 +364,7 @@
uint c;
- #if !defined(__GNUC__) && !defined(_MSC_VER)
- #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro"
- #endif
-
-
- #ifdef _MSC_VER
+ #ifndef __GNUC__
c = ttmath_addvector_x64(ss1, ss2, ss1_size, ss2_size, result);
#endif
@@ -456,16 +437,10 @@
uint * p1 = table;
const uint * p2 = ss2.table;
-
// we don't have to use TTMATH_REFERENCE_ASSERT here
// this algorithm doesn't require it
- #if !defined(__GNUC__) && !defined(_MSC_VER)
- #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro"
- #endif
-
-
- #ifdef _MSC_VER
+ #ifndef __GNUC__
c = ttmath_sbb_x64(p1,p2,b,c);
#endif
@@ -529,12 +504,7 @@
TTMATH_ASSERT( index < value_size )
- #if !defined(__GNUC__) && !defined(_MSC_VER)
- #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro"
- #endif
-
-
- #ifdef _MSC_VER
+ #ifndef __GNUC__
c = ttmath_subindexed_x64(p1,b,index,value);
#endif
@@ -599,12 +569,7 @@
uint c;
- #if !defined(__GNUC__) && !defined(_MSC_VER)
- #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro"
- #endif
-
-
- #ifdef _MSC_VER
+ #ifndef __GNUC__
c = ttmath_subvector_x64(ss1, ss2, ss1_size, ss2_size, result);
#endif
@@ -680,14 +645,9 @@
{
sint b = value_size;
uint * p1 = table;
-
-
- #if !defined(__GNUC__) && !defined(_MSC_VER)
- #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro"
- #endif
- #ifdef _MSC_VER
+ #ifndef __GNUC__
c = ttmath_rcl_x64(p1,b,c);
#endif
@@ -742,12 +702,7 @@
uint * p1 = table;
- #if !defined(__GNUC__) && !defined(_MSC_VER)
- #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro"
- #endif
-
-
- #ifdef _MSC_VER
+ #ifndef __GNUC__
c = ttmath_rcr_x64(p1,b,c);
#endif
@@ -803,12 +758,7 @@
uint * p1 = table;
- #if !defined(__GNUC__) && !defined(_MSC_VER)
- #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro"
- #endif
-
-
- #ifdef _MSC_VER
+ #ifndef __GNUC__
c = ttmath_rcl2_x64(p1,b,bits,c);
#endif
@@ -880,12 +830,8 @@
sint b = value_size;
uint * p1 = table;
- #if !defined(__GNUC__) && !defined(_MSC_VER)
- #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro"
- #endif
-
- #ifdef _MSC_VER
+ #ifndef __GNUC__
c = ttmath_rcr2_x64(p1,b,bits,c);
#endif
@@ -949,13 +895,8 @@
{
sint result;
-
- #if !defined(__GNUC__) && !defined(_MSC_VER)
- #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro"
- #endif
-
-
- #ifdef _MSC_VER
+
+ #ifndef __GNUC__
unsigned long nIndex = 0;
@@ -998,13 +939,8 @@
{
sint result;
-
- #if !defined(__GNUC__) && !defined(_MSC_VER)
- #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro"
- #endif
-
-
- #ifdef _MSC_VER
+
+ #ifndef __GNUC__
unsigned long nIndex = 0;
@@ -1057,12 +993,8 @@
uint old_bit;
uint v = value;
- #if !defined(__GNUC__) && !defined(_MSC_VER)
- #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro"
- #endif
-
- #ifdef _MSC_VER
+ #ifndef __GNUC__
old_bit = _bittestandset64((__int64*)&value,bit) != 0;
#endif
@@ -1118,12 +1050,8 @@
uint result1_;
uint result2_;
- #if !defined(__GNUC__) && !defined(_MSC_VER)
- #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro"
- #endif
-
- #ifdef _MSC_VER
+ #ifndef __GNUC__
result1_ = _umul128(a,b,&result2_);
#endif
@@ -1181,12 +1109,8 @@
TTMATH_ASSERT( c != 0 )
- #if !defined(__GNUC__) && !defined(_MSC_VER)
- #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro"
- #endif
-
- #ifdef _MSC_VER
+ #ifndef __GNUC__
ttmath_div_x64(&a,&b,c);
r_ = a;
Modified: trunk/boost/geometry/extensions/contrib/ttmath/ttmathuint_x86_64_msvc.asm
==============================================================================
--- trunk/boost/geometry/extensions/contrib/ttmath/ttmathuint_x86_64_msvc.asm (original)
+++ trunk/boost/geometry/extensions/contrib/ttmath/ttmathuint_x86_64_msvc.asm 2011-02-19 08:33:14 EST (Sat, 19 Feb 2011)
@@ -36,9 +36,9 @@
;
;
-; compile with debug info: ml64.exe /Zd /Zi ttmathuint_x86_64_msvc.asm
-; compile without debug info: ml64.exe ttmathuint_x86_64_msvc.asm
-; this create ttmathuint_x86_64_msvc.obj file which can be linked with your program
+; compile with debug info: ml64.exe /c /Zd /Zi ttmathuint_x86_64_msvc.asm
+; compile without debug info: ml64.exe /c ttmathuint_x86_64_msvc.asm
+; this creates ttmathuint_x86_64_msvc.obj file which can be linked with your program
;
PUBLIC ttmath_adc_x64
Modified: trunk/boost/geometry/extensions/contrib/ttmath_stub.hpp
==============================================================================
--- trunk/boost/geometry/extensions/contrib/ttmath_stub.hpp (original)
+++ trunk/boost/geometry/extensions/contrib/ttmath_stub.hpp 2011-02-19 08:33:14 EST (Sat, 19 Feb 2011)
@@ -4,6 +4,7 @@
#include <boost/math/constants/constants.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/coordinate_cast.hpp>
#include <ttmath.h>
@@ -139,8 +140,37 @@
}
};
-}
-}}} // boost::geometry::math
+} // detail
+
+} // ttmath
+
+
+namespace detail
+{
+
+template <ttmath::uint Exponent, ttmath::uint Mantissa>
+struct coordinate_cast<ttmath::Big<Exponent, Mantissa> >
+{
+ static inline ttmath::Big<Exponent, Mantissa> apply(std::string const& source)
+ {
+ return ttmath::Big<Exponent, Mantissa> (source);
+ }
+};
+
+
+template <>
+struct coordinate_cast<ttmath_big>
+{
+ static inline ttmath_big apply(std::string const& source)
+ {
+ return ttmath_big(source);
+ }
+};
+
+} // namespace detail
+
+
+}} // boost::geometry
Modified: trunk/boost/geometry/extensions/gis/io/wkt/read_wkt.hpp
==============================================================================
--- trunk/boost/geometry/extensions/gis/io/wkt/read_wkt.hpp (original)
+++ trunk/boost/geometry/extensions/gis/io/wkt/read_wkt.hpp 2011-02-19 08:33:14 EST (Sat, 19 Feb 2011)
@@ -34,6 +34,7 @@
#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/util/coordinate_cast.hpp>
#include <boost/geometry/extensions/gis/io/wkt/detail/wkt.hpp>
@@ -98,14 +99,6 @@
Point& point, std::string const& wkt)
{
typedef typename coordinate_type<Point>::type coordinate_type;
- typedef typename boost::mpl::if_c
- <
- boost::is_fundamental<coordinate_type>::type::value,
- coordinate_type,
- double
- >::type type;
-
-
// Stop at end of tokens, or at "," ot ")"
bool finished = (it == end || *it == "," || *it == ")");
@@ -118,13 +111,9 @@
// Note that it is much slower than atof. However, it is more standard
// and in parsing the change in performance falls probably away against
// the tokenizing
- set<Dimension>(point, finished ? type()
-#if defined(BOOST_GEOMETRY_NO_LEXICAL_CAST)
- : atof(it->c_str())
-#else
- : boost::lexical_cast<type>(it->c_str())
-#endif
- );
+ set<Dimension>(point, finished
+ ? coordinate_type()
+ : coordinate_cast<coordinate_type>::apply(*it));
}
catch(boost::bad_lexical_cast const& blc)
{
@@ -232,7 +221,7 @@
};
-// Geometry might be a value-type or reference-type
+// Geometry is a value-type or reference-type
template <typename Geometry>
struct container_appender
{
@@ -326,15 +315,6 @@
typedef typename ring_return_type<Polygon>::type ring_return_type;
typedef container_appender<ring_return_type> appender;
- template <typename Rings>
- static inline void apply_rings(
- tokenizer::iterator& it, tokenizer::iterator end,
- std::string const& wkt, Rings& rings, int n)
- {
- appender::apply(it, end, wkt, *(boost::begin(rings) + (n - 1)));
- }
-
-
static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
std::string const& wkt, Polygon& poly)
{
@@ -353,8 +333,12 @@
}
else
{
- write::resize(interior_rings(poly), n);
- apply_rings(it, end, wkt, interior_rings(poly), n);
+ typename ring_type<Polygon>::type ring;
+ appender::apply(it, end, wkt, ring);
+ traits::push_back
+ <
+ typename traits::interior_mutable_type<Polygon>::type
+ >::apply(interior_rings(poly), ring);
}
if (it != end && *it == ",")
Modified: trunk/boost/geometry/extensions/gis/io/wkt/write_wkt.hpp
==============================================================================
--- trunk/boost/geometry/extensions/gis/io/wkt/write_wkt.hpp (original)
+++ trunk/boost/geometry/extensions/gis/io/wkt/write_wkt.hpp 2011-02-19 08:33:14 EST (Sat, 19 Feb 2011)
@@ -160,7 +160,7 @@
static inline void apply(std::basic_ostream<Char, Traits>& os,
Polygon const& poly)
{
- typedef typename ring_type<Polygon>::type ring;
+ typedef typename ring_type<Polygon const>::type ring;
os << PrefixPolicy::apply();
// TODO: check EMPTY here
Modified: trunk/boost/geometry/geometries/adapted/boost_polygon/holes_proxy.hpp
==============================================================================
--- trunk/boost/geometry/geometries/adapted/boost_polygon/holes_proxy.hpp (original)
+++ trunk/boost/geometry/geometries/adapted/boost_polygon/holes_proxy.hpp 2011-02-19 08:33:14 EST (Sat, 19 Feb 2011)
@@ -41,11 +41,18 @@
> proxy_type;
typedef hole_iterator<Polygon, proxy_type> iterator_type;
+ // The next line does not work probably because coordinate_type is part of the
+ // polygon_traits, but not of the polygon_with_holes_traits
+ // typedef typename boost::polygon::polygon_traits<Polygon>::coordinate_type coordinate_type;
+
+ // So we use:
+ typedef typename Polygon::coordinate_type coordinate_type;
+
inline holes_proxy(Polygon& p)
: polygon(p)
{}
- void clear()
+ inline void clear()
{
Polygon empty;
// Clear the holes
@@ -56,9 +63,9 @@
);
}
- void resize(std::size_t new_size)
+ inline void resize(std::size_t new_size)
{
- std::vector<boost::polygon::polygon_data<double> > temporary_copy
+ std::vector<boost::polygon::polygon_data<coordinate_type> > temporary_copy
(
boost::polygon::begin_holes(polygon),
boost::polygon::end_holes(polygon)
@@ -67,6 +74,21 @@
polygon.set_holes(temporary_copy.begin(), temporary_copy.end());
}
+ template <typename Ring>
+ inline void push_back(Ring const& ring)
+ {
+ std::vector<boost::polygon::polygon_data<coordinate_type> > temporary_copy
+ (
+ boost::polygon::begin_holes(polygon),
+ boost::polygon::end_holes(polygon)
+ );
+ boost::polygon::polygon_data<coordinate_type> added;
+ boost::polygon::set_points(added, ring.begin(), ring.end());
+ temporary_copy.push_back(added);
+ polygon.set_holes(temporary_copy.begin(), temporary_copy.end());
+ }
+
+
Polygon& polygon;
};
@@ -120,7 +142,7 @@
template <typename Polygon>
struct clear<adapt::bp::holes_proxy<Polygon> >
{
- static inline void apply(adapt::bp::holes_proxy<Polygon>& proxy)
+ static inline void apply(adapt::bp::holes_proxy<Polygon> proxy)
{
proxy.clear();
}
@@ -129,12 +151,22 @@
template <typename Polygon>
struct resize<adapt::bp::holes_proxy<Polygon> >
{
- static inline void apply(adapt::bp::holes_proxy<Polygon>& proxy, std::size_t new_size)
+ static inline void apply(adapt::bp::holes_proxy<Polygon> proxy, std::size_t new_size)
{
proxy.resize(new_size);
}
};
+template <typename Polygon>
+struct push_back<adapt::bp::holes_proxy<Polygon> >
+{
+ template <typename Ring>
+ static inline void apply(adapt::bp::holes_proxy<Polygon> proxy, Ring const& ring)
+ {
+ proxy.push_back(ring);
+ }
+};
+
} // namespace traits
Modified: trunk/boost/geometry/geometries/adapted/boost_polygon/ring.hpp
==============================================================================
--- trunk/boost/geometry/geometries/adapted/boost_polygon/ring.hpp (original)
+++ trunk/boost/geometry/geometries/adapted/boost_polygon/ring.hpp 2011-02-19 08:33:14 EST (Sat, 19 Feb 2011)
@@ -36,7 +36,7 @@
};
template <typename CoordinateType>
-struct clear<boost::polygon::polygon_data<CoordinateType> >
+struct clear<boost::polygon::polygon_data<CoordinateType>& >
{
static inline void apply(boost::polygon::polygon_data<CoordinateType>& data)
{
@@ -47,7 +47,7 @@
};
template <typename CoordinateType>
-struct push_back<boost::polygon::polygon_data<CoordinateType> >
+struct push_back<boost::polygon::polygon_data<CoordinateType>& >
{
typedef boost::polygon::point_data<CoordinateType> point_type;
Modified: trunk/boost/geometry/geometries/adapted/boost_polygon/ring_proxy.hpp
==============================================================================
--- trunk/boost/geometry/geometries/adapted/boost_polygon/ring_proxy.hpp (original)
+++ trunk/boost/geometry/geometries/adapted/boost_polygon/ring_proxy.hpp 2011-02-19 08:33:14 EST (Sat, 19 Feb 2011)
@@ -45,8 +45,7 @@
boost::polygon::end_points(ring)
);
temporary_vector.push_back(point);
- //boost::polygon::set_points(ring, temporary_vector.begin(), temporary_vector.end());
- ring.set(temporary_vector.begin(), temporary_vector.end());
+ boost::polygon::set_points(ring, temporary_vector.begin(), temporary_vector.end());
}
};
@@ -84,22 +83,29 @@
static const bool is_mutable = !boost::is_const<Polygon>::type::value;
inline ring_proxy(Polygon& p)
- : m_polygon(p)
+ : m_polygon_pointer(&p)
, m_do_hole(false)
{}
// Constructor used from hole_iterator
inline ring_proxy(Polygon& p, hole_iterator_type hole_it)
- : m_polygon(p)
+ : m_polygon_pointer(&p)
, m_do_hole(true)
, m_hole_it(hole_it)
{}
+ // Default constructor, for mutable polygons / appending (interior) rings
+ inline ring_proxy()
+ : m_polygon_pointer(&m_polygon_for_default_constructor)
+ , m_do_hole(false)
+ {}
+
+
iterator_type begin() const
{
return m_do_hole
? boost::polygon::begin_points(*m_hole_it)
- : boost::polygon::begin_points(m_polygon)
+ : boost::polygon::begin_points(*m_polygon_pointer)
;
}
@@ -107,7 +113,7 @@
{
return m_do_hole
? boost::polygon::begin_points(*m_hole_it)
- : boost::polygon::begin_points(m_polygon)
+ : boost::polygon::begin_points(*m_polygon_pointer)
;
}
@@ -115,7 +121,7 @@
{
return m_do_hole
? boost::polygon::end_points(*m_hole_it)
- : boost::polygon::end_points(m_polygon)
+ : boost::polygon::end_points(*m_polygon_pointer)
;
}
@@ -123,7 +129,7 @@
{
return m_do_hole
? boost::polygon::end_points(*m_hole_it)
- : boost::polygon::end_points(m_polygon)
+ : boost::polygon::end_points(*m_polygon_pointer)
;
}
@@ -137,7 +143,7 @@
}
else
{
- boost::polygon::set_points(m_polygon,
+ boost::polygon::set_points(*m_polygon_pointer,
boost::polygon::begin_points(p),
boost::polygon::end_points(p));
}
@@ -173,15 +179,16 @@
}
else
{
- detail::modify<is_mutable>::push_back(m_polygon, point);
+ detail::modify<is_mutable>::push_back(*m_polygon_pointer, point);
}
}
-
private :
- Polygon& m_polygon;
+ Polygon* m_polygon_pointer;
bool m_do_hole;
hole_iterator_type m_hole_it;
+
+ Polygon m_polygon_for_default_constructor;
};
@@ -235,7 +242,7 @@
template <typename Polygon>
struct clear<adapt::bp::ring_proxy<Polygon> >
{
- static inline void apply(adapt::bp::ring_proxy<Polygon>& proxy)
+ static inline void apply(adapt::bp::ring_proxy<Polygon> proxy)
{
proxy.clear();
}
@@ -245,7 +252,7 @@
template <typename Polygon>
struct resize<adapt::bp::ring_proxy<Polygon> >
{
- static inline void apply(adapt::bp::ring_proxy<Polygon>& proxy, std::size_t new_size)
+ static inline void apply(adapt::bp::ring_proxy<Polygon> proxy, std::size_t new_size)
{
proxy.resize(new_size);
}
@@ -254,7 +261,7 @@
template <typename Polygon>
struct push_back<adapt::bp::ring_proxy<Polygon> >
{
- static inline void apply(adapt::bp::ring_proxy<Polygon>& proxy,
+ static inline void apply(adapt::bp::ring_proxy<Polygon> proxy,
typename boost::polygon::polygon_traits<Polygon>::point_type const& point)
{
proxy.push_back(point);
Modified: trunk/boost/geometry/geometries/concepts/linestring_concept.hpp
==============================================================================
--- trunk/boost/geometry/geometries/concepts/linestring_concept.hpp (original)
+++ trunk/boost/geometry/geometries/concepts/linestring_concept.hpp 2011-02-19 08:33:14 EST (Sat, 19 Feb 2011)
@@ -83,7 +83,7 @@
{
// Check if it can be modified
Geometry* ls;
- traits::clear<Geometry>::apply(*ls);
+ traits::clear<Geometry&>::apply(*ls);
}
#endif
};
Modified: trunk/boost/geometry/geometries/concepts/ring_concept.hpp
==============================================================================
--- trunk/boost/geometry/geometries/concepts/ring_concept.hpp (original)
+++ trunk/boost/geometry/geometries/concepts/ring_concept.hpp 2011-02-19 08:33:14 EST (Sat, 19 Feb 2011)
@@ -58,7 +58,7 @@
BOOST_CONCEPT_USAGE(Ring)
{
Geometry* ring;
- traits::clear<Geometry>::apply(*ring);
+ traits::clear<Geometry&>::apply(*ring);
}
#endif
};
Added: trunk/boost/geometry/util/coordinate_cast.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/geometry/util/coordinate_cast.hpp 2011-02-19 08:33:14 EST (Sat, 19 Feb 2011)
@@ -0,0 +1,49 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2011, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_UTIL_COORDINATE_CAST_HPP
+#define BOOST_GEOMETRY_UTIL_COORDINATE_CAST_HPP
+
+#include <cstdlib>
+#include <string>
+#include <boost/lexical_cast.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+/*!
+\brief cast coordinates from a string to a coordinate type
+\detail By default it uses lexical_cast. However, lexical_cast seems not to support
+ ttmath / partial specializations. Therefore this small utility is added.
+ See also "define_pi" where the same issue is solved
+*/
+template <typename CoordinateType>
+struct coordinate_cast
+{
+ static inline CoordinateType apply(std::string const& source)
+ {
+#if defined(BOOST_GEOMETRY_NO_LEXICAL_CAST)
+ return atof(source.c_str());
+#else
+ return boost::lexical_cast<CoordinateType>(source);
+#endif
+ }
+};
+
+
+} // namespace detail
+#endif
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_UTIL_COORDINATE_CAST_HPP
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk