Library for big numbers from http://www.ttmath.org/

Dependents:   PIDHeater82 Conceptcontroller_v_1_0 AlarmClockApp COG4050_adxl355_tilt ... more

TTMath is a small library which allows one to perform arithmetic operations with big unsigned integer, big signed integer and big floating point numbers. It provides standard mathematical operations like adding, subtracting, multiplying, dividing.

TTMath is BSD Licensed (new/modified BSD)

For more information about ttmath see http://www.ttmath.org/

Files at this revision

API Documentation at this revision

Comitter:
stevep
Date:
Tue Jul 30 18:43:48 2013 +0000
Commit message:
v0.9.3 of ttmath

Changed in this revision

ttmath.h Show annotated file Show diff for this revision Revisions of this file
ttmathbig.h Show annotated file Show diff for this revision Revisions of this file
ttmathdec.h Show annotated file Show diff for this revision Revisions of this file
ttmathint.h Show annotated file Show diff for this revision Revisions of this file
ttmathmisc.h Show annotated file Show diff for this revision Revisions of this file
ttmathobjects.h Show annotated file Show diff for this revision Revisions of this file
ttmathparser.h Show annotated file Show diff for this revision Revisions of this file
ttmaththreads.h Show annotated file Show diff for this revision Revisions of this file
ttmathtypes.h Show annotated file Show diff for this revision Revisions of this file
ttmathuint.h Show annotated file Show diff for this revision Revisions of this file
ttmathuint_noasm.h Show annotated file Show diff for this revision Revisions of this file
ttmathuint_x86.h Show annotated file Show diff for this revision Revisions of this file
ttmathuint_x86_64.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 04a9f72bbca7 ttmath.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ttmath.h	Tue Jul 30 18:43:48 2013 +0000
@@ -0,0 +1,2854 @@
+/*
+ * This file is a part of TTMath Bignum Library
+ * and is distributed under the (new) BSD licence.
+ * Author: Tomasz Sowa <t.sowa@ttmath.org>
+ */
+
+/* 
+ * Copyright (c) 2006-2012, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+#ifndef headerfilettmathmathtt
+#define headerfilettmathmathtt
+
+/*!
+    \file ttmath.h
+    \brief Mathematics functions.
+*/
+
+#ifdef _MSC_VER
+//warning C4127: conditional expression is constant
+#pragma warning( disable: 4127 )
+//warning C4702: unreachable code
+#pragma warning( disable: 4702 )
+//warning C4800: forcing value to bool 'true' or 'false' (performance warning)
+#pragma warning( disable: 4800 )
+#endif
+
+
+#include "ttmathbig.h"
+#include "ttmathobjects.h"
+
+
+namespace ttmath
+{
+    /*
+      *
+     *  functions defined here are used only with Big<> types
+     *
+     *
+     */
+
+
+    /*
+      *
+     *  functions for rounding
+     *
+     *
+     */
+
+
+    /*!
+        this function skips the fraction from x
+        e.g  2.2  = 2
+             2.7  = 2
+             -2.2 = 2
+             -2.7 = 2
+    */
+    template<class ValueType>
+    ValueType SkipFraction(const ValueType & x)
+    {
+        ValueType result( x );
+        result.SkipFraction();
+
+    return result;
+    }
+
+
+    /*!
+        this function rounds to the nearest integer value
+        e.g  2.2  = 2
+             2.7  = 3
+             -2.2 = -2
+             -2.7 = -3
+    */
+    template<class ValueType>
+    ValueType Round(const ValueType & x, ErrorCode * err = 0)
+    {
+        if( x.IsNan() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+        return x; // NaN
+        }
+
+        ValueType result( x );
+        uint c = result.Round();
+
+        if( err )
+            *err = c ? err_overflow : err_ok;
+
+    return result;
+    }
+
+
+
+    /*!
+        this function returns a value representing the smallest integer
+        that is greater than or equal to x
+
+        Ceil(-3.7) = -3
+        Ceil(-3.1) = -3
+        Ceil(-3.0) = -3
+        Ceil(4.0)  = 4
+        Ceil(4.2)  = 5
+        Ceil(4.8)  = 5
+    */
+    template<class ValueType>
+    ValueType Ceil(const ValueType & x, ErrorCode * err = 0)
+    {
+        if( x.IsNan() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+        return x; // NaN
+        }
+
+        ValueType result(x);
+        uint c = 0;
+
+        result.SkipFraction();
+
+        if( result != x )
+        {
+            // x is with fraction
+            // if x is negative we don't have to do anything
+            if( !x.IsSign() )
+            {
+                ValueType one;
+                one.SetOne();
+
+                c += result.Add(one);
+            }
+        }
+
+        if( err )
+            *err = c ? err_overflow : err_ok;
+
+    return result;    
+    }
+
+
+    /*!
+        this function returns a value representing the largest integer
+        that is less than or equal to x
+
+        Floor(-3.6) = -4
+        Floor(-3.1) = -4
+        Floor(-3)   = -3
+        Floor(2)    = 2
+        Floor(2.3)  = 2
+        Floor(2.8)  = 2
+    */
+    template<class ValueType>
+    ValueType Floor(const ValueType & x, ErrorCode * err = 0)
+    {
+        if( x.IsNan() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+        return x; // NaN
+        }
+
+        ValueType result(x);
+        uint c = 0;
+
+        result.SkipFraction();
+
+        if( result != x )
+        {
+            // x is with fraction
+            // if x is positive we don't have to do anything
+            if( x.IsSign() )
+            {
+                ValueType one;
+                one.SetOne();
+
+                c += result.Sub(one);
+            }
+        }
+
+        if( err )
+            *err = c ? err_overflow : err_ok;
+
+    return result;    
+    }
+
+
+
+    /*
+      *
+     *  logarithms and the exponent
+     *
+     *
+     */
+
+    
+    /*!
+        this function calculates the natural logarithm (logarithm with the base 'e')
+    */
+    template<class ValueType>
+    ValueType Ln(const ValueType & x, ErrorCode * err = 0)
+    {
+        if( x.IsNan() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+        return x; // NaN
+        }
+
+        ValueType result;
+        uint state = result.Ln(x);
+
+        if( err )
+        {
+            switch( state )
+            {
+            case 0:
+                *err = err_ok;
+                break;
+            case 1:
+                *err = err_overflow;
+                break;
+            case 2:
+                *err = err_improper_argument;
+                break;
+            default:
+                *err = err_internal_error;
+                break;
+            }
+        }
+
+
+    return result;
+    }
+
+
+    /*!
+        this function calculates the logarithm
+    */
+    template<class ValueType>
+    ValueType Log(const ValueType & x, const ValueType & base, ErrorCode * err = 0)
+    {
+        if( x.IsNan() )
+        {
+            if( err ) *err = err_improper_argument;
+            return x;
+        }
+
+        if( base.IsNan() )
+        {
+            if( err ) *err = err_improper_argument;
+            return base;
+        }
+
+        ValueType result;
+        uint state = result.Log(x, base);
+
+        if( err )
+        {
+            switch( state )
+            {
+            case 0:
+                *err = err_ok;
+                break;
+            case 1:
+                *err = err_overflow;
+                break;
+            case 2:
+            case 3:
+                *err = err_improper_argument;
+                break;
+            default:
+                *err = err_internal_error;
+                break;
+            }
+        }
+
+    return result;
+    }
+
+
+    /*!
+        this function calculates the expression e^x
+    */
+    template<class ValueType>
+    ValueType Exp(const ValueType & x, ErrorCode * err = 0)
+    {
+        if( x.IsNan() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+        return x; // NaN
+        }
+
+        ValueType result;
+        uint c = result.Exp(x);
+
+        if( err )
+            *err = c ? err_overflow : err_ok;
+
+    return result;
+    }
+
+
+    /*!
+    *
+    *    trigonometric functions
+    *
+    */
+
+
+    /*
+        this namespace consists of auxiliary functions
+        (something like 'private' in a class)
+    */
+    namespace auxiliaryfunctions
+    {
+
+    /*!
+        an auxiliary function for calculating the Sine
+        (you don't have to call this function) 
+    */
+    template<class ValueType>
+    uint PrepareSin(ValueType & x, bool & change_sign)
+    {
+    ValueType temp;
+
+        change_sign = false;
+    
+        if( x.IsSign() )
+        {
+            // we're using the formula 'sin(-x) = -sin(x)'
+            change_sign = !change_sign;
+            x.ChangeSign();
+        }
+    
+        // we're reducing the period 2*PI
+        // (for big values there'll always be zero)
+        temp.Set2Pi();
+        
+        if( x.Mod(temp) )
+            return 1;
+        
+
+        // we're setting 'x' as being in the range of <0, 0.5PI>
+
+        temp.SetPi();
+
+        if( x > temp )
+        {
+            // x is in (pi, 2*pi>
+            x.Sub( temp );
+            change_sign = !change_sign;
+        }
+        
+        temp.Set05Pi();
+
+        if( x > temp )
+        {
+            // x is in (0.5pi, pi>
+            x.Sub( temp );
+            x = temp - x;
+        }
+
+    return 0;
+    }
+
+    
+    /*!
+        an auxiliary function for calculating the Sine
+        (you don't have to call this function) 
+
+        it returns Sin(x) where 'x' is from <0, PI/2>
+        we're calculating the Sin with using Taylor series in zero or PI/2
+        (depending on which point of these two points is nearer to the 'x')
+
+        Taylor series:
+        sin(x) = sin(a) + cos(a)*(x-a)/(1!)
+                 - sin(a)*((x-a)^2)/(2!) - cos(a)*((x-a)^3)/(3!)
+                 + sin(a)*((x-a)^4)/(4!) + ...
+
+        when a=0 it'll be:
+        sin(x) = (x)/(1!) - (x^3)/(3!) + (x^5)/(5!) - (x^7)/(7!) + (x^9)/(9!) ...
+
+        and when a=PI/2:
+        sin(x) = 1 - ((x-PI/2)^2)/(2!) + ((x-PI/2)^4)/(4!) - ((x-PI/2)^6)/(6!) ...
+    */
+    template<class ValueType>
+    ValueType Sin0pi05(const ValueType & x)
+    {
+    ValueType result;
+    ValueType numerator, denominator;
+    ValueType d_numerator, d_denominator;
+    ValueType one, temp, old_result;
+
+        // temp = pi/4
+        temp.Set05Pi();
+        temp.exponent.SubOne();
+
+        one.SetOne();
+
+        if( x < temp ) 
+        {    
+            // we're using the Taylor series with a=0
+            result    = x;
+            numerator = x;
+            denominator = one;
+
+            // d_numerator = x^2
+            d_numerator = x;
+            d_numerator.Mul(x);
+
+            d_denominator = 2;
+        }
+        else
+        {
+            // we're using the Taylor series with a=PI/2
+            result = one;
+            numerator = one;
+            denominator = one;
+
+            // d_numerator = (x-pi/2)^2
+            ValueType pi05;
+            pi05.Set05Pi();
+
+            temp = x;
+            temp.Sub( pi05 );
+            d_numerator = temp;
+            d_numerator.Mul( temp );
+
+            d_denominator = one;
+        }
+
+        uint c = 0;
+        bool addition = false;
+
+        old_result = result;
+        for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i)
+        {
+            // we're starting from a second part of the formula
+            c += numerator.    Mul( d_numerator );
+            c += denominator.  Mul( d_denominator );
+            c += d_denominator.Add( one );
+            c += denominator.  Mul( d_denominator );
+            c += d_denominator.Add( one );
+            temp = numerator;
+            c += temp.Div(denominator);
+
+            if( c )
+                // Sin is from <-1,1> and cannot make an overflow
+                // but the carry can be from the Taylor series
+                // (then we only break our calculations)
+                break;
+
+            if( addition )
+                result.Add( temp );
+            else
+                result.Sub( temp );
+
+
+            addition = !addition;
+    
+            // we're testing whether the result has changed after adding
+            // the next part of the Taylor formula, if not we end the loop
+            // (it means 'x' is zero or 'x' is PI/2 or this part of the formula
+            // is too small)
+            if( result == old_result )
+                break;
+
+            old_result = result;
+        }
+
+    return result;
+    }
+
+    } // namespace auxiliaryfunctions
+
+
+
+    /*!
+        this function calculates the Sine
+    */
+    template<class ValueType>
+    ValueType Sin(ValueType x, ErrorCode * err = 0)
+    {
+    using namespace auxiliaryfunctions;
+
+    ValueType one, result;
+    bool change_sign;    
+    
+        if( x.IsNan() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+        return x;
+        }
+
+        if( err )
+            *err = err_ok;
+
+        if( PrepareSin( x, change_sign ) )
+        {
+            // x is too big, we cannnot reduce the 2*PI period
+            // prior to version 0.8.5 the result was zero
+            
+            // result has NaN flag set by default
+
+            if( err )
+                *err = err_overflow; // maybe another error code? err_improper_argument?
+
+        return result; // NaN is set by default
+        }
+
+        result = Sin0pi05( x );
+    
+        one.SetOne();
+
+        // after calculations there can be small distortions in the result
+        if( result > one )
+            result = one;
+        else
+        if( result.IsSign() )
+            // we've calculated the sin from <0, pi/2> and the result
+            // should be positive
+            result.SetZero();
+
+        if( change_sign )
+            result.ChangeSign();    
+        
+    return result;
+    }
+
+    
+    /*!
+        this function calulates the Cosine
+        we're using the formula cos(x) = sin(x + PI/2)
+    */
+    template<class ValueType>
+    ValueType Cos(ValueType x, ErrorCode * err = 0)
+    {
+        if( x.IsNan() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+        return x; // NaN
+        }
+
+        ValueType pi05;
+        pi05.Set05Pi();
+
+        uint c = x.Add( pi05 );
+
+        if( c )
+        {
+            if( err )
+                *err = err_overflow;
+    
+        return ValueType(); // result is undefined (NaN is set by default)
+        }
+
+    return Sin(x, err);
+    }
+    
+
+    /*!
+        this function calulates the Tangent
+        we're using the formula tan(x) = sin(x) / cos(x)
+
+        it takes more time than calculating the Tan directly
+        from for example Taylor series but should be a bit preciser
+        because Tan receives its values from -infinity to +infinity
+        and when we calculate it from any series then we can make
+        a greater mistake than calculating 'sin/cos'
+    */
+    template<class ValueType>
+    ValueType Tan(const ValueType & x, ErrorCode * err = 0)
+    {
+        ValueType result = Cos(x, err);
+        
+        if( err && *err != err_ok )
+            return result;
+
+        if( result.IsZero() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+            result.SetNan();
+
+        return result;
+        }
+
+    return Sin(x, err) / result;
+    }
+
+
+    /*!
+        this function calulates the Tangent
+        look at the description of Tan(...)
+
+        (the abbreviation of Tangent can be 'tg' as well)
+    */
+    template<class ValueType>
+    ValueType Tg(const ValueType & x, ErrorCode * err = 0)
+    {
+        return Tan(x, err);
+    }
+
+
+    /*!
+        this function calulates the Cotangent
+        we're using the formula tan(x) = cos(x) / sin(x)
+
+        (why do we make it in this way? 
+        look at information in Tan() function)
+    */
+    template<class ValueType>
+    ValueType Cot(const ValueType & x, ErrorCode * err = 0)
+    {
+        ValueType result = Sin(x, err);
+
+        if( err && *err != err_ok )
+            return result;
+
+        if( result.IsZero() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+            result.SetNan();
+
+        return result;
+        }
+    
+    return Cos(x, err) / result;
+    }
+
+
+    /*!
+        this function calulates the Cotangent
+        look at the description of Cot(...)
+
+        (the abbreviation of Cotangent can be 'ctg' as well)
+    */
+    template<class ValueType>
+    ValueType Ctg(const ValueType & x, ErrorCode * err = 0)
+    {
+        return Cot(x, err);
+    }
+
+
+    /*
+      *
+     *  inverse trigonometric functions
+     *
+     *
+     */
+
+    namespace auxiliaryfunctions
+    {
+
+    /*!
+        an auxiliary function for calculating the Arc Sine
+
+        we're calculating asin from the following formula:
+        asin(x) = x + (1*x^3)/(2*3) + (1*3*x^5)/(2*4*5) + (1*3*5*x^7)/(2*4*6*7) + ... 
+        where abs(x) <= 1
+
+        we're using this formula when x is from <0, 1/2>
+    */
+    template<class ValueType>
+    ValueType ASin_0(const ValueType & x)
+    {
+    ValueType nominator, denominator, nominator_add, nominator_x, denominator_add, denominator_x;
+    ValueType two, result(x), x2(x);
+    ValueType nominator_temp, denominator_temp, old_result = result;
+    uint c = 0;
+
+    x2.Mul(x);
+    two = 2;
+
+    nominator.SetOne();
+    denominator     = two;
+    nominator_add   = nominator;
+    denominator_add = denominator;
+    nominator_x     = x;
+    denominator_x   = 3;
+
+        for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i)
+        {
+            c += nominator_x.Mul(x2);
+            nominator_temp = nominator_x;    
+            c += nominator_temp.Mul(nominator);
+            denominator_temp = denominator;
+            c += denominator_temp.Mul(denominator_x);
+            c += nominator_temp.Div(denominator_temp);
+
+            // if there is a carry somewhere we only break the calculating
+            // the result should be ok -- it's from <-pi/2, pi/2>
+            if( c ) 
+                break;
+
+            result.Add(nominator_temp);
+            
+            if( result == old_result )
+                 // there's no sense to calculate more
+                break;
+
+            old_result = result;
+
+
+            c += nominator_add.Add(two);
+            c += denominator_add.Add(two);
+            c += nominator.Mul(nominator_add);
+            c += denominator.Mul(denominator_add);
+            c += denominator_x.Add(two);
+        }
+
+    return result;
+    }
+
+
+
+    /*!
+        an auxiliary function for calculating the Arc Sine
+
+        we're calculating asin from the following formula:
+        asin(x) = pi/2 - sqrt(2)*sqrt(1-x) * asin_temp
+        asin_temp = 1 + (1*(1-x))/((2*3)*(2)) + (1*3*(1-x)^2)/((2*4*5)*(4)) + (1*3*5*(1-x)^3)/((2*4*6*7)*(8)) + ... 
+
+        where abs(x) <= 1
+
+        we're using this formula when x is from (1/2, 1>
+    */
+    template<class ValueType>
+    ValueType ASin_1(const ValueType & x)
+    {
+    ValueType nominator, denominator, nominator_add, nominator_x, nominator_x_add, denominator_add, denominator_x;
+    ValueType denominator2;
+    ValueType one, two, result;
+    ValueType nominator_temp, denominator_temp, old_result;
+    uint c = 0;
+
+    two = 2;
+
+    one.SetOne();
+    nominator        = one;
+    result            = one;
+    old_result        = result;
+    denominator     = two;
+    nominator_add   = nominator;
+    denominator_add = denominator;
+    nominator_x     = one;
+    nominator_x.Sub(x);
+    nominator_x_add = nominator_x;
+    denominator_x   = 3;
+    denominator2    = two;
+
+
+        for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i)
+        {
+            nominator_temp = nominator_x;    
+            c += nominator_temp.Mul(nominator);
+            denominator_temp = denominator;
+            c += denominator_temp.Mul(denominator_x);
+            c += denominator_temp.Mul(denominator2);
+            c += nominator_temp.Div(denominator_temp);
+
+            // if there is a carry somewhere we only break the calculating
+            // the result should be ok -- it's from <-pi/2, pi/2>
+            if( c ) 
+                break;
+
+            result.Add(nominator_temp);
+            
+            if( result == old_result )
+                 // there's no sense to calculate more
+                break;
+
+            old_result = result;
+
+            c += nominator_x.Mul(nominator_x_add);
+            c += nominator_add.Add(two);
+            c += denominator_add.Add(two);
+            c += nominator.Mul(nominator_add);
+            c += denominator.Mul(denominator_add);
+            c += denominator_x.Add(two);
+            c += denominator2.Mul(two);
+        }
+
+        
+        nominator_x_add.exponent.AddOne(); // *2
+        one.exponent.SubOne(); // =0.5
+        nominator_x_add.Pow(one); // =sqrt(nominator_x_add)
+        result.Mul(nominator_x_add);
+
+        one.Set05Pi();
+        one.Sub(result);
+
+    return one;
+    }
+
+
+    } // namespace auxiliaryfunctions
+
+
+    /*!
+        this function calculates the Arc Sine
+        x is from <-1,1>
+    */
+    template<class ValueType>
+    ValueType ASin(ValueType x, ErrorCode * err = 0)
+    {
+    using namespace auxiliaryfunctions;
+
+        ValueType result, one;
+        one.SetOne();
+        bool change_sign = false;
+
+        if( x.IsNan() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+        return x;
+        }
+
+        if( x.GreaterWithoutSignThan(one) )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+            return result; // NaN is set by default
+        }
+
+        if( x.IsSign() )
+        {
+            change_sign = true;
+            x.Abs();
+        }
+
+        one.exponent.SubOne(); // =0.5
+
+        // asin(-x) = -asin(x)
+        if( x.GreaterWithoutSignThan(one) )
+            result = ASin_1(x);    
+        else
+            result = ASin_0(x);
+
+        if( change_sign )
+            result.ChangeSign();
+
+        if( err )
+            *err = err_ok;
+
+    return result;
+    }
+
+
+    /*!
+        this function calculates the Arc Cosine
+
+        we're using the formula:
+        acos(x) = pi/2 - asin(x)
+    */
+    template<class ValueType>
+    ValueType ACos(const ValueType & x, ErrorCode * err = 0)
+    {
+    ValueType temp;
+
+        temp.Set05Pi();
+        temp.Sub(ASin(x, err));
+
+    return temp;
+    }
+
+
+
+    namespace auxiliaryfunctions
+    {
+
+    /*!
+        an auxiliary function for calculating the Arc Tangent
+
+        arc tan (x) where x is in <0; 0.5)
+        (x can be in (-0.5 ; 0.5) too)
+
+        we're using the Taylor series expanded in zero:
+        atan(x) = x - (x^3)/3 + (x^5)/5 - (x^7)/7 + ...
+    */
+    template<class ValueType>
+    ValueType ATan0(const ValueType & x)
+    {
+        ValueType nominator, denominator, nominator_add, denominator_add, temp;
+        ValueType result, old_result;
+        bool adding = false;
+        uint c = 0;
+
+        result        = x;
+        old_result    = result;
+        nominator     = x;
+        nominator_add = x;
+        nominator_add.Mul(x);
+
+        denominator.SetOne();
+        denominator_add = 2;
+
+        for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i)
+        {
+            c += nominator.Mul(nominator_add);
+            c += denominator.Add(denominator_add);
+    
+            temp = nominator;
+            c += temp.Div(denominator);
+
+            if( c )
+                // the result should be ok
+                break;
+
+            if( adding )
+                result.Add(temp);
+            else
+                result.Sub(temp);
+
+            if( result == old_result )
+                 // there's no sense to calculate more
+                break;
+
+            old_result = result;
+            adding     = !adding;
+        }
+
+    return result;
+    }
+
+
+    /*!
+        an auxiliary function for calculating the Arc Tangent
+
+        where x is in <0 ; 1>
+    */
+    template<class ValueType>
+    ValueType ATan01(const ValueType & x)
+    {
+        ValueType half;
+        half.Set05();
+
+        /*
+            it would be better if we chose about sqrt(2)-1=0.41... instead of 0.5 here
+
+            because as you can see below:
+            when x = sqrt(2)-1
+            abs(x) = abs( (x-1)/(1+x) )
+            so when we're calculating values around x
+            then they will be better converged to each other
+
+            for example if we have x=0.4999 then during calculating ATan0(0.4999)
+            we have to make about 141 iterations but when we have x=0.5
+            then during calculating ATan0( (x-1)/(1+x) ) we have to make 
+            only about 89 iterations (both for Big<3,9>)
+
+            in the future this 0.5 can be changed
+        */
+        if( x.SmallerWithoutSignThan(half) )
+            return ATan0(x);
+
+
+        /*
+            x>=0.5 and x<=1
+            (x can be even smaller than 0.5)
+
+            y = atac(x)
+            x = tan(y)
+
+            tan(y-b) = (tan(y)-tab(b)) / (1+tan(y)*tan(b))
+            y-b      = atan( (tan(y)-tab(b)) / (1+tan(y)*tan(b)) )
+            y        = b + atan( (x-tab(b)) / (1+x*tan(b)) )
+
+            let b = pi/4
+            tan(b) = tan(pi/4) = 1
+            y = pi/4 + atan( (x-1)/(1+x) )
+
+            so
+            atac(x) = pi/4 + atan( (x-1)/(1+x) )
+            when x->1 (x converges to 1) the (x-1)/(1+x) -> 0
+            and we can use ATan0() function here
+        */
+
+        ValueType n(x),d(x),one,result;
+
+        one.SetOne();
+        n.Sub(one);
+        d.Add(one);
+        n.Div(d);
+
+        result = ATan0(n);
+
+        n.Set05Pi();
+        n.exponent.SubOne(); // =pi/4
+        result.Add(n);
+
+    return result;
+    }
+
+
+    /*!
+        an auxiliary function for calculating the Arc Tangent
+        where x > 1
+
+        we're using the formula:
+        atan(x) = pi/2 - atan(1/x) for x>0
+    */
+    template<class ValueType>
+    ValueType ATanGreaterThanPlusOne(const ValueType & x)
+    {
+    ValueType temp, atan;
+
+        temp.SetOne();
+        
+        if( temp.Div(x) )
+        {
+            // if there was a carry here that means x is very big
+            // and atan(1/x) fast converged to 0
+            atan.SetZero();
+        }
+        else
+            atan = ATan01(temp);
+        
+        temp.Set05Pi();
+        temp.Sub(atan);
+
+    return temp;
+    }
+
+    } // namespace auxiliaryfunctions
+
+
+    /*!
+        this function calculates the Arc Tangent
+    */
+    template<class ValueType>
+    ValueType ATan(ValueType x)
+    {
+    using namespace auxiliaryfunctions;
+
+        ValueType one, result;
+        one.SetOne();
+        bool change_sign = false;
+
+        if( x.IsNan() )
+            return x;
+
+        // if x is negative we're using the formula:
+        // atan(-x) = -atan(x)
+        if( x.IsSign() )
+        {
+            change_sign = true;
+            x.Abs();
+        }
+
+        if( x.GreaterWithoutSignThan(one) )
+            result = ATanGreaterThanPlusOne(x);
+        else
+            result = ATan01(x);
+
+        if( change_sign )
+            result.ChangeSign();
+
+    return result;
+    }
+
+
+    /*!
+        this function calculates the Arc Tangent
+        look at the description of ATan(...)
+
+        (the abbreviation of Arc Tangent can be 'atg' as well)
+    */
+    template<class ValueType>
+    ValueType ATg(const ValueType & x)
+    {
+        return ATan(x);
+    }
+
+
+    /*!
+        this function calculates the Arc Cotangent
+    
+        we're using the formula:
+        actan(x) = pi/2 - atan(x)
+    */
+    template<class ValueType>
+    ValueType ACot(const ValueType & x)
+    {
+    ValueType result;
+
+        result.Set05Pi();
+        result.Sub(ATan(x));
+
+    return result;
+    }
+
+
+    /*!
+        this function calculates the Arc Cotangent
+        look at the description of ACot(...)
+
+        (the abbreviation of Arc Cotangent can be 'actg' as well)
+    */
+    template<class ValueType>
+    ValueType ACtg(const ValueType & x)
+    {
+        return ACot(x);
+    }
+
+
+    /*
+      *
+     *  hyperbolic functions
+     *
+     *
+     */
+
+
+    /*!
+        this function calculates the Hyperbolic Sine
+
+        we're using the formula sinh(x)= ( e^x - e^(-x) ) / 2
+    */
+    template<class ValueType>
+    ValueType Sinh(const ValueType & x, ErrorCode * err = 0)
+    {
+        if( x.IsNan() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+        return x; // NaN
+        }
+
+        ValueType ex, emx;
+        uint c = 0;
+
+        c += ex.Exp(x);
+        c += emx.Exp(-x);
+
+        c += ex.Sub(emx);
+        c += ex.exponent.SubOne();
+
+        if( err )
+            *err = c ? err_overflow : err_ok;
+
+    return ex;
+    }
+
+
+    /*!
+        this function calculates the Hyperbolic Cosine
+
+        we're using the formula cosh(x)= ( e^x + e^(-x) ) / 2
+    */
+    template<class ValueType>
+    ValueType Cosh(const ValueType & x, ErrorCode * err = 0)
+    {
+        if( x.IsNan() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+        return x; // NaN
+        }
+
+        ValueType ex, emx;
+        uint c = 0;
+
+        c += ex.Exp(x);
+        c += emx.Exp(-x);
+
+        c += ex.Add(emx);
+        c += ex.exponent.SubOne();
+
+        if( err )
+            *err = c ? err_overflow : err_ok;
+
+    return ex;
+    }
+
+
+    /*!
+        this function calculates the Hyperbolic Tangent
+
+        we're using the formula tanh(x)= ( e^x - e^(-x) ) / ( e^x + e^(-x) )
+    */
+    template<class ValueType>
+    ValueType Tanh(const ValueType & x, ErrorCode * err = 0)
+    {
+        if( x.IsNan() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+        return x; // NaN
+        }
+
+        ValueType ex, emx, nominator, denominator;
+        uint c = 0;
+
+        c += ex.Exp(x);
+        c += emx.Exp(-x);
+
+        nominator = ex;
+        c += nominator.Sub(emx);
+        denominator = ex;
+        c += denominator.Add(emx);
+        
+        c += nominator.Div(denominator);
+
+        if( err )
+            *err = c ? err_overflow : err_ok;
+
+    return nominator;
+    }
+
+
+    /*!
+        this function calculates the Hyperbolic Tangent
+        look at the description of Tanh(...)
+
+        (the abbreviation of Hyperbolic Tangent can be 'tgh' as well)
+    */
+    template<class ValueType>
+    ValueType Tgh(const ValueType & x, ErrorCode * err = 0)
+    {
+        return Tanh(x, err);
+    }
+
+    /*!
+        this function calculates the Hyperbolic Cotangent
+
+        we're using the formula coth(x)= ( e^x + e^(-x) ) / ( e^x - e^(-x) )
+    */
+    template<class ValueType>
+    ValueType Coth(const ValueType & x, ErrorCode * err = 0)
+    {
+        if( x.IsNan() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+        return x; // NaN
+        }
+
+        if( x.IsZero() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+            return ValueType(); // NaN is set by default
+        }
+
+        ValueType ex, emx, nominator, denominator;
+        uint c = 0;
+
+        c += ex.Exp(x);
+        c += emx.Exp(-x);
+
+        nominator = ex;
+        c += nominator.Add(emx);
+        denominator = ex;
+        c += denominator.Sub(emx);
+        
+        c += nominator.Div(denominator);
+
+        if( err )
+            *err = c ? err_overflow : err_ok;
+
+    return nominator;
+    }
+
+
+    /*!
+        this function calculates the Hyperbolic Cotangent
+        look at the description of Coth(...)
+
+        (the abbreviation of Hyperbolic Cotangent can be 'ctgh' as well)
+    */
+    template<class ValueType>
+    ValueType Ctgh(const ValueType & x, ErrorCode * err = 0)
+    {
+        return Coth(x, err);
+    }
+
+
+    /*
+      *
+     *  inverse hyperbolic functions
+     *
+     *
+     */
+
+
+    /*!
+        inverse hyperbolic sine
+
+        asinh(x) = ln( x + sqrt(x^2 + 1) )
+    */
+    template<class ValueType>
+    ValueType ASinh(const ValueType & x, ErrorCode * err = 0)
+    {
+        if( x.IsNan() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+        return x; // NaN
+        }
+
+        ValueType xx(x), one, result;
+        uint c = 0;
+        one.SetOne();
+
+        c += xx.Mul(x);
+        c += xx.Add(one);
+        one.exponent.SubOne(); // one=0.5
+        // xx is >= 1 
+        c += xx.PowFrac(one); // xx=sqrt(xx)
+        c += xx.Add(x);
+        c += result.Ln(xx); // xx > 0
+
+        // here can only be a carry
+        if( err )
+            *err = c ? err_overflow : err_ok;
+
+    return result;
+    }
+
+
+    /*!
+        inverse hyperbolic cosine
+
+        acosh(x) = ln( x + sqrt(x^2 - 1) )  x in <1, infinity)
+    */
+    template<class ValueType>
+    ValueType ACosh(const ValueType & x, ErrorCode * err = 0)
+    {
+        if( x.IsNan() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+        return x; // NaN
+        }
+
+        ValueType xx(x), one, result;
+        uint c = 0;
+        one.SetOne();
+
+        if( x < one )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+        return result; // NaN is set by default
+        }
+
+        c += xx.Mul(x);
+        c += xx.Sub(one);
+        // xx is >= 0
+        // we can't call a PowFrac when the 'x' is zero
+        // if x is 0 the sqrt(0) is 0
+        if( !xx.IsZero() )
+        {
+            one.exponent.SubOne(); // one=0.5
+            c += xx.PowFrac(one); // xx=sqrt(xx)
+        }
+        c += xx.Add(x);
+        c += result.Ln(xx); // xx >= 1
+
+        // here can only be a carry
+        if( err )
+            *err = c ? err_overflow : err_ok;
+
+    return result;
+    }
+
+
+    /*!
+        inverse hyperbolic tangent
+
+        atanh(x) = 0.5 * ln( (1+x) / (1-x) )  x in (-1, 1)
+    */
+    template<class ValueType>
+    ValueType ATanh(const ValueType & x, ErrorCode * err = 0)
+    {
+        if( x.IsNan() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+        return x; // NaN
+        }
+
+        ValueType nominator(x), denominator, one, result;
+        uint c = 0;
+        one.SetOne();
+
+        if( !x.SmallerWithoutSignThan(one) )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+        return result; // NaN is set by default
+        }
+
+        c += nominator.Add(one);
+        denominator = one;
+        c += denominator.Sub(x);
+        c += nominator.Div(denominator);
+        c += result.Ln(nominator);
+        c += result.exponent.SubOne();
+
+        // here can only be a carry
+        if( err )
+            *err = c ? err_overflow : err_ok;
+
+    return result;
+    }
+
+
+    /*!
+        inverse hyperbolic tantent
+    */
+    template<class ValueType>
+    ValueType ATgh(const ValueType & x, ErrorCode * err = 0)
+    {
+        return ATanh(x, err);
+    }
+
+
+    /*!
+        inverse hyperbolic cotangent
+
+        acoth(x) = 0.5 * ln( (x+1) / (x-1) )  x in (-infinity, -1) or (1, infinity)
+    */
+    template<class ValueType>
+    ValueType ACoth(const ValueType & x, ErrorCode * err = 0)
+    {
+        if( x.IsNan() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+        return x; // NaN
+        }
+
+        ValueType nominator(x), denominator(x), one, result;
+        uint c = 0;
+        one.SetOne();
+
+        if( !x.GreaterWithoutSignThan(one) )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+        return result; // NaN is set by default
+        }
+
+        c += nominator.Add(one);
+        c += denominator.Sub(one);
+        c += nominator.Div(denominator);
+        c += result.Ln(nominator);
+        c += result.exponent.SubOne();
+
+        // here can only be a carry
+        if( err )
+            *err = c ? err_overflow : err_ok;
+
+    return result;
+    }
+
+
+    /*!
+        inverse hyperbolic cotantent
+    */
+    template<class ValueType>
+    ValueType ACtgh(const ValueType & x, ErrorCode * err = 0)
+    {
+        return ACoth(x, err);
+    }
+
+
+
+
+
+    /*
+      *
+     *  functions for converting between degrees, radians and gradians
+     *
+     *
+     */
+
+
+    /*!
+        this function converts degrees to radians
+        
+        it returns: x * pi / 180
+    */
+    template<class ValueType>
+    ValueType DegToRad(const ValueType & x, ErrorCode * err = 0)
+    {
+    ValueType result, temp;
+    uint c = 0;
+
+        if( x.IsNan() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+        return x;
+        }
+
+        result = x;
+
+        // it is better to make division first and then multiplication
+        // the result is more accurate especially when x is: 90,180,270 or 360
+        temp = 180;
+        c += result.Div(temp);
+
+        temp.SetPi();
+        c += result.Mul(temp);
+
+        if( err )
+            *err = c ? err_overflow : err_ok;
+
+    return result;
+    }
+
+
+    /*!
+        this function converts radians to degrees
+        
+        it returns: x * 180 / pi
+    */
+    template<class ValueType>
+    ValueType RadToDeg(const ValueType & x, ErrorCode * err = 0)
+    {
+    ValueType result, delimiter;
+    uint c = 0;
+
+        if( x.IsNan() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+        return x;
+        }
+
+        result = 180;
+        c += result.Mul(x);
+
+        delimiter.SetPi();
+        c += result.Div(delimiter);
+
+        if( err )
+            *err = c ? err_overflow : err_ok;
+
+    return result;
+    }
+
+
+    /*!
+        this function converts degrees in the long format into one value
+
+        long format: (degrees, minutes, seconds)
+        minutes and seconds must be greater than or equal zero
+
+        result: 
+        if d>=0 : result= d + ((s/60)+m)/60
+        if d<0  : result= d - ((s/60)+m)/60
+
+        ((s/60)+m)/60 = (s+60*m)/3600 (second version is faster because 
+        there's only one division)
+
+        for example:
+        DegToDeg(10, 30, 0) = 10.5
+        DegToDeg(10, 24, 35.6)=10.4098(8)
+    */
+    template<class ValueType>
+    ValueType DegToDeg(    const ValueType & d, const ValueType & m, const ValueType & s,
+                        ErrorCode * err = 0)
+    {
+    ValueType delimiter, multipler;
+    uint c = 0;
+
+        if( d.IsNan() || m.IsNan() || s.IsNan() || m.IsSign() || s.IsSign() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+            delimiter.SetZeroNan(); // not needed, only to get rid of GCC warning about an uninitialized variable
+
+        return delimiter;
+        }
+
+        multipler = 60;
+        delimiter = 3600;
+
+        c += multipler.Mul(m);
+        c += multipler.Add(s);
+        c += multipler.Div(delimiter);
+
+        if( d.IsSign() )
+            multipler.ChangeSign();
+
+        c += multipler.Add(d);
+
+        if( err )
+            *err = c ? err_overflow : err_ok;
+
+    return multipler;
+    }
+
+
+    /*!
+        this function converts degrees in the long format to radians
+    */
+    template<class ValueType>
+    ValueType DegToRad(    const ValueType & d, const ValueType & m, const ValueType & s,
+                        ErrorCode * err = 0)
+    {
+        ValueType temp_deg = DegToDeg(d,m,s,err);
+
+        if( err && *err!=err_ok )
+            return temp_deg;
+
+    return DegToRad(temp_deg, err);
+    }
+
+
+    /*!
+        this function converts gradians to radians
+        
+        it returns: x * pi / 200
+    */
+    template<class ValueType>
+    ValueType GradToRad(const ValueType & x, ErrorCode * err = 0)
+    {
+    ValueType result, temp;
+    uint c = 0;
+
+        if( x.IsNan() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+        return x;
+        }
+
+        result = x;
+
+        // it is better to make division first and then multiplication
+        // the result is more accurate especially when x is: 100,200,300 or 400
+        temp = 200;
+        c += result.Div(temp);
+
+        temp.SetPi();
+        c += result.Mul(temp);
+
+        if( err )
+            *err = c ? err_overflow : err_ok;
+
+    return result;
+    }
+
+
+    /*!
+        this function converts radians to gradians
+        
+        it returns: x * 200 / pi
+    */
+    template<class ValueType>
+    ValueType RadToGrad(const ValueType & x, ErrorCode * err = 0)
+    {
+    ValueType result, delimiter;
+    uint c = 0;
+
+        if( x.IsNan() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+        return x;
+        }
+
+        result = 200;
+        c += result.Mul(x);
+
+        delimiter.SetPi();
+        c += result.Div(delimiter);
+
+        if( err )
+            *err = c ? err_overflow : err_ok;
+
+    return result;
+    }
+
+
+    /*!
+        this function converts degrees to gradians
+        
+        it returns: x * 200 / 180
+    */
+    template<class ValueType>
+    ValueType DegToGrad(const ValueType & x, ErrorCode * err = 0)
+    {
+    ValueType result, temp;
+    uint c = 0;
+
+        if( x.IsNan() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+        return x;
+        }
+
+        result = x;
+
+        temp = 200;
+        c += result.Mul(temp);
+
+        temp = 180;
+        c += result.Div(temp);
+
+        if( err )
+            *err = c ? err_overflow : err_ok;
+
+    return result;
+    }
+
+
+    /*!
+        this function converts degrees in the long format to gradians
+    */
+    template<class ValueType>
+    ValueType DegToGrad( const ValueType & d, const ValueType & m, const ValueType & s,
+                         ErrorCode * err = 0)
+    {
+        ValueType temp_deg = DegToDeg(d,m,s,err);
+
+        if( err && *err!=err_ok )
+            return temp_deg;
+
+    return DegToGrad(temp_deg, err);
+    }
+
+
+    /*!
+        this function converts degrees to gradians
+        
+        it returns: x * 180 / 200
+    */
+    template<class ValueType>
+    ValueType GradToDeg(const ValueType & x, ErrorCode * err = 0)
+    {
+    ValueType result, temp;
+    uint c = 0;
+
+        if( x.IsNan() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+        return x;
+        }
+
+        result = x;
+
+        temp = 180;
+        c += result.Mul(temp);
+
+        temp = 200;
+        c += result.Div(temp);
+
+        if( err )
+            *err = c ? err_overflow : err_ok;
+
+    return result;
+    }
+
+
+
+
+    /*
+      *
+     *  another functions
+     *
+     *
+     */
+
+
+    /*!
+        this function calculates the square root
+
+        Sqrt(9) = 3
+    */
+    template<class ValueType>
+    ValueType Sqrt(ValueType x, ErrorCode * err = 0)
+    {
+        if( x.IsNan() || x.IsSign() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+            x.SetNan();
+
+        return x;
+        }
+
+        uint c = x.Sqrt();
+
+        if( err )
+            *err = c ? err_overflow : err_ok;
+
+    return x;
+    }
+
+
+
+    namespace auxiliaryfunctions
+    {
+
+    template<class ValueType>
+    bool RootCheckIndexSign(ValueType & x, const ValueType & index, ErrorCode * err)
+    {
+        if( index.IsSign() )
+        {
+            // index cannot be negative
+            if( err )
+                *err = err_improper_argument;
+
+            x.SetNan();
+
+        return true;
+        }
+
+    return false;
+    }
+
+
+    template<class ValueType>
+    bool RootCheckIndexZero(ValueType & x, const ValueType & index, ErrorCode * err)
+    {
+        if( index.IsZero() )
+        {
+            if( x.IsZero() )
+            {
+                // there isn't root(0;0) - we assume it's not defined
+                if( err )
+                    *err = err_improper_argument;
+
+                x.SetNan();
+
+            return true;
+            }
+    
+            // root(x;0) is 1 (if x!=0)
+            x.SetOne();
+
+            if( err )
+                *err = err_ok;
+
+        return true;
+        }
+
+    return false;
+    }
+
+
+    template<class ValueType>
+    bool RootCheckIndexOne(const ValueType & index, ErrorCode * err)
+    {
+        ValueType one;
+        one.SetOne();
+
+        if( index == one )
+        {
+            //root(x;1) is x
+            // we do it because if we used the PowFrac function
+            // we would lose the precision
+            if( err )
+                *err = err_ok;
+
+        return true;
+        }
+
+    return false;
+    }
+
+
+    template<class ValueType>
+    bool RootCheckIndexTwo(ValueType & x, const ValueType & index, ErrorCode * err)
+    {
+        if( index == 2 )
+        {
+            x = Sqrt(x, err);
+
+        return true;
+        }
+
+    return false;
+    }
+
+
+    template<class ValueType>
+    bool RootCheckIndexFrac(ValueType & x, const ValueType & index, ErrorCode * err)
+    {
+        if( !index.IsInteger() )
+        {
+            // index must be integer
+            if( err )
+                *err = err_improper_argument;
+
+            x.SetNan();
+
+        return true;
+        }
+
+    return false;
+    }
+
+
+    template<class ValueType>
+    bool RootCheckXZero(ValueType & x, ErrorCode * err)
+    {
+        if( x.IsZero() )
+        {
+            // root(0;index) is zero (if index!=0)
+            // RootCheckIndexZero() must be called beforehand
+            x.SetZero();
+
+            if( err )
+                *err = err_ok;
+
+        return true;
+        }
+
+    return false;
+    }
+
+
+    template<class ValueType>
+    bool RootCheckIndex(ValueType & x, const ValueType & index, ErrorCode * err, bool * change_sign)
+    {
+        *change_sign = false;
+
+        if( index.Mod2() )
+        {
+            // index is odd (1,3,5...)
+            if( x.IsSign() )
+            {
+                *change_sign = true;
+                x.Abs();
+            }
+        }
+        else
+        {
+            // index is even
+            // x cannot be negative
+            if( x.IsSign() )
+            {
+                if( err )
+                    *err = err_improper_argument;
+
+                x.SetNan();
+
+                return true;
+            }
+        }
+
+    return false;
+    }
+
+
+    template<class ValueType>
+    uint RootCorrectInteger(ValueType & old_x, ValueType & x, const ValueType & index)
+    {
+        if( !old_x.IsInteger() || x.IsInteger() || !index.exponent.IsSign() )
+            return 0;
+
+        // old_x is integer,
+        // x is not integer,
+        // index is relatively small (index.exponent<0 or index.exponent<=0)
+        // (because we're using a special powering algorithm Big::PowUInt())
+
+        uint c = 0;
+
+        ValueType temp(x);
+        c += temp.Round();
+
+        ValueType temp_round(temp);
+        c += temp.PowUInt(index);
+
+        if( temp == old_x )
+            x = temp_round;
+
+    return (c==0)? 0 : 1;
+    }
+
+
+
+    } // namespace auxiliaryfunctions 
+
+
+
+    /*!
+        indexth Root of x
+        index must be integer and not negative <0;1;2;3....)
+
+        if index==0 the result is one
+        if x==0 the result is zero and we assume root(0;0) is not defined
+
+        if index is even (2;4;6...) the result is x^(1/index) and x>0
+        if index is odd (1;2;3;...) the result is either 
+            -(abs(x)^(1/index)) if x<0    or
+                   x^(1/index)) if x>0
+
+        (for index==1 the result is equal x)
+    */
+    template<class ValueType>
+    ValueType Root(ValueType x, const ValueType & index, ErrorCode * err = 0)
+    {
+        using namespace auxiliaryfunctions;
+
+        if( x.IsNan() || index.IsNan() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+            x.SetNan();
+
+        return x;
+        }
+
+        if( RootCheckIndexSign(x, index, err) ) return x;
+        if( RootCheckIndexZero(x, index, err) ) return x;
+        if( RootCheckIndexOne (   index, err) ) return x;
+        if( RootCheckIndexTwo (x, index, err) ) return x;
+        if( RootCheckIndexFrac(x, index, err) ) return x;
+        if( RootCheckXZero    (x,        err) ) return x;
+
+        // index integer and index!=0
+        // x!=0
+
+        ValueType old_x(x);
+        bool change_sign;
+
+        if( RootCheckIndex(x, index, err, &change_sign ) ) return x;
+
+        ValueType temp;
+        uint c = 0;
+
+        // we're using the formula: root(x ; n) = exp( ln(x) / n )
+        c += temp.Ln(x);
+        c += temp.Div(index);
+        c += x.Exp(temp);
+
+        if( change_sign )
+        {
+            // x is different from zero
+            x.SetSign();
+        }
+
+        c += RootCorrectInteger(old_x, x, index);
+
+        if( err )
+            *err = c ? err_overflow : err_ok;
+
+    return x;
+    }
+
+
+
+    /*!
+        absolute value of x
+        e.g.  -2 = 2 
+               2 = 2
+    */
+    template<class ValueType>
+    ValueType Abs(const ValueType & x)
+    {
+        ValueType result( x );
+        result.Abs();
+
+    return result;
+    }
+
+
+    /*!
+        it returns the sign of the value
+        e.g.  -2 = -1 
+               0 = 0
+              10 = 1
+    */
+    template<class ValueType>
+    ValueType Sgn(ValueType x)
+    {
+        x.Sgn();
+
+    return x;
+    }
+
+
+    /*!
+        the remainder from a division
+
+        e.g.
+        mod( 12.6 ;  3) =  0.6   because 12.6  = 3*4 + 0.6
+        mod(-12.6 ;  3) = -0.6   bacause -12.6 = 3*(-4) + (-0.6)
+        mod( 12.6 ; -3) =  0.6
+        mod(-12.6 ; -3) = -0.6
+    */
+    template<class ValueType>
+    ValueType Mod(ValueType a, const ValueType & b, ErrorCode * err = 0)
+    {
+        if( a.IsNan() || b.IsNan() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+            a.SetNan();
+
+        return a;
+        }
+
+        uint c = a.Mod(b);
+
+        if( err )
+            *err = c ? err_overflow : err_ok;
+
+    return a;
+    }
+
+
+
+    namespace auxiliaryfunctions
+    {
+
+    /*!
+        this function is used to store factorials in a given container
+        'more' means how many values should be added at the end
+
+            e.g.
+            std::vector<ValueType> fact;
+            SetFactorialSequence(fact, 3);
+            // now the container has three values: 1  1  2
+
+            SetFactorialSequence(fact, 2);
+            // now the container has five values:  1  1  2  6  24
+    */
+    template<class ValueType>
+    void SetFactorialSequence(std::vector<ValueType> & fact, uint more = 20)
+    {
+        if( more == 0 )
+            more = 1;
+
+        uint start = static_cast<uint>(fact.size());
+        fact.resize(fact.size() + more);
+
+        if( start == 0 )
+        {
+            fact[0] = 1;
+            ++start;
+        }
+
+        for(uint i=start ; i<fact.size() ; ++i)
+        {
+            fact[i] = fact[i-1];
+            fact[i].MulInt(i);
+        }
+    }
+
+
+    /*!
+        an auxiliary function used to calculate Bernoulli numbers
+
+        this function returns a sum:
+        sum(m) = sum_{k=0}^{m-1} {2^k * (m k) * B(k)}    k in [0, m-1]   (m k) means binomial coefficient = (m! / (k! * (m-k)!))
+
+        you should have sufficient factorials in cgamma.fact
+        (cgamma.fact should have at least m items)
+
+        n_ should be equal 2
+    */
+    template<class ValueType>
+    ValueType SetBernoulliNumbersSum(CGamma<ValueType> & cgamma, const ValueType & n_, uint m,
+                                      const volatile StopCalculating * stop = 0)
+    {
+    ValueType k_, temp, temp2, temp3, sum;
+
+        sum.SetZero();
+        
+        for(uint k=0 ; k<m ; ++k)            // k<m means k<=m-1
+        {
+            if( stop && (k & 15)==0 )        // means: k % 16 == 0
+                if( stop->WasStopSignal() )
+                    return ValueType();        // NaN
+
+            if( k>1 && (k & 1) == 1 )        // for that k the Bernoulli number is zero
+                continue;
+
+            k_ = k;
+
+            temp = n_;                // n_ is equal 2
+            temp.Pow(k_);
+            // temp = 2^k
+
+            temp2 = cgamma.fact[m];
+            temp3 = cgamma.fact[k];
+            temp3.Mul(cgamma.fact[m-k]);
+            temp2.Div(temp3);
+            // temp2 = (m k) = m! / ( k! * (m-k)! )
+
+            temp.Mul(temp2);
+            temp.Mul(cgamma.bern[k]);
+
+            sum.Add(temp);
+            // sum += 2^k * (m k) * B(k)
+
+            if( sum.IsNan() )
+                break;
+        }
+
+    return sum;
+    }
+
+
+    /*!
+        an auxiliary function used to calculate Bernoulli numbers
+        start is >= 2
+
+        we use the recurrence formula: 
+           B(m) = 1 / (2*(1 - 2^m)) * sum(m)
+           where sum(m) is calculated by SetBernoulliNumbersSum()
+    */
+    template<class ValueType>
+    bool SetBernoulliNumbersMore(CGamma<ValueType> & cgamma, uint start, const volatile StopCalculating * stop = 0)
+    {
+    ValueType denominator, temp, temp2, temp3, m_, sum, sum2, n_, k_;
+
+        const uint n = 2;
+        n_ = n;
+
+        // start is >= 2
+        for(uint m=start ; m<cgamma.bern.size() ; ++m)
+        {
+            if( (m & 1) == 1 )
+            {
+                cgamma.bern[m].SetZero();
+            }
+            else
+            {
+                m_ = m;
+
+                temp = n_;                // n_ = 2
+                temp.Pow(m_);
+                // temp = 2^m
+
+                denominator.SetOne();
+                denominator.Sub(temp);
+                if( denominator.exponent.AddOne() ) // it means: denominator.MulInt(2)
+                    denominator.SetNan();
+
+                // denominator = 2 * (1 - 2^m)
+
+                cgamma.bern[m] = SetBernoulliNumbersSum(cgamma, n_, m, stop);
+
+                if( stop && stop->WasStopSignal() )
+                {
+                    cgamma.bern.resize(m);        // valid numbers are in [0, m-1]
+                    return false;
+                }
+
+                cgamma.bern[m].Div(denominator);
+            }
+        }
+
+    return true;
+    }
+
+
+    /*!
+        this function is used to calculate Bernoulli numbers,
+        returns false if there was a stop signal,
+        'more' means how many values should be added at the end
+
+            e.g.
+            typedef Big<1,2> MyBig;
+            CGamma<MyBig> cgamma;
+            SetBernoulliNumbers(cgamma, 3);
+            // now we have three first Bernoulli numbers:  1  -0.5  0.16667
+            
+            SetBernoulliNumbers(cgamma, 4);
+            // now we have 7 Bernoulli numbers:  1  -0.5  0.16667   0   -0.0333   0   0.0238
+    */
+    template<class ValueType>
+    bool SetBernoulliNumbers(CGamma<ValueType> & cgamma, uint more = 20, const volatile StopCalculating * stop = 0)
+    {
+        if( more == 0 )
+            more = 1;
+
+        uint start = static_cast<uint>(cgamma.bern.size());
+        cgamma.bern.resize(cgamma.bern.size() + more);
+
+        if( start == 0 )
+        {
+            cgamma.bern[0].SetOne();
+            ++start;
+        }
+
+        if( cgamma.bern.size() == 1 )
+            return true;
+
+        if( start == 1 )
+        {
+            cgamma.bern[1].Set05();
+            cgamma.bern[1].ChangeSign();
+            ++start;
+        }
+
+        // we should have sufficient factorials in cgamma.fact
+        if( cgamma.fact.size() < cgamma.bern.size() )
+            SetFactorialSequence(cgamma.fact, static_cast<uint>(cgamma.bern.size() - cgamma.fact.size()));
+
+
+    return SetBernoulliNumbersMore(cgamma, start, stop);
+    }
+
+
+    /*!
+        an auxiliary function used to calculate the Gamma() function
+
+        we calculate a sum:
+           sum(n) = sum_{m=2} { B(m) / ( (m^2 - m) * n^(m-1) )  } = 1/(12*n) - 1/(360*n^3) + 1/(1260*n^5) + ...
+           B(m) means a mth Bernoulli number
+           the sum starts from m=2, we calculate as long as the value will not change after adding a next part
+    */
+    template<class ValueType>
+    ValueType GammaFactorialHighSum(const ValueType & n, CGamma<ValueType> & cgamma, ErrorCode & err,
+                                    const volatile StopCalculating * stop)
+    {
+    ValueType temp, temp2, denominator, sum, oldsum;
+
+        sum.SetZero();
+
+        for(uint m=2 ; m<TTMATH_ARITHMETIC_MAX_LOOP ; m+=2)
+        {
+            if( stop && (m & 3)==0 ) // (m & 3)==0 means: (m % 4)==0
+                if( stop->WasStopSignal() )
+                {
+                    err = err_interrupt;
+                    return ValueType(); // NaN
+                }
+
+            temp = (m-1);
+            denominator = n;
+            denominator.Pow(temp);
+            // denominator = n ^ (m-1)
+
+            temp = m;
+            temp2 = temp;
+            temp.Mul(temp2);
+            temp.Sub(temp2);
+            // temp = m^2 - m
+
+            denominator.Mul(temp);
+            // denominator = (m^2 - m) * n ^ (m-1)
+
+            if( m >= cgamma.bern.size() )
+            {
+                if( !SetBernoulliNumbers(cgamma, m - cgamma.bern.size() + 1 + 3, stop) ) // 3 more than needed
+                {
+                    // there was the stop signal
+                    err = err_interrupt;
+                    return ValueType(); // NaN
+                }
+            }
+
+            temp = cgamma.bern[m];
+            temp.Div(denominator);
+
+            oldsum = sum;
+            sum.Add(temp);
+
+            if( sum.IsNan() || oldsum==sum )
+                break;
+        }
+
+    return sum;
+    }
+
+
+    /*!
+        an auxiliary function used to calculate the Gamma() function
+
+        we calculate a helper function GammaFactorialHigh() by using Stirling's series:
+           n! = (n/e)^n * sqrt(2*pi*n) * exp( sum(n) )
+           where n is a real number (not only an integer) and is sufficient large (greater than TTMATH_GAMMA_BOUNDARY)
+           and sum(n) is calculated by GammaFactorialHighSum()
+    */
+    template<class ValueType>
+    ValueType GammaFactorialHigh(const ValueType & n, CGamma<ValueType> & cgamma, ErrorCode & err,
+                                 const volatile StopCalculating * stop)
+    {
+    ValueType temp, temp2, temp3, denominator, sum;
+
+        temp.Set2Pi();
+        temp.Mul(n);
+        temp2 = Sqrt(temp);
+        // temp2 = sqrt(2*pi*n)
+
+        temp = n;
+        temp3.SetE();
+        temp.Div(temp3);
+        temp.Pow(n);
+        // temp = (n/e)^n
+
+        sum = GammaFactorialHighSum(n, cgamma, err, stop);
+        temp3.Exp(sum);
+        // temp3 = exp(sum)
+
+        temp.Mul(temp2);
+        temp.Mul(temp3);
+
+    return temp;
+    }
+
+
+    /*!
+        an auxiliary function used to calculate the Gamma() function
+
+        Gamma(x) = GammaFactorialHigh(x-1)
+    */
+    template<class ValueType>
+    ValueType GammaPlusHigh(ValueType n, CGamma<ValueType> & cgamma, ErrorCode & err, const volatile StopCalculating * stop)
+    {
+    ValueType one;
+
+        one.SetOne();
+        n.Sub(one);
+
+    return GammaFactorialHigh(n, cgamma, err, stop);
+    }
+
+
+    /*!
+        an auxiliary function used to calculate the Gamma() function
+    
+        we use this function when n is integer and a small value (from 0 to TTMATH_GAMMA_BOUNDARY]
+        we use the formula:
+           gamma(n) = (n-1)! = 1 * 2 * 3 * ... * (n-1) 
+    */
+    template<class ValueType>
+    ValueType GammaPlusLowIntegerInt(uint n, CGamma<ValueType> & cgamma)
+    {
+        TTMATH_ASSERT( n > 0 )
+
+        if( n - 1 < static_cast<uint>(cgamma.fact.size()) )
+            return cgamma.fact[n - 1];
+
+        ValueType res;
+        uint start = 2;
+
+        if( cgamma.fact.size() < 2 )
+        {
+            res.SetOne();
+        }
+        else
+        {
+            start = static_cast<uint>(cgamma.fact.size());
+            res   = cgamma.fact[start-1];
+        }
+
+        for(uint i=start ; i<n ; ++i)
+            res.MulInt(i);
+
+    return res;
+    }
+    
+
+    /*!
+        an auxiliary function used to calculate the Gamma() function
+
+        we use this function when n is integer and a small value (from 0 to TTMATH_GAMMA_BOUNDARY]
+    */
+    template<class ValueType>
+    ValueType GammaPlusLowInteger(const ValueType & n, CGamma<ValueType> & cgamma)
+    {
+    sint n_;
+
+        n.ToInt(n_);
+
+    return GammaPlusLowIntegerInt(n_, cgamma);
+    }
+
+
+    /*!
+        an auxiliary function used to calculate the Gamma() function
+
+        we use this function when n is a small value (from 0 to TTMATH_GAMMA_BOUNDARY]
+        we use a recurrence formula:
+           gamma(z+1) = z * gamma(z)
+           then: gamma(z) = gamma(z+1) / z
+
+           e.g.
+           gamma(3.89) = gamma(2001.89) / ( 3.89 * 4.89 * 5.89 * ... * 1999.89 * 2000.89 )
+    */
+    template<class ValueType>
+    ValueType GammaPlusLow(ValueType n, CGamma<ValueType> & cgamma, ErrorCode & err, const volatile StopCalculating * stop)
+    {
+    ValueType one, denominator, temp, boundary;
+
+        if( n.IsInteger() )
+            return GammaPlusLowInteger(n, cgamma);
+
+        one.SetOne();
+        denominator = n;
+        boundary    = TTMATH_GAMMA_BOUNDARY;
+
+        while( n < boundary )
+        {
+            n.Add(one);
+            denominator.Mul(n);
+        }
+
+        n.Add(one);
+
+        // now n is sufficient big
+        temp = GammaPlusHigh(n, cgamma, err, stop);
+        temp.Div(denominator);
+
+    return temp;
+    }
+
+
+    /*!
+        an auxiliary function used to calculate the Gamma() function
+    */
+    template<class ValueType>
+    ValueType GammaPlus(const ValueType & n, CGamma<ValueType> & cgamma, ErrorCode & err, const volatile StopCalculating * stop)
+    {
+        if( n > TTMATH_GAMMA_BOUNDARY )
+            return GammaPlusHigh(n, cgamma, err, stop);
+
+    return GammaPlusLow(n, cgamma, err, stop);
+    }
+
+
+    /*!
+        an auxiliary function used to calculate the Gamma() function
+
+        this function is used when n is negative
+        we use the reflection formula:
+           gamma(1-z) * gamma(z) = pi / sin(pi*z)
+           then: gamma(z) = pi / (sin(pi*z) * gamma(1-z))
+
+    */
+    template<class ValueType>
+    ValueType GammaMinus(const ValueType & n, CGamma<ValueType> & cgamma, ErrorCode & err, const volatile StopCalculating * stop)
+    {
+    ValueType pi, denominator, temp, temp2;
+
+        if( n.IsInteger() )
+        {
+            // gamma function is not defined when n is negative and integer
+            err = err_improper_argument;
+            return temp; // NaN
+        }
+
+        pi.SetPi();
+
+        temp = pi;
+        temp.Mul(n);
+        temp2 = Sin(temp);
+        // temp2 = sin(pi * n)
+
+        temp.SetOne();
+        temp.Sub(n);
+        temp = GammaPlus(temp, cgamma, err, stop);
+        // temp = gamma(1 - n)
+
+        temp.Mul(temp2);
+        pi.Div(temp);
+
+    return pi;
+    }
+
+    } // namespace auxiliaryfunctions
+
+
+
+    /*!
+        this function calculates the Gamma function
+
+        it's multithread safe, you should create a CGamma<> object and use it whenever you call the Gamma()
+        e.g.
+            typedef Big<1,2> MyBig;
+            MyBig x=234, y=345.53;
+            CGamma<MyBig> cgamma;
+            std::cout << Gamma(x, cgamma) << std::endl;
+            std::cout << Gamma(y, cgamma) << std::endl;
+        in the CGamma<> object the function stores some coefficients (factorials, Bernoulli numbers),
+        and they will be reused in next calls to the function
+
+        each thread should have its own CGamma<> object, and you can use these objects with Factorial() function too
+    */
+    template<class ValueType>
+    ValueType Gamma(const ValueType & n, CGamma<ValueType> & cgamma, ErrorCode * err = 0,
+                    const volatile StopCalculating * stop = 0)
+    {
+    using namespace auxiliaryfunctions;
+
+    ValueType result;
+    ErrorCode err_tmp;
+
+        if( n.IsNan() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+        return n;
+        }
+
+        if( cgamma.history.Get(n, result, err_tmp) )
+        {
+            if( err )
+                *err = err_tmp;
+
+            return result;
+        }
+
+        err_tmp = err_ok;
+
+        if( n.IsSign() )
+        {
+            result = GammaMinus(n, cgamma, err_tmp, stop);
+        }
+        else
+        if( n.IsZero() )
+        {
+            err_tmp = err_improper_argument;
+            result.SetNan();
+        }
+        else
+        {
+            result = GammaPlus(n, cgamma, err_tmp, stop);
+        }
+
+        if( result.IsNan() && err_tmp==err_ok )
+            err_tmp = err_overflow;
+
+        if( err )
+            *err = err_tmp;
+
+        if( stop && !stop->WasStopSignal() )
+            cgamma.history.Add(n, result, err_tmp);
+
+    return result;
+    }
+
+
+    /*!
+        this function calculates the Gamma function
+
+        note: this function should be used only in a single-thread environment
+    */
+    template<class ValueType>
+    ValueType Gamma(const ValueType & n, ErrorCode * err = 0)
+    {
+    // warning: this static object is not thread safe
+    static CGamma<ValueType> cgamma;
+
+    return Gamma(n, cgamma, err);
+    }
+
+
+
+    namespace auxiliaryfunctions
+    {
+
+    /*!
+        an auxiliary function for calculating the factorial function
+
+        we use the formula:
+           x! = gamma(x+1)
+    */
+    template<class ValueType>
+    ValueType Factorial2(ValueType x,
+                         CGamma<ValueType> * cgamma = 0,
+                         ErrorCode * err = 0,
+                         const volatile StopCalculating * stop = 0)
+    {
+    ValueType result, one;
+
+        if( x.IsNan() || x.IsSign() || !x.IsInteger() )
+        {
+            if( err )
+                *err = err_improper_argument;
+
+            x.SetNan();
+
+        return x;
+        }
+
+        one.SetOne();
+        x.Add(one);
+
+        if( cgamma )
+            return Gamma(x, *cgamma, err, stop);
+
+    return Gamma(x, err);
+    }
+    
+    } // namespace auxiliaryfunctions
+
+
+
+    /*!
+        the factorial from given 'x'
+        e.g.
+        Factorial(4) = 4! = 1*2*3*4
+
+        it's multithread safe, you should create a CGamma<> object and use it whenever you call the Factorial()
+        e.g.
+            typedef Big<1,2> MyBig;
+            MyBig x=234, y=54345;
+            CGamma<MyBig> cgamma;
+            std::cout << Factorial(x, cgamma) << std::endl;
+            std::cout << Factorial(y, cgamma) << std::endl;
+        in the CGamma<> object the function stores some coefficients (factorials, Bernoulli numbers),
+        and they will be reused in next calls to the function
+
+        each thread should have its own CGamma<> object, and you can use these objects with Gamma() function too
+    */
+    template<class ValueType>
+    ValueType Factorial(const ValueType & x, CGamma<ValueType> & cgamma, ErrorCode * err = 0,
+                        const volatile StopCalculating * stop = 0)
+    {
+        return auxiliaryfunctions::Factorial2(x, &cgamma, err, stop);
+    }
+
+
+    /*!
+        the factorial from given 'x'
+        e.g.
+        Factorial(4) = 4! = 1*2*3*4
+
+        note: this function should be used only in a single-thread environment
+    */
+    template<class ValueType>
+    ValueType Factorial(const ValueType & x, ErrorCode * err = 0)
+    {
+        return auxiliaryfunctions::Factorial2(x, (CGamma<ValueType>*)0, err, 0);
+    }
+
+
+    /*!
+        this method prepares some coefficients: factorials and Bernoulli numbers
+        stored in 'fact' and 'bern' objects
+
+        we're defining the method here because we're using Gamma() function which
+        is not available in ttmathobjects.h
+
+        read the doc info in ttmathobjects.h file where CGamma<> struct is declared
+    */
+    template<class ValueType>
+    void CGamma<ValueType>::InitAll()
+    {
+        ValueType x = TTMATH_GAMMA_BOUNDARY + 1;
+        
+        // history.Remove(x) removes only one object
+        // we must be sure that there are not others objects with the key 'x'
+        while( history.Remove(x) )
+        {
+        }
+
+        // the simplest way to initialize is to call the Gamma function with (TTMATH_GAMMA_BOUNDARY + 1)
+        // when x is larger then fewer coefficients we need
+        Gamma(x, *this);
+    }
+
+
+
+} // namespace
+
+
+/*!
+    this is for convenience for the user
+    he can only use '#include <ttmath/ttmath.h>'
+*/
+#include "ttmathparser.h"
+
+// Dec is not finished yet
+//#include "ttmathdec.h"
+
+
+
+#ifdef _MSC_VER
+//warning C4127: conditional expression is constant
+#pragma warning( default: 4127 )
+//warning C4702: unreachable code
+#pragma warning( default: 4702 )
+//warning C4800: forcing value to bool 'true' or 'false' (performance warning)
+#pragma warning( default: 4800 )
+#endif
+
+#endif
+
diff -r 000000000000 -r 04a9f72bbca7 ttmathbig.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ttmathbig.h	Tue Jul 30 18:43:48 2013 +0000
@@ -0,0 +1,6046 @@
+/*
+ * This file is a part of TTMath Bignum Library
+ * and is distributed under the (new) BSD licence.
+ * Author: Tomasz Sowa <t.sowa@ttmath.org>
+ */
+
+/* 
+ * Copyright (c) 2006-2012, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef headerfilettmathbig
+#define headerfilettmathbig
+
+/*!
+    \file ttmathbig.h
+    \brief A Class for representing floating point numbers
+*/
+
+#include "ttmathint.h"
+#include "ttmaththreads.h"
+
+#include <iostream>
+
+#ifdef TTMATH_MULTITHREADS
+#include <signal.h>
+#endif
+
+namespace ttmath
+{
+
+
+/*!
+    \brief Big implements the floating point numbers
+*/
+template <uint exp, uint man>
+class Big
+{
+
+/*
+    value = mantissa * 2^exponent    
+
+    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()
+*/
+
+
+public:
+
+Int<exp>  exponent;
+UInt<man> mantissa;
+unsigned char info;
+
+
+/*!
+    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
+*/
+#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)
+*/
+#define TTMATH_BIG_ZERO  32
+
+
+    /*!
+        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;
+        }
+
+    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();
+    }
+
+
+
+    /*!
+        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;
+
+        uint comp = mantissa.CompensationToLeft();
+
+    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);
+        }
+
+    return false;
+    }
+
+
+public:
+
+    /*!
+        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()
+    {
+        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));
+    }
+
+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(); // !! 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);
+    }
+
+
+
+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;
+    }
+
+
+
+
+
+    /*!
+    *
+    *    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;
+
+        one.SetOne();
+
+    return Sub(one);
+    }
+
+
+private:
+
+
+    /*!
+        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);
+
+            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 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();
+        }
+
+        if( ss2<0 )
+            ss2 = -ss2;
+
+
+    return MulUInt( uint(ss2) );
+    }
+
+
+private:
+
+
+    /*!
+        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;
+
+    return true;
+    }
+
+
+private:
+
+    /*!
+        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);
+    }
+    
+
+public:
+
+
+    /*!
+        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);
+        }
+    }
+
+
+private:
+
+    /*!
+        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 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()
+
+        c += Standardizing();
+
+    return CheckCarry(c);
+    }
+
+
+public:
+
+    /*!
+        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)
+    {
+        if( this == &ss2 )
+        {
+            Big<exp, man> copy_ss2(ss2);
+            return DivRef(copy_ss2, round);
+        }
+        else
+        {
+            return DivRef(ss2, round);
+        }
+    }
+
+
+private:
+
+    /*!
+        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;
+        }
+
+    return CheckCarry(c);
+    }
+
+
+public:
+
+    /*!
+        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)
+    {
+        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;
+        }
+
+    return CheckCarry(c);
+    }
+
+
+private:
+
+#ifdef TTMATH_CONSTANTSGENERATOR
+public:
+#endif
+
+    /*!
+        Exponent this = exp(x) = e^x where x is in (-1,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;
+    }
+
+public:
+
+
+    /*!
+        Exponent this = exp(x) = e^x
+
+        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);
+    }
+
+
+
+
+private:
+
+#ifdef TTMATH_CONSTANTSGENERATOR
+public:
+#endif
+
+    /*!
+        Natural logarithm this = ln(x) where x in range <1,2)
+
+        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;
+    }
+
+
+
+
+public:
+
+
+    /*!
+        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);
+    }
+
+
+private:
+
+    /*!
+        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));
+
+    return 0;
+    }
+
+
+public:
+
+    /*!
+        this method converts 'this' into uint
+    */
+    uint ToUInt() const
+    {
+    uint result;
+
+        ToUInt(result);
+
+    return result;
+    }
+
+
+    /*!
+        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;
+
+    return 0;
+    }
+
+
+    /*!
+        this method converts 'this' into sint
+    */
+    sint ToInt() const
+    {
+    sint result;
+
+        ToInt(result);
+
+    return result;
+    }
+
+
+    /*!
+        this method converts 'this' into 'result'
+
+        if the value is too big this method returns a carry (1)
+    */
+    uint ToInt(uint & result) const
+    {
+        return ToUInt(result);
+    }
+
+
+    /*!
+        this method converts 'this' into 'result'
+
+        if the value is too big this method returns a carry (1)
+    */
+    uint ToInt(sint & result) const
+    {
+    uint result_uint;
+
+        uint c = ToUIntOrInt(result_uint);
+        result = sint(result_uint);
+
+        if( c )
+            return 1;
+
+        uint mask = 0;
+
+        if( IsSign() )
+        {
+            mask = TTMATH_UINT_MAX_VALUE;
+            result = -result;
+        }
+
+    return ((result & TTMATH_UINT_HIGHEST_BIT) == (mask & TTMATH_UINT_HIGHEST_BIT)) ? 0 : 1;
+    }
+
+
+private:
+
+    /*!
+        an auxiliary method for converting 'this' into 'result'
+
+        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];
+            }
+
+            result.Rcl( how_many_bits % TTMATH_BITS_PER_UINT, 0 );
+        }
+
+    return 0;
+    }
+
+
+public:
+
+    /*!
+        this method converts 'this' into 'result'
+
+        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( c )
+            return 1;
+
+        if( IsSign() )
+            return 1;
+
+    return 0;
+    }
+
+
+    /*!
+        this method converts 'this' into 'result'
+
+        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);
+    }
+
+
+    /*!
+        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;
+
+        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;
+    }
+
+
+    /*!
+        a method for converting 'uint' to this class
+    */
+    uint FromUInt(uint value)
+    {
+        if( value == 0 )
+        {
+            SetZero();
+            return 0;
+        }
+
+        info = 0;
+
+        for(uint i=0 ; i<man-1 ; ++i)
+            mantissa.table[i] = 0;
+
+        mantissa.table[man-1] = value;
+        exponent = -sint(man-1) * sint(TTMATH_BITS_PER_UINT);
+
+        // there shouldn't be a carry because 'value' has the 'uint' type 
+        Standardizing();
+
+    return 0;
+    }
+
+
+    /*!
+        a method for converting 'uint' to this class
+    */
+    uint FromInt(uint value)
+    {
+        return FromUInt(value);
+    }
+
+
+    /*!
+        a method for converting 'sint' to this class
+    */
+    uint FromInt(sint value)
+    {
+    bool is_sign = false;
+
+        if( value < 0 )
+        {
+            value   = -value;
+            is_sign = true;
+        }
+
+        FromUInt(uint(value));
+
+        if( is_sign )
+            SetSign();
+
+    return 0;
+    }
+
+
+
+    /*!
+        this method converts from standard double into this class
+
+        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':
+
+        S EEEEEEEEEEE FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+        0 1        11 12                                                63
+
+        The value V represented by the word may be determined as follows:
+
+        * 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 
+    */
+
+#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[0]);
+            }
+            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
+    }
+
+
+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();
+    }
+
+
+#else
+
+public:
+
+    // 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; // never be a carry
+    }
+
+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();
+    }
+
+#endif
+
+
+public:
+
+
+    /*!
+        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;
+
+        ToDouble(result);
+
+    return result;
+    }
+
+
+private:
+
+
+    /*!
+        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
+        }
+
+    return false;
+    }
+
+
+public:
+
+    /*!
+        this method converts from this class into the 'float'
+
+        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;
+    }
+
+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)
+
+        temp.u[1] |= m.table[1];
+        temp.u[0] |= m.table[0];
+
+    return temp.d;
+    }
+
+#else
+
+    // 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;
+    }
+
+#endif
+
+
+public:
+
+
+    /*!
+        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);
+    }
+
+
+#ifdef TTMATH_PLATFORM32
+
+    /*!
+        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);
+
+    return *this;
+    }
+
+#endif
+
+
+
+#ifdef TTMATH_PLATFORM64
+
+
+    /*!
+        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);
+    }
+
+#endif
+
+
+private:
+
+    /*!
+        an auxiliary method for converting from UInt and Int
+
+        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);
+    }
+
+#endif
+
+
+
+private:
+
+
+    /*!
+        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'
+
+        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);
+        }
+
+        c += Div( temp );
+
+    return (c==0)? 0 : 1;
+    }
+
+
+#ifndef TTMATH_MULTITHREADS
+
+    /*!
+        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];
+
+    return (c==0)? 0 : 1;
+    }
+
+#else
+
+    /*!
+        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
+        }
+
+        result = plog_history[index];
+
+    return (c==0)? 0 : 1;
+    }
+
+#endif
+
+    /*!
+        an auxiliary method for converting into the string (private)
+
+        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);
+    }
+
+
+
+public:
+
+    /*!
+        a method for converting a string into its value
+
+        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
+
+        '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);
+    }
+
+#endif
+
+
+private:
+
+
+    /*!
+        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();
+
+            if( after_source )
+                *after_source = source;
+
+            if( value_read )
+                *value_read = value_read_temp;
+
+            return 1;
+        }
+
+        SetZero();
+        FromString_TestSign( source, is_sign );
+
+        uint c = FromString_ReadPartBeforeComma( source, conv, value_read_temp );
+
+        if( FromString_TestCommaOperator(source, conv) )
+            c += FromString_ReadPartAfterComma( source, conv, value_read_temp );
+
+        if( value_read_temp && conv.base == 10 )
+            c += FromString_ReadScientificIfExists( source );
+
+        if( is_sign && !IsZero() )
+            ChangeSign();
+
+        if( after_source )
+            *after_source = source;
+
+        if( value_read )
+            *value_read = value_read_temp;
+
+    return CheckCarry(c);
+    }
+
+
+    /*!
+        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);
+
+        is_sign = false;
+
+        if( *source == '-' )
+        {
+            is_sign = true;
+            ++source;
+        }
+        else
+        if( *source == '+' )
+        {
+            ++source;
+        }
+    }
+
+
+    /*!
+        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;
+
+        return true;
+        }
+
+    return 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 );
+
+        for( ; true ; ++source )
+        {
+            if( conv.group!=0 && *source==static_cast<char>(conv.group) )
+                continue;
+
+            character = Misc::CharToDigit(*source, conv.base);
+
+            if( character == -1 )
+                break;
+
+            value_read = true;
+            temp = character;
+
+            if( Mul(base_) )
+                return 1;
+
+            if( Add(temp) )
+                return 1;
+        }
+
+    return 0;
+    }
+
+
+    /*!
+        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, power = 0;
+    UInt<1> power_;
+    Big<exp, man> sum, base_(conv.base);
+
+        // we don't remove any white characters here
+        sum.SetZero();
+
+        for( ; sum.exponent.IsSign() || sum.exponent.IsZero() ; ++source )
+        {
+            if( conv.group!=0 && *source==static_cast<char>(conv.group) )
+                continue;
+            
+            character = Misc::CharToDigit(*source, conv.base);
+
+            if( character == -1 )
+                break;
+
+            value_read = true;
+
+            // there actually shouldn't be a carry here
+            c += sum.Mul(base_);
+            c += sum.Add(character);
+            power += 1;
+
+            if( power == 0 )
+                c += 1;
+        }
+
+        // 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 );
+
+        power_ = power;
+        c += base_.Pow(power_);
+        c += sum.Div(base_);
+        c += Add(sum);
+
+    return (c==0)? 0 : 1;
+    }
+
+
+    /*!
+        this method checks whether there is a scientific part: [e|E][-|+]value
+
+        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;
+
+        bool scientific_read = false;
+        const char_type * before_scientific = source;
+
+        if( FromString_TestScientific(source) )
+            c += FromString_ReadPartScientific( source, scientific_read );
+
+        if( !scientific_read )
+            source = before_scientific;
+
+    return (c==0)? 0 : 1;
+    }
+
+
+
+    /*!
+        we're testing whether is there the character 'e'
+
+        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;
+
+        return true;
+        }
+
+    return false;
+    }
+
+
+    /*!
+        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 );
+
+        if( scientific_read )
+        {
+            if( was_sign )
+                new_exponent.ChangeSign();
+
+            temp = 10;
+            c += temp.Pow( new_exponent );
+            c += Mul(temp);
+        }
+
+    return (c==0)? 0 : 1;
+    }
+
+
+    /*!
+        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);
+
+        new_exponent.SetZero();
+        base = 10;
+
+        for( ; (character=Misc::CharToDigit(*source, 10)) != -1 ; ++source )
+        {
+            scientific_read = true;
+
+            temp = character;
+
+            if( new_exponent.Mul(base) )
+                return 1;
+
+            if( new_exponent.Add(temp) )
+                return 1;
+        }
+
+    return 0;
+    }
+
+
+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() );
+
+    return *this;
+    }
+
+
+#endif
+
+
+
+    /*!
+    *
+    *    methods for comparing
+    *
+    */
+
+
+    /*!
+        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;
+
+    return exponent < ss2.exponent;
+    }
+
+
+    /*!
+        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 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;
+        }
+
+        if( ss2.IsZero() )
+            // this!=0 and ss2==0
+            return true;
+
+        // 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 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;
+        }
+
+        if( ss2.IsZero() )
+            // this!=0 and ss2==0
+            return false;
+
+        if( exponent==ss2.exponent && mantissa==ss2.mantissa )
+            return true;
+
+    return false;
+    }
+
+
+    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;
+
+        // both signs are the same
+
+        if( IsSign() )
+            return ss2.SmallerWithoutSignThan( *this );
+
+    return SmallerWithoutSignThan( ss2 );
+    }
+
+
+    bool operator==(const Big<exp,man> & ss2) const
+    {
+        if( IsSign() != ss2.IsSign() )
+            return false;
+
+    return EqualWithoutSign( ss2 );
+    }
+
+
+    bool operator>(const Big<exp,man> & ss2) const
+    {
+        if( IsSign() && !ss2.IsSign() )
+            // this<0 and ss2>=0
+            return false;
+
+        if( !IsSign() && ss2.IsSign() )
+            // this>=0 and ss2<0
+            return true;
+
+        // both signs are the same
+
+        if( IsSign() )
+            return ss2.GreaterWithoutSignThan( *this );
+
+    return GreaterWithoutSignThan( ss2 );
+    }
+
+
+    bool operator>=(const Big<exp,man> & ss2) const
+    {
+        return !operator<( ss2 );
+    }
+
+
+    bool operator<=(const Big<exp,man> & ss2) const
+    {
+        return !operator>( ss2 );
+    }
+
+
+    bool operator!=(const Big<exp,man> & ss2) const
+    {
+        return !operator==(ss2);
+    }
+
+
+
+
+
+    /*!
+    *
+    *    standard mathematical operators 
+    *
+    */
+
+
+    /*!
+        an operator for changing the sign
+
+        this method is not changing 'this' but the changed value is returned
+    */
+    Big<exp,man> operator-() const
+    {
+        Big<exp,man> temp(*this);
+
+        temp.ChangeSign();
+
+    return temp;
+    }
+
+
+    Big<exp,man> operator-(const Big<exp,man> & ss2) const
+    {
+    Big<exp,man> temp(*this);
+
+        temp.Sub(ss2);
+
+    return temp;
+    }
+
+    Big<exp,man> & operator-=(const Big<exp,man> & ss2)
+    {
+        Sub(ss2);
+
+    return *this;
+    }
+
+
+    Big<exp,man> operator+(const Big<exp,man> & ss2) const
+    {
+    Big<exp,man> temp(*this);
+
+        temp.Add(ss2);
+
+    return temp;
+    }
+
+
+    Big<exp,man> & operator+=(const Big<exp,man> & ss2)
+    {
+        Add(ss2);
+
+    return *this;
+    }
+
+
+    Big<exp,man> operator*(const Big<exp,man> & ss2) const
+    {
+    Big<exp,man> temp(*this);
+
+        temp.Mul(ss2);
+
+    return temp;
+    }
+
+
+    Big<exp,man> & operator*=(const Big<exp,man> & ss2)
+    {
+        Mul(ss2);
+
+    return *this;
+    }
+
+
+    Big<exp,man> operator/(const Big<exp,man> & ss2) const
+    {
+    Big<exp,man> temp(*this);
+
+        temp.Div(ss2);
+
+    return temp;
+    }
+
+
+    Big<exp,man> & operator/=(const Big<exp,man> & ss2)
+    {
+        Div(ss2);
+
+    return *this;
+    }
+
+
+    /*!
+        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();
+
+    return temp;
+    }
+
+
+    Big<exp,man> & operator--()
+    {
+        SubOne();
+
+    return *this;
+    }
+
+
+    Big<exp,man> operator--(int)
+    {
+    Big<exp,man> temp( *this );
+
+        SubOne();
+
+    return temp;
+    }
+
+
+
+    /*!
+    *
+    *    bitwise operators
+    *   (we do not define bitwise not)
+    */
+
+
+    Big<exp,man> operator&(const Big<exp,man> & p2) const
+    {
+        Big<exp,man> temp( *this );
+
+        temp.BitAnd(p2);
+
+    return temp;
+    }
+
+
+    Big<exp,man> & operator&=(const Big<exp,man> & p2)
+    {
+        BitAnd(p2);
+
+    return *this;
+    }
+
+
+    Big<exp,man> operator|(const Big<exp,man> & p2) const
+    {
+        Big<exp,man> temp( *this );
+
+        temp.BitOr(p2);
+
+    return temp;
+    }
+
+
+    Big<exp,man> & operator|=(const Big<exp,man> & p2)
+    {
+        BitOr(p2);
+
+    return *this;
+    }
+
+
+    Big<exp,man> operator^(const Big<exp,man> & p2) const
+    {
+        Big<exp,man> temp( *this );
+
+        temp.BitXor(p2);
+
+    return temp;
+    }
+
+
+    Big<exp,man> & operator^=(const Big<exp,man> & p2)
+    {
+        BitXor(p2);
+
+    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;
+        }
+
+        // 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;
+
+        if( !exponent.IsSign() )
+        {
+            // exponent >= 0 -- the value doesn't have any fractions
+            // we return zero
+            SetZero();
+            return;
+        }
+
+        if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) )
+        {
+            // the value is from (-1,1)
+            // we don't make anything with the value
+            return;
+        }
+
+        // e will be from (-man*TTMATH_BITS_PER_UINT, 0)
+        sint e = exponent.ToInt();
+
+        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);
+
+        // 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;
+
+        if( !exponent.IsSign() )
+            // exponent >=0 -- the value don't have any fractions
+            return true;
+
+        if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) )
+            // the value is from (-1,1)
+            return false;
+
+        // exponent is in range (-man*TTMATH_BITS_PER_UINT, 0)
+        sint e = exponent.ToInt();
+        e = -e; // e means how many bits we must check
+
+        uint len  = e / TTMATH_BITS_PER_UINT;
+        uint rest = e % TTMATH_BITS_PER_UINT;
+        uint i    = 0;
+
+        for( ; i<len ; ++i )
+            if( mantissa.table[i] != 0 )
+                return false;
+
+        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
+
+            -2.3 = -2
+            -2.8 = 3
+    */
+    uint Round()
+    {
+    Big<exp,man> half;
+    uint c;
+
+        if( IsNan() )
+            return 1;
+
+        if( IsZero() )
+            return 0;
+
+        half.Set05();
+
+        if( IsSign() )
+        {
+            // 'this' is < 0
+            c = Sub( half );
+        }
+        else
+        {
+            // 'this' is > 0
+            c = Add( half );
+        }
+
+        SkipFraction();
+
+    return CheckCarry(c);
+    }
+
+    
+
+    /*!
+    *
+    *    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;
+
+        l.ToString(ss);
+        s << ss;
+
+    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);
+    }
+
+
+#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();
+
+        l.FromString( ss );
+
+    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);
+    }
+
+
+#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
+
+};
+
+
+} // namespace
+
+#endif
+
diff -r 000000000000 -r 04a9f72bbca7 ttmathdec.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ttmathdec.h	Tue Jul 30 18:43:48 2013 +0000
@@ -0,0 +1,420 @@
+/*
+ * This file is a part of TTMath Bignum Library
+ * and is distributed under the (new) BSD licence.
+ * Author: Tomasz Sowa <t.sowa@ttmath.org>
+ */
+
+/* 
+ * Copyright (c) 2012, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef headerfilettmathdec
+#define headerfilettmathdec
+
+#include "ttmathtypes.h"
+#include "ttmaththreads.h"
+#include "ttmathuint.h"
+
+
+
+namespace ttmath
+{
+
+template<uint value_size, uint dec_digits>
+class Dec
+{
+public:
+
+    UInt<value_size> value;
+    unsigned char info;
+
+
+    /*!
+        Sign
+        the mask of a bit from 'info' which means that there is a sign
+        (when the bit is set)
+    */
+    #define TTMATH_DEC_SIGN 128
+
+
+    /*!
+        Not a number
+        if this bit is set that there is not a valid number
+    */
+    #define TTMATH_DEC_NAN  64
+
+
+
+
+    Dec()
+    {
+        info = TTMATH_DEC_NAN;
+    }
+
+
+    Dec(const char * s)
+    {
+        info = TTMATH_DEC_NAN;
+        FromString(s);
+    }
+
+
+    Dec<value_size, dec_digits> & operator=(const char * s)
+    {
+        FromString(s);
+
+    return *this;
+    }
+
+
+    uint FromString(const char * s, const char ** after_source = 0, bool * value_read = 0)
+    {
+        return FromStringBase(s, after_source, value_read);
+    }
+
+
+    void ToString(std::string & result) const
+    {
+        ToStringBase(result);
+    }
+
+
+    /*!
+        this method clears a specific bit in the 'info' variable
+
+        bit is one of: 
+    */
+    void ClearInfoBit(unsigned char bit)
+    {
+        info = info & (~bit);
+    }
+
+
+    /*!
+        this method sets a specific bit in the 'info' variable
+
+        bit is one of: 
+
+    */
+    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: 
+    */
+    bool IsInfoBit(unsigned char bit) const
+    {
+        return (info & bit) != 0;
+    }
+
+
+    bool IsNan() const 
+    {
+        return IsInfoBit(TTMATH_DEC_NAN);
+    }
+
+
+    bool IsSign() const 
+    {
+        return IsInfoBit(TTMATH_DEC_SIGN);
+    }
+
+
+    /*!
+        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_DEC_SIGN);
+    }
+
+
+    void SetNaN()
+    {
+        SetInfoBit(TTMATH_DEC_NAN);
+    }
+
+
+    void Abs()
+    {
+        ClearInfoBit(TTMATH_DEC_SIGN);
+    }
+
+
+
+    uint Add(const Dec<value_size, dec_digits> & arg)
+    {
+    uint c = 0;
+
+        if( IsSign() == arg.IsSign() )
+        {
+            c += value.Add(arg.value);        
+        }
+        else
+        {
+            bool is_sign;
+
+            if( value > arg.value )
+            {
+                is_sign = IsSign();
+                value.Sub(arg.value);
+            }
+            else
+            {
+                is_sign = arg.IsSign();
+                UInt<value_size> temp(this->value);
+                value = arg.value;
+                value.Sub(temp);
+            }
+
+            is_sign ? SetSign() : Abs();
+        }
+
+        if( c )
+            SetNaN();
+
+    return (c==0)? 0 : 1;
+    }
+
+/*
+    uint Sub(const Dec<value_size, dec_digits> & arg)
+    {
+    }
+*/
+
+private:
+
+
+
+
+
+
+#ifndef TTMATH_MULTITHREADS
+
+    /*!
+    */
+    void SetMultipler(UInt<value_size> & result)
+    {
+        // this guardian is initialized before the program runs (static POD type)
+        static int guardian = 0;
+        static UInt<value_size> multipler;
+    
+        if( guardian == 0 )
+        {
+            multipler = 10;
+            multipler.Pow(dec_digits);
+            guardian = 1;
+        }
+
+        result = multipler;
+    }
+
+#else
+
+    /*!
+    */
+    void SetMultipler(UInt<value_size> & result)
+    {
+        // this guardian is initialized before the program runs (static POD type)
+        volatile static sig_atomic_t guardian = 0;
+        static UInt<value_size> * pmultipler;
+    
+        // double-checked locking
+        if( guardian == 0 )
+        {
+            ThreadLock thread_lock;
+
+            // locking
+            if( thread_lock.Lock() )
+            {
+                static UInt<value_size> multipler;
+
+                if( guardian == 0 )
+                {
+                    pmultipler = &multipler;
+                    multipler = 10;
+                    multipler.Pow(dec_digits);
+                    guardian = 1;
+                }
+            }
+            else
+            {
+                // there was a problem with locking, we store the result directly in 'result' object
+                result = 10;
+                result.Pow(dec_digits);
+                
+            return;
+            }
+
+            // automatically unlocking
+        }
+
+        result = *pmultipler;
+    }
+
+#endif
+
+
+
+    /*!
+        an auxiliary method for converting from a string
+    */
+    template<class char_type>
+    uint FromStringBase(const char_type * s, const char_type ** after_source = 0, bool * value_read = 0)
+    {
+        UInt<value_size> multipler;
+        const char_type * after;
+        uint c = 0;
+        info = 0;
+
+        Misc::SkipWhiteCharacters(s);
+
+        if( *s == '-' )
+        {
+            s += 1;
+            SetSign();
+        }
+        else
+        if( *s == '+' )
+        {
+            s += 1;
+        }
+
+        c += value.FromString(s, 10, &after, value_read);
+
+        if( after_source )
+            *after_source = after;
+
+        SetMultipler(multipler);
+        c += value.Mul(multipler);
+
+        if( *after == '.' )
+            c += FromStringBaseAfterComma(after+1, after_source);
+
+        if( c )
+            SetInfoBit(TTMATH_DEC_NAN);
+
+    return (c==0)? 0 : 1;
+    }
+
+
+    template<class char_type>
+    uint FromStringBaseAfterComma(const char_type * s, const char_type ** after_source = 0, bool * value_read = 0)
+    {
+        UInt<value_size> temp;
+        UInt<value_size> multipler;
+        sint z;
+        uint c = 0;
+        size_t i = dec_digits;
+
+        SetMultipler(multipler);
+
+        for( ; i>0 && (z=Misc::CharToDigit(*s, 10)) != -1 ; --i, ++s )
+        {
+            multipler.DivInt(10);
+            temp.SetZero();
+
+            if( value_read )
+                *value_read = true;
+
+            if( c == 0 )
+            {
+                temp.table[0] = z;
+                c += temp.Mul(multipler);
+                c += value.Add(temp);
+            }
+        }
+
+        if( i == 0 && (z=Misc::CharToDigit(*s, 10)) != -1 && z >= 5 )
+            c += value.AddOne();
+
+        if( after_source )
+        {
+            while( (z=Misc::CharToDigit(*s, 10)) != -1 )
+                s += 1;
+
+            *after_source = s;
+        }
+
+    return c;
+    }
+
+
+
+    template<class string_type>
+    void ToStringBase(string_type & result) const
+    {
+        if( IsNan() )
+        {
+            result = "NaN";
+            return;
+        }
+
+        value.ToStringBase(result, 10, IsSign());
+
+        if( dec_digits > 0 )
+        {
+            size_t size = result.size();
+
+            if( IsSign() && size > 0 )
+                size -= 1;
+
+            if( dec_digits >= size )
+            {
+                size_t zeroes = dec_digits - size + 1;
+                size_t start  = IsSign() ? 1 : 0;
+                result.insert(start, zeroes, '0');
+            }
+
+            result.insert(result.end() - dec_digits, '.');
+        }
+    }
+
+
+
+};
+
+
+} // namespace
+
+#endif
+
diff -r 000000000000 -r 04a9f72bbca7 ttmathint.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ttmathint.h	Tue Jul 30 18:43:48 2013 +0000
@@ -0,0 +1,1923 @@
+/*
+ * This file is a part of TTMath Bignum Library
+ * and is distributed under the (new) BSD licence.
+ * Author: Tomasz Sowa <t.sowa@ttmath.org>
+ */
+
+/* 
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+#ifndef headerfilettmathint
+#define headerfilettmathint
+
+/*!
+    \file ttmathint.h
+    \brief template class Int<uint>
+*/
+
+#include "ttmathuint.h"
+
+namespace ttmath
+{
+
+
+/*!
+    \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....
+*/
+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
+
+        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
+    *
+    */
+
+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;
+    }
+
+
+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
+
+        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 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);        
+
+    return CorrectCarryAfterAdding(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
+
+        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);        
+
+    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 two values with a sign
+
+        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);
+    }
+
+
+private:
+
+
+    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 0;
+    }
+
+
+public:
+
+
+    /*!
+        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);
+    }
+
+
+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();
+
+    return (c==0)? 0 : 1;
+    }
+
+
+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;
+    }
+
+
+
+    /*!
+    *
+    *    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;
+    }
+
+
+    /*!
+        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);
+    }
+
+#endif
+
+
+
+
+#ifdef TTMATH_PLATFORM64
+
+    /*!
+        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);
+    }
+
+#endif
+
+
+
+    /*!
+        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() );
+    }
+
+#endif
+
+
+    /*!
+        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;
+        }
+
+    return 0;
+    }
+
+#endif
+
+
+
+#ifdef TTMATH_PLATFORM64
+
+    /*!
+        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;
+
+    return 0;
+    }
+
+#endif
+
+
+
+
+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>::ToStringBase(result, b, true);
+        }
+        else
+        {
+            UInt<value_size>::ToStringBase(result, b, false);
+        }
+    }
+
+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'
+    */
+    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;
+    }
+
+#endif
+
+
+
+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;
+    }
+
+
+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() );
+
+    return *this;
+    }
+
+#endif
+
+
+    /*!
+        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;
+    }
+
+
+
+    /*!
+    *
+    *    methods for comparing
+    *
+    *
+    */
+
+    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);
+    }
+
+    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]);
+
+        if( a1 != a2 )
+            return a1 < a2;
+
+
+        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 false;
+    }
+
+
+    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]);
+
+        if( a1 != a2 )
+            return a1 > a2;
+
+
+        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 false;
+    }
+
+
+    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]);
+
+        if( a1 != a2 )
+            return a1 < a2;
+
+
+        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;
+    }
+
+
+    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]);
+
+        if( a1 != a2 )
+            return a1 > a2;
+
+
+        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;
+    }
+
+
+
+    /*!
+    *
+    *    standard mathematical operators 
+    *
+    */
+
+
+    /*!
+        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();
+        
+    return temp;
+    }
+
+
+    Int<value_size> operator-(const Int<value_size> & p2) const
+    {
+    Int<value_size> temp(*this);
+
+        temp.Sub(p2);
+
+    return temp;
+    }
+
+
+    Int<value_size> & operator-=(const Int<value_size> & p2)
+    {
+        Sub(p2);
+
+    return *this;
+    }
+
+
+    Int<value_size> operator+(const Int<value_size> & p2) const
+    {
+    Int<value_size> temp(*this);
+
+        temp.Add(p2);
+
+    return temp;
+    }
+
+
+    Int<value_size> & operator+=(const Int<value_size> & p2)
+    {
+        Add(p2);
+
+    return *this;
+    }
+
+
+    Int<value_size> operator*(const Int<value_size> & p2) const
+    {
+    Int<value_size> temp(*this);
+
+        temp.Mul(p2);
+
+    return temp;
+    }
+
+
+    Int<value_size> & operator*=(const Int<value_size> & p2)
+    {
+        Mul(p2);
+
+    return *this;
+    }
+
+
+    Int<value_size> operator/(const Int<value_size> & p2) const
+    {
+    Int<value_size> temp(*this);
+
+        temp.Div(p2);
+
+    return temp;
+    }
+
+
+    Int<value_size> & operator/=(const Int<value_size> & p2)
+    {
+        Div(p2);
+
+    return *this;
+    }
+
+
+    Int<value_size> operator%(const Int<value_size> & p2) const
+    {
+    Int<value_size> temp(*this);
+    Int<value_size> remainder;
+    
+        temp.Div(p2, remainder);
+
+    return remainder;
+    }
+
+
+    Int<value_size> & operator%=(const Int<value_size> & p2)
+    {
+    Int<value_size> remainder;
+    
+        Div(p2, remainder);
+        operator=(remainder);
+
+    return *this;
+    }
+
+
+    /*!
+        Prefix operator e.g. ++variable
+    */
+    UInt<value_size> & operator++()
+    {
+        AddOne();
+
+    return *this;
+    }
+
+
+    /*!
+        Postfix operator e.g. variable++
+    */
+    UInt<value_size> operator++(int)
+    {
+    UInt<value_size> temp( *this );
+
+        AddOne();
+
+    return temp;
+    }
+
+
+    UInt<value_size> & operator--()
+    {
+        SubOne();
+
+    return *this;
+    }
+
+
+    UInt<value_size> operator--(int)
+    {
+    UInt<value_size> temp( *this );
+
+        SubOne();
+
+    return temp;
+    }
+
+
+
+    /*!
+    *
+    *    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;
+
+        l.ToString(ss);
+        s << ss;
+
+    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);
+    }
+
+
+#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();
+
+        l.FromString(ss);
+
+    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);
+    }
+
+
+#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
+
+
+};
+
+} // namespace
+
+#endif
+
diff -r 000000000000 -r 04a9f72bbca7 ttmathmisc.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ttmathmisc.h	Tue Jul 30 18:43:48 2013 +0000
@@ -0,0 +1,251 @@
+/*
+ * This file is a part of TTMath Bignum Library
+ * and is distributed under the (new) BSD licence.
+ * Author: Tomasz Sowa <t.sowa@ttmath.org>
+ */
+
+/* 
+ * Copyright (c) 2006-2010, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef headerfilettmathmisc
+#define headerfilettmathmisc
+
+
+/*!
+    \file ttmathmisc.h
+    \brief some helpful functions
+*/
+
+
+#include <string>
+
+
+namespace ttmath
+{
+
+/*!
+    some helpful functions
+*/
+class Misc
+{
+public:
+
+
+/*
+ *
+ *    AssignString(result, str)
+ *    result = str
+ *
+ */
+
+/*!
+    result = str
+*/
+static void AssignString(std::string & result, const char * str)
+{
+    result = str;
+}
+
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
+/*!
+    result = str
+*/
+static void AssignString(std::wstring & result, const char * str)
+{
+    result.clear();
+
+    for( ; *str ; ++str )
+        result += *str;
+}
+
+
+/*!
+    result = str
+*/
+static void AssignString(std::wstring & result, const std::string & str)
+{
+    return AssignString(result, str.c_str());
+}
+
+
+/*!
+    result = str
+*/
+static void AssignString(std::string & result, const wchar_t * str)
+{
+    result.clear();
+
+    for( ; *str ; ++str )
+        result += static_cast<char>(*str);
+}
+
+
+/*!
+    result = str
+*/
+static void AssignString(std::string & result, const std::wstring & str)
+{
+    return AssignString(result, str.c_str());
+}
+
+#endif
+
+
+/*
+ *
+ *    AddString(result, str)
+ *    result += str
+ *
+ */
+
+
+/*!
+    result += str
+*/
+static void AddString(std::string & result, const char * str)
+{
+    result += str;
+}
+
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
+/*!
+    result += str
+*/
+static void AddString(std::wstring & result, const char * str)
+{
+    for( ; *str ; ++str )
+        result += *str;
+}
+
+#endif
+
+
+/*
+    this method omits any white characters from the string
+    char_type is char or wchar_t
+*/
+template<class char_type>
+static void SkipWhiteCharacters(const char_type * & c)
+{
+    // 13 is at the end in a DOS text file (\r\n)
+    while( (*c==' ' ) || (*c=='\t') || (*c==13 ) || (*c=='\n') )
+        ++c;
+}
+
+
+
+
+/*!
+    this static method converts one character into its value
+
+    for example:
+        1 -> 1
+        8 -> 8
+        A -> 10
+        f -> 15
+
+    this method don't check whether c is correct or not
+*/
+static uint CharToDigit(uint c)
+{
+    if(c>='0' && c<='9')
+        return c-'0';
+
+    if(c>='a' && c<='z')
+        return c-'a'+10;
+
+return c-'A'+10;
+}
+
+
+/*!
+    this method changes a character 'c' into its value
+    (if there can't be a correct value it returns -1)
+
+    for example:
+    c=2, base=10 -> function returns 2
+    c=A, base=10 -> function returns -1
+    c=A, base=16 -> function returns 10
+*/
+static sint CharToDigit(uint c, uint base)
+{
+    if( c>='0' && c<='9' )
+        c=c-'0';
+    else
+    if( c>='a' && c<='z' )
+        c=c-'a'+10;
+    else
+    if( c>='A' && c<='Z' )
+        c=c-'A'+10;
+    else
+        return -1;
+
+
+    if( c >= base )
+        return -1;
+
+
+return sint(c);
+}
+
+
+
+/*!
+    this method converts a digit into a char
+    digit should be from <0,F>
+    (we don't have to get a base)
+    
+    for example:
+        1  -> 1
+        8  -> 8
+        10 -> A
+        15 -> F
+*/
+static uint DigitToChar(uint digit)
+{
+    if( digit < 10 )
+        return digit + '0';
+
+return digit - 10 + 'A';
+}
+
+
+}; // struct Misc
+
+}
+
+
+#endif
+
diff -r 000000000000 -r 04a9f72bbca7 ttmathobjects.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ttmathobjects.h	Tue Jul 30 18:43:48 2013 +0000
@@ -0,0 +1,810 @@
+/*
+ * This file is a part of TTMath Mathematical Library
+ * and is distributed under the (new) BSD licence.
+ * Author: Tomasz Sowa <t.sowa@ttmath.org>
+ */
+
+/* 
+ * Copyright (c) 2006-2010, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef headerfilettmathobject
+#define headerfilettmathobject
+
+/*!
+    \file ttmathobjects.h
+    \brief Mathematic functions.
+*/
+
+#include <string>
+#include <vector>
+#include <list>
+#include <map>
+
+#include "ttmathtypes.h"
+#include "ttmathmisc.h"
+
+
+namespace ttmath
+{
+
+/*!
+    objects of this class are used with the mathematical parser
+    they hold variables or functions defined by a user
+
+    each object has its own table in which we're keeping variables or functions
+*/
+class Objects
+{
+public:
+
+
+    /*!
+        one item (variable or function)
+        'items' will be on the table
+    */
+    struct Item
+    {
+        // name of a variable of a function
+        // internally we store variables and funcions as std::string (not std::wstring even when wide characters are used)
+        std::string value;
+
+        // number of parameters required by the function
+        // (if there's a variable this 'param' is ignored)
+        int param;
+
+        Item() {}
+        Item(const std::string & v, int p) : value(v), param(p) {}
+    };
+
+    // 'Table' is the type of our table
+    typedef std::map<std::string, Item> Table;
+    typedef    Table::iterator Iterator;
+    typedef    Table::const_iterator CIterator;
+
+
+
+    /*!
+        this method returns true if a character 'c' is a character
+        which can be in a name
+        
+        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(int c, bool can_be_digit)
+    {
+        if( (c>='a' && c<='z') || (c>='A' && c<='Z') )
+            return true;
+
+        if( can_be_digit && ((c>='0' && c<='9') || c=='_') )
+            return true;
+
+    return false;
+    }
+
+
+    /*!
+        this method returns true if the name can be as a name of an object
+    */
+    template<class string_type>
+    static bool IsNameCorrect(const string_type & name)
+    {
+        if( name.empty() )
+            return false;
+
+        if( !CorrectCharacter(name[0], false) )
+            return false;
+
+        typename string_type::const_iterator i = name.begin();
+
+        for(++i ; i!=name.end() ; ++i)
+            if( !CorrectCharacter(*i, true) )
+                return false;
+        
+    return true;
+    }
+
+
+    /*!
+        this method returns true if such an object is defined (name exists)
+    */
+    bool IsDefined(const std::string & name)
+    {
+        Iterator i = table.find(name);
+
+        if( i != table.end() )
+            // we have this object in our table
+            return true;
+
+    return false;
+    }
+
+
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
+    /*!
+        this method returns true if such an object is defined (name exists)
+    */
+    bool IsDefined(const std::wstring & name)
+    {
+        // we should check whether the name (in wide characters) are correct
+        // before calling AssignString() function
+        if( !IsNameCorrect(name) )
+            return false;
+
+        Misc::AssignString(str_tmp1, name);
+
+    return IsDefined(str_tmp1);
+    }
+
+#endif
+
+
+    /*!
+        this method adds one object (variable of function) into the table
+    */
+    ErrorCode Add(const std::string & name, const std::string & value, int param = 0)
+    {
+        if( !IsNameCorrect(name) )
+            return err_incorrect_name;
+
+        Iterator i = table.find(name);
+
+        if( i != table.end() )
+            // we have this object in our table
+            return err_object_exists;
+
+        table.insert( std::make_pair(name, Item(value, param)) );
+
+    return err_ok;
+    }
+
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
+    /*!
+        this method adds one object (variable of function) into the table
+    */
+    ErrorCode Add(const std::wstring & name, const std::wstring & value, int param = 0)
+    {
+        // we should check whether the name (in wide characters) are correct
+        // before calling AssignString() function
+        if( !IsNameCorrect(name) )
+            return err_incorrect_name;
+
+        Misc::AssignString(str_tmp1, name);
+        Misc::AssignString(str_tmp2, value);
+        
+    return Add(str_tmp1, str_tmp2, param);
+    }
+
+#endif
+
+
+    /*!
+        this method returns 'true' if the table is empty
+    */
+    bool Empty() const
+    {
+        return table.empty();
+    }
+
+
+    /*!
+        this method clears the table
+    */
+    void Clear()
+    {
+        return table.clear();
+    }
+
+
+    /*!
+        this method returns 'const_iterator' on the first item on the table
+    */
+    CIterator Begin() const
+    {
+        return table.begin();
+    }
+
+
+    /*!
+        this method returns 'const_iterator' pointing at the space after last item
+        (returns table.end())
+    */
+    CIterator End() const
+    {
+        return table.end();
+    }
+
+
+    /*!
+        this method changes the value and the number of parameters for a specific object
+    */
+    ErrorCode EditValue(const std::string & name, const std::string & value, int param = 0)
+    {
+        if( !IsNameCorrect(name) )
+            return err_incorrect_name;
+
+        Iterator i = table.find(name);
+
+        if( i == table.end() )
+            return err_unknown_object;
+    
+        i->second.value = value;
+        i->second.param = param;
+
+    return err_ok;
+    }
+
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
+
+    /*!
+        this method changes the value and the number of parameters for a specific object
+    */
+    ErrorCode EditValue(const std::wstring & name, const std::wstring & value, int param = 0)
+    {
+        // we should check whether the name (in wide characters) are correct
+        // before calling AssignString() function
+        if( !IsNameCorrect(name) )
+            return err_incorrect_name;
+
+        Misc::AssignString(str_tmp1, name);
+        Misc::AssignString(str_tmp2, value);
+        
+    return EditValue(str_tmp1, str_tmp2, param);
+    }
+
+#endif
+
+
+    /*!
+        this method changes the name of a specific object
+    */
+    ErrorCode EditName(const std::string & old_name, const std::string & new_name)
+    {
+        if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) )
+            return err_incorrect_name;
+
+        Iterator old_i = table.find(old_name);
+        if( old_i == table.end() )
+            return err_unknown_object;
+        
+        if( old_name == new_name )
+            // the new name is the same as the old one
+            // we treat it as a normal situation
+            return err_ok;
+
+        ErrorCode err = Add(new_name, old_i->second.value, old_i->second.param);
+        
+        if( err == err_ok ) 
+        {
+            old_i = table.find(old_name);
+            TTMATH_ASSERT( old_i != table.end() )
+
+            table.erase(old_i);
+        }
+
+    return err;
+    }
+
+
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
+
+    /*!
+        this method changes the name of a specific object
+    */
+    ErrorCode EditName(const std::wstring & old_name, const std::wstring & new_name)
+    {
+        // we should check whether the name (in wide characters) are correct
+        // before calling AssignString() function
+        if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) )
+            return err_incorrect_name;
+
+        Misc::AssignString(str_tmp1, old_name);
+        Misc::AssignString(str_tmp2, new_name);
+
+    return EditName(str_tmp1, str_tmp2);
+    }
+
+#endif
+
+
+    /*!
+        this method deletes an object
+    */
+    ErrorCode Delete(const std::string & name)
+    {
+        if( !IsNameCorrect(name) )
+            return err_incorrect_name;
+
+        Iterator i = table.find(name);
+
+        if( i == table.end() )
+            return err_unknown_object;
+
+        table.erase( i );
+
+    return err_ok;
+    }
+
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
+
+    /*!
+        this method deletes an object
+    */
+    ErrorCode Delete(const std::wstring & name)
+    {
+        // we should check whether the name (in wide characters) are correct
+        // before calling AssignString() function
+        if( !IsNameCorrect(name) )
+            return err_incorrect_name;
+
+        Misc::AssignString(str_tmp1, name);
+
+    return Delete(str_tmp1);
+    }    
+        
+#endif
+
+
+    /*!
+        this method gets the value of a specific object
+    */
+    ErrorCode GetValue(const std::string & name, std::string & value) const
+    {
+        if( !IsNameCorrect(name) )
+            return err_incorrect_name;
+
+        CIterator i = table.find(name);
+
+        if( i == table.end() )
+        {
+            value.clear();
+            return err_unknown_object;
+        }
+
+        value = i->second.value;
+
+    return err_ok;
+    }
+
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
+    /*!
+        this method gets the value of a specific object
+    */
+    ErrorCode GetValue(const std::wstring & name, std::wstring & value)
+    {
+        // we should check whether the name (in wide characters) are correct
+        // before calling AssignString() function
+        if( !IsNameCorrect(name) )
+            return err_incorrect_name;
+
+        Misc::AssignString(str_tmp1, name);
+        ErrorCode err = GetValue(str_tmp1, str_tmp2);
+        Misc::AssignString(value, str_tmp2);
+
+    return err;
+    }
+
+#endif
+
+
+    /*!
+        this method gets the value of a specific object
+        (this version is used for not copying the whole string)
+    */
+    ErrorCode GetValue(const std::string & name, const char ** value) const
+    {
+        if( !IsNameCorrect(name) )
+            return err_incorrect_name;
+
+        CIterator i = table.find(name);
+
+        if( i == table.end() )
+        {
+            *value = 0;
+            return err_unknown_object;
+        }
+
+        *value = i->second.value.c_str();
+
+    return err_ok;
+    }
+
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
+    /*!
+        this method gets the value of a specific object
+        (this version is used for not copying the whole string)
+    */
+    ErrorCode GetValue(const std::wstring & name, const char ** value)
+    {
+        // we should check whether the name (in wide characters) are correct
+        // before calling AssignString() function
+        if( !IsNameCorrect(name) )
+            return err_incorrect_name;
+
+        Misc::AssignString(str_tmp1, name);
+
+    return GetValue(str_tmp1, value);
+    }
+
+#endif
+
+
+    /*!
+        this method gets the value and the number of parameters
+        of a specific object
+    */
+    ErrorCode GetValueAndParam(const std::string & name, std::string & value, int * param) const
+    {
+        if( !IsNameCorrect(name) )
+            return err_incorrect_name;
+
+        CIterator i = table.find(name);
+
+        if( i == table.end() )
+        {
+            value.empty();
+            *param = 0;
+            return err_unknown_object;
+        }
+
+        value = i->second.value;
+        *param = i->second.param;
+
+    return err_ok;
+    }
+
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
+    /*!
+        this method gets the value and the number of parameters
+        of a specific object
+    */
+    ErrorCode GetValueAndParam(const std::wstring & name, std::wstring & value, int * param)
+    {
+        // we should check whether the name (in wide characters) are correct
+        // before calling AssignString() function
+        if( !IsNameCorrect(name) )
+            return err_incorrect_name;
+
+        Misc::AssignString(str_tmp1, name);
+        ErrorCode err = GetValueAndParam(str_tmp1, str_tmp2, param);
+        Misc::AssignString(value, str_tmp2);
+
+    return err;
+    }
+
+#endif
+
+
+    /*!
+        this method sets the value and the number of parameters
+        of a specific object
+        (this version is used for not copying the whole string)
+    */
+    ErrorCode GetValueAndParam(const std::string & name, const char ** value, int * param) const
+    {
+        if( !IsNameCorrect(name) )
+            return err_incorrect_name;
+
+        CIterator i = table.find(name);
+
+        if( i == table.end() )
+        {
+            *value = 0;
+            *param = 0;
+            return err_unknown_object;
+        }
+
+        *value = i->second.value.c_str();
+        *param = i->second.param;
+
+    return err_ok;
+    }
+
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
+
+    /*!
+        this method sets the value and the number of parameters
+        of a specific object
+        (this version is used for not copying the whole string
+        but in fact we make one copying during AssignString())
+    */
+    ErrorCode GetValueAndParam(const std::wstring & name, const char ** value, int * param)
+    {
+        // we should check whether the name (in wide characters) are correct
+        // before calling AssignString() function
+        if( !IsNameCorrect(name) )
+            return err_incorrect_name;
+
+        Misc::AssignString(str_tmp1, name);
+
+    return GetValueAndParam(str_tmp1, value, param);
+    }
+
+
+#endif
+
+
+    /*!
+        this method returns a pointer into the table
+    */
+    Table * GetTable()
+    {
+        return &table;
+    }
+
+
+private:
+
+    Table table;
+    std::string str_tmp1, str_tmp2;
+
+}; // end of class Objects
+
+
+
+
+
+
+
+/*!
+    objects of the class History are used to keep values in functions
+    which take a lot of time during calculating, for instance in the 
+    function Factorial(x)
+
+    it means that when we're calculating e.g. Factorial(1000) and the 
+    Factorial finds that we have calculated it before, the value (result)
+    is taken from the history
+*/
+template<class ValueType>
+class History
+{
+    /*!
+        one item in the History's object holds a key, a value for the key
+        and a corresponding error code
+    */
+    struct Item
+    {
+        ValueType key, value;
+        ErrorCode err;
+    };
+
+
+    /*!
+        we use std::list for simply deleting the first item
+        but because we're searching through the whole container
+        (in the method Get) the container should not be too big
+        (linear time of searching)
+    */
+    typedef std::list<Item> buffer_type;
+    buffer_type buffer;
+    typename buffer_type::size_type buffer_max_size;
+
+public:
+    
+    /*!
+        default constructor
+        default max size of the History's container is 15 items
+    */
+    History()
+    {
+        buffer_max_size = 15;
+    }
+
+
+    /*!
+        a constructor which takes another value of the max size
+        of the History's container
+    */
+    History(typename buffer_type::size_type new_size)
+    {
+        buffer_max_size = new_size;
+    }
+
+
+    /*!
+        this method adds one item into the History
+        if the size of the container is greater than buffer_max_size
+        the first item will be removed
+    */
+    void Add(const ValueType & key, const ValueType & value, ErrorCode err)
+    {
+        Item item;
+        item.key   = key;
+        item.value = value;
+        item.err   = err;
+
+        buffer.insert( buffer.end(), item );
+
+        if( buffer.size() > buffer_max_size )
+            buffer.erase(buffer.begin());
+    }
+
+
+    /*!
+        this method checks whether we have an item which has the key equal 'key'
+
+        if there's such item the method sets the 'value' and the 'err'
+        and returns true otherwise it returns false and 'value' and 'err'
+        remain unchanged
+    */
+    bool Get(const ValueType & key, ValueType & value, ErrorCode & err)
+    {
+        typename buffer_type::iterator i = buffer.begin();
+
+        for( ; i != buffer.end() ; ++i )
+        {
+            if( i->key == key )
+            {
+                value = i->value;
+                err   = i->err;
+                return true;
+            }
+        }
+
+    return false;
+    }
+
+
+    /*!
+        this methods deletes an item
+
+        we assume that there is only one item with the 'key'
+        (this methods removes the first one)
+    */
+    bool Remove(const ValueType & key)
+    {
+        typename buffer_type::iterator i = buffer.begin();
+
+        for( ; i != buffer.end() ; ++i )
+        {
+            if( i->key == key )
+            {
+                buffer.erase(i);
+                return true;
+            }
+        }
+
+    return false;
+    }
+
+
+}; // end of class History
+
+
+
+/*!
+    this is an auxiliary class used when calculating Gamma() or Factorial()
+
+    in multithreaded environment you can provide an object of this class to
+    the Gamma() or Factorial() function, e.g;
+        typedef Big<1, 3> MyBig;
+        MyBig x = 123456;
+        CGamma<MyBig> cgamma;
+        std::cout << Gamma(x, cgamma);
+    each thread should have its own CGamma<> object
+
+    in a single-thread environment a CGamma<> object is a static variable
+    in a second version of Gamma() and you don't have to explicitly use it, e.g.
+        typedef Big<1, 3> MyBig;
+        MyBig x = 123456;
+        std::cout << Gamma(x);
+*/
+template<class ValueType>
+struct CGamma
+{
+    /*!
+        this table holds factorials
+            1
+            1
+            2
+            6
+            24
+            120
+            720
+            .......
+    */
+    std::vector<ValueType> fact;
+
+
+    /*!
+        this table holds Bernoulli numbers
+            1
+            -0.5
+            0.166666666666666666666666667
+            0
+            -0.0333333333333333333333333333
+            0
+            0.0238095238095238095238095238
+            0
+            -0.0333333333333333333333333333
+            0
+            0.075757575757575757575757576
+            .....
+    */
+    std::vector<ValueType> bern;
+
+
+    /*!
+        here we store some calculated values
+        (this is for speeding up, if the next argument of Gamma() or Factorial()
+        is in the 'history' then the result we are not calculating but simply
+        return from the 'history' object)
+    */
+    History<ValueType> history;
+
+
+    /*!
+        this method prepares some coefficients: factorials and Bernoulli numbers
+        stored in 'fact' and 'bern' objects
+        
+        how many values should be depends on the size of the mantissa - if
+        the mantissa is larger then we must calculate more values
+            for a mantissa which consists of 256 bits (8 words on a 32bit platform)
+            we have to calculate about 30 values (the size of fact and bern will be 30),
+            and for a 2048 bits mantissa we have to calculate 306 coefficients
+
+        you don't have to call this method, these coefficients will be automatically calculated
+        when they are needed
+
+        you must note that calculating these coefficients is a little time-consuming operation,
+        (especially when the mantissa is large) and first call to Gamma() or Factorial()
+        can take more time than next calls, and in the end this is the point when InitAll()
+        comes in handy: you can call this method somewhere at the beginning of your program
+    */
+    void InitAll();
+    // definition is in ttmath.h
+};
+
+
+
+
+} // namespace
+
+#endif
+
diff -r 000000000000 -r 04a9f72bbca7 ttmathparser.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ttmathparser.h	Tue Jul 30 18:43:48 2013 +0000
@@ -0,0 +1,2778 @@
+/*
+ * This file is a part of TTMath Bignum Library
+ * and is distributed under the (new) BSD licence.
+ * Author: Tomasz Sowa <t.sowa@ttmath.org>
+ */
+
+/* 
+ * Copyright (c) 2006-2010, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+#ifndef headerfilettmathparser
+#define headerfilettmathparser
+
+/*!
+    \file ttmathparser.h
+    \brief A mathematical parser
+*/
+
+#include <cstdio>
+#include <vector>
+#include <map>
+#include <set>
+
+#include "ttmath.h"
+#include "ttmathobjects.h"
+#include "ttmathmisc.h"
+
+
+
+namespace ttmath
+{
+
+/*! 
+    \brief Mathematical parser
+
+    let x will be an input string meaning an expression for converting:
+    
+    x = [+|-]Value[operator[+|-]Value][operator[+|-]Value]...
+    where:
+        an operator can be:
+            ^ (pow)   (the heighest priority)
+
+            * (mul)   (or multiplication without an operator -- short mul)
+            / (div)   (* and / have the same priority)
+
+            + (add)
+            - (sub)   (+ and - have the same priority)
+
+            < (lower than)
+            > (greater than)
+            <= (lower or equal than)
+            >= (greater or equal than)
+            == (equal)
+            != (not equal)   (all above logical operators have the same priority)
+            
+            && (logical and)
+
+            || (logical or) (the lowest priority)
+
+        short mul:
+          if the second Value (Var below) is either a variable or function there might not be 
+         an operator between them, e.g.
+            "[+|-]Value Var" is treated as "[+|-]Value * Var" and the multiplication
+            has the same priority as a normal multiplication:
+            4x       = 4 * x
+            2^3m     = (2^3)* m
+            6h^3     = 6 * (h^3)
+            2sin(pi) = 2 * sin(pi)
+            etc.
+
+        Value can be:
+            constant e.g. 100, can be preceded by operators for changing the base (radix): [#|&]
+                               # - hex
+                               & - bin
+                               sample: #10  = 16
+                                       &10  = 2
+            variable e.g. pi
+            another expression between brackets e.g (x)
+            function e.g. sin(x)
+
+    for example a correct input string can be:
+        "1"
+        "2.1234"
+        "2,1234"    (they are the same, by default we can either use a comma or a dot)
+        "1 + 2"
+        "(1 + 2) * 3"
+        "pi"
+        "sin(pi)"
+        "(1+2)*(2+3)"
+        "log(2;1234)"    there's a semicolon here (not a comma), we use it in functions
+                         for separating parameters
+        "1 < 2"  (the result will be: 1)
+        "4 < 3"  (the result will be: 0)
+        "2+x"    (of course if the variable 'x' is defined)
+        "4x+10"
+        "#20+10"     = 32 + 10 = 42
+        "10 ^ -&101" = 10 ^ -5 = 0.00001
+        "8 * -&10"   = 8 * -2  = -16
+        etc.
+
+    we can also use a semicolon for separating any 'x' input strings
+    for example:
+        "1+2;4+5"
+    the result will be on the stack as follows:
+        stack[0].value=3
+        stack[1].value=9
+*/
+template<class ValueType>
+class Parser
+{
+private:
+
+/*!
+    there are 5 mathematical operators as follows (with their standard priorities):
+        add (+)
+        sub (-)
+        mul (*)
+        div (/)
+        pow (^)
+        and 'shortmul' used when there is no any operators between
+        a first parameter and a variable or function
+        (the 'shortmul' has the same priority as the normal multiplication )
+*/
+    class MatOperator
+    {
+    public:
+
+        enum Type
+        {
+            none,add,sub,mul,div,pow,lt,gt,let,get,eq,neq,lor,land,shortmul
+        };
+
+        enum Assoc
+        {
+            right,        // right-associative
+            non_right    // associative or left-associative
+        };
+
+        Type  GetType()     const { return type; }
+        int   GetPriority() const { return priority; }
+        Assoc GetAssoc()    const { return assoc; }
+
+        void SetType(Type t)
+        {
+            type  = t;
+            assoc = non_right;
+
+            switch( type )
+            {        
+            case lor:
+                priority = 4;
+                break;
+
+            case land:
+                priority = 5;
+                break;
+
+            case eq:
+            case neq:
+            case lt:
+            case gt:
+            case let:
+            case get:
+                priority = 7;
+                break;
+
+            case add:
+            case sub:
+                priority = 10;
+                break;
+
+            case mul:
+            case shortmul:
+            case div:
+                priority = 12;
+                break;
+
+            case pow:
+                priority = 14;
+                assoc    = right;
+                break;
+
+            default:
+                Error( err_internal_error );
+                break;
+            }
+        }
+
+        MatOperator(): type(none), priority(0), assoc(non_right)
+        {
+        }
+
+    private:
+
+        Type  type;
+        int   priority;
+        Assoc assoc;
+    }; // end of MatOperator class
+
+
+
+public:
+
+
+
+    /*!
+        Objects of type 'Item' we are keeping on our stack
+    */
+    struct Item
+    {
+        enum Type
+        {
+            none, numerical_value, mat_operator, first_bracket,
+            last_bracket, variable, semicolon
+        };
+
+        // The kind of type which we're keeping
+        Type type;
+
+        // if type == numerical_value
+        ValueType value;
+
+        // if type == mat_operator
+        MatOperator moperator;
+
+        /*
+            if type == first_bracket
+
+            if 'function' is set to true it means that the first recognized bracket
+            was the bracket from function in other words we must call a function when
+            we'll find the 'last' bracket
+        */
+        bool function;
+
+        // if function is true
+        std::string function_name;
+
+        /*
+            the sign of value
+
+            it can be for type==numerical_value or type==first_bracket
+            when it's true it means e.g. that value is equal -value
+        */
+        bool sign;
+
+        Item(): type(none), function(false), sign(false)
+        {
+        }
+
+    }; // end of Item struct
+
+
+/*!
+    stack on which we're keeping the Items
+
+    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;
+
+
+private:
+
+
+/*!
+    size of the stack when we're starting parsing of the string
+
+    if it's to small while parsing the stack will be automatically resized
+*/
+const int default_stack_size;
+
+
+
+/*!
+    index of an object in our stack
+    it's pointing on the place behind the last element
+    for example at the beginning of parsing its value is zero
+*/
+unsigned int stack_index;
+
+
+/*!
+    code of the last error
+*/
+ErrorCode error;
+
+
+/*!
+    pointer to the currently reading char
+    when an error has occured it may be used to count the index of the wrong character
+*/
+const char * pstring;
+
+
+/*!
+    the base (radix) of the mathematic system (for example it may be '10')
+*/
+int base;
+
+
+/*!
+    the unit of angles used in: sin,cos,tan,cot,asin,acos,atan,acot
+    0 - deg
+    1 - rad (default)
+    2 - grad
+*/
+int deg_rad_grad;
+
+
+
+/*!
+    a pointer to an object which tell us whether we should stop calculating or not
+*/
+const volatile StopCalculating * pstop_calculating;
+
+
+
+/*!
+    a pointer to the user-defined variables' table
+*/
+const Objects * puser_variables;
+
+/*!
+    a pointer to the user-defined functions' table
+*/
+const Objects * puser_functions;
+
+
+typedef std::map<std::string, ValueType> FunctionLocalVariables;
+
+/*!
+    a pointer to the local variables of a function
+*/
+const FunctionLocalVariables * pfunction_local_variables;
+
+
+/*!
+    a temporary set using during parsing user defined variables
+*/
+std::set<std::string> visited_variables;
+
+
+/*!
+    a temporary set using during parsing user defined functions
+*/
+std::set<std::string> visited_functions;
+
+
+
+
+/*!
+    pfunction is the type of pointer to a mathematic function
+
+    these mathematic functions are private members of this class,
+    they are the wrappers for standard mathematics function
+
+    'pstack' is the pointer to the first argument on our stack
+    'amount_of_arg' tell us how many argument there are in our stack
+    'result' is the reference for result of function 
+*/
+typedef void (Parser<ValueType>::*pfunction)(int pstack, int amount_of_arg, ValueType & result);
+
+
+/*!
+    pfunction is the type of pointer to a method which returns value of variable
+*/
+typedef void (ValueType::*pfunction_var)();
+
+
+/*!
+    table of mathematic functions
+
+    this map consists of:
+        std::string - function's name
+        pfunction - pointer to specific function
+*/
+typedef std::map<std::string, pfunction> FunctionsTable;
+FunctionsTable functions_table;
+
+
+/*!
+    table of mathematic operators
+
+    this map consists of:
+        std::string - operators's name
+        MatOperator::Type - type of the operator
+*/
+typedef std::map<std::string, typename MatOperator::Type> OperatorsTable;
+OperatorsTable operators_table;
+
+
+/*!
+    table of mathematic variables
+
+    this map consists of:
+        std::string     - variable's name
+        pfunction_var - pointer to specific function which returns value of variable
+*/
+typedef std::map<std::string, pfunction_var> VariablesTable;
+VariablesTable variables_table;
+
+
+/*!
+    some coefficients used when calculating the gamma (or factorial) function
+*/
+CGamma<ValueType> cgamma;
+
+
+/*!
+    temporary object for a whole string when Parse(std::wstring) is used
+*/
+std::string wide_to_ansi;
+
+
+/*!
+    group character (used when parsing)
+    default zero (not used)
+*/
+int group;
+
+
+/*!
+    characters used as a comma
+    default: '.' and ','
+    comma2 can be zero (it means it is not used)
+*/
+int comma, comma2;
+
+
+/*!
+    an additional character used as a separator between function parameters
+    (semicolon is used always)
+*/
+int param_sep;
+
+
+/*!
+    true if something was calculated (at least one mathematical operator was used or a function or a variable)
+*/
+bool calculated;
+
+
+
+/*!
+    we're using this method for reporting an error
+*/
+static void Error(ErrorCode code)
+{
+    throw code;
+}
+
+
+/*!
+    this method skips the white character from the string
+
+    it's moving the 'pstring' to the first no-white character
+*/
+void SkipWhiteCharacters()
+{
+    while( (*pstring==' ' ) || (*pstring=='\t') )
+        ++pstring;
+}
+
+
+/*!
+    an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
+*/
+void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, const std::string & name)
+{
+    if( variable )
+    {
+        if( visited_variables.find(name) != visited_variables.end() )
+            Error( err_variable_loop );
+    }
+    else
+    {
+        if( visited_functions.find(name) != visited_functions.end() )
+            Error( err_functions_loop );
+    }
+}
+
+
+/*!
+    an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
+*/
+void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const std::string & name)
+{
+    if( variable )
+        visited_variables.insert( name );
+    else
+        visited_functions.insert( name );
+}
+
+
+/*!
+    an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
+*/
+void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const std::string & name)
+{
+    if( variable )
+        visited_variables.erase( name );
+    else
+        visited_functions.erase( name );
+}
+
+
+/*!
+    this method returns the value of a variable or function
+    by creating a new instance of the mathematical parser 
+    and making the standard parsing algorithm on the given string
+
+    this method is used only during parsing user defined variables or functions
+
+    (there can be a recurrence here therefore we're using 'visited_variables'
+    and 'visited_functions' sets to make a stop condition)
+*/
+ValueType RecurrenceParsingVariablesOrFunction(bool variable, const std::string & name, const char * new_string,
+                                               FunctionLocalVariables * local_variables = 0)
+{
+    RecurrenceParsingVariablesOrFunction_CheckStopCondition(variable, name);
+    RecurrenceParsingVariablesOrFunction_AddName(variable, name);
+
+    Parser<ValueType> NewParser(*this);
+    ErrorCode err;
+
+    NewParser.pfunction_local_variables = local_variables;
+
+    try
+    {
+        err = NewParser.Parse(new_string);
+    }
+    catch(...)
+    {
+        RecurrenceParsingVariablesOrFunction_DeleteName(variable, name);
+
+    throw;
+    }
+
+    RecurrenceParsingVariablesOrFunction_DeleteName(variable, name);
+
+    if( err != err_ok )
+        Error( err );
+
+    if( NewParser.stack.size() != 1 )
+        Error( err_must_be_only_one_value );
+
+    if( NewParser.stack[0].type != Item::numerical_value )
+        // I think there shouldn't be this error here
+        Error( err_incorrect_value );
+
+return NewParser.stack[0].value;
+}
+
+
+public:
+
+
+/*!
+    this method returns the user-defined value of a variable
+*/
+bool GetValueOfUserDefinedVariable(const std::string & variable_name,ValueType & result)
+{
+    if( !puser_variables )
+        return false;
+
+    const char * string_value;
+
+    if( puser_variables->GetValue(variable_name, &string_value) != err_ok )
+        return false;
+
+    result = RecurrenceParsingVariablesOrFunction(true, variable_name, string_value);
+    calculated = true;
+
+return true;
+}
+
+
+/*!
+    this method returns the value of a local variable of a function
+*/
+bool GetValueOfFunctionLocalVariable(const std::string & variable_name, ValueType & result)
+{
+    if( !pfunction_local_variables )
+        return false;
+
+    typename FunctionLocalVariables::const_iterator i = pfunction_local_variables->find(variable_name);
+
+    if( i == pfunction_local_variables->end() )
+        return false;
+
+    result = i->second;
+
+return true;
+}
+
+
+/*!
+    this method returns the value of a variable from variables' table
+
+    we make an object of type ValueType then call a method which 
+    sets the correct value in it and finally we'll return the object
+*/
+ValueType GetValueOfVariable(const std::string & variable_name)
+{
+ValueType result;
+
+    if( GetValueOfFunctionLocalVariable(variable_name, result) )
+        return result;
+
+    if( GetValueOfUserDefinedVariable(variable_name, result) )
+        return result;
+
+
+    typename std::map<std::string, pfunction_var>::iterator i =
+                                                    variables_table.find(variable_name);
+
+    if( i == variables_table.end() )
+        Error( err_unknown_variable );
+
+    (result.*(i->second))();
+    calculated = true;
+
+return result;
+}
+
+
+private:
+
+/*!
+    wrappers for mathematic functions
+
+    'sindex' is pointing on the first argument on our stack 
+             (the second argument has 'sindex+2'
+             because 'sindex+1' is guaranted for the 'semicolon' operator)
+             the third artument has of course 'sindex+4' etc.
+
+    'result' will be the result of the function
+
+    (we're using exceptions here for example when function gets an improper argument)
+*/
+
+
+/*!
+    used by: sin,cos,tan,cot
+*/
+ValueType ConvertAngleToRad(const ValueType & input)
+{
+    if( deg_rad_grad == 1 ) // rad
+        return input;
+
+    ValueType result;
+    ErrorCode err;
+
+    if( deg_rad_grad == 0 ) // deg
+        result = ttmath::DegToRad(input, &err);
+    else // grad
+        result = ttmath::GradToRad(input, &err);
+
+    if( err != err_ok )
+        Error( err );
+
+return result;
+}
+
+
+/*!
+    used by: asin,acos,atan,acot
+*/
+ValueType ConvertRadToAngle(const ValueType & input)
+{
+    if( deg_rad_grad == 1 ) // rad
+        return input;
+
+    ValueType result;
+    ErrorCode err;
+
+    if( deg_rad_grad == 0 ) // deg
+        result = ttmath::RadToDeg(input, &err);
+    else // grad
+        result = ttmath::RadToGrad(input, &err);
+
+    if( err != err_ok )
+        Error( err );
+
+return result;
+}
+
+
+void Gamma(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    ErrorCode err;
+    
+    result = ttmath::Gamma(stack[sindex].value, cgamma, &err, pstop_calculating);
+
+    if(err != err_ok)
+        Error( err );
+}
+
+
+/*!
+    factorial
+    result = 1 * 2 * 3 * 4 * .... * x
+*/
+void Factorial(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    ErrorCode err;
+
+    result = ttmath::Factorial(stack[sindex].value, cgamma, &err, pstop_calculating);
+
+    if(err != err_ok)
+        Error( err );
+}
+
+
+void Abs(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    result = ttmath::Abs(stack[sindex].value);
+}
+
+void Sin(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    ErrorCode err;
+    result = ttmath::Sin( ConvertAngleToRad(stack[sindex].value), &err );
+
+    if(err != err_ok)
+        Error( err );
+}
+
+void Cos(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    ErrorCode err;
+    result = ttmath::Cos( ConvertAngleToRad(stack[sindex].value), &err );
+
+    if(err != err_ok)
+        Error( err );
+}
+
+void Tan(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    ErrorCode err;
+    result = ttmath::Tan(ConvertAngleToRad(stack[sindex].value), &err);
+
+    if(err != err_ok)
+        Error( err );
+}
+
+void Cot(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    ErrorCode err;
+    result = ttmath::Cot(ConvertAngleToRad(stack[sindex].value), &err);
+
+    if(err != err_ok)
+        Error( err );
+}
+
+void Int(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    result = ttmath::SkipFraction(stack[sindex].value);
+}
+
+
+void Round(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    result = stack[sindex].value;
+
+    if( result.Round() )
+        Error( err_overflow );
+}
+
+
+void Ln(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    ErrorCode err;
+    result = ttmath::Ln(stack[sindex].value, &err);
+
+    if(err != err_ok)
+        Error( err );
+}
+
+void Log(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 2 )
+        Error( err_improper_amount_of_arguments );
+
+    ErrorCode err;
+    result = ttmath::Log(stack[sindex].value, stack[sindex+2].value, &err);
+
+    if(err != err_ok)
+        Error( err );
+}
+
+void Exp(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    ErrorCode err;
+    result = ttmath::Exp(stack[sindex].value, &err);
+
+    if(err != err_ok)
+        Error( err );
+}
+
+
+void Max(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args == 0 )
+    {
+        result.SetMax();
+
+    return;
+    }
+
+    result = stack[sindex].value;
+
+    for(int i=1 ; i<amount_of_args ; ++i)
+    {
+        if( result < stack[sindex + i*2].value )
+            result = stack[sindex + i*2].value;
+    }
+}
+
+
+void Min(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args == 0 )
+    {
+        result.SetMin();
+
+    return;
+    }
+
+    result = stack[sindex].value;
+
+    for(int i=1 ; i<amount_of_args ; ++i)
+    {
+        if( result > stack[sindex + i*2].value )
+            result = stack[sindex + i*2].value;
+    }
+}
+
+
+void ASin(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    ErrorCode err;
+    ValueType temp = ttmath::ASin(stack[sindex].value, &err);
+
+    if(err != err_ok)
+        Error( err );
+
+    result = ConvertRadToAngle(temp);
+}
+
+
+void ACos(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    ErrorCode err;
+    ValueType temp = ttmath::ACos(stack[sindex].value, &err);
+
+    if(err != err_ok)
+        Error( err );
+
+    result = ConvertRadToAngle(temp);
+}
+
+
+void ATan(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    result = ConvertRadToAngle(ttmath::ATan(stack[sindex].value));
+}
+
+
+void ACot(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    result = ConvertRadToAngle(ttmath::ACot(stack[sindex].value));
+}
+
+
+void Sgn(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    result = ttmath::Sgn(stack[sindex].value);
+}
+
+
+void Mod(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 2 )
+        Error( err_improper_amount_of_arguments );
+
+    if( stack[sindex+2].value.IsZero() )
+        Error( err_improper_argument );
+
+    result = stack[sindex].value;
+    uint c = result.Mod(stack[sindex+2].value);
+
+    if( c )
+        Error( err_overflow );
+}
+
+
+void If(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 3 )
+        Error( err_improper_amount_of_arguments );
+
+
+    if( !stack[sindex].value.IsZero() )
+        result = stack[sindex+2].value;
+    else
+        result = stack[sindex+4].value;
+}
+
+
+void Or(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args < 2 )
+        Error( err_improper_amount_of_arguments );
+
+    for(int i=0 ; i<amount_of_args ; ++i)
+    {
+        if( !stack[sindex+i*2].value.IsZero() )
+        {
+            result.SetOne();
+            return;
+        }
+    }
+
+    result.SetZero();
+}
+
+
+void And(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args < 2 )
+        Error( err_improper_amount_of_arguments );
+
+    for(int i=0 ; i<amount_of_args ; ++i)
+    {
+        if( stack[sindex+i*2].value.IsZero() )
+        {
+            result.SetZero();
+            return;
+        }
+    }
+
+    result.SetOne();
+}
+
+
+void Not(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+
+    if( stack[sindex].value.IsZero() )
+        result.SetOne();
+    else
+        result.SetZero();
+}
+
+
+void DegToRad(int sindex, int amount_of_args, ValueType & result)
+{
+    ErrorCode err = err_ok;
+
+    if( amount_of_args == 1 )
+    {
+        result = ttmath::DegToRad(stack[sindex].value, &err);
+    }
+    else
+    if( amount_of_args == 3 )
+    {
+        result = ttmath::DegToRad(    stack[sindex].value, stack[sindex+2].value,
+                                    stack[sindex+4].value, &err);
+    }
+    else
+        Error( err_improper_amount_of_arguments );
+
+
+    if( err != err_ok )
+        Error( err );
+}
+
+
+void RadToDeg(int sindex, int amount_of_args, ValueType & result)
+{
+    ErrorCode err;
+
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+    
+    result = ttmath::RadToDeg(stack[sindex].value, &err);
+
+    if( err != err_ok )
+        Error( err );
+}
+
+
+void DegToDeg(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 3 )
+        Error( err_improper_amount_of_arguments );
+
+    ErrorCode err;
+    result = ttmath::DegToDeg(    stack[sindex].value, stack[sindex+2].value,
+                                stack[sindex+4].value, &err);
+
+    if( err != err_ok )
+        Error( err );
+}
+
+
+void GradToRad(int sindex, int amount_of_args, ValueType & result)
+{
+    ErrorCode err;
+
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+    
+    result = ttmath::GradToRad(stack[sindex].value, &err);
+
+    if( err != err_ok )
+        Error( err );
+}
+
+
+void RadToGrad(int sindex, int amount_of_args, ValueType & result)
+{
+    ErrorCode err;
+
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+    
+    result = ttmath::RadToGrad(stack[sindex].value, &err);
+
+    if( err != err_ok )
+        Error( err );
+}
+
+
+void DegToGrad(int sindex, int amount_of_args, ValueType & result)
+{
+    ErrorCode err = err_ok;
+
+    if( amount_of_args == 1 )
+    {
+        result = ttmath::DegToGrad(stack[sindex].value, &err);
+    }
+    else
+    if( amount_of_args == 3 )
+    {
+        result = ttmath::DegToGrad(    stack[sindex].value, stack[sindex+2].value,
+                                    stack[sindex+4].value, &err);
+    }
+    else
+        Error( err_improper_amount_of_arguments );
+
+
+    if( err != err_ok )
+        Error( err );
+}
+
+
+void GradToDeg(int sindex, int amount_of_args, ValueType & result)
+{
+    ErrorCode err;
+
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+    
+    result = ttmath::GradToDeg(stack[sindex].value, &err);
+
+    if( err != err_ok )
+        Error( err );
+}
+
+
+void Ceil(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    ErrorCode err;
+    result = ttmath::Ceil(stack[sindex].value, &err);
+
+    if( err != err_ok )
+        Error( err );
+}
+
+
+void Floor(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    ErrorCode err;
+    result = ttmath::Floor(stack[sindex].value, &err);
+
+    if( err != err_ok )
+        Error( err );
+}
+
+void Sqrt(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    ErrorCode err;
+    result = ttmath::Sqrt(stack[sindex].value, &err);
+
+    if( err != err_ok )
+        Error( err );
+}
+
+
+void Sinh(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    ErrorCode err;
+    result = ttmath::Sinh(stack[sindex].value, &err);
+
+    if( err != err_ok )
+        Error( err );
+}
+
+
+void Cosh(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    ErrorCode err;
+    result = ttmath::Cosh(stack[sindex].value, &err);
+
+    if( err != err_ok )
+        Error( err );
+}
+
+
+void Tanh(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    ErrorCode err;
+    result = ttmath::Tanh(stack[sindex].value, &err);
+
+    if( err != err_ok )
+        Error( err );
+}
+
+
+void Coth(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    ErrorCode err;
+    result = ttmath::Coth(stack[sindex].value, &err);
+
+    if( err != err_ok )
+        Error( err );
+}
+
+
+void Root(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 2 )
+        Error( err_improper_amount_of_arguments );
+
+    ErrorCode err;
+    result = ttmath::Root(stack[sindex].value, stack[sindex+2].value, &err);
+
+    if( err != err_ok )
+        Error( err );
+}
+
+
+
+void ASinh(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    ErrorCode err;
+    result = ttmath::ASinh(stack[sindex].value, &err);
+
+    if( err != err_ok )
+        Error( err );
+}
+
+
+void ACosh(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    ErrorCode err;
+    result = ttmath::ACosh(stack[sindex].value, &err);
+
+    if( err != err_ok )
+        Error( err );
+}
+
+
+void ATanh(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    ErrorCode err;
+    result = ttmath::ATanh(stack[sindex].value, &err);
+
+    if( err != err_ok )
+        Error( err );
+}
+
+
+void ACoth(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    ErrorCode err;
+    result = ttmath::ACoth(stack[sindex].value, &err);
+
+    if( err != err_ok )
+        Error( err );
+}
+
+
+void BitAnd(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 2 )
+        Error( err_improper_amount_of_arguments );
+
+    uint err;
+    result = stack[sindex].value;
+    err = result.BitAnd(stack[sindex+2].value);
+
+    switch(err)
+    {
+    case 1:
+        Error( err_overflow );
+        break;
+    case 2:
+        Error( err_improper_argument );
+        break;
+    }
+}
+
+void BitOr(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 2 )
+        Error( err_improper_amount_of_arguments );
+
+    uint err;
+    result = stack[sindex].value;
+    err = result.BitOr(stack[sindex+2].value);
+
+    switch(err)
+    {
+    case 1:
+        Error( err_overflow );
+        break;
+    case 2:
+        Error( err_improper_argument );
+        break;
+    }
+}
+
+
+void BitXor(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 2 )
+        Error( err_improper_amount_of_arguments );
+
+    uint err;
+    result = stack[sindex].value;
+    err = result.BitXor(stack[sindex+2].value);
+
+    switch(err)
+    {
+    case 1:
+        Error( err_overflow );
+        break;
+    case 2:
+        Error( err_improper_argument );
+        break;
+    }
+}
+
+
+void Sum(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args == 0 )
+        Error( err_improper_amount_of_arguments );
+
+    result = stack[sindex].value;
+
+    for(int i=1 ; i<amount_of_args ; ++i )
+        if( result.Add( stack[ sindex + i*2 ].value ) )
+            Error( err_overflow );
+}    
+
+void Avg(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args == 0 )
+        Error( err_improper_amount_of_arguments );
+
+    result = stack[sindex].value;
+
+    for(int i=1 ; i<amount_of_args ; ++i )
+        if( result.Add( stack[ sindex + i*2 ].value ) )
+            Error( err_overflow );
+
+    if( result.Div( amount_of_args ) )
+        Error( err_overflow );
+}    
+
+
+void Frac(int sindex, int amount_of_args, ValueType & result)
+{
+    if( amount_of_args != 1 )
+        Error( err_improper_amount_of_arguments );
+
+    result = stack[sindex].value;
+    result.RemainFraction();
+}
+
+
+
+
+/*!
+    we use such a method because 'wvsprintf' is not everywhere defined
+*/
+void Sprintf(char * buffer, int par)
+{
+char buf[30]; // char, not wchar_t
+int i;
+
+    #ifdef _MSC_VER
+    #pragma warning( disable: 4996 )
+    //warning C4996: 'sprintf': This function or variable may be unsafe.
+    #endif
+
+    sprintf(buf, "%d", par);
+    for(i=0 ; buf[i] != 0 ; ++i)
+        buffer[i] = buf[i];
+
+    buffer[i] = 0;
+
+    #ifdef _MSC_VER
+    #pragma warning( default: 4996 )
+    #endif
+}
+
+
+
+
+/*!
+    this method returns the value from a user-defined function
+
+    (look at the description in 'CallFunction(...)')
+*/
+bool GetValueOfUserDefinedFunction(const std::string & function_name, int amount_of_args, int sindex)
+{
+    if( !puser_functions )
+        return false;
+
+    const char * string_value;
+    int param;
+
+    if( puser_functions->GetValueAndParam(function_name, &string_value, &param) != err_ok )
+        return false;
+
+    if( param != amount_of_args )
+        Error( err_improper_amount_of_arguments );
+
+
+    FunctionLocalVariables local_variables;
+
+    if( amount_of_args > 0 )
+    {
+        char buffer[30];
+
+        // x = x1
+        buffer[0] = 'x';
+        buffer[1] = 0;
+        local_variables.insert( std::make_pair(buffer, stack[sindex].value) );
+
+        for(int i=0 ; i<amount_of_args ; ++i)
+        {
+            buffer[0] = 'x';
+            Sprintf(buffer+1, i+1);
+            local_variables.insert( std::make_pair(buffer, stack[sindex + i*2].value) );
+        }
+    }
+
+    stack[sindex-1].value = RecurrenceParsingVariablesOrFunction(false, function_name, string_value, &local_variables);
+    calculated = true;
+
+return true;
+}
+
+
+/*
+    we're calling a specific function
+
+    function_name  - name of the function
+    amount_of_args - how many arguments there are on our stack
+                     (function must check whether this is a correct value or not)
+    sindex         - index of the first argument on the stack (sindex is greater than zero)
+                       if there aren't any arguments on the stack 'sindex' pointing on
+                     a non existend element (after the first bracket)
+
+    result will be stored in 'stack[sindex-1].value'
+    (we don't have to set the correct type of this element, it'll be set later)
+*/
+void CallFunction(const std::string & function_name, int amount_of_args, int sindex)
+{
+    if( GetValueOfUserDefinedFunction(function_name, amount_of_args, sindex) )
+        return;
+
+    typename FunctionsTable::iterator i = functions_table.find( function_name );
+
+    if( i == functions_table.end() )
+        Error( err_unknown_function );
+
+    /*
+        calling the specify function
+    */
+    (this->*(i->second))(sindex, amount_of_args, stack[sindex-1].value);
+    calculated = true;
+}
+
+
+
+
+
+/*!
+    inserting a function to the functions' table
+
+    function_name - name of the function
+    pf - pointer to the function (to the wrapper)
+*/
+void InsertFunctionToTable(const char * function_name, pfunction pf)
+{
+    std::string str;
+    Misc::AssignString(str, function_name);
+
+    functions_table.insert( std::make_pair(str, pf) );
+}
+
+
+
+/*!
+    inserting a function to the variables' table
+    (this function returns value of variable)
+
+    variable_name - name of the function
+    pf - pointer to the function
+*/
+void InsertVariableToTable(const char * variable_name, pfunction_var pf)
+{
+    std::string str;
+    Misc::AssignString(str, variable_name);
+
+    variables_table.insert( std::make_pair(str, pf) );
+}
+
+
+/*!
+    this method creates the table of functions
+*/
+void CreateFunctionsTable()
+{
+    InsertFunctionToTable("gamma",        &Parser<ValueType>::Gamma);
+    InsertFunctionToTable("factorial",    &Parser<ValueType>::Factorial);
+    InsertFunctionToTable("abs",           &Parser<ValueType>::Abs);
+    InsertFunctionToTable("sin",           &Parser<ValueType>::Sin);
+    InsertFunctionToTable("cos",           &Parser<ValueType>::Cos);
+    InsertFunctionToTable("tan",           &Parser<ValueType>::Tan);
+    InsertFunctionToTable("tg",            &Parser<ValueType>::Tan);
+    InsertFunctionToTable("cot",          &Parser<ValueType>::Cot);
+    InsertFunctionToTable("ctg",          &Parser<ValueType>::Cot);
+    InsertFunctionToTable("int",           &Parser<ValueType>::Int);
+    InsertFunctionToTable("round",         &Parser<ValueType>::Round);
+    InsertFunctionToTable("ln",            &Parser<ValueType>::Ln);
+    InsertFunctionToTable("log",           &Parser<ValueType>::Log);
+    InsertFunctionToTable("exp",           &Parser<ValueType>::Exp);
+    InsertFunctionToTable("max",           &Parser<ValueType>::Max);
+    InsertFunctionToTable("min",           &Parser<ValueType>::Min);
+    InsertFunctionToTable("asin",       &Parser<ValueType>::ASin);
+    InsertFunctionToTable("acos",       &Parser<ValueType>::ACos);
+    InsertFunctionToTable("atan",       &Parser<ValueType>::ATan);
+    InsertFunctionToTable("atg",           &Parser<ValueType>::ATan);
+    InsertFunctionToTable("acot",       &Parser<ValueType>::ACot);
+    InsertFunctionToTable("actg",       &Parser<ValueType>::ACot);
+    InsertFunctionToTable("sgn",           &Parser<ValueType>::Sgn);
+    InsertFunctionToTable("mod",           &Parser<ValueType>::Mod);
+    InsertFunctionToTable("if",           &Parser<ValueType>::If);
+    InsertFunctionToTable("or",           &Parser<ValueType>::Or);
+    InsertFunctionToTable("and",          &Parser<ValueType>::And);
+    InsertFunctionToTable("not",          &Parser<ValueType>::Not);
+    InsertFunctionToTable("degtorad",    &Parser<ValueType>::DegToRad);
+    InsertFunctionToTable("radtodeg",    &Parser<ValueType>::RadToDeg);
+    InsertFunctionToTable("degtodeg",    &Parser<ValueType>::DegToDeg);
+    InsertFunctionToTable("gradtorad",    &Parser<ValueType>::GradToRad);
+    InsertFunctionToTable("radtograd",    &Parser<ValueType>::RadToGrad);
+    InsertFunctionToTable("degtograd",    &Parser<ValueType>::DegToGrad);
+    InsertFunctionToTable("gradtodeg",    &Parser<ValueType>::GradToDeg);
+    InsertFunctionToTable("ceil",        &Parser<ValueType>::Ceil);
+    InsertFunctionToTable("floor",        &Parser<ValueType>::Floor);
+    InsertFunctionToTable("sqrt",        &Parser<ValueType>::Sqrt);
+    InsertFunctionToTable("sinh",        &Parser<ValueType>::Sinh);
+    InsertFunctionToTable("cosh",        &Parser<ValueType>::Cosh);
+    InsertFunctionToTable("tanh",        &Parser<ValueType>::Tanh);
+    InsertFunctionToTable("tgh",        &Parser<ValueType>::Tanh);
+    InsertFunctionToTable("coth",        &Parser<ValueType>::Coth);
+    InsertFunctionToTable("ctgh",        &Parser<ValueType>::Coth);
+    InsertFunctionToTable("root",        &Parser<ValueType>::Root);
+    InsertFunctionToTable("asinh",        &Parser<ValueType>::ASinh);
+    InsertFunctionToTable("acosh",        &Parser<ValueType>::ACosh);
+    InsertFunctionToTable("atanh",        &Parser<ValueType>::ATanh);
+    InsertFunctionToTable("atgh",        &Parser<ValueType>::ATanh);
+    InsertFunctionToTable("acoth",        &Parser<ValueType>::ACoth);
+    InsertFunctionToTable("actgh",        &Parser<ValueType>::ACoth);
+    InsertFunctionToTable("bitand",        &Parser<ValueType>::BitAnd);
+    InsertFunctionToTable("bitor",        &Parser<ValueType>::BitOr);
+    InsertFunctionToTable("bitxor",        &Parser<ValueType>::BitXor);
+    InsertFunctionToTable("band",        &Parser<ValueType>::BitAnd);
+    InsertFunctionToTable("bor",        &Parser<ValueType>::BitOr);
+    InsertFunctionToTable("bxor",        &Parser<ValueType>::BitXor);
+    InsertFunctionToTable("sum",        &Parser<ValueType>::Sum);
+    InsertFunctionToTable("avg",        &Parser<ValueType>::Avg);
+    InsertFunctionToTable("frac",        &Parser<ValueType>::Frac);
+}
+
+
+/*!
+    this method creates the table of variables
+*/
+void CreateVariablesTable()
+{
+    InsertVariableToTable("pi", &ValueType::SetPi);
+    InsertVariableToTable("e",  &ValueType::SetE);
+}
+
+
+/*!
+    converting from a big letter to a small one
+*/
+int ToLowerCase(int c)
+{
+    if( c>='A' && c<='Z' )
+        return c - 'A' + 'a';
+
+return c;
+}
+
+
+/*!
+    this method read the name of a variable or a function
+    
+        'result' will be the name of a variable or a function
+        function return 'false' if this name is the name of a variable
+        or function return 'true' if this name is the name of a function
+
+    what should be returned is tested just by a '(' character that means if there's
+    a '(' character after a name that function returns 'true'
+*/
+bool ReadName(std::string & result)
+{
+int character;
+
+
+    result.erase();
+    character = *pstring;
+
+    /*
+        the first letter must be from range 'a' - 'z' or 'A' - 'Z'
+    */
+    if( ! (( character>='a' && character<='z' ) || ( character>='A' && character<='Z' )) )
+        Error( err_unknown_character );
+
+
+    do
+    {
+        result   += static_cast<char>( character );
+        character = * ++pstring;
+    }
+    while(    (character>='a' && character<='z') ||
+            (character>='A' && character<='Z') ||
+            (character>='0' && character<='9') ||
+            character=='_' );
+    
+
+    SkipWhiteCharacters();
+    
+
+    /*
+        if there's a character '(' that means this name is a name of a function
+    */
+    if( *pstring == '(' )
+    {
+        ++pstring;
+        return true;
+    }
+    
+    
+return false;
+}
+
+
+/*!
+    we're checking whether the first character is '-' or '+'
+    if it is we'll return 'true' and if it is equally '-' we'll set the 'sign' member of 'result'
+*/
+bool TestSign(Item & result)
+{
+    SkipWhiteCharacters();
+    result.sign = false;
+
+    if( *pstring == '-' || *pstring == '+' )
+    {
+        if( *pstring == '-' )
+            result.sign = true;
+
+        ++pstring;
+
+    return true;
+    }
+
+return false;
+}
+
+
+/*!
+    we're reading the name of a variable or a function
+    if is there a function we'll return 'true'
+*/
+bool ReadVariableOrFunction(Item & result)
+{
+std::string name;
+bool is_it_name_of_function = ReadName(name);
+
+    if( is_it_name_of_function )
+    {
+        /*
+            we've read the name of a function
+        */
+        result.function_name = name;
+        result.type     = Item::first_bracket;
+        result.function = true;
+    }
+    else
+    {
+        /*
+            we've read the name of a variable and we're getting its value now
+        */
+        result.value = GetValueOfVariable( name );
+    }
+
+return is_it_name_of_function;
+}
+
+
+
+
+/*!
+    we're reading a numerical value directly from the string
+*/
+void ReadValue(Item & result, int reading_base)
+{
+const char * new_stack_pointer;
+bool value_read;
+Conv conv;
+
+    conv.base   = reading_base;
+    conv.comma  = comma;
+    conv.comma2 = comma2;
+    conv.group  = group;
+
+    uint carry = result.value.FromString(pstring, conv, &new_stack_pointer, &value_read);
+    pstring    = new_stack_pointer;
+
+    if( carry )
+        Error( err_overflow );
+
+    if( !value_read )
+        Error( err_unknown_character );
+}
+
+
+/*!
+    this method returns true if 'character' is a proper first digit for the value (or a comma -- can be first too)
+*/
+bool ValueStarts(int character, int base)
+{
+    if( character == comma )
+        return true;
+
+    if( comma2!=0 && character==comma2 )
+        return true;
+
+    if( Misc::CharToDigit(character, base) != -1 )
+        return true;
+
+return false;
+}
+
+
+/*!
+    we're reading the item
+  
+    return values:
+        0 - all ok, the item is successfully read
+        1 - the end of the string (the item is not read)
+        2 - the final bracket ')'
+*/
+int ReadValueVariableOrFunction(Item & result)
+{
+bool it_was_sign = false;
+int  character;
+
+
+    if( TestSign(result) )
+        // 'result.sign' was set as well
+        it_was_sign = true;
+
+    SkipWhiteCharacters();
+    character = ToLowerCase( *pstring );
+
+
+    if( character == 0 )
+    {
+        if( it_was_sign )
+            // at the end of the string a character like '-' or '+' has left
+            Error( err_unexpected_end );
+
+        // there's the end of the string here
+        return 1;
+    }
+    else
+    if( character == '(' )
+    {
+        // we've got a normal bracket (not a function)
+        result.type = Item::first_bracket;
+        result.function = false;
+        ++pstring;
+
+    return 0;
+    }
+    else
+    if( character == ')' )
+    {
+        // we've got a final bracket
+        // (in this place we can find a final bracket only when there are empty brackets
+        // without any values inside or with a sign '-' or '+' inside)
+
+        if( it_was_sign )
+            Error( err_unexpected_final_bracket );
+
+        result.type = Item::last_bracket;
+
+        // we don't increment 'pstring', this final bracket will be read next by the 
+        // 'ReadOperatorAndCheckFinalBracket(...)' method
+
+    return 2;
+    }
+    else
+    if( character == '#' )
+    {
+        ++pstring;
+        SkipWhiteCharacters();
+
+        // after '#' character we do not allow '-' or '+' (can be white characters)
+        if(    ValueStarts(*pstring, 16) )
+            ReadValue( result, 16 );
+        else
+            Error( err_unknown_character );
+    }
+    else
+    if( character == '&' )
+    {
+        ++pstring;
+        SkipWhiteCharacters();
+
+        // after '&' character we do not allow '-' or '+' (can be white characters)
+        if(    ValueStarts(*pstring, 2) )
+            ReadValue( result, 2 );
+        else
+            Error( err_unknown_character );
+    }
+    else
+    if(    ValueStarts(character, base) )
+    {
+        ReadValue( result, base );
+    }
+    else
+    if( character>='a' && character<='z' )
+    {
+        if( ReadVariableOrFunction(result) )
+            // we've read the name of a function
+            return 0;
+    }
+    else
+        Error( err_unknown_character );
+
+
+
+    /*
+        we've got a value in the 'result'
+        this value is from a variable or directly from the string
+    */
+    result.type = Item::numerical_value;
+    
+    if( result.sign )
+    {
+        result.value.ChangeSign();
+        result.sign = false;
+    }
+    
+
+return 0;
+}
+
+
+void InsertOperatorToTable(const char * name, typename MatOperator::Type type)
+{
+    operators_table.insert( std::make_pair(std::string(name), type) );
+}
+
+
+/*!
+    this method creates the table of operators
+*/
+void CreateMathematicalOperatorsTable()
+{
+    InsertOperatorToTable("||", MatOperator::lor);
+    InsertOperatorToTable("&&", MatOperator::land);
+    InsertOperatorToTable("!=", MatOperator::neq);
+    InsertOperatorToTable("==", MatOperator::eq);
+    InsertOperatorToTable(">=", MatOperator::get);
+    InsertOperatorToTable("<=", MatOperator::let);
+    InsertOperatorToTable(">",  MatOperator::gt);
+    InsertOperatorToTable("<",  MatOperator::lt);
+    InsertOperatorToTable("-",  MatOperator::sub);
+    InsertOperatorToTable("+",  MatOperator::add);
+    InsertOperatorToTable("/",  MatOperator::div);
+    InsertOperatorToTable("*",  MatOperator::mul);
+    InsertOperatorToTable("^",  MatOperator::pow);
+}
+
+
+/*!
+    returns true if 'str2' is the substring of str1
+
+    e.g.
+    true when str1="test" and str2="te"
+*/
+bool IsSubstring(const std::string & str1, const std::string & str2)
+{
+    if( str2.length() > str1.length() )
+        return false;
+
+    for(typename std::string::size_type i=0 ; i<str2.length() ; ++i)
+        if( str1[i] != str2[i] )
+            return false;
+
+return true;
+}
+
+
+/*!
+    this method reads a mathematical (or logical) operator
+*/
+void ReadMathematicalOperator(Item & result)
+{
+std::string oper;
+typename OperatorsTable::iterator iter_old, iter_new;
+
+    iter_old = operators_table.end();
+
+    for( ; true ; ++pstring )
+    {
+        oper += *pstring;
+        iter_new = operators_table.lower_bound(oper);
+        
+        if( iter_new == operators_table.end() || !IsSubstring(iter_new->first, oper) )
+        {
+            oper.erase( --oper.end() ); // we've got mininum one element
+
+            if( iter_old != operators_table.end() && iter_old->first == oper )
+            {
+                result.type = Item::mat_operator;
+                result.moperator.SetType( iter_old->second );
+                break;
+            }
+            
+            Error( err_unknown_operator );
+        }
+    
+        iter_old = iter_new;
+    }
+}
+
+
+/*!
+    this method makes a calculation for the percentage operator
+    e.g.
+    1000-50% = 1000-(1000*0,5) = 500
+*/
+void OperatorPercentage()
+{
+    if( stack_index < 3                                        ||
+        stack[stack_index-1].type != Item::numerical_value    ||
+        stack[stack_index-2].type != Item::mat_operator        ||
+        stack[stack_index-3].type != Item::numerical_value    )
+        Error(err_percent_from);
+
+    ++pstring;
+    SkipWhiteCharacters();
+
+    uint c = 0;
+    c += stack[stack_index-1].value.Div(100);
+    c += stack[stack_index-1].value.Mul(stack[stack_index-3].value);
+
+    if( c )
+        Error(err_overflow);
+}
+
+
+/*!
+    this method reads a mathematic operators
+    or the final bracket or the semicolon operator
+
+    return values:
+        0 - ok
+        1 - the string is finished
+*/
+int ReadOperator(Item & result)
+{
+    SkipWhiteCharacters();
+
+    if( *pstring == '%' )
+        OperatorPercentage();
+
+
+    if( *pstring == 0 )
+        return 1;
+    else
+    if( *pstring == ')' )
+    {
+        result.type = Item::last_bracket;
+        ++pstring;
+    }
+    else
+    if( *pstring == ';' || (param_sep!=0 && *pstring==param_sep) )
+    {
+        result.type = Item::semicolon;
+        ++pstring;
+    }
+    else
+    if( (*pstring>='a' && *pstring<='z') || (*pstring>='A' && *pstring<='Z') )
+    {
+        // short mul (without any operators)
+
+        result.type = Item::mat_operator;
+        result.moperator.SetType( MatOperator::shortmul );
+    }
+    else
+        ReadMathematicalOperator(result);
+
+return 0;
+}
+
+
+
+/*!
+    this method is making the standard mathematic operation like '-' '+' '*' '/' and '^'
+
+    the operation is made between 'value1' and 'value2'
+    the result of this operation is stored in the 'value1'
+*/
+void MakeStandardMathematicOperation(ValueType & value1, typename MatOperator::Type mat_operator,
+                                    const ValueType & value2)
+{
+uint res;
+
+    calculated = true;
+
+    switch( mat_operator )
+    {
+    case MatOperator::land:
+        (!value1.IsZero() && !value2.IsZero()) ? value1.SetOne() : value1.SetZero();
+        break;
+
+    case MatOperator::lor:
+        (!value1.IsZero() || !value2.IsZero()) ? value1.SetOne() : value1.SetZero();
+        break;
+
+    case MatOperator::eq:
+        (value1 == value2) ? value1.SetOne() : value1.SetZero();
+        break;
+
+    case MatOperator::neq:
+        (value1 != value2) ? value1.SetOne() : value1.SetZero();
+        break;
+
+    case MatOperator::lt:
+        (value1 < value2) ? value1.SetOne() : value1.SetZero();
+        break;
+
+    case MatOperator::gt:
+        (value1 > value2) ? value1.SetOne() : value1.SetZero();
+        break;
+
+    case MatOperator::let:
+        (value1 <= value2) ? value1.SetOne() : value1.SetZero();
+        break;
+
+    case MatOperator::get:
+        (value1 >= value2) ? value1.SetOne() : value1.SetZero();
+        break;
+
+    case MatOperator::sub:
+        if( value1.Sub(value2) ) Error( err_overflow );
+        break;
+
+    case MatOperator::add:
+        if( value1.Add(value2) ) Error( err_overflow );
+        break;
+
+    case MatOperator::mul:
+    case MatOperator::shortmul:
+        if( value1.Mul(value2) ) Error( err_overflow );
+        break;
+
+    case MatOperator::div:
+        if( value2.IsZero() )    Error( err_division_by_zero );
+        if( value1.Div(value2) ) Error( err_overflow );
+        break;
+
+    case MatOperator::pow:
+        res = value1.Pow( value2 );
+
+        if( res == 1 ) Error( err_overflow );
+        else
+        if( res == 2 ) Error( err_improper_argument );
+
+        break;
+
+    default:
+        /*
+            on the stack left an unknown operator but we had to recognize its before
+            that means there's an error in our algorithm
+        */
+        Error( err_internal_error );
+    }
+}
+
+
+
+
+/*!
+    this method is trying to roll the stack up with the operator's priority
+
+    for example if there are:
+        "1 - 2 +" 
+    we can subtract "1-2" and the result store on the place where is '1' and copy the last
+    operator '+', that means there'll be '-1+' on our stack
+
+    but if there are:
+        "1 - 2 *"
+    we can't roll the stack up because the operator '*' has greater priority than '-'
+*/
+void TryRollingUpStackWithOperatorPriority()
+{
+    while(    stack_index>=4 &&
+            stack[stack_index-4].type == Item::numerical_value &&
+            stack[stack_index-3].type == Item::mat_operator    &&
+            stack[stack_index-2].type == Item::numerical_value &&
+            stack[stack_index-1].type == Item::mat_operator    &&
+            (
+                (
+                    // the first operator has greater priority
+                    stack[stack_index-3].moperator.GetPriority() > stack[stack_index-1].moperator.GetPriority()
+                ) ||
+                (
+                    // or both operators have the same priority and the first operator is not right associative
+                    stack[stack_index-3].moperator.GetPriority() == stack[stack_index-1].moperator.GetPriority() &&
+                    stack[stack_index-3].moperator.GetAssoc()    == MatOperator::non_right
+                )
+            )
+         )
+    {
+        MakeStandardMathematicOperation(stack[stack_index-4].value,
+                                        stack[stack_index-3].moperator.GetType(),
+                                        stack[stack_index-2].value);
+
+
+        /*
+            copying the last operator and setting the stack pointer to the correct value
+        */
+        stack[stack_index-3] = stack[stack_index-1];
+        stack_index -= 2;
+    }
+}
+
+
+/*!
+    this method is trying to roll the stack up without testing any operators
+
+    for example if there are:
+        "1 - 2" 
+    there'll be "-1" on our stack
+*/
+void TryRollingUpStack()
+{
+    while(    stack_index >= 3 &&
+            stack[stack_index-3].type == Item::numerical_value &&
+            stack[stack_index-2].type == Item::mat_operator &&
+            stack[stack_index-1].type == Item::numerical_value )
+    {
+        MakeStandardMathematicOperation(    stack[stack_index-3].value,
+                                            stack[stack_index-2].moperator.GetType(),
+                                            stack[stack_index-1].value );
+
+        stack_index -= 2;
+    }
+}
+
+
+/*!
+    this method is reading a value or a variable or a function
+    (the normal first bracket as well) and push it into the stack
+*/
+int ReadValueVariableOrFunctionAndPushItIntoStack(Item & temp)
+{
+int code = ReadValueVariableOrFunction( temp );
+    
+    if( code == 0 )
+    {
+        if( stack_index < stack.size() )
+            stack[stack_index] = temp;
+        else
+            stack.push_back( temp );
+
+        ++stack_index;
+    }
+
+    if( code == 2 )
+        // there was a final bracket, we didn't push it into the stack 
+        // (it'll be read by the 'ReadOperatorAndCheckFinalBracket' method next)
+        code = 0;
+
+
+return code;
+}
+
+
+
+/*!
+    this method calculate how many parameters there are on the stack
+    and the index of the first parameter
+
+    if there aren't any parameters on the stack this method returns
+    'size' equals zero and 'index' pointing after the first bracket
+    (on non-existend element)
+*/
+void HowManyParameters(int & size, int & index)
+{
+    size  = 0;
+    index = stack_index;
+
+    if( index == 0 )
+        // we haven't put a first bracket on the stack
+        Error( err_unexpected_final_bracket );
+
+
+    if( stack[index-1].type == Item::first_bracket )
+        // empty brackets
+        return;
+
+    for( --index ; index>=1 ; index-=2 )
+    {
+        if( stack[index].type != Item::numerical_value )
+        {
+            /*
+                this element must be 'numerical_value', if not that means 
+                there's an error in our algorithm
+            */
+            Error( err_internal_error );
+        }
+
+        ++size;
+
+        if( stack[index-1].type != Item::semicolon )
+            break;
+    }
+
+    if( index<1 || stack[index-1].type != Item::first_bracket )
+    {
+        /*
+            we haven't put a first bracket on the stack
+        */
+        Error( err_unexpected_final_bracket );
+    }
+}
+
+
+/*!
+    this method is being called when the final bracket ')' is being found
+
+    this method's rolling the stack up, counting how many parameters there are
+    on the stack and if there was a function it's calling the function
+*/
+void RollingUpFinalBracket()
+{
+int amount_of_parameters;
+int index;
+
+    
+    if( stack_index<1 ||
+        (stack[stack_index-1].type != Item::numerical_value &&
+         stack[stack_index-1].type != Item::first_bracket)
+      )
+        Error( err_unexpected_final_bracket );
+    
+
+    TryRollingUpStack();
+    HowManyParameters(amount_of_parameters, index);
+
+    // 'index' will be greater than zero
+    // 'amount_of_parameters' can be zero
+
+
+    if( amount_of_parameters==0 && !stack[index-1].function )
+        Error( err_unexpected_final_bracket );
+
+
+    bool was_sign = stack[index-1].sign;
+
+
+    if( stack[index-1].function )
+    {
+        // the result of a function will be on 'stack[index-1]'
+        // and then at the end we'll set the correct type (numerical value) of this element
+        CallFunction(stack[index-1].function_name, amount_of_parameters, index);
+    }
+    else
+    {
+        /*
+            there was a normal bracket (not a funcion)
+        */
+        if( amount_of_parameters != 1 )
+            Error( err_unexpected_semicolon_operator );
+
+
+        /*
+            in the place where is the bracket we put the result
+        */
+        stack[index-1] = stack[index];
+    }
+
+
+    /*
+        if there was a '-' character before the first bracket
+        we change the sign of the expression
+    */
+    stack[index-1].sign = false;
+
+    if( was_sign )
+        stack[index-1].value.ChangeSign();
+
+    stack[index-1].type = Item::numerical_value;
+
+
+    /*
+        the pointer of the stack will be pointing on the next (non-existing now) element
+    */
+    stack_index = index;
+}
+
+
+/*!
+    this method is putting the operator on the stack
+*/
+
+void PushOperatorIntoStack(Item & temp)
+{
+    if( stack_index < stack.size() )
+        stack[stack_index] = temp;
+    else
+        stack.push_back( temp );
+
+    ++stack_index;
+}
+
+
+
+/*!
+    this method is reading a operator and if it's a final bracket
+    it's calling RollingUpFinalBracket() and reading a operator again
+*/
+int ReadOperatorAndCheckFinalBracket(Item & temp)
+{
+    do
+    {
+        if( ReadOperator(temp) == 1 )
+        {
+            /*
+                the string is finished
+            */
+        return 1;
+        }
+
+        if( temp.type == Item::last_bracket )
+            RollingUpFinalBracket();
+
+    }
+    while( temp.type == Item::last_bracket );
+
+return 0;
+}
+
+
+/*!
+    we check wheter there are only numerical value's or 'semicolon' operators on the stack
+*/
+void CheckIntegrityOfStack()
+{
+    for(unsigned int i=0 ; i<stack_index; ++i)
+    {
+        if( stack[i].type != Item::numerical_value &&
+            stack[i].type != Item::semicolon)
+        {
+            /*
+                on the stack we must only have 'numerical_value' or 'semicolon' operator
+                if there is something another that means
+                we probably didn't close any of the 'first' bracket
+            */
+            Error( err_stack_not_clear );
+        }
+    }
+}
+
+
+
+/*!
+    the main loop of parsing
+*/
+void Parse()
+{
+Item item;    
+int result_code;
+
+
+    while( true )
+    {
+        if( pstop_calculating && pstop_calculating->WasStopSignal() )
+            Error( err_interrupt );
+
+        result_code = ReadValueVariableOrFunctionAndPushItIntoStack( item );
+
+        if( result_code == 0 )
+        {
+            if( item.type == Item::first_bracket )
+                continue;
+            
+            result_code = ReadOperatorAndCheckFinalBracket( item );
+        }
+    
+        
+        if( result_code==1 || item.type==Item::semicolon )
+        {
+            /*
+                the string is finished or the 'semicolon' operator has appeared
+            */
+
+            if( stack_index == 0 )
+                Error( err_nothing_has_read );
+            
+            TryRollingUpStack();
+
+            if( result_code == 1 )
+            {
+                CheckIntegrityOfStack();
+
+            return;
+            }
+        }            
+    
+
+        PushOperatorIntoStack( item );
+        TryRollingUpStackWithOperatorPriority();
+    }
+}
+
+/*!
+    this method is called at the end of the parsing process
+
+    on our stack we can have another value than 'numerical_values' for example
+    when someone use the operator ';' in the global scope or there was an error during
+    parsing and the parser hasn't finished its job
+
+    if there was an error the stack is cleaned up now
+    otherwise we resize stack and leave on it only 'numerical_value' items
+*/
+void NormalizeStack()
+{
+    if( error!=err_ok || stack_index==0 )
+    {
+        stack.clear();
+        return;
+    }
+    
+    
+    /*
+        'stack_index' tell us how many elements there are on the stack,
+        we must resize the stack now because 'stack_index' is using only for parsing
+        and stack has more (or equal) elements than value of 'stack_index'
+    */
+    stack.resize( stack_index );
+
+    for(uint i=stack_index-1 ; i!=uint(-1) ; --i)
+    {
+        if( stack[i].type != Item::numerical_value )
+            stack.erase( stack.begin() + i );
+    }
+}
+
+
+public:
+
+
+/*!
+    the default constructor
+*/
+Parser(): default_stack_size(100)
+{
+    pstop_calculating = 0;
+    puser_variables   = 0;
+    puser_functions   = 0;
+    pfunction_local_variables = 0;
+    base              = 10;
+    deg_rad_grad      = 1;
+    error             = err_ok;
+    group             = 0;
+    comma             = '.';
+    comma2            = ',';
+    param_sep         = 0;
+
+    CreateFunctionsTable();
+    CreateVariablesTable();
+    CreateMathematicalOperatorsTable();
+}
+
+
+/*!
+    the assignment operator
+*/
+Parser<ValueType> & operator=(const Parser<ValueType> & p)
+{
+    pstop_calculating = p.pstop_calculating;
+    puser_variables   = p.puser_variables;
+    puser_functions   = p.puser_functions;
+    pfunction_local_variables = 0;
+    base              = p.base;
+    deg_rad_grad      = p.deg_rad_grad;
+    error             = p.error;
+    group             = p.group;
+    comma             = p.comma;
+    comma2            = p.comma2;
+    param_sep         = p.param_sep;
+
+    /*
+        we don't have to call 'CreateFunctionsTable()' etc.
+        we can only copy these tables
+    */
+    functions_table   = p.functions_table;
+    variables_table   = p.variables_table;
+    operators_table   = p.operators_table;
+
+    visited_variables = p.visited_variables;
+    visited_functions = p.visited_functions;
+
+return *this;
+}
+
+
+/*!
+    the copying constructor
+*/
+Parser(const Parser<ValueType> & p): default_stack_size(p.default_stack_size)
+{
+    operator=(p);
+}
+
+
+/*!
+    the new base of mathematic system
+    default is 10
+*/
+void SetBase(int b)
+{
+    if( b>=2 && b<=16 )
+        base = b;
+}
+
+
+/*!
+    the unit of angles used in: sin,cos,tan,cot,asin,acos,atan,acot
+    0 - deg
+    1 - rad (default)
+    2 - grad
+*/
+void SetDegRadGrad(int angle)
+{
+    if( angle >= 0 || angle <= 2 )
+        deg_rad_grad = angle;
+}
+
+/*!
+    this method sets a pointer to the object which tell us whether we should stop
+    calculations
+*/
+void SetStopObject(const volatile StopCalculating * ps)
+{
+    pstop_calculating = ps;
+}
+
+
+/*!
+    this method sets the new table of user-defined variables
+    if you don't want any other variables just put zero value into the 'puser_variables' variable
+
+    (you can have only one table at the same time)
+*/
+void SetVariables(const Objects * pv)
+{
+    puser_variables = pv;
+}
+
+
+/*!
+    this method sets the new table of user-defined functions
+    if you don't want any other functions just put zero value into the 'puser_functions' variable
+
+    (you can have only one table at the same time)
+*/
+void SetFunctions(const Objects * pf)
+{
+    puser_functions = pf;
+}
+
+
+/*!
+    setting the group character
+    default zero (not used)
+*/
+void SetGroup(int g)
+{
+    group = g;
+}
+
+
+/*!
+    setting the main comma operator and the additional comma operator
+    the additional operator can be zero (which means it is not used)
+    default are: '.' and ','
+*/
+void SetComma(int c, int c2 = 0)
+{
+    comma  = c;
+    comma2 = c2;
+}
+
+
+/*!
+    setting an additional character which is used as a parameters separator
+    the main parameters separator is a semicolon (is used always)
+
+    this character is used also as a global separator
+*/
+void SetParamSep(int s)
+{
+    param_sep = s;
+}
+
+
+/*!
+    the main method using for parsing string
+*/
+ErrorCode Parse(const char * str)
+{
+    stack_index  = 0;
+    pstring      = str;
+    error        = err_ok;
+    calculated   = false;
+
+    stack.resize( default_stack_size );
+
+    try
+    {
+        Parse();
+    }
+    catch(ErrorCode c)
+    {
+        error = c;
+        calculated = false;
+    }
+
+    NormalizeStack();
+
+return error;
+}
+
+
+/*!
+    the main method using for parsing string
+*/
+ErrorCode Parse(const std::string & str)
+{
+    return Parse(str.c_str());
+}
+
+
+#ifndef TTMATH_DONT_USE_WCHAR
+
+/*!
+    the main method using for parsing string
+*/
+ErrorCode Parse(const wchar_t * str)
+{
+    Misc::AssignString(wide_to_ansi, str);
+
+return Parse(wide_to_ansi.c_str());
+
+    // !! wide_to_ansi clearing can be added here
+}
+
+
+/*!
+    the main method using for parsing string
+*/
+ErrorCode Parse(const std::wstring & str)
+{
+    return Parse(str.c_str());
+}
+
+#endif
+
+
+/*!
+    this method returns true is something was calculated
+    (at least one mathematical operator was used or a function or variable)
+    e.g. true if the string to Parse() looked like this:
+    "1+1"
+    "2*3"
+    "sin(5)"
+
+    if the string was e.g. "678" the result is false
+*/
+bool Calculated()
+{
+    return calculated;
+}
+
+
+/*!
+    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();
+}
+
+
+};
+
+
+
+} // namespace
+
+
+#endif
+
diff -r 000000000000 -r 04a9f72bbca7 ttmaththreads.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ttmaththreads.h	Tue Jul 30 18:43:48 2013 +0000
@@ -0,0 +1,251 @@
+/*
+ * This file is a part of TTMath Bignum Library
+ * and is distributed under the (new) BSD licence.
+ * Author: Tomasz Sowa <t.sowa@ttmath.org>
+ */
+
+/* 
+ * Copyright (c) 2006-2009, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+#ifndef headerfilettmaththreads
+#define headerfilettmaththreads
+
+#include "ttmathtypes.h"
+
+#ifdef TTMATH_WIN32_THREADS
+#include <windows.h>
+#include <cstdio>
+#endif
+
+#ifdef TTMATH_POSIX_THREADS
+#include <pthread.h>
+#endif
+
+
+
+/*!
+    \file ttmaththreads.h
+    \brief Some objects used in multithreads environment
+*/
+
+
+/*
+    this is a simple skeleton of a program in multithreads environment:
+
+    #define TTMATH_MULTITHREADS
+    #include<ttmath/ttmath.h>
+    
+    TTMATH_MULTITHREADS_HELPER
+
+    int main()
+    {
+    [...]
+    }
+
+    make sure that macro TTMATH_MULTITHREADS is defined and (somewhere in *.cpp file)
+    use TTMATH_MULTITHREADS_HELPER macro (outside of any classes/functions/namespaces scope)
+*/
+
+
+namespace ttmath
+{
+
+
+#ifdef TTMATH_WIN32_THREADS
+
+    /*
+        we use win32 threads
+    */
+
+
+    /*!
+        in multithreads environment you should use TTMATH_MULTITHREADS_HELPER macro
+        somewhere in *.cpp file
+
+        (at the moment in win32 this macro does nothing)
+    */
+    #define TTMATH_MULTITHREADS_HELPER
+
+
+    /*!
+        objects of this class are used to synchronize
+    */
+    class ThreadLock
+    {
+        HANDLE mutex_handle;
+
+
+        void CreateName(char * buffer) const
+        {
+            #ifdef _MSC_VER
+            #pragma warning (disable : 4996)
+            // warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead.
+            #endif
+
+            sprintf(buffer, "TTMATH_LOCK_%ul", (unsigned long)GetCurrentProcessId());
+
+            #ifdef _MSC_VER
+            #pragma warning (default : 4996)
+            #endif
+        }
+
+
+    public:
+
+        bool Lock()
+        {
+        char buffer[50];
+
+            CreateName(buffer);
+            mutex_handle = CreateMutexA(0, false, buffer);
+
+            if( mutex_handle == 0 )
+                return false;
+
+            WaitForSingleObject(mutex_handle, INFINITE);
+
+        return true;
+        }
+
+
+        ThreadLock()
+        {
+            mutex_handle = 0;
+        }
+
+
+        ~ThreadLock()
+        {
+            if( mutex_handle != 0 )
+            {
+                ReleaseMutex(mutex_handle);
+                CloseHandle(mutex_handle);
+            }
+        }
+    };
+
+#endif  // #ifdef TTMATH_WIN32_THREADS
+
+
+
+
+
+#ifdef TTMATH_POSIX_THREADS
+
+    /*
+        we use posix threads
+    */
+
+
+    /*!
+        in multithreads environment you should use TTMATH_MULTITHREADS_HELPER macro
+        somewhere in *.cpp file
+        (this macro defines a pthread_mutex_t object used by TTMath library)
+    */
+    #define TTMATH_MULTITHREADS_HELPER                          \
+    namespace ttmath                                            \
+    {                                                           \
+    pthread_mutex_t ttmath_mutex = PTHREAD_MUTEX_INITIALIZER;   \
+    }
+
+
+    /*!
+        ttmath_mutex will be defined by TTMATH_MULTITHREADS_HELPER macro 
+    */
+    extern pthread_mutex_t ttmath_mutex;
+
+
+    /*!
+        objects of this class are used to synchronize
+    */
+    class ThreadLock
+    {
+    public:
+
+        bool Lock()
+        {
+            if( pthread_mutex_lock(&ttmath_mutex) != 0 )
+                return false;
+
+        return true;
+        }
+
+
+        ~ThreadLock()
+        {
+            pthread_mutex_unlock(&ttmath_mutex);
+        }
+    };
+
+#endif // #ifdef TTMATH_POSIX_THREADS
+
+
+
+
+#if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS)
+
+    /*!
+        we don't use win32 and pthreads
+    */
+
+    /*!
+    */
+    #define TTMATH_MULTITHREADS_HELPER
+
+
+    /*!
+        objects of this class are used to synchronize
+        actually we don't synchronize, the method Lock() returns always 'false'
+    */
+    class ThreadLock
+    {
+    public:
+
+        bool Lock()
+        {
+            return false;
+        }
+    };
+
+
+#endif // #if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS)
+
+
+
+
+
+} // namespace
+
+#endif
+
+
diff -r 000000000000 -r 04a9f72bbca7 ttmathtypes.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ttmathtypes.h	Tue Jul 30 18:43:48 2013 +0000
@@ -0,0 +1,677 @@
+/*
+ * This file is a part of TTMath Bignum Library
+ * and is distributed under the (new) BSD licence.
+ * Author: Tomasz Sowa <t.sowa@ttmath.org>
+ */
+
+/* 
+ * Copyright (c) 2006-2012, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef headerfilettmathtypes
+#define headerfilettmathtypes
+
+/*!
+    \file ttmathtypes.h
+    \brief constants used in the library
+    
+    As our library is written in header files (templates) we cannot use
+    constants like 'const int' etc. because we should have some source files
+    *.cpp to define this variables. Only what we can have are constants
+    defined by #define preprocessor macros.
+
+    All macros are preceded by TTMATH_ prefix
+*/
+
+
+#include <stdexcept>
+#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
+    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        3
+
+#define TTMATH_PRERELEASE_VER    0
+
+
+
+/*!
+    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__
+
+        /*
+            other platforms than x86 and amd64 are not recognized at the moment
+            so you should set TTMATH_PLATFORMxx manually
+        */
+
+        // we're using a 32bit platform
+        #define TTMATH_PLATFORM32
+
+    #else
+
+        //    we're using a 64bit platform
+        #define TTMATH_PLATFORM64
+
+    #endif
+
+#endif
+
+
+/*!
+    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
+*/
+#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, CLANG (LLVM) 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 or CLANG (LLVM) by default use no asm version
+            (CLANG defines __GNUC__ too)
+        */
+        #define TTMATH_NOASM
+    #endif
+
+#endif
+
+
+namespace ttmath
+{
+
+
+#ifdef TTMATH_PLATFORM32
+
+    /*!
+        on 32bit platforms one word (uint, sint) will be equal 32bits
+    */
+    typedef unsigned int uint;
+    typedef signed   int sint;
+
+    /*!
+        on 32 bit platform ulint and slint will be equal 64 bits
+    */
+    #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
+
+    /*!
+        how many bits there are in the uint type
+    */
+    #define TTMATH_BITS_PER_UINT 32u
+
+    /*!
+        the mask for the highest bit in the unsigned 32bit word (2^31)
+    */
+    #define TTMATH_UINT_HIGHEST_BIT 2147483648u
+
+    /*!
+        the max value of the unsigned 32bit word (2^32 - 1)
+        (all bits equal one)
+    */
+    #define TTMATH_UINT_MAX_VALUE 4294967295u
+
+    /*!
+        the number of words (32bit words on 32bit platform)
+        which are kept in built-in variables for a Big<> type
+        (these variables are defined in ttmathbig.h)
+    */
+    #define TTMATH_BUILTIN_VARIABLES_SIZE 256u
+
+    /*!
+        this macro returns the number of machine words 
+        capable to hold min_bits bits
+        e.g. TTMATH_BITS(128) returns 4
+    */
+    #define TTMATH_BITS(min_bits) ((min_bits-1)/32 + 1)
+
+#else
+
+    /*!
+        on 64bit platforms one word (uint, sint) will be equal 64bits
+    */
+    #ifdef _MSC_VER
+        /* in VC 'long' type has 32 bits, __int64 is VC extension */
+        typedef unsigned __int64 uint;
+        typedef signed   __int64 sint;
+    #else
+        typedef unsigned long uint;
+        typedef signed   long sint;
+    #endif 
+
+    /*!
+        on 64bit platforms we do not define ulint and slint
+    */
+
+    /*!
+        how many bits there are in the uint type
+    */
+    #define TTMATH_BITS_PER_UINT 64ul
+
+    /*!
+        the mask for the highest bit in the unsigned 64bit word (2^63)
+    */
+    #define TTMATH_UINT_HIGHEST_BIT 9223372036854775808ul
+
+    /*!
+        the max value of the unsigned 64bit word (2^64 - 1)
+        (all bits equal one)
+    */
+    #define TTMATH_UINT_MAX_VALUE 18446744073709551615ul
+
+    /*!
+        the number of words (64bit words on 64bit platforms)
+        which are kept in built-in variables for a Big<> type
+        (these variables are defined in ttmathbig.h)
+    */
+    #define TTMATH_BUILTIN_VARIABLES_SIZE 128ul
+
+    /*!
+        this macro returns the number of machine words 
+        capable to hold min_bits bits
+        e.g. TTMATH_BITS(128) returns 2
+    */
+    #define TTMATH_BITS(min_bits) ((min_bits-1)/64 + 1)
+
+#endif
+}
+
+
+#if defined(TTMATH_MULTITHREADS) && !defined(TTMATH_MULTITHREADS_NOSYNC)
+    #if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS)
+
+        #if defined(_WIN32)
+            #define TTMATH_WIN32_THREADS
+        #elif defined(unix) || defined(__unix__) || defined(__unix)
+            #define TTMATH_POSIX_THREADS
+        #endif
+
+    #endif
+#endif
+
+
+
+/*!
+    this variable defines how many iterations are performed
+    during some kind of calculating when we're making any long formulas
+    (for example Taylor series)
+
+    it's used in ExpSurrounding0(...), LnSurrounding1(...), Sin0pi05(...), etc.
+
+    note! there'll not be so many iterations, iterations are stopped when
+    there is no sense to continue calculating (for example when the result
+    still remains unchanged after adding next series and we know that the next
+    series are smaller than previous ones)
+*/
+#define TTMATH_ARITHMETIC_MAX_LOOP 10000
+
+
+
+/*!
+    this is a limit when calculating Karatsuba multiplication
+    if the size of a vector is smaller than TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE
+    the Karatsuba algorithm will use standard schoolbook multiplication
+*/
+#ifdef TTMATH_DEBUG_LOG
+    // if TTMATH_DEBUG_LOG is defined then we should use the same size regardless of the compiler
+    #define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 3
+#else
+    #ifdef __GNUC__
+        #define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 3
+    #else
+        #define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 5
+    #endif
+#endif
+
+
+/*!
+    this is a special value used when calculating the Gamma(x) function
+    if x is greater than this value then the Gamma(x) will be calculated using
+    some kind of series
+
+    don't use smaller values than about 100
+*/
+#define TTMATH_GAMMA_BOUNDARY 2000
+
+
+
+
+
+namespace ttmath
+{
+
+    /*!
+        lib type codes:
+          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
+    */
+    enum LibTypeCode
+    {
+      asm_vc_32 = 0,
+      asm_gcc_32,
+      asm_vc_64,
+      asm_gcc_64,
+      no_asm_32,
+      no_asm_64
+    };
+
+
+    /*!
+        error codes
+    */
+    enum ErrorCode
+    {
+        err_ok = 0,
+        err_nothing_has_read,
+        err_unknown_character,
+        err_unexpected_final_bracket,
+        err_stack_not_clear,
+        err_unknown_variable,
+        err_division_by_zero,
+        err_interrupt,
+        err_overflow,
+        err_unknown_function,
+        err_unknown_operator,
+        err_unexpected_semicolon_operator,
+        err_improper_amount_of_arguments,
+        err_improper_argument,
+        err_unexpected_end,
+        err_internal_error,
+        err_incorrect_name,
+        err_incorrect_value,
+        err_variable_exists,
+        err_variable_loop,
+        err_functions_loop,
+        err_must_be_only_one_value,
+        err_object_exists,
+        err_unknown_object,
+        err_still_calculating,
+        err_in_short_form_used_function,
+        err_percent_from
+    };
+
+
+    /*!
+        this struct is used when converting to/from a string
+        /temporarily only in Big::ToString() and Big::FromString()/
+    */
+    struct Conv
+    {
+        /*!
+            base (radix) on which the value will be shown (or read)
+            default: 10
+        */
+        uint base;
+
+
+        /*!
+            used only in Big::ToString()
+            if true the value will be always shown in the scientific mode, e.g: 123e+30
+            default: false
+        */
+        bool scient;
+
+
+        /*!
+            used only in Big::ToString()
+            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
+        */
+        sint scient_from;
+
+
+        /*!
+            if 'base_round' is true and 'base' is different from 2, 4, 8, or 16
+            and the result value is not an integer then we make an additional rounding
+            (after converting the last digit from the result is skipped)
+            default: true
+
+            e.g.
+            Conv c;
+            c.base_round = false;
+            Big<1, 1> a = "0.1";                       // decimal input
+            std::cout << a.ToString(c) << std::endl;   // the result is: 0.099999999
+        */
+        bool base_round;
+
+
+        /*!
+            used only in Big::ToString()
+            tells how many digits after comma are possible
+            default: -1 which means all digits are printed
+
+            set it to zero if you want integer value only
+
+            for example when the value is:
+                12.345678 and 'round' is 4
+            then the result will be 
+                12.3457   (the last digit was rounded)
+        */
+        sint round;
+
+
+        /*!
+            if true that not mattered digits in the mantissa will be cut off
+            (zero characters at the end -- after the comma operator)
+            e.g. 1234,78000 will be: 1234,78
+            default: true
+        */
+        bool trim_zeroes;
+
+
+        /*!
+            the main comma operator (used when reading and writing)
+            default is a dot '.'
+        */
+        uint comma;
+
+
+        /*!
+            additional comma operator (used only when reading) 
+            if you don't want it just set it to zero
+            default is a comma ','
+
+            this allowes you to convert from a value:
+            123.45 as well as from 123,45
+        */
+        uint comma2;
+
+
+        /*!
+            it sets the character which is used for grouping
+            if group=' ' then: 1234,56789 will be printed as: 1 234,567 89
+
+            if you don't want grouping just set it to zero (which is default)
+        */
+        uint group;
+
+
+        /*!
+            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
+
+
+
+
+        Conv()
+        {
+            // default values
+            base         = 10;
+            scient       = false;
+            scient_from  = 15;
+            base_round   = true;
+            round        = -1;
+            trim_zeroes  = true;
+            comma        = '.';
+            comma2       = ',';
+            group        = 0;
+            group_digits = 3;
+            group_exp    = 0;
+        }
+    };
+
+
+
+    /*!
+        this simple class can be used in multithreading model
+        (you can write your own class derived from this one)
+
+        for example: in some functions like Factorial() 
+        /at the moment only Factorial/ you can give a pointer to 
+        the 'stop object', if the method WasStopSignal() of this 
+        object returns true that means we should break the calculating
+        and return
+    */
+    class StopCalculating
+    {
+    public:
+        virtual bool WasStopSignal() const volatile { return false; }
+        virtual ~StopCalculating(){}
+    };
+
+
+    /*!
+        a small class which is useful when compiling with gcc
+
+        object of this type holds the name and the line of a file
+        in which the macro TTMATH_ASSERT or TTMATH_REFERENCE_ASSERT was used
+    */
+    class ExceptionInfo
+    {
+    const char * file;
+    int line;
+
+    public:
+        ExceptionInfo() : file(0), line(0) {}
+        ExceptionInfo(const char * f, int l) : file(f), line(l) {}
+
+        std::string Where() const
+        {
+            if( !file )
+                return "unknown";
+
+            std::ostringstream result;
+            result << file << ":" << line;
+
+        return result.str();
+        }
+    };
+
+
+    /*!
+        A small class used for reporting 'reference' errors
+
+        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)
+    */
+    class ReferenceError : public std::logic_error, public ExceptionInfo
+    {
+    public:
+
+        ReferenceError() : std::logic_error("reference error")
+        {
+        }
+
+        ReferenceError(const char * f, int l) :
+                            std::logic_error("reference error"), ExceptionInfo(f,l)
+        {
+        }
+
+        std::string Where() const
+        {
+            return ExceptionInfo::Where();
+        }
+    };
+
+
+    /*!
+        a small class used for reporting errors
+
+        in the library is used macro TTMATH_ASSERT which
+        (if the condition in it is false) throw an exception
+        of this type
+
+        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_ASSERT
+        was used)
+    */
+    class RuntimeError : public std::runtime_error, public ExceptionInfo
+    {
+    public:
+
+        RuntimeError() : std::runtime_error("internal error")
+        {
+        }
+
+        RuntimeError(const char * f, int l) :
+                        std::runtime_error("internal error"), ExceptionInfo(f,l)
+        {
+        }
+
+        std::string Where() const
+        {
+            return ExceptionInfo::Where();
+        }
+    };
+
+
+
+    /*!
+        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__)
+
+            #define TTMATH_REFERENCE_ASSERT(expression) \
+                if( &(expression) == this ) throw ttmath::ReferenceError(__FILE__, __LINE__);
+
+            #define TTMATH_ASSERT(expression) \
+                if( !(expression) ) throw ttmath::RuntimeError(__FILE__, __LINE__);
+
+        #else
+
+            #define TTMATH_REFERENCE_ASSERT(expression) \
+                if( &(expression) == this ) throw ReferenceError();
+
+            #define TTMATH_ASSERT(expression) \
+                if( !(expression) ) throw RuntimeError();
+        #endif
+
+    #else
+        #define TTMATH_REFERENCE_ASSERT(expression)
+        #define TTMATH_ASSERT(expression)
+    #endif
+
+
+
+    #ifdef TTMATH_DEBUG_LOG
+        #define TTMATH_LOG(msg)                             PrintLog(msg, std::cout);
+        #define TTMATH_LOGC(msg, carry)                     PrintLog(msg, carry, std::cout);
+        #define TTMATH_VECTOR_LOG(msg, vector, len)         PrintVectorLog(msg, std::cout, vector, len);
+        #define TTMATH_VECTOR_LOGC(msg, carry, vector, len) PrintVectorLog(msg, carry, std::cout, vector, len);
+    #else
+        #define TTMATH_LOG(msg)
+        #define TTMATH_LOGC(msg, carry)
+        #define TTMATH_VECTOR_LOG(msg, vector, len)
+        #define TTMATH_VECTOR_LOGC(msg, carry, vector, len)
+    #endif
+
+
+
+
+} // namespace
+
+
+#endif
+
+
diff -r 000000000000 -r 04a9f72bbca7 ttmathuint.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ttmathuint.h	Tue Jul 30 18:43:48 2013 +0000
@@ -0,0 +1,4166 @@
+/*
+ * This file is a part of TTMath Bignum Library
+ * and is distributed under the (new) BSD licence.
+ * Author: Tomasz Sowa <t.sowa@ttmath.org>
+ */
+
+/* 
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+#ifndef headerfilettmathuint
+#define headerfilettmathuint
+
+
+/*!
+    \file ttmathuint.h
+    \brief template class UInt<uint>
+*/
+
+#include <iostream>
+#include <iomanip>
+
+
+#include "ttmathtypes.h"
+#include "ttmathmisc.h"
+
+
+
+/*!
+    \brief a namespace for the TTMath library
+*/
+namespace ttmath
+{
+
+/*! 
+    \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....
+*/
+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")
+    }
+
+
+    /*!
+        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;
+
+
+        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;
+
+        TTMATH_LOG("UInt::SetFromTable")
+    }
+
+#endif
+
+
+
+
+
+    /*!
+    *
+    *    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);
+    }
+
+
+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")
+    }
+    
+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);
+        }
+
+        TTMATH_LOGC("UInt::Rcl", last_c)
+
+    return last_c;
+    }
+
+private:
+
+    /*!    
+        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;
+        }
+
+        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
+
+        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
+     *
+     *
+    */
+
+public:
+
+    /*!
+        multiplication: this = this * ss2
+
+        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
+    */
+
+private:
+
+    /*!
+        multiplication: this = this * ss2
+
+        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;
+    }
+
+
+public:
+
+    /*!
+        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);
+
+        TTMATH_LOG("UInt::Mul2Big")
+    }
+
+
+private:
+
+    /*!
+        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);
+    }
+
+
+
+    /*!
+        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
+
+        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")
+    }
+
+
+
+private:
+
+    /*!
+        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);
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wtautological-compare"
+#endif
+
+            for(uint i=0 ; i<ss_size*2 ; ++i)
+                result[i] = res.table[i];
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+        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);
+        }
+    }
+
+
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4717)
+//warning C4717: recursive on all control paths, function will cause runtime stack overflow
+//we have the stop point in Mul3Big2() method
+#endif
+
+
+    /*!
+        an auxiliary method for calculating the Karatsuba multiplication
+
+            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)
+
+            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);
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wtautological-compare"
+#endif
+
+        // clearing the rest of z1
+        for(i=first_size*2 ; i<first_size*3 ; ++i)
+            z1.table[i] = 0;
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+        
+        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 )
+        {
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wtautological-compare"
+#endif
+
+            for( i=first_size*2 ; i<first_size*3 ; ++i )
+                if( ++z1.table[i] != 0 )
+                     break;  // break if there was no carry 
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+        }
+
+        // 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 )
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wtautological-compare"
+#endif
+
+            for(i=z1_size ; i<first_size*3 ; ++i)
+            {
+                TTMATH_ASSERT( z1.table[i] == 0 )
+            }
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+             
+            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
+#pragma warning (default : 4717)
+#endif
+
+
+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
+     *
+     *
+    */
+    
+public:
+
+
+    /*!
+        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);
+    }
+
+
+
+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 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;
+    
+        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:
+
+    /*!
+        the second division algorithm
+
+        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
+
+        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;
+            }
+        }
+
+        TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual")
+
+    return false;
+    }
+
+
+public:
+
+    /*!
+        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);
+    }
+
+
+private:
+
+    /*!
+        the third division algorithm
+
+        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")
+
+    return 0;
+    }
+
+
+
+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);
+
+        if( j+n == value_size )
+            u2 = u_value_size;
+        else
+            u2 = table[j+n];
+
+        Div3_MakeBiggerV(v, vv);
+
+        for(uint i = j+1 ; i<value_size ; ++i)
+            q.table[i] = 0;
+
+        while( true )
+        {
+            u1 = table[j+n-1];
+            u0 = table[j+n-2];
+            v1 = v.table[n-1];
+            v0 = v.table[n-2];
+
+            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);
+
+            q.table[j] = qp;
+
+            // the next loop
+            if( j-- == 0 )
+                break;
+
+            u2 = table[j+n];
+        }
+
+        if( remainder )
+            Div3_Unnormalize(remainder, n, d);
+
+    *this = q;
+
+    TTMATH_LOG("UInt::Div3_Division")
+    }
+
+
+    void Div3_MakeNewU(UInt<value_size+1> & uu, uint j, uint n, uint u_max)
+    {
+    uint i;
+
+        for(i=0 ; i<n ; ++i, ++j)
+            uu.table[i] = table[j];
+
+        // '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;
+
+        for( ++i ; i<value_size+1 ; ++i)
+            uu.table[i] = 0;
+
+        TTMATH_LOG("UInt::Div3_MakeNewU")
+    }
+
+
+    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];
+
+        TTMATH_LOG("UInt::Div3_CopyNewU")
+    }
+
+
+    /*!
+        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];
+
+        vv.table[value_size] = 0;
+
+        TTMATH_LOG("UInt::Div3_MakeBiggerV")
+    }
+    
+
+    /*!
+        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')
+
+        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
+
+        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;
+        }
+
+        TTMATH_LOG("UInt::Div3_Normalize")
+
+    return res;
+    }
+
+
+    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);
+
+        *remainder = *this;
+
+        TTMATH_LOG("UInt::Div3_Unnormalize")
+    }
+
+
+    uint Div3_Calculate(uint u2, uint u1, uint u0, uint v1, uint v0)
+    {    
+    UInt<2> u_temp;
+    uint rp;
+    bool next_test;
+
+        TTMATH_ASSERT( v1 != 0 )
+
+        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 )
+
+        do
+        {
+            bool decrease = false;
+
+            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;
+
+                if( temp1 > temp2 )
+                    decrease = true;
+            }
+
+            next_test = false;
+
+            if( decrease )
+            {
+                u_temp.SubOne();
+
+                rp += v1;
+
+                if( rp >= v1 ) // it means that there wasn't a carry (r<b from the book)
+                    next_test = true;
+            }
+        }
+        while( next_test );
+
+        TTMATH_LOG("UInt::Div3_Calculate")
+
+    return u_temp.table[0];
+    }
+
+
+
+    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);
+
+        if( uu.Sub(vv_temp) )  
+        {
+            // there was a carry
+            
+            //
+            // !!! this part of code was not tested
+            //
+
+            --qp;
+            uu.Add(vv);
+
+            // 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")
+    }
+
+
+
+
+
+
+public:
+
+
+    /*!
+        power this = this ^ pow
+        binary algorithm (r-to-l)
+
+        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;
+
+        UInt<value_size> start(*this);
+        UInt<value_size> result;
+        result.SetOne();
+        uint c = 0;
+
+        while( !c )
+        {
+            if( pow.table[0] & 1 )
+                c += result.Mul(start);
+
+            pow.Rcr2_one(0);
+            if( pow.IsZero() )
+                break;
+
+            c += start.Mul(start);
+        }
+
+        *this = result;
+
+        TTMATH_LOGC("UInt::Pow(UInt<>)", c)
+
+    return (c==0)? 0 : 1;
+    }
+
+
+    /*!
+        square root
+        e.g. Sqrt(9) = 3
+        ('digit-by-digit' algorithm)
+    */
+    void Sqrt()
+    {
+    UInt<value_size> bit, temp;
+
+        if( IsZero() )
+            return;
+
+        UInt<value_size> value(*this);
+
+        SetZero();
+        bit.SetZero();
+        bit.table[value_size-1] = (TTMATH_UINT_HIGHEST_BIT >> 1);
+        
+        while( bit > value )
+            bit.Rcr(2);
+
+        while( !bit.IsZero() )
+        {
+            temp = *this;
+            temp.Add(bit);
+
+            if( value >= temp )
+            {
+                value.Sub(temp);
+                Rcr(1);
+                Add(bit);
+            }
+            else
+            {
+                Rcr(1);
+            }
+
+            bit.Rcr(2);
+        }
+
+        TTMATH_LOG("UInt::Sqrt")
+    }
+
+
+
+    /*!
+        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;
+        }
+
+        uint * p = table;
+
+        // 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;
+        }
+
+        // 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;
+
+        (*p) &= mask;
+
+        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;
+    }
+
+
+    /*!
+        this method returns true if the lowest bit of the value is set
+    */
+    bool IsTheLowestBitSet() const
+    {
+        return (*table & 1) != 0;
+    }
+
+
+    /*!
+        returning true if only the highest bit is set
+    */
+    bool IsOnlyTheHighestBitSet() const
+    {
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wtautological-compare"
+#endif
+
+        for(uint i=0 ; i<value_size-1 ; ++i)
+            if( table[i] != 0 )
+                return false;
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+        if( table[value_size-1] != TTMATH_UINT_HIGHEST_BIT )
+            return false;
+
+    return true;
+    }
+
+
+    /*!
+        returning true if only the lowest bit is set
+    */
+    bool IsOnlyTheLowestBitSet() const
+    {
+        if( table[0] != 1 )
+            return false;
+
+        for(uint i=1 ; i<value_size ; ++i)
+            if( table[i] != 0 )
+                return false;
+
+    return true;
+    }
+
+
+    /*!
+        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;
+
+    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;
+
+        if( rest == 0 )
+            return true;
+
+        uint mask = TTMATH_UINT_MAX_VALUE >> (TTMATH_BITS_PER_UINT - rest);
+
+    return (table[i] & mask) == 0;
+    }
+
+
+
+    /*!
+    *
+    *    conversion methods
+    *
+    */
+
+
+
+    /*!
+        this method converts an UInt<another_size> type to this class
+
+        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 FromUInt(const UInt<argument_size> & p)
+    {
+        uint min_size = (value_size < argument_size)? value_size : argument_size;
+        uint i;
+
+        for(i=0 ; i<min_size ; ++i)
+            table[i] = p.table[i];
+
+
+        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
+
+        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;
+
+        TTMATH_LOG("UInt::FromUInt(uint)")
+
+        // there'll never be a carry here
+    return 0;
+    }
+
+
+    /*!
+        this method converts the uint type to this class
+    */
+    uint FromInt(uint value)
+    {
+        return FromUInt(value);
+    }
+
+
+    /*!
+        this method converts the sint type to this class
+    */
+    uint FromInt(sint value)
+    {
+        uint c = FromUInt(uint(value));
+
+        if( c || value < 0 )
+            return 1;
+
+    return 0;
+    }
+
+
+    /*!
+        this operator converts an UInt<another_size> type to this class
+
+        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];
+
+        TTMATH_LOG("UInt::operator=(UInt<>)")
+
+        return *this;
+    }
+
+
+    /*!
+        this method converts the uint type to this class
+    */
+    UInt<value_size> & operator=(uint i)
+    {
+        FromUInt(i);
+
+    return *this;
+    }
+
+
+    /*!
+        a constructor for converting the uint to this class
+    */
+    UInt(uint i)
+    {
+        FromUInt(i);
+    }
+
+
+    /*!
+        this method converts the sint type to this class
+    */
+    UInt<value_size> & operator=(sint i)
+    {
+        FromInt(i);
+
+    return *this;
+    }
+
+
+    /*!
+        a constructor for converting the sint to this class
+
+        look at the description of UInt::operator=(sint)
+    */
+    UInt(sint i)
+    {
+        FromInt(i);
+    }
+
+
+#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
+
+
+
+#ifdef TTMATH_PLATFORM64
+
+
+    /*!
+        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);
+    }
+
+
+#endif
+
+
+
+
+
+    /*!
+        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() );
+    }
+
+#endif
+
+
+
+
+    /*!
+        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 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;
+    }
+
+
+#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
+    {
+        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;
+
+        uint c = ToUInt(temp);
+        result = slint(temp);
+
+        if( c || result < 0 )
+            return 1;
+
+    return 0;
+    }
+
+#endif
+
+
+
+#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;
+
+        uint c = ToUInt(temp);
+        result = int(temp);
+
+        if( c || result < 0 )
+            return 1;
+
+    return 0;
+    }
+
+
+#endif
+
+
+
+
+protected:
+
+    /*!
+        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];
+    }
+
+
+public:
+
+
+    /*!    
+        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;
+        }
+    }
+
+
+
+    /*!    
+        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
+
+
+
+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); // !! IMPROVE ME: there can be used MulInt here
+                c += Add(temp);
+            }
+        }        
+
+        if( after_source )
+            *after_source = s;
+
+        TTMATH_LOGC("UInt::FromString", c)
+
+    return (c==0)? 0 : 1;
+    }
+
+
+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
+
+        if the value from s is too large the rest digits will be skipped
+
+        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 );
+    }
+
+
+    /*!
+        this operator converts a string into its value (with base = 10)
+    */
+    UInt<value_size> & operator=(const char * s)
+    {
+        FromString(s);
+
+    return *this;
+    }
+
+
+    /*!
+        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;
+    }
+
+
+
+#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);
+    }
+
+
+    /*!
+        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)
+    */
+    UInt<value_size> & operator=(const wchar_t * s)
+    {
+        FromString(s);
+
+    return *this;
+    }
+
+
+    /*!
+        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;
+    }
+
+#endif
+
+
+    /*!
+    *
+    *    methods for comparing
+    *
+    */
+
+
+    /*!
+        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;
+
+        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];
+        }
+
+    // they're equal
+    return false;
+    }
+
+
+
+    /*!
+        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)
+
+        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;
+
+
+        for( ; i>=0 ; --i)
+        {
+            if( table[i] != l.table[i] )
+                return table[i] > l.table[i];
+        }
+
+    // they're equal
+    return false;
+    }
+
+
+    /*!
+        this method returns true if 'this' is 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)
+    */
+    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;
+
+
+        for( ; i>=0 ; --i)
+            if( table[i] != l.table[i] )
+                return false;
+
+    return true;
+    }
+
+
+
+    /*!
+        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)
+    */
+    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;
+
+
+        for( ; i>=0 ; --i)
+        {
+            if( table[i] != l.table[i] )
+                return table[i] < l.table[i];
+        }
+
+    // they're equal
+    return true;
+    }
+
+
+
+    /*!
+        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)
+    */
+    bool CmpBiggerEqual(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;
+
+
+        for( ; i>=0 ; --i)
+        {
+            if( table[i] != l.table[i] )
+                return table[i] > l.table[i];
+        }
+
+    // they're equal
+    return true;
+    }
+
+
+    /*
+        operators for comparising
+    */
+
+    bool operator<(const UInt<value_size> & l) const
+    {
+        return CmpSmaller(l);
+    }
+
+
+    bool operator>(const UInt<value_size> & l) const
+    {
+        return CmpBigger(l);
+    }
+
+
+    bool operator==(const UInt<value_size> & l) const
+    {
+        return CmpEqual(l);
+    }
+
+
+    bool operator!=(const UInt<value_size> & l) const
+    {
+        return !operator==(l);
+    }
+
+
+    bool operator<=(const UInt<value_size> & l) const
+    {
+        return CmpSmallerEqual(l);
+    }
+
+    bool operator>=(const UInt<value_size> & l) const
+    {
+        return CmpBiggerEqual(l);
+    }
+
+
+    /*!
+    *
+    *    standard mathematical operators 
+    *
+    */
+
+    UInt<value_size> operator-(const UInt<value_size> & p2) const
+    {
+    UInt<value_size> temp(*this);
+
+        temp.Sub(p2);
+
+    return temp;
+    }
+
+    UInt<value_size> & operator-=(const UInt<value_size> & p2)
+    {
+        Sub(p2);
+
+    return *this;
+    }
+
+    UInt<value_size> operator+(const UInt<value_size> & p2) const
+    {
+    UInt<value_size> temp(*this);
+
+        temp.Add(p2);
+
+    return temp;
+    }
+
+    UInt<value_size> & operator+=(const UInt<value_size> & p2)
+    {
+        Add(p2);
+
+    return *this;
+    }
+
+
+    UInt<value_size> operator*(const UInt<value_size> & p2) const
+    {
+    UInt<value_size> temp(*this);
+
+        temp.Mul(p2);
+
+    return temp;
+    }
+
+
+    UInt<value_size> & operator*=(const UInt<value_size> & p2)
+    {
+        Mul(p2);
+
+    return *this;
+    }
+
+
+    UInt<value_size> operator/(const UInt<value_size> & p2) const
+    {
+    UInt<value_size> temp(*this);
+
+        temp.Div(p2);
+
+    return temp;
+    }
+
+
+    UInt<value_size> & operator/=(const UInt<value_size> & p2)
+    {
+        Div(p2);
+
+    return *this;
+    }
+
+
+    UInt<value_size> operator%(const UInt<value_size> & p2) const
+    {
+    UInt<value_size> temp(*this);
+    UInt<value_size> remainder;
+    
+        temp.Div( p2, remainder );
+
+    return remainder;
+    }
+
+
+    UInt<value_size> & operator%=(const UInt<value_size> & p2)
+    {
+    UInt<value_size> remainder;
+    
+        Div( p2, remainder );
+        operator=(remainder);
+
+    return *this;
+    }
+
+
+    /*!
+        Prefix operator e.g ++variable
+    */
+    UInt<value_size> & operator++()
+    {
+        AddOne();
+
+    return *this;
+    }
+
+
+    /*!
+        Postfix operator e.g variable++
+    */
+    UInt<value_size> operator++(int)
+    {
+    UInt<value_size> temp( *this );
+
+        AddOne();
+
+    return temp;
+    }
+
+
+    UInt<value_size> & operator--()
+    {
+        SubOne();
+
+    return *this;
+    }
+
+
+    UInt<value_size> operator--(int)
+    {
+    UInt<value_size> temp( *this );
+
+        SubOne();
+
+    return temp;
+    }
+
+
+
+    /*!
+    *
+    *    bitwise operators
+    *
+    */
+
+    UInt<value_size> operator~() const
+    {
+        UInt<value_size> temp( *this );
+
+        temp.BitNot();
+
+    return temp;
+    }
+
+
+    UInt<value_size> operator&(const UInt<value_size> & p2) const
+    {
+        UInt<value_size> temp( *this );
+
+        temp.BitAnd(p2);
+
+    return temp;
+    }
+
+
+    UInt<value_size> & operator&=(const UInt<value_size> & p2)
+    {
+        BitAnd(p2);
+
+    return *this;
+    }
+
+
+    UInt<value_size> operator|(const UInt<value_size> & p2) const
+    {
+        UInt<value_size> temp( *this );
+
+        temp.BitOr(p2);
+
+    return temp;
+    }
+
+
+    UInt<value_size> & operator|=(const UInt<value_size> & p2)
+    {
+        BitOr(p2);
+
+    return *this;
+    }
+
+
+    UInt<value_size> operator^(const UInt<value_size> & p2) const
+    {
+        UInt<value_size> temp( *this );
+
+        temp.BitXor(p2);
+
+    return temp;
+    }
+
+
+    UInt<value_size> & operator^=(const UInt<value_size> & p2)
+    {
+        BitXor(p2);
+
+    return *this;
+    }
+
+
+    UInt<value_size> operator>>(int move) const
+    {
+    UInt<value_size> temp( *this );
+
+        temp.Rcr(move);
+
+    return temp;
+    }
+
+
+    UInt<value_size> & operator>>=(int move)
+    {
+        Rcr(move);
+
+    return *this;
+    }
+
+
+    UInt<value_size> operator<<(int move) const
+    {
+    UInt<value_size> temp( *this );
+
+        temp.Rcl(move);
+
+    return temp;
+    }
+
+
+    UInt<value_size> & operator<<=(int move)
+    {
+        Rcl(move);
+
+    return *this;
+    }
+
+
+    /*!
+    *
+    *    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;
+
+        l.ToString(ss);
+        s << ss;
+
+    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);
+    }
+
+
+#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();
+
+        l.FromString(ss);
+
+    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);
+    }
+
+
+#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
+    */
+
+#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);
+
+#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_);
+
+#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);
+
+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);
+
+};
+
+
+
+/*!
+    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];
+
+    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; };
+};
+
+
+} //namespace
+
+
+#include "ttmathuint_x86.h"
+#include "ttmathuint_x86_64.h"
+#include "ttmathuint_noasm.h"
+
+#endif
+
diff -r 000000000000 -r 04a9f72bbca7 ttmathuint_noasm.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ttmathuint_noasm.h	Tue Jul 30 18:43:48 2013 +0000
@@ -0,0 +1,1018 @@
+/*
+ * This file is a part of TTMath Bignum Library
+ * and is distributed under the (new) BSD licence.
+ * Author: Tomasz Sowa <t.sowa@ttmath.org>
+ */
+
+/* 
+ * Copyright (c) 2006-2010, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef headerfilettmathuint_noasm
+#define headerfilettmathuint_noasm
+
+
+#ifdef TTMATH_NOASM
+
+/*!
+    \file ttmathuint_noasm.h
+    \brief template class UInt<uint> with methods without any assembler code
+
+    this file is included at the end of ttmathuint.h
+*/
+
+
+namespace ttmath
+{
+
+    /*!
+        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
+    */
+    template<uint value_size>
+    const char * UInt<value_size>::LibTypeStr()
+    {
+        #ifdef TTMATH_PLATFORM32
+            static const char info[] = "no_asm_32";
+        #endif        
+
+        #ifdef TTMATH_PLATFORM64
+            static const char info[] = "no_asm_64";
+        #endif
+
+    return info;
+    }
+
+    
+    /*!
+        returning the currect type of the library
+    */
+    template<uint value_size>
+    LibTypeCode UInt<value_size>::LibType()
+    {
+        #ifdef TTMATH_PLATFORM32
+            LibTypeCode info = no_asm_32;
+        #endif        
+
+        #ifdef TTMATH_PLATFORM64
+            LibTypeCode info = no_asm_64;
+        #endif
+
+    return info;
+    }
+
+
+    /*!
+        this method adds two words together
+        returns carry
+
+        this method is created only when TTMATH_NOASM macro is defined
+    */
+    template<uint value_size>
+    uint UInt<value_size>::AddTwoWords(uint a, uint b, uint carry, uint * result)
+    {
+    uint temp;
+
+        if( carry == 0 )
+        {
+            temp = a + b;
+
+            if( temp < a )
+                carry = 1;
+        }
+        else
+        {
+            carry = 1;
+            temp  = a + b + carry;
+
+            if( temp > a ) // !(temp<=a)
+                carry = 0;
+        }
+
+        *result = temp;
+
+    return carry;
+    }
+
+
+
+    /*!
+        this method adding ss2 to the this and adding carry if it's defined
+        (this = this + ss2 + c)
+
+        c must be zero or one (might be a bigger value than 1)
+        function returns carry (1) (if it was)
+    */
+    
+    template<uint value_size>
+    uint UInt<value_size>::Add(const UInt<value_size> & ss2, uint c)
+    {
+    uint i;
+
+        for(i=0 ; i<value_size ; ++i)
+            c = AddTwoWords(table[i], ss2.table[i], c, &table[i]);
+
+        TTMATH_LOGC("UInt::Add", c)
+    
+    return c;
+    }
+
+
+    /*!
+        this method adds one word (at a specific position)
+        and returns a carry (if it was)
+
+        if we've got (value_size=3):
+            table[0] = 10;
+            table[1] = 30;
+            table[2] = 5;    
+        and we call:
+            AddInt(2,1)
+        then it'll be:
+            table[0] = 10;
+            table[1] = 30 + 2;
+            table[2] = 5;
+
+        of course if there was a carry from table[2] it would be returned
+    */
+    template<uint value_size>
+    uint UInt<value_size>::AddInt(uint value, uint index)
+    {
+    uint i, c;
+
+        TTMATH_ASSERT( index < value_size )
+
+
+        c = AddTwoWords(table[index], value, 0, &table[index]);
+
+        for(i=index+1 ; i<value_size && c ; ++i)
+            c = AddTwoWords(table[i], 0, c, &table[i]);
+
+        TTMATH_LOGC("UInt::AddInt", c)
+    
+    return c;
+    }
+
+
+
+
+
+    /*!
+        this method adds only two unsigned words to the existing value
+        and these words begin on the 'index' position
+        (it's used in the multiplication algorithm 2)
+
+        index should be equal or smaller than value_size-2 (index <= value_size-2)
+        x1 - lower word, x2 - higher word
+
+        for example if we've got value_size equal 4 and:
+            table[0] = 3
+            table[1] = 4
+            table[2] = 5
+            table[3] = 6
+        then let
+            x1 = 10
+            x2 = 20
+        and
+            index = 1
+
+        the result of this method will be:
+            table[0] = 3
+            table[1] = 4 + x1 = 14
+            table[2] = 5 + x2 = 25
+            table[3] = 6
+        
+        and no carry at the end of table[3]
+
+        (of course if there was a carry in table[2](5+20) then 
+        this carry would be passed to the table[3] etc.)
+    */
+    template<uint value_size>
+    uint UInt<value_size>::AddTwoInts(uint x2, uint x1, uint index)
+    {
+    uint i, c;
+
+        TTMATH_ASSERT( index < value_size - 1 )
+
+
+        c = AddTwoWords(table[index],   x1, 0, &table[index]);
+        c = AddTwoWords(table[index+1], x2, c, &table[index+1]);
+
+        for(i=index+2 ; i<value_size && c ; ++i)
+            c = AddTwoWords(table[i], 0, c, &table[i]);
+
+        TTMATH_LOGC("UInt::AddTwoInts", c)
+    
+    return c;
+    }
+
+
+
+    /*!
+        this static method addes one vector to the other
+        'ss1' is larger in size or equal to 'ss2'
+
+        ss1 points to the first (larger) vector
+        ss2 points to the second vector
+        ss1_size - size of the ss1 (and size of the result too)
+        ss2_size - size of the ss2
+        result - is the result vector (which has size the same as ss1: ss1_size)
+
+        Example:  ss1_size is 5, ss2_size is 3
+        ss1:      ss2:   result (output):
+          5        1         5+1
+          4        3         4+3
+          2        7         2+7
+          6                  6
+          9                  9
+      of course the carry is propagated and will be returned from the last item
+      (this method is used by the Karatsuba multiplication algorithm)
+    */
+    template<uint value_size>
+    uint UInt<value_size>::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
+    {
+    uint i, c = 0;
+
+        TTMATH_ASSERT( ss1_size >= ss2_size )
+        
+        for(i=0 ; i<ss2_size ; ++i)
+            c = AddTwoWords(ss1[i], ss2[i], c, &result[i]);
+
+        for( ; i<ss1_size ; ++i)
+            c = AddTwoWords(ss1[i], 0, c, &result[i]);
+
+        TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size)
+
+    return c;
+    }
+
+
+
+
+    /*!
+        this method subtractes one word from the other
+        returns carry
+
+        this method is created only when TTMATH_NOASM macro is defined
+    */
+    template<uint value_size>
+    uint UInt<value_size>::SubTwoWords(uint a, uint b, uint carry, uint * result)
+    {
+        if( carry == 0 )
+        {
+            *result = a - b;
+
+            if( a < b )
+                carry = 1;
+        }
+        else
+        {
+            carry   = 1;
+            *result = a - b - carry;
+
+            if( a > b ) // !(a <= b )
+                carry = 0;
+        }
+
+    return carry;
+    }
+
+
+
+
+    /*!
+        this method's subtracting ss2 from the 'this' and subtracting
+        carry if it has been defined
+        (this = this - ss2 - c)
+
+        c must be zero or one (might be a bigger value than 1)
+        function returns carry (1) (if it was)
+    */
+    template<uint value_size>
+    uint UInt<value_size>::Sub(const UInt<value_size> & ss2, uint c)
+    {
+    uint i;
+
+        for(i=0 ; i<value_size ; ++i)
+            c = SubTwoWords(table[i], ss2.table[i], c, &table[i]);
+
+        TTMATH_LOGC("UInt::Sub", c)
+
+    return c;
+    }
+
+
+
+
+    /*!
+        this method subtracts one word (at a specific position)
+        and returns a carry (if it was)
+
+        if we've got (value_size=3):
+            table[0] = 10;
+            table[1] = 30;
+            table[2] = 5;    
+        and we call:
+            SubInt(2,1)
+        then it'll be:
+            table[0] = 10;
+            table[1] = 30 - 2;
+            table[2] = 5;
+
+        of course if there was a carry from table[2] it would be returned
+    */
+    template<uint value_size>
+    uint UInt<value_size>::SubInt(uint value, uint index)
+    {
+    uint i, c;
+
+        TTMATH_ASSERT( index < value_size )
+
+
+        c = SubTwoWords(table[index], value, 0, &table[index]);
+
+        for(i=index+1 ; i<value_size && c ; ++i)
+            c = SubTwoWords(table[i], 0, c, &table[i]);
+
+        TTMATH_LOGC("UInt::SubInt", c)
+    
+    return c;
+    }
+
+
+    /*!
+        this static method subtractes one vector from the other
+        'ss1' is larger in size or equal to 'ss2'
+
+        ss1 points to the first (larger) vector
+        ss2 points to the second vector
+        ss1_size - size of the ss1 (and size of the result too)
+        ss2_size - size of the ss2
+        result - is the result vector (which has size the same as ss1: ss1_size)
+
+        Example:  ss1_size is 5, ss2_size is 3
+        ss1:      ss2:   result (output):
+          5        1         5-1
+          4        3         4-3
+          2        7         2-7
+          6                  6-1  (the borrow from previous item)
+          9                  9
+                         return (carry): 0
+      of course the carry (borrow) is propagated and will be returned from the last item
+      (this method is used by the Karatsuba multiplication algorithm)
+    */
+    template<uint value_size>
+    uint UInt<value_size>::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
+    {
+    uint i, c = 0;
+
+        TTMATH_ASSERT( ss1_size >= ss2_size )
+        
+        for(i=0 ; i<ss2_size ; ++i)
+            c = SubTwoWords(ss1[i], ss2[i], c, &result[i]);
+
+        for( ; i<ss1_size ; ++i)
+            c = SubTwoWords(ss1[i], 0, c, &result[i]);
+
+        TTMATH_VECTOR_LOGC("UInt::SubVector", c, result, ss1_size)
+
+    return c;
+    }
+
+
+
+    /*!
+        this method moves all bits into the left hand side
+        return value <- this <- c
+
+        the lowest *bit* will be held the 'c' and
+        the state of one additional bit (on the left hand side)
+        will be returned
+
+        for example:
+        let this is 001010000
+        after Rcl2_one(1) there'll be 010100001 and Rcl2_one returns 0
+    */
+    template<uint value_size>
+    uint UInt<value_size>::Rcl2_one(uint c)
+    {
+    uint i, new_c;
+
+        if( c != 0 )
+            c = 1;
+
+        for(i=0 ; i<value_size ; ++i)
+        {
+            new_c    = (table[i] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0;
+            table[i] = (table[i] << 1) | c;
+            c        = new_c;
+        }
+
+        TTMATH_LOGC("UInt::Rcl2_one", c)
+
+    return c;
+    }
+
+
+
+
+
+
+
+    /*!
+        this method moves all bits into the right hand side
+        c -> this -> return value
+
+        the highest *bit* will be held the 'c' and
+        the state of one additional bit (on the right hand side)
+        will be returned
+
+        for example:
+        let this is 000000010
+        after Rcr2_one(1) there'll be 100000001 and Rcr2_one returns 0
+    */
+    template<uint value_size>
+    uint UInt<value_size>::Rcr2_one(uint c)
+    {
+    sint i; // signed i
+    uint new_c;
+
+        if( c != 0 )
+            c = TTMATH_UINT_HIGHEST_BIT;
+
+        for(i=sint(value_size)-1 ; i>=0 ; --i)
+        {
+            new_c    = (table[i] & 1) ? TTMATH_UINT_HIGHEST_BIT : 0;
+            table[i] = (table[i] >> 1) | c;
+            c        = new_c;
+        }
+
+        c = (c != 0)? 1 : 0;
+
+        TTMATH_LOGC("UInt::Rcr2_one", c)
+
+    return c;
+    }
+
+
+
+
+    /*!
+        this method moves all bits into the left hand side
+        return value <- this <- c
+
+        the lowest *bits* will be held the 'c' and
+        the state of one additional bit (on the left hand side)
+        will be returned
+
+        for example:
+        let this is 001010000
+        after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1
+    */
+    template<uint value_size>
+    uint UInt<value_size>::Rcl2(uint bits, uint c)
+    {
+        TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
+
+        uint move = TTMATH_BITS_PER_UINT - bits;
+        uint i, new_c;
+
+        if( c != 0 )
+            c = TTMATH_UINT_MAX_VALUE >> move;
+
+        for(i=0 ; i<value_size ; ++i)
+        {
+            new_c    = table[i] >> move;
+            table[i] = (table[i] << bits) | c;
+            c        = new_c;
+        }
+
+        TTMATH_LOGC("UInt::Rcl2", (c & 1))
+
+    return (c & 1);
+    }
+
+
+
+
+    /*!
+        this method moves all bits into the right hand side
+        C -> this -> return value
+
+        the highest *bits* will be held the 'c' and
+        the state of one additional bit (on the right hand side)
+        will be returned
+
+        for example:
+        let this is 000000010
+        after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1
+    */
+    template<uint value_size>
+    uint UInt<value_size>::Rcr2(uint bits, uint c)
+    {
+        TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
+
+        uint move = TTMATH_BITS_PER_UINT - bits;
+        sint i; // signed
+        uint new_c;
+
+        if( c != 0 )
+            c = TTMATH_UINT_MAX_VALUE << move;
+
+        for(i=value_size-1 ; i>=0 ; --i)
+        {
+            new_c    = table[i] << move;
+            table[i] = (table[i] >> bits) | c;
+            c        = new_c;
+        }
+
+        c = (c & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0;
+
+        TTMATH_LOGC("UInt::Rcr2", c)
+
+    return c;
+    }
+
+
+
+
+    /*!
+        this method returns the number of the highest set bit in x
+        if the 'x' is zero this method returns '-1'
+    */
+    template<uint value_size>
+    sint UInt<value_size>::FindLeadingBitInWord(uint x)
+    {
+        if( x == 0 )
+            return -1;
+
+        uint bit = TTMATH_BITS_PER_UINT - 1;
+        
+        while( (x & TTMATH_UINT_HIGHEST_BIT) == 0 )
+        {
+            x = x << 1;
+            --bit;
+        }
+
+    return bit;
+    }
+
+
+
+    /*!
+        this method returns the number of the highest set bit in x
+        if the 'x' is zero this method returns '-1'
+    */
+    template<uint value_size>
+    sint UInt<value_size>::FindLowestBitInWord(uint x)
+    {
+        if( x == 0 )
+            return -1;
+
+        uint bit = 0;
+        
+        while( (x & 1) == 0 )
+        {
+            x = x >> 1;
+            ++bit;
+        }
+
+    return bit;
+    }
+
+
+
+    /*!
+        this method sets a special bit in the 'value'
+        and returns the last state of the bit (zero or one)
+
+        bit is from <0,TTMATH_BITS_PER_UINT-1>
+
+        e.g.
+         uint x = 100;
+         uint bit = SetBitInWord(x, 3);
+         now: x = 108 and bit = 0
+    */
+    template<uint value_size>
+    uint UInt<value_size>::SetBitInWord(uint & value, uint bit)
+    {
+        TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT )
+
+        uint mask = 1;
+
+        if( bit > 0 )
+            mask = mask << bit;
+
+        uint last = value & mask;
+        value     = value | mask;
+
+    return (last != 0) ? 1 : 0;
+    }
+
+
+
+
+
+
+    /*!
+     *
+     * Multiplication
+     *
+     *
+    */
+
+
+    /*!
+        multiplication: result_high:result_low = a * b
+        result_high - higher word of the result
+        result_low  - lower word of the result
+    
+        this methos never returns a carry
+        this method is used in the second version of the multiplication algorithms
+    */
+    template<uint value_size>
+    void UInt<value_size>::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low)
+    {
+    #ifdef TTMATH_PLATFORM32
+
+        /*
+            on 32bit platforms we have defined 'unsigned long long int' type known as 'ulint' in ttmath namespace
+            this type has 64 bits, then we're using only one multiplication: 32bit * 32bit = 64bit
+        */
+
+        union uint_
+        {
+            struct
+            {
+                uint low;  // 32 bits
+                uint high; // 32 bits
+            } u_;
+
+            ulint u;       // 64 bits
+        } res;
+
+        res.u = ulint(a) * ulint(b);     // multiply two 32bit words, the result has 64 bits
+
+        *result_high = res.u_.high;
+        *result_low  = res.u_.low;
+
+    #else
+
+        /*
+            64 bits platforms
+
+            we don't have a native type which has 128 bits
+            then we're splitting 'a' and 'b' to 4 parts (high and low halves)
+            and using 4 multiplications (with additions and carry correctness)
+        */
+
+        uint_ a_;
+        uint_ b_;
+        uint_ res_high1, res_high2;
+        uint_ res_low1,  res_low2;
+        
+        a_.u = a;
+        b_.u = b;
+
+        /*
+            the multiplication is as follows (schoolbook algorithm with O(n^2) ):
+
+                                                   32 bits         32 bits
+
+                                             +--------------------------------+
+                                             |   a_.u_.high   |   a_.u_.low   |
+                                             +--------------------------------+
+                                             |   b_.u_.high   |   b_.u_.low   |
+            +--------------------------------+--------------------------------+
+            |           res_high1.u          |           res_low1.u           |
+            +--------------------------------+--------------------------------+
+            |           res_high2.u          |           res_low2.u           |
+            +--------------------------------+--------------------------------+
+
+                          64 bits                          64 bits
+        */
+
+
+        uint_ temp;
+
+        res_low1.u        = uint(b_.u_.low) * uint(a_.u_.low);
+
+        temp.u            = uint(res_low1.u_.high) + uint(b_.u_.low) * uint(a_.u_.high);
+        res_low1.u_.high  = temp.u_.low;
+        res_high1.u_.low  = temp.u_.high;
+        res_high1.u_.high = 0;
+
+        res_low2.u_.low   = 0;
+        temp.u            = uint(b_.u_.high) * uint(a_.u_.low);
+        res_low2.u_.high  = temp.u_.low;
+
+        res_high2.u       = uint(b_.u_.high) * uint(a_.u_.high) + uint(temp.u_.high);
+
+        uint c = AddTwoWords(res_low1.u, res_low2.u, 0, &res_low2.u);
+        AddTwoWords(res_high1.u, res_high2.u, c, &res_high2.u);                 // there is no carry from here
+
+        *result_high = res_high2.u;
+        *result_low  = res_low2.u;
+
+    #endif
+    }
+
+
+
+
+    /*!
+     *
+     * Division
+     *
+     *
+    */
+    
+
+    /*!
+        this method calculates 64bits word a:b / 32bits c (a higher, b lower word)
+        r = a:b / c and rest - remainder
+        
+        *
+        * WARNING:
+        * the c has to be suitably large for the result being keeped in one word,
+        * if c is equal zero there'll be a hardware interruption (0)
+        * and probably the end of your program
+        *
+    */
+    template<uint value_size>
+    void UInt<value_size>::DivTwoWords(uint a, uint b, uint c, uint * r, uint * rest)
+    {
+    // (a < c ) for the result to be one word
+    TTMATH_ASSERT( c != 0 && a < c )
+
+    #ifdef TTMATH_PLATFORM32
+
+        union
+        {
+            struct
+            {
+                uint low;  // 32 bits
+                uint high; // 32 bits
+            } u_;
+
+            ulint u;       // 64 bits
+        } ab;
+
+        ab.u_.high = a;
+        ab.u_.low  = b;
+
+        *r    = uint(ab.u / c);
+        *rest = uint(ab.u % c);
+
+    #else
+
+        uint_ c_;
+        c_.u = c;
+
+
+        if( a == 0 )
+        {
+            *r    = b / c;
+            *rest = b % c;
+        }
+        else
+        if( c_.u_.high == 0 )
+        {
+            // higher half of 'c' is zero
+            // then higher half of 'a' is zero too (look at the asserts at the beginning - 'a' is smaller than 'c')
+            uint_ a_, b_, res_, temp1, temp2;
+
+            a_.u = a;
+            b_.u = b;
+
+            temp1.u_.high = a_.u_.low;
+            temp1.u_.low  = b_.u_.high;
+
+            res_.u_.high  = (unsigned int)(temp1.u / c);
+            temp2.u_.high = (unsigned int)(temp1.u % c);
+            temp2.u_.low  = b_.u_.low;
+            
+            res_.u_.low  = (unsigned int)(temp2.u / c);
+            *rest        = temp2.u % c;
+
+            *r = res_.u;
+        }
+        else
+        {
+            return DivTwoWords2(a, b, c,  r,  rest);
+        }
+
+    #endif
+    }
+
+
+#ifdef TTMATH_PLATFORM64
+
+
+    /*!
+        this method is available only on 64bit platforms
+        
+        the same algorithm like the third division algorithm in ttmathuint.h
+        but now with the radix=2^32
+    */
+    template<uint value_size>
+    void UInt<value_size>::DivTwoWords2(uint a, uint b, uint c, uint * r, uint * rest)
+    {
+        // a is not zero
+        // c_.u_.high is not zero
+
+        uint_ a_, b_, c_, u_, q_;
+        unsigned int u3; // 32 bit
+
+        a_.u  = a;
+        b_.u  = b;
+        c_.u  = c;
+
+        // normalizing
+        uint d = DivTwoWordsNormalize(a_, b_, c_);
+
+        // loop from j=1 to j=0
+        //   the first step (for j=2) is skipped because our result is only in one word,
+        //   (first 'q' were 0 and nothing would be changed)
+        u_.u_.high = a_.u_.high;
+        u_.u_.low  = a_.u_.low;
+        u3         = b_.u_.high;
+        q_.u_.high = DivTwoWordsCalculate(u_, u3, c_);
+        MultiplySubtract(u_, u3, q_.u_.high, c_);
+        
+        u_.u_.high = u_.u_.low;
+        u_.u_.low  = u3;
+        u3         = b_.u_.low;
+        q_.u_.low  = DivTwoWordsCalculate(u_, u3, c_);
+        MultiplySubtract(u_, u3, q_.u_.low, c_);
+
+        *r = q_.u;
+
+        // unnormalizing for the remainder
+        u_.u_.high = u_.u_.low;
+        u_.u_.low  = u3;
+        *rest = DivTwoWordsUnnormalize(u_.u, d);
+    }
+
+
+
+    
+    template<uint value_size>
+    uint UInt<value_size>::DivTwoWordsNormalize(uint_ & a_, uint_ & b_, uint_ & c_)
+    {
+        uint d = 0;
+
+        for( ; (c_.u & TTMATH_UINT_HIGHEST_BIT) == 0 ; ++d )
+        {
+            c_.u = c_.u << 1;
+            
+            uint bc = b_.u & TTMATH_UINT_HIGHEST_BIT; // carry from 'b'
+
+            b_.u = b_.u << 1;
+            a_.u = a_.u << 1; // carry bits from 'a' are simply skipped 
+
+            if( bc )
+                a_.u = a_.u | 1;
+        }
+
+    return d;
+    }
+
+
+    template<uint value_size>
+    uint UInt<value_size>::DivTwoWordsUnnormalize(uint u, uint d)
+    {
+        if( d == 0 )
+            return u;
+
+        u = u >> d;
+
+    return u;
+    }
+
+
+    template<uint value_size>
+    unsigned int UInt<value_size>::DivTwoWordsCalculate(uint_ u_, unsigned int u3, uint_ v_)
+    {
+    bool next_test;
+    uint_ qp_, rp_, temp_;
+
+        qp_.u = u_.u / uint(v_.u_.high);
+        rp_.u = u_.u % uint(v_.u_.high);
+
+        TTMATH_ASSERT( qp_.u_.high==0 || qp_.u_.high==1 )
+
+        do
+        {
+            bool decrease = false;
+
+            if( qp_.u_.high == 1 )
+                decrease = true;
+            else
+            {
+                temp_.u_.high = rp_.u_.low;
+                temp_.u_.low  = u3;
+
+                if( qp_.u * uint(v_.u_.low) > temp_.u )
+                    decrease = true;
+            }
+            
+            next_test = false;
+
+            if( decrease )
+            {
+                --qp_.u;
+                rp_.u += v_.u_.high;
+
+                if( rp_.u_.high == 0 ) 
+                    next_test = true;
+            }
+        }
+        while( next_test );
+
+    return qp_.u_.low;
+    }
+
+
+    template<uint value_size>
+    void UInt<value_size>::MultiplySubtract(uint_ & u_, unsigned int & u3, unsigned int & q, uint_ v_)
+    {
+    uint_ temp_;
+        
+        uint res_high;
+        uint res_low;
+
+        MulTwoWords(v_.u, q, &res_high, &res_low);
+
+        uint_ sub_res_high_;
+        uint_ sub_res_low_;
+
+        temp_.u_.high = u_.u_.low;
+        temp_.u_.low  = u3;
+
+        uint c = SubTwoWords(temp_.u, res_low, 0, &sub_res_low_.u);
+            
+        temp_.u_.high = 0;
+        temp_.u_.low  = u_.u_.high;
+        c = SubTwoWords(temp_.u, res_high, c, &sub_res_high_.u);
+
+        if( c )
+        {
+            --q;
+
+            c = AddTwoWords(sub_res_low_.u, v_.u, 0, &sub_res_low_.u);
+            AddTwoWords(sub_res_high_.u, 0, c, &sub_res_high_.u);
+        }
+
+        u_.u_.high = sub_res_high_.u_.low;
+        u_.u_.low  = sub_res_low_.u_.high;
+        u3         = sub_res_low_.u_.low;
+    }
+
+#endif // #ifdef TTMATH_PLATFORM64
+
+
+
+} //namespace
+
+
+#endif //ifdef TTMATH_NOASM
+#endif
+
+
+
+
+
diff -r 000000000000 -r 04a9f72bbca7 ttmathuint_x86.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ttmathuint_x86.h	Tue Jul 30 18:43:48 2013 +0000
@@ -0,0 +1,1603 @@
+/*
+ * This file is a part of TTMath Bignum Library
+ * and is distributed under the (new) BSD licence.
+ * Author: Tomasz Sowa <t.sowa@ttmath.org>
+ */
+
+/* 
+ * Copyright (c) 2006-2009, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+#ifndef headerfilettmathuint_x86
+#define headerfilettmathuint_x86
+
+
+#ifndef TTMATH_NOASM
+#ifdef TTMATH_PLATFORM32
+
+
+/*!
+    \file ttmathuint_x86.h
+    \brief template class UInt<uint> with assembler code for 32bit x86 processors
+
+    this file is included at the end of ttmathuint.h
+*/
+
+
+
+/*!
+    \brief a namespace for the TTMath library
+*/
+namespace ttmath
+{
+
+    /*!
+        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
+    */
+    template<uint value_size>
+    const char * UInt<value_size>::LibTypeStr()
+    {
+        #ifndef __GNUC__
+            static const char info[] = "asm_vc_32";
+        #endif        
+
+        #ifdef __GNUC__
+            static const char info[] = "asm_gcc_32";
+        #endif
+
+    return info;
+    }
+
+
+    /*!
+        returning the currect type of the library
+    */
+    template<uint value_size>
+    LibTypeCode UInt<value_size>::LibType()
+    {
+        #ifndef __GNUC__
+            LibTypeCode info = asm_vc_32;
+        #endif        
+
+        #ifdef __GNUC__
+            LibTypeCode info = asm_gcc_32;
+        #endif
+
+    return info;
+    }
+
+
+
+    /*!
+    *
+    *    basic mathematic functions
+    *
+    */
+
+
+    /*!
+        adding ss2 to the this and adding carry if it's defined
+        (this = this + ss2 + c)
+
+        c must be zero or one (might be a bigger value than 1)
+        function returns carry (1) (if it has been)
+    */
+    template<uint value_size>
+    uint UInt<value_size>::Add(const UInt<value_size> & ss2, uint c)
+    {
+    uint b = value_size;
+    uint * p1 = table;
+    uint * p2 = const_cast<uint*>(ss2.table);
+
+        // we don't have to use TTMATH_REFERENCE_ASSERT here
+        // this algorithm doesn't require it
+
+        #ifndef __GNUC__
+            
+            //    this part might be compiled with for example visual c
+
+            __asm
+            {
+                push eax
+                push ebx
+                push ecx
+                push edx
+                push esi
+
+                mov ecx,[b]
+                
+                mov ebx,[p1]
+                mov esi,[p2]
+
+                xor edx,edx          // edx=0
+                mov eax,[c]
+                neg eax              // CF=1 if rax!=0 , CF=0 if rax==0
+
+            ttmath_loop:
+                mov eax,[esi+edx*4]
+                adc [ebx+edx*4],eax
+
+                inc edx
+                dec ecx
+            jnz ttmath_loop
+
+                adc ecx, ecx
+                mov [c], ecx
+
+                pop esi
+                pop edx
+                pop ecx
+                pop ebx
+                pop eax
+            }
+
+
+
+        #endif        
+            
+
+        #ifdef __GNUC__
+        uint dummy, dummy2;
+            //    this part should be compiled with gcc
+            
+            __asm__ __volatile__(
+
+                "xorl %%edx, %%edx                \n"
+                "negl %%eax                        \n"  // CF=1 if rax!=0 , CF=0 if rax==0
+
+            "1:                                    \n"
+                "movl (%%esi,%%edx,4), %%eax    \n"
+                "adcl %%eax, (%%ebx,%%edx,4)    \n"
+            
+                "incl %%edx                        \n"
+                "decl %%ecx                        \n"
+            "jnz 1b                                \n"
+
+                "adc %%ecx, %%ecx                \n"
+
+                : "=c" (c), "=a" (dummy), "=d" (dummy2)
+                : "0" (b),  "1" (c), "b" (p1), "S" (p2)
+                : "cc", "memory" );
+        #endif
+
+        TTMATH_LOGC("UInt::Add", c)
+
+    return c;
+    }
+
+
+
+    /*!
+        adding one word (at a specific position)
+        and returning a carry (if it has been)
+
+        e.g.
+
+        if we've got (value_size=3):
+            table[0] = 10;
+            table[1] = 30;
+            table[2] = 5;    
+        and we call:
+            AddInt(2,1)
+        then it'll be:
+            table[0] = 10;
+            table[1] = 30 + 2;
+            table[2] = 5;
+
+        of course if there was a carry from table[2] it would be returned
+    */
+    template<uint value_size>
+    uint UInt<value_size>::AddInt(uint value, uint index)
+    {
+    uint b = value_size;
+    uint * p1 = table;
+    uint c;
+
+        TTMATH_ASSERT( index < value_size )
+
+        #ifndef __GNUC__
+
+            __asm
+            {
+                push eax
+                push ebx
+                push ecx
+                push edx
+
+                mov ecx, [b]
+                sub ecx, [index]                
+
+                mov edx, [index]
+                mov ebx, [p1]
+
+                mov eax, [value]
+
+            ttmath_loop:
+                add [ebx+edx*4], eax
+            jnc ttmath_end
+
+                mov eax, 1
+                inc edx
+                dec ecx
+            jnz ttmath_loop
+
+            ttmath_end:
+                setc al
+                movzx edx, al
+                mov [c], edx
+
+                pop edx
+                pop ecx
+                pop ebx
+                pop eax
+            }
+
+        #endif        
+            
+
+        #ifdef __GNUC__
+        uint dummy, dummy2;
+
+            __asm__ __volatile__(
+            
+                "subl %%edx, %%ecx                 \n"
+
+            "1:                                    \n"
+                "addl %%eax, (%%ebx,%%edx,4)    \n"
+            "jnc 2f                                \n"
+                
+                "movl $1, %%eax                    \n"
+                "incl %%edx                        \n"
+                "decl %%ecx                        \n"
+            "jnz 1b                                \n"
+
+            "2:                                    \n"
+                "setc %%al                        \n"
+                "movzx %%al, %%edx                \n"
+
+                : "=d" (c),    "=a" (dummy), "=c" (dummy2)
+                : "0" (index), "1" (value),  "2" (b), "b" (p1)
+                : "cc", "memory" );
+
+        #endif
+    
+        TTMATH_LOGC("UInt::AddInt", c)
+
+    return c;
+    }
+
+
+
+
+    /*!
+        adding only two unsigned words to the existing value
+        and these words begin on the 'index' position
+        (it's used in the multiplication algorithm 2)
+
+        index should be equal or smaller than value_size-2 (index <= value_size-2)
+        x1 - lower word, x2 - higher word
+
+        for example if we've got value_size equal 4 and:
+            table[0] = 3
+            table[1] = 4
+            table[2] = 5
+            table[3] = 6
+        then let
+            x1 = 10
+            x2 = 20
+        and
+            index = 1
+
+        the result of this method will be:
+            table[0] = 3
+            table[1] = 4 + x1 = 14
+            table[2] = 5 + x2 = 25
+            table[3] = 6
+        
+        and no carry at the end of table[3]
+
+        (of course if there was a carry in table[2](5+20) then 
+        this carry would be passed to the table[3] etc.)
+    */
+    template<uint value_size>
+    uint UInt<value_size>::AddTwoInts(uint x2, uint x1, uint index)
+    {
+    uint b = value_size;
+    uint * p1 = table;
+    uint c;
+
+        TTMATH_ASSERT( index < value_size - 1 )
+
+        #ifndef __GNUC__
+            __asm
+            {
+                push eax
+                push ebx
+                push ecx
+                push edx
+
+                mov ecx, [b]
+                sub ecx, [index]                
+
+                mov ebx, [p1]
+                mov edx, [index]
+
+                mov eax, [x1]
+                add [ebx+edx*4], eax
+                inc edx
+                dec ecx
+
+                mov eax, [x2]
+            
+            ttmath_loop:
+                adc [ebx+edx*4], eax
+            jnc ttmath_end
+
+                mov eax, 0
+                inc edx
+                dec ecx
+            jnz ttmath_loop
+
+            ttmath_end:
+                setc al
+                movzx edx, al
+                mov [c], edx
+                
+                pop edx
+                pop ecx
+                pop ebx
+                pop eax
+
+            }
+        #endif        
+            
+
+        #ifdef __GNUC__
+        uint dummy, dummy2;
+
+            __asm__ __volatile__(
+            
+                "subl %%edx, %%ecx                 \n"
+                
+                "addl %%esi, (%%ebx,%%edx,4)     \n"
+                "incl %%edx                        \n"
+                "decl %%ecx                        \n"
+
+            "1:                                    \n"
+                "adcl %%eax, (%%ebx,%%edx,4)    \n"
+            "jnc 2f                                \n"
+
+                "mov $0, %%eax                    \n"
+                "incl %%edx                        \n"
+                "decl %%ecx                        \n"
+            "jnz 1b                                \n"
+
+            "2:                                    \n"
+                "setc %%al                        \n"
+                "movzx %%al, %%eax                \n"
+
+                : "=a" (c), "=c" (dummy), "=d" (dummy2)
+                : "0" (x2), "1" (b),      "2" (index), "b" (p1), "S" (x1)
+                : "cc", "memory" );
+
+        #endif
+
+        TTMATH_LOGC("UInt::AddTwoInts", c)
+    
+    return c;
+    }
+
+
+
+    /*!
+        this static method addes one vector to the other
+        'ss1' is larger in size or equal to 'ss2'
+
+        ss1 points to the first (larger) vector
+        ss2 points to the second vector
+        ss1_size - size of the ss1 (and size of the result too)
+        ss2_size - size of the ss2
+        result - is the result vector (which has size the same as ss1: ss1_size)
+
+        Example:  ss1_size is 5, ss2_size is 3
+        ss1:      ss2:   result (output):
+          5        1         5+1
+          4        3         4+3
+          2        7         2+7
+          6                  6
+          9                  9
+      of course the carry is propagated and will be returned from the last item
+      (this method is used by the Karatsuba multiplication algorithm)
+    */
+    template<uint value_size>
+    uint UInt<value_size>::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
+    {
+        TTMATH_ASSERT( ss1_size >= ss2_size )
+
+        uint rest = ss1_size - ss2_size;
+        uint c;
+
+        #ifndef __GNUC__
+
+            //    this part might be compiled with for example visual c
+            __asm
+            {
+                pushad
+
+                mov ecx, [ss2_size]
+                xor edx, edx               // edx = 0, cf = 0
+
+                mov esi, [ss1]
+                mov ebx, [ss2]
+                mov edi, [result]
+
+            ttmath_loop:
+                mov eax, [esi+edx*4]
+                adc eax, [ebx+edx*4]
+                mov [edi+edx*4], eax
+
+                inc edx
+                dec ecx
+            jnz ttmath_loop
+
+                adc ecx, ecx             // ecx has the cf state
+
+                mov ebx, [rest]
+                or ebx, ebx
+                jz ttmath_end
+                
+                xor ebx, ebx             // ebx = 0
+                neg ecx                  // setting cf from ecx
+                mov ecx, [rest]          // ecx is != 0
+            
+            ttmath_loop2:
+                mov eax, [esi+edx*4]
+                adc eax, ebx 
+                mov [edi+edx*4], eax
+
+                inc edx
+                dec ecx
+            jnz ttmath_loop2
+
+                adc ecx, ecx
+
+            ttmath_end:
+                mov [c], ecx
+
+                popad
+            }
+
+        #endif        
+            
+
+        #ifdef __GNUC__
+            
+        //    this part should be compiled with gcc
+        uint dummy1, dummy2, dummy3;
+
+            __asm__ __volatile__(
+                "push %%edx                            \n"
+                "xor %%edx, %%edx                    \n"   // edx = 0, cf = 0
+            "1:                                        \n"
+                "mov (%%esi,%%edx,4), %%eax            \n"
+                "adc (%%ebx,%%edx,4), %%eax            \n"
+                "mov %%eax, (%%edi,%%edx,4)            \n"
+
+                "inc %%edx                            \n"
+                "dec %%ecx                            \n"
+            "jnz 1b                                    \n"
+
+                "adc %%ecx, %%ecx                    \n"   // ecx has the cf state
+                "pop %%eax                            \n"   // eax = rest
+
+                "or %%eax, %%eax                    \n"
+                "jz 3f                                \n"
+                
+                "xor %%ebx, %%ebx                    \n"   // ebx = 0
+                "neg %%ecx                            \n"   // setting cf from ecx
+                "mov %%eax, %%ecx                    \n"   // ecx=rest and is != 0
+            "2:                                        \n"
+                "mov (%%esi, %%edx, 4), %%eax        \n"
+                "adc %%ebx, %%eax                     \n"
+                "mov %%eax, (%%edi, %%edx, 4)        \n"
+
+                "inc %%edx                            \n"
+                "dec %%ecx                            \n"
+            "jnz 2b                                    \n"
+
+                "adc %%ecx, %%ecx                    \n"
+            "3:                                        \n"
+
+                : "=a" (dummy1), "=b" (dummy2), "=c" (c),       "=d" (dummy3)
+                :                "1" (ss2),     "2" (ss2_size), "3" (rest),   "S" (ss1),  "D" (result)
+                : "cc", "memory" );
+
+        #endif
+
+        TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size)
+
+    return c;
+    }
+
+
+    /*!
+        subtracting ss2 from the 'this' and subtracting
+        carry if it has been defined
+        (this = this - ss2 - c)
+
+        c must be zero or one (might be a bigger value than 1)
+        function returns carry (1) (if it has been)
+    */
+    template<uint value_size>
+    uint UInt<value_size>::Sub(const UInt<value_size> & ss2, uint c)
+    {
+    uint b = value_size;
+    uint * p1 = table;
+    uint * p2 = const_cast<uint*>(ss2.table);
+
+        // we don't have to use TTMATH_REFERENCE_ASSERT here
+        // this algorithm doesn't require it
+
+        #ifndef __GNUC__
+
+            __asm
+            {
+                push eax
+                push ebx
+                push ecx
+                push edx
+                push esi
+
+                mov ecx,[b]
+                
+                mov ebx,[p1]
+                mov esi,[p2]
+
+                xor edx,edx          // edx=0
+                mov eax,[c]
+                neg eax              // CF=1 if rax!=0 , CF=0 if rax==0
+
+            ttmath_loop:
+                mov eax,[esi+edx*4]
+                sbb [ebx+edx*4],eax
+
+                inc edx
+                dec ecx
+            jnz ttmath_loop
+
+                adc ecx, ecx
+                mov [c], ecx
+
+                pop esi
+                pop edx
+                pop ecx
+                pop ebx
+                pop eax
+            }
+
+        #endif
+
+
+        #ifdef __GNUC__
+        uint dummy, dummy2;
+
+            __asm__  __volatile__(
+
+                "xorl %%edx, %%edx                \n"
+                "negl %%eax                        \n"  // CF=1 if rax!=0 , CF=0 if rax==0
+
+            "1:                                    \n"
+                "movl (%%esi,%%edx,4), %%eax    \n"
+                "sbbl %%eax, (%%ebx,%%edx,4)    \n"
+            
+                "incl %%edx                        \n"
+                "decl %%ecx                        \n"
+            "jnz 1b                                \n"
+
+                "adc %%ecx, %%ecx                \n"
+
+                : "=c" (c), "=a" (dummy), "=d" (dummy2)
+                : "0" (b),  "1" (c), "b" (p1), "S" (p2)
+                : "cc", "memory" );
+
+        #endif
+
+        TTMATH_LOGC("UInt::Sub", c)
+
+    return c;
+    }
+
+
+
+
+    /*!
+        this method subtracts one word (at a specific position)
+        and returns a carry (if it was)
+
+        e.g.
+
+        if we've got (value_size=3):
+            table[0] = 10;
+            table[1] = 30;
+            table[2] = 5;    
+        and we call:
+            SubInt(2,1)
+        then it'll be:
+            table[0] = 10;
+            table[1] = 30 - 2;
+            table[2] = 5;
+
+        of course if there was a carry from table[2] it would be returned
+    */
+    template<uint value_size>
+    uint UInt<value_size>::SubInt(uint value, uint index)
+    {
+    uint b = value_size;
+    uint * p1 = table;
+    uint c;
+
+        TTMATH_ASSERT( index < value_size )
+
+        #ifndef __GNUC__
+
+            __asm
+            {
+                push eax
+                push ebx
+                push ecx
+                push edx
+
+                mov ecx, [b]
+                sub ecx, [index]                
+
+                mov edx, [index]
+                mov ebx, [p1]
+
+                mov eax, [value]
+
+            ttmath_loop:
+                sub [ebx+edx*4], eax
+            jnc ttmath_end
+
+                mov eax, 1
+                inc edx
+                dec ecx
+            jnz ttmath_loop
+
+            ttmath_end:
+                setc al
+                movzx edx, al
+                mov [c], edx
+
+                pop edx
+                pop ecx
+                pop ebx
+                pop eax
+            }
+
+        #endif        
+            
+
+        #ifdef __GNUC__
+        uint dummy, dummy2;
+
+            __asm__ __volatile__(
+            
+                "subl %%edx, %%ecx                 \n"
+
+            "1:                                    \n"
+                "subl %%eax, (%%ebx,%%edx,4)    \n"
+            "jnc 2f                                \n"
+                
+                "movl $1, %%eax                    \n"
+                "incl %%edx                        \n"
+                "decl %%ecx                        \n"
+            "jnz 1b                                \n"
+
+            "2:                                    \n"
+                "setc %%al                        \n"
+                "movzx %%al, %%edx                \n"
+
+                : "=d" (c),    "=a" (dummy), "=c" (dummy2)
+                : "0" (index), "1" (value),  "2" (b), "b" (p1)
+                : "cc", "memory" );
+
+        #endif
+        
+        TTMATH_LOGC("UInt::SubInt", c)
+    
+    return c;
+    }
+
+
+
+    /*!
+        this static method subtractes one vector from the other
+        'ss1' is larger in size or equal to 'ss2'
+
+        ss1 points to the first (larger) vector
+        ss2 points to the second vector
+        ss1_size - size of the ss1 (and size of the result too)
+        ss2_size - size of the ss2
+        result - is the result vector (which has size the same as ss1: ss1_size)
+
+        Example:  ss1_size is 5, ss2_size is 3
+        ss1:      ss2:   result (output):
+          5        1         5-1
+          4        3         4-3
+          2        7         2-7
+          6                  6-1  (the borrow from previous item)
+          9                  9
+                      return (carry): 0
+      of course the carry (borrow) is propagated and will be returned from the last item
+      (this method is used by the Karatsuba multiplication algorithm)
+    */
+    template<uint value_size>
+    uint UInt<value_size>::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
+    {
+        TTMATH_ASSERT( ss1_size >= ss2_size )
+
+        uint rest = ss1_size - ss2_size;
+        uint c;
+
+        #ifndef __GNUC__
+            
+            //    this part might be compiled with for example visual c
+
+            /*
+                the asm code is nearly the same as in AddVector
+                only two instructions 'adc' are changed to 'sbb'
+            */
+            __asm
+            {
+                pushad
+
+                mov ecx, [ss2_size]
+                xor edx, edx               // edx = 0, cf = 0
+
+                mov esi, [ss1]
+                mov ebx, [ss2]
+                mov edi, [result]
+
+            ttmath_loop:
+                mov eax, [esi+edx*4]
+                sbb eax, [ebx+edx*4]
+                mov [edi+edx*4], eax
+
+                inc edx
+                dec ecx
+            jnz ttmath_loop
+
+                adc ecx, ecx             // ecx has the cf state
+
+                mov ebx, [rest]
+                or ebx, ebx
+                jz ttmath_end
+                
+                xor ebx, ebx             // ebx = 0
+                neg ecx                  // setting cf from ecx
+                mov ecx, [rest]          // ecx is != 0
+
+            ttmath_loop2:
+                mov eax, [esi+edx*4]
+                sbb eax, ebx 
+                mov [edi+edx*4], eax
+
+                inc edx
+                dec ecx
+            jnz ttmath_loop2
+
+                adc ecx, ecx
+
+            ttmath_end:
+                mov [c], ecx
+
+                popad
+            }
+
+        #endif        
+            
+
+        #ifdef __GNUC__
+            
+        //    this part should be compiled with gcc
+        uint dummy1, dummy2, dummy3;
+
+            __asm__ __volatile__(
+                "push %%edx                            \n"
+                "xor %%edx, %%edx                    \n"   // edx = 0, cf = 0
+            "1:                                        \n"
+                "mov (%%esi,%%edx,4), %%eax            \n"
+                "sbb (%%ebx,%%edx,4), %%eax            \n"
+                "mov %%eax, (%%edi,%%edx,4)            \n"
+
+                "inc %%edx                            \n"
+                "dec %%ecx                            \n"
+            "jnz 1b                                    \n"
+
+                "adc %%ecx, %%ecx                    \n"   // ecx has the cf state
+                "pop %%eax                            \n"   // eax = rest
+
+                "or %%eax, %%eax                    \n"
+                "jz 3f                                \n"
+                
+                "xor %%ebx, %%ebx                    \n"   // ebx = 0
+                "neg %%ecx                            \n"   // setting cf from ecx
+                "mov %%eax, %%ecx                    \n"   // ecx=rest and is != 0
+            "2:                                        \n"
+                "mov (%%esi, %%edx, 4), %%eax        \n"
+                "sbb %%ebx, %%eax                     \n"
+                "mov %%eax, (%%edi, %%edx, 4)        \n"
+
+                "inc %%edx                            \n"
+                "dec %%ecx                            \n"
+            "jnz 2b                                    \n"
+
+                "adc %%ecx, %%ecx                    \n"
+            "3:                                        \n"
+
+                : "=a" (dummy1), "=b" (dummy2), "=c" (c),       "=d" (dummy3)
+                :                "1" (ss2),     "2" (ss2_size), "3" (rest),   "S" (ss1),  "D" (result)
+                : "cc", "memory" );
+
+        #endif
+
+        TTMATH_VECTOR_LOGC("UInt::SubVector", c, result, ss1_size)
+
+    return c;
+    }
+
+
+
+    /*!
+        this method moves all bits into the left hand side
+        return value <- this <- c
+
+        the lowest *bit* will be held the 'c' and
+        the state of one additional bit (on the left hand side)
+        will be returned
+
+        for example:
+        let this is 001010000
+        after Rcl2_one(1) there'll be 010100001 and Rcl2_one returns 0
+    */
+    template<uint value_size>
+    uint UInt<value_size>::Rcl2_one(uint c)
+    {
+    uint b = value_size;
+    uint * p1 = table;
+
+        #ifndef __GNUC__
+            __asm
+            {
+                push ebx
+                push ecx
+                push edx
+
+                mov ebx, [p1]
+                xor edx, edx
+                mov ecx, [c]
+                neg ecx
+                mov ecx, [b]
+
+            ttmath_loop:
+                rcl dword ptr [ebx+edx*4], 1
+                
+                inc edx
+                dec ecx
+            jnz ttmath_loop
+
+                adc ecx, ecx
+                mov [c], ecx
+                
+                pop edx
+                pop ecx
+                pop ebx
+            }
+        #endif
+
+
+        #ifdef __GNUC__
+        uint dummy, dummy2;
+
+        __asm__  __volatile__(
+
+            "xorl %%edx, %%edx            \n"   // edx=0
+            "negl %%eax                    \n"   // CF=1 if eax!=0 , CF=0 if eax==0
+
+        "1:                                \n"
+            "rcll $1, (%%ebx, %%edx, 4)    \n"
+
+            "incl %%edx                    \n"
+            "decl %%ecx                    \n"
+        "jnz 1b                            \n"
+
+            "adcl %%ecx, %%ecx            \n"
+
+            : "=c" (c), "=a" (dummy), "=d" (dummy2)
+            : "0" (b),  "1" (c), "b" (p1)
+            : "cc", "memory" );
+
+        #endif
+
+        TTMATH_LOGC("UInt::Rcl2_one", c)
+
+    return c;
+    }
+
+
+
+    /*!
+        this method moves all bits into the right hand side
+        c -> this -> return value
+
+        the highest *bit* will be held the 'c' and
+        the state of one additional bit (on the right hand side)
+        will be returned
+
+        for example:
+        let this is 000000010
+        after Rcr2_one(1) there'll be 100000001 and Rcr2_one returns 0
+    */
+    template<uint value_size>
+    uint UInt<value_size>::Rcr2_one(uint c)
+    {
+    uint b = value_size;
+    uint * p1 = table;
+
+        #ifndef __GNUC__
+            __asm
+            {
+                push ebx
+                push ecx
+
+                mov ebx, [p1]
+                mov ecx, [c]
+                neg ecx
+                mov ecx, [b]
+
+            ttmath_loop:
+                rcr dword ptr [ebx+ecx*4-4], 1
+                
+                dec ecx
+            jnz ttmath_loop
+
+                adc ecx, ecx
+                mov [c], ecx
+
+                pop ecx
+                pop ebx
+            }
+        #endif
+
+
+        #ifdef __GNUC__
+        uint dummy;
+
+        __asm__  __volatile__(
+
+            "negl %%eax                        \n"   // CF=1 if eax!=0 , CF=0 if eax==0
+
+        "1:                                    \n"
+            "rcrl $1, -4(%%ebx, %%ecx, 4)    \n"
+
+            "decl %%ecx                        \n"
+        "jnz 1b                                \n"
+
+            "adcl %%ecx, %%ecx                \n"
+
+            : "=c" (c), "=a" (dummy)
+            : "0" (b),  "1" (c), "b" (p1)
+            : "cc", "memory" );
+
+        #endif
+
+        TTMATH_LOGC("UInt::Rcr2_one", c)
+
+    return c;
+    }
+
+
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4731)
+//warning C4731: frame pointer register 'ebp' modified by inline assembly code
+#endif
+    
+
+
+    /*!
+        this method moves all bits into the left hand side
+        return value <- this <- c
+
+        the lowest *bits* will be held the 'c' and
+        the state of one additional bit (on the left hand side)
+        will be returned
+
+        for example:
+        let this is 001010000
+        after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1
+    */
+    template<uint value_size>
+    uint UInt<value_size>::Rcl2(uint bits, uint c)
+    {
+    TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
+        
+    uint b = value_size;
+    uint * p1 = table;
+
+        #ifndef __GNUC__
+            __asm
+            {
+                push eax
+                push ebx
+                push ecx
+                push edx
+                push esi
+                push edi
+                push ebp
+
+                mov edi, [b]
+
+                mov ecx, 32
+                sub ecx, [bits]
+                mov edx, -1
+                shr edx, cl
+
+                mov ecx, [bits]
+                mov ebx, [p1]
+                mov eax, [c]
+
+                mov ebp, edx         // ebp = mask (modified ebp - don't read/write to variables)
+
+                xor edx, edx         // edx = 0
+                mov esi, edx
+                or eax, eax
+                cmovnz esi, ebp      // if(c) esi=mask else esi=0
+
+            ttmath_loop:
+                rol dword ptr [ebx+edx*4], cl
+                
+                mov eax, [ebx+edx*4]
+                and eax, ebp
+                xor [ebx+edx*4], eax // clearing bits
+                or [ebx+edx*4], esi  // saving old value
+                mov esi, eax
+
+                inc edx
+                dec edi
+            jnz ttmath_loop
+
+                pop ebp              // restoring ebp
+
+                and eax, 1
+                mov [c], eax
+
+                pop edi
+                pop esi
+                pop edx
+                pop ecx
+                pop ebx
+                pop eax
+            }
+        #endif
+
+
+        #ifdef __GNUC__
+        uint dummy, dummy2, dummy3;
+
+        __asm__  __volatile__(
+
+            "push %%ebp                        \n"
+            
+            "movl %%ecx, %%esi                \n"
+            "movl $32, %%ecx                \n"
+            "subl %%esi, %%ecx                \n"    // ecx = 32 - bits
+            "movl $-1, %%edx                \n"    // edx = -1 (all bits set to one)
+            "shrl %%cl, %%edx                \n"    // shifting (0 -> edx -> cf)  (cl times)
+            "movl %%edx, %%ebp                \n"    // ebp = edx = mask
+            "movl %%esi, %%ecx                \n"
+
+            "xorl %%edx, %%edx                \n"
+            "movl %%edx, %%esi                \n"
+            "orl %%eax, %%eax                \n"
+            "cmovnz %%ebp, %%esi            \n"    // if(c) esi=mask else esi=0
+
+        "1:                                    \n"
+            "roll %%cl, (%%ebx,%%edx,4)        \n"
+
+            "movl (%%ebx,%%edx,4), %%eax    \n"
+            "andl %%ebp, %%eax                \n"
+            "xorl %%eax, (%%ebx,%%edx,4)    \n"
+            "orl  %%esi, (%%ebx,%%edx,4)    \n"
+            "movl %%eax, %%esi                \n"
+            
+            "incl %%edx                        \n"
+            "decl %%edi                        \n"
+        "jnz 1b                                \n"
+            
+            "and $1, %%eax                    \n"
+
+            "pop %%ebp                        \n"
+
+            : "=a" (c), "=D" (dummy), "=S" (dummy2), "=d" (dummy3)
+            : "0" (c),  "1" (b), "b" (p1), "c" (bits)
+            : "cc", "memory" );
+
+        #endif
+
+        TTMATH_LOGC("UInt::Rcl2", c)
+
+    return c;
+    }
+
+
+
+
+    /*!
+        this method moves all bits into the right hand side
+        C -> this -> return value
+
+        the highest *bits* will be held the 'c' and
+        the state of one additional bit (on the right hand side)
+        will be returned
+
+        for example:
+        let this is 000000010
+        after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1
+    */
+    template<uint value_size>
+    uint UInt<value_size>::Rcr2(uint bits, uint c)
+    {
+    TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
+
+    uint b = value_size;
+    uint * p1 = table;
+
+        #ifndef __GNUC__
+            __asm
+            {
+                push eax
+                push ebx
+                push ecx
+                push edx
+                push esi
+                push edi
+                push ebp
+
+                mov edi, [b]
+
+                mov ecx, 32
+                sub ecx, [bits]
+                mov edx, -1
+                shl edx, cl
+
+                mov ecx, [bits]
+                mov ebx, [p1]
+                mov eax, [c]
+
+                mov ebp, edx         // ebp = mask (modified ebp - don't read/write to variables)
+
+                xor edx, edx         // edx = 0
+                mov esi, edx
+                add edx, edi
+                dec edx              // edx is pointing at the end of the table (on last word)
+                or eax, eax
+                cmovnz esi, ebp      // if(c) esi=mask else esi=0
+
+            ttmath_loop:
+                ror dword ptr [ebx+edx*4], cl
+                
+                mov eax, [ebx+edx*4]
+                and eax, ebp 
+                xor [ebx+edx*4], eax // clearing bits
+                or [ebx+edx*4], esi  // saving old value
+                mov esi, eax
+
+                dec edx
+                dec edi
+            jnz ttmath_loop
+
+                pop ebp              // restoring ebp
+
+                rol eax, 1           // 31bit will be first
+                and eax, 1  
+                mov [c], eax
+
+                pop edi
+                pop esi
+                pop edx
+                pop ecx
+                pop ebx
+                pop eax
+            }
+        #endif
+
+
+        #ifdef __GNUC__
+        uint dummy, dummy2, dummy3;
+
+            __asm__  __volatile__(
+
+            "push %%ebp                        \n"
+            
+            "movl %%ecx, %%esi                \n"
+            "movl $32, %%ecx                \n"
+            "subl %%esi, %%ecx                \n"    // ecx = 32 - bits
+            "movl $-1, %%edx                \n"    // edx = -1 (all bits set to one)
+            "shll %%cl, %%edx                \n"    // shifting (cf <- edx <- 0)  (cl times)
+            "movl %%edx, %%ebp                \n"    // ebp = edx = mask
+            "movl %%esi, %%ecx                \n"
+
+            "xorl %%edx, %%edx                \n"
+            "movl %%edx, %%esi                \n"
+            "addl %%edi, %%edx                \n"
+            "decl %%edx                        \n"    // edx is pointing at the end of the table (on last word)
+            "orl %%eax, %%eax                \n"
+            "cmovnz %%ebp, %%esi            \n"    // if(c) esi=mask else esi=0
+
+        "1:                                    \n"
+            "rorl %%cl, (%%ebx,%%edx,4)        \n"
+
+            "movl (%%ebx,%%edx,4), %%eax    \n"
+            "andl %%ebp, %%eax                \n"
+            "xorl %%eax, (%%ebx,%%edx,4)    \n"
+            "orl  %%esi, (%%ebx,%%edx,4)    \n"
+            "movl %%eax, %%esi                \n"
+            
+            "decl %%edx                        \n"
+            "decl %%edi                        \n"
+        "jnz 1b                                \n"
+            
+            "roll $1, %%eax                    \n"
+            "andl $1, %%eax                    \n"
+
+            "pop %%ebp                        \n"
+
+            : "=a" (c), "=D" (dummy), "=S" (dummy2), "=d" (dummy3)
+            : "0" (c),  "1" (b), "b" (p1), "c" (bits)
+            : "cc", "memory" );
+
+        #endif
+
+        TTMATH_LOGC("UInt::Rcr2", c)
+
+    return c;
+    }
+
+
+#ifdef _MSC_VER
+#pragma warning (default : 4731)
+#endif
+
+
+    /*
+        this method returns the number of the highest set bit in one 32-bit word
+        if the 'x' is zero this method returns '-1'
+    */
+    template<uint value_size>
+    sint UInt<value_size>::FindLeadingBitInWord(uint x)
+    {
+    sint result;
+
+        #ifndef __GNUC__
+            __asm
+            {
+                push eax
+                push edx
+
+                mov edx,-1
+                bsr eax,[x]
+                cmovz eax,edx
+                mov [result], eax
+
+                pop edx
+                pop eax
+            }
+        #endif
+
+
+        #ifdef __GNUC__
+        uint dummy;
+
+                __asm__ (
+
+                "movl $-1, %1          \n"
+                "bsrl %2, %0           \n"
+                "cmovz %1, %0          \n"
+
+                : "=r" (result), "=&r" (dummy)
+                : "r" (x)
+                : "cc" );
+
+        #endif
+
+    return result;
+    }
+
+
+
+    /*
+        this method returns the number of the smallest set bit in one 32-bit word
+        if the 'x' is zero this method returns '-1'
+    */
+    template<uint value_size>
+    sint UInt<value_size>::FindLowestBitInWord(uint x)
+    {
+    sint result;
+
+        #ifndef __GNUC__
+            __asm
+            {
+                push eax
+                push edx
+
+                mov edx,-1
+                bsf eax,[x]
+                cmovz eax,edx
+                mov [result], eax
+
+                pop edx
+                pop eax
+            }
+        #endif
+
+
+        #ifdef __GNUC__
+        uint dummy;
+
+                __asm__ (
+
+                "movl $-1, %1          \n"
+                "bsfl %2, %0           \n"
+                "cmovz %1, %0          \n"
+
+                : "=r" (result), "=&r" (dummy)
+                : "r" (x)
+                : "cc" );
+
+        #endif
+
+    return result;
+    }
+
+
+
+    /*!
+        this method sets a special bit in the 'value'
+        and returns the last state of the bit (zero or one)
+
+        bit is from <0,31>
+        e.g.
+         uint x = 100;
+         uint bit = SetBitInWord(x, 3);
+         now: x = 108 and bit = 0
+    */
+    template<uint value_size>
+    uint UInt<value_size>::SetBitInWord(uint & value, uint bit)
+    {
+        TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT )
+
+        uint old_bit;
+        uint v = value;
+
+        #ifndef __GNUC__
+            __asm
+            {
+            push ebx
+            push eax
+
+            mov eax, [v]
+            mov ebx, [bit]
+            bts eax, ebx
+            mov [v], eax
+
+            setc bl
+            movzx ebx, bl
+            mov [old_bit], ebx
+
+            pop eax
+            pop ebx
+            }
+        #endif
+
+
+        #ifdef __GNUC__
+            __asm__ (
+
+            "btsl %%ebx, %%eax        \n"
+            "setc %%bl                \n"
+            "movzx %%bl, %%ebx        \n"
+            
+            : "=a" (v), "=b" (old_bit)
+            : "0" (v),  "1" (bit)
+            : "cc" );
+
+        #endif
+
+        value = v;
+
+    return old_bit;
+    }
+
+
+
+
+    /*!
+        multiplication: result_high:result_low = a * b
+        result_high - higher word of the result
+        result_low  - lower word of the result
+    
+        this methos never returns a carry
+        this method is used in the second version of the multiplication algorithms
+    */
+    template<uint value_size>
+    void UInt<value_size>::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low)
+    {
+    /*
+        we must use these temporary variables in order to inform the compilator
+        that value pointed with result1 and result2 has changed
+
+        this has no effect in visual studio but it's useful when
+        using gcc and options like -Ox
+    */
+    uint result1_;
+    uint result2_;
+
+        #ifndef __GNUC__
+
+            __asm
+            {
+            push eax
+            push edx
+
+            mov eax, [a]
+            mul dword ptr [b]
+
+            mov [result2_], edx
+            mov [result1_], eax
+
+            pop edx
+            pop eax
+            }
+
+        #endif
+
+
+        #ifdef __GNUC__
+
+        __asm__ (
+        
+            "mull %%edx            \n"
+
+            : "=a" (result1_), "=d" (result2_)
+            : "0" (a),         "1" (b)
+            : "cc" );
+
+        #endif
+
+
+        *result_low  = result1_;
+        *result_high = result2_;
+    }
+
+
+
+
+
+    /*!
+     *
+     * Division
+     *
+     *
+    */
+    
+
+
+
+    /*!
+        this method calculates 64bits word a:b / 32bits c (a higher, b lower word)
+        r = a:b / c and rest - remainder
+
+        *
+        * WARNING:
+        * if r (one word) is too small for the result or c is equal zero
+        * there'll be a hardware interruption (0)
+        * and probably the end of your program
+        *
+    */
+    template<uint value_size>
+    void UInt<value_size>::DivTwoWords(uint a, uint b, uint c, uint * r, uint * rest)
+    {
+        uint r_;
+        uint rest_;
+        /*
+            these variables have similar meaning like those in
+            the multiplication algorithm MulTwoWords
+        */
+
+        TTMATH_ASSERT( c != 0 )
+
+        #ifndef __GNUC__
+            __asm
+            {
+                push eax
+                push edx
+
+                mov edx, [a]
+                mov eax, [b]
+                div dword ptr [c]
+
+                mov [r_], eax
+                mov [rest_], edx
+
+                pop edx
+                pop eax
+            }
+        #endif
+
+
+        #ifdef __GNUC__
+        
+            __asm__ (
+
+            "divl %%ecx                \n"
+
+            : "=a" (r_), "=d" (rest_)
+            : "0" (b),   "1" (a), "c" (c)
+            : "cc" );
+
+        #endif
+
+
+        *r = r_;
+        *rest = rest_;
+
+    }
+
+
+
+} //namespace
+
+
+
+#endif //ifdef TTMATH_PLATFORM32
+#endif //ifndef TTMATH_NOASM
+#endif
+
diff -r 000000000000 -r 04a9f72bbca7 ttmathuint_x86_64.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ttmathuint_x86_64.h	Tue Jul 30 18:43:48 2013 +0000
@@ -0,0 +1,1147 @@
+/*
+ * This file is a part of TTMath Bignum Library
+ * and is distributed under the (new) BSD licence.
+ * Author: Tomasz Sowa <t.sowa@ttmath.org>
+ */
+
+/* 
+ * Copyright (c) 2006-2010, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef headerfilettmathuint_x86_64
+#define headerfilettmathuint_x86_64
+
+
+#ifndef TTMATH_NOASM
+#ifdef TTMATH_PLATFORM64
+
+
+/*!
+    \file ttmathuint_x86_64.h
+    \brief template class UInt<uint> with assembler code for 64bit x86_64 processors
+
+    this file is included at the end of ttmathuint.h
+*/
+
+#ifndef __GNUC__
+#include <intrin.h>
+#endif
+
+
+namespace ttmath
+{
+
+    #ifndef __GNUC__
+
+        extern "C"
+            {
+            uint __fastcall ttmath_adc_x64(uint* p1, const uint* p2, uint nSize, uint c);
+            uint __fastcall ttmath_addindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue);
+            uint __fastcall ttmath_addindexed2_x64(uint* p1, uint nSize, uint nPos, uint nValue1, uint nValue2);
+            uint __fastcall ttmath_addvector_x64(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result);
+            uint __fastcall ttmath_sbb_x64(uint* p1, const uint* p2, uint nSize, uint c);
+            uint __fastcall ttmath_subindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue);
+            uint __fastcall ttmath_subvector_x64(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result);
+            uint __fastcall ttmath_rcl_x64(uint* p1, uint nSize, uint nLowestBit);
+            uint __fastcall ttmath_rcr_x64(uint* p1, uint nSize, uint nLowestBit);
+            uint __fastcall ttmath_div_x64(uint* pnValHi, uint* pnValLo, uint nDiv);
+            uint __fastcall ttmath_rcl2_x64(uint* p1, uint nSize, uint nBits, uint c);
+            uint __fastcall ttmath_rcr2_x64(uint* p1, uint nSize, uint nBits, uint c);
+            };
+    #endif
+
+
+    /*!
+        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
+    */
+    template<uint value_size>
+    const char * UInt<value_size>::LibTypeStr()
+    {
+        #ifndef __GNUC__
+            static const char info[] = "asm_vc_64";
+        #endif        
+
+        #ifdef __GNUC__
+            static const char info[] = "asm_gcc_64";
+        #endif
+
+    return info;
+    }
+
+
+    /*!
+        returning the currect type of the library
+    */
+    template<uint value_size>
+    LibTypeCode UInt<value_size>::LibType()
+    {
+        #ifndef __GNUC__
+            LibTypeCode info = asm_vc_64;
+        #endif        
+
+        #ifdef __GNUC__
+            LibTypeCode info = asm_gcc_64;
+        #endif
+
+    return info;
+    }
+
+
+    /*!
+    *
+    *    basic mathematic functions
+    *
+    */
+
+
+
+    /*!
+        this method adding ss2 to the this and adding carry if it's defined
+        (this = this + ss2 + c)
+
+        ***this method is created only on a 64bit platform***
+
+        c must be zero or one (might be a bigger value than 1)
+        function returns carry (1) (if it was)
+    */
+    template<uint value_size>
+    uint UInt<value_size>::Add(const UInt<value_size> & ss2, uint c)
+    {
+    uint b = value_size;
+    uint * p1 = table;
+    const uint * p2 = ss2.table;
+
+        // we don't have to use TTMATH_REFERENCE_ASSERT here
+        // this algorithm doesn't require it
+
+        #ifndef __GNUC__
+            c = ttmath_adc_x64(p1,p2,b,c);
+        #endif
+
+        #ifdef __GNUC__
+        uint dummy, dummy2;
+
+            /*
+                this part should be compiled with gcc
+            */
+            __asm__ __volatile__(
+    
+                "xorq %%rdx, %%rdx                \n"
+                "negq %%rax                        \n"     // CF=1 if rax!=0 , CF=0 if rax==0
+
+            "1:                                    \n"
+                "movq (%%rsi,%%rdx,8), %%rax    \n"
+                "adcq %%rax, (%%rbx,%%rdx,8)    \n"
+            
+                "incq %%rdx                        \n"
+                "decq %%rcx                        \n"
+            "jnz 1b                                \n"
+
+                "adcq %%rcx, %%rcx                \n"
+
+                : "=c" (c), "=a" (dummy), "=d" (dummy2)
+                : "0" (b),  "1" (c), "b" (p1), "S" (p2)
+                : "cc", "memory" );
+
+        #endif
+
+        TTMATH_LOGC("UInt::Add", c)
+    
+    return c;
+    }
+
+
+
+    /*!
+        this method adds one word (at a specific position)
+        and returns a carry (if it was)
+
+        ***this method is created only on a 64bit platform***
+
+
+        if we've got (value_size=3):
+            table[0] = 10;
+            table[1] = 30;
+            table[2] = 5;    
+        and we call:
+            AddInt(2,1)
+        then it'll be:
+            table[0] = 10;
+            table[1] = 30 + 2;
+            table[2] = 5;
+
+        of course if there was a carry from table[2] it would be returned
+    */
+    template<uint value_size>
+    uint UInt<value_size>::AddInt(uint value, uint index)
+    {
+    uint b = value_size;
+    uint * p1 = table;
+    uint c;
+
+        TTMATH_ASSERT( index < value_size )
+
+        #ifndef __GNUC__
+            c = ttmath_addindexed_x64(p1,b,index,value);
+        #endif
+
+
+        #ifdef __GNUC__
+        uint dummy, dummy2;
+    
+            __asm__ __volatile__(
+
+                "subq %%rdx, %%rcx                 \n"
+
+            "1:                                    \n"
+                "addq %%rax, (%%rbx,%%rdx,8)    \n"
+            "jnc 2f                                \n"
+                
+                "movq $1, %%rax                    \n"
+                "incq %%rdx                        \n"
+                "decq %%rcx                        \n"
+            "jnz 1b                                \n"
+
+            "2:                                    \n"
+                "setc %%al                        \n"
+                "movzx %%al, %%rdx                \n"
+
+                : "=d" (c),    "=a" (dummy), "=c" (dummy2)
+                : "0" (index), "1" (value),  "2" (b), "b" (p1)
+                : "cc", "memory" );
+
+        #endif
+
+        TTMATH_LOGC("UInt::AddInt", c)
+    
+    return c;
+    }
+
+
+
+    /*!
+        this method adds only two unsigned words to the existing value
+        and these words begin on the 'index' position
+        (it's used in the multiplication algorithm 2)
+
+        ***this method is created only on a 64bit platform***
+
+        index should be equal or smaller than value_size-2 (index <= value_size-2)
+        x1 - lower word, x2 - higher word
+
+        for example if we've got value_size equal 4 and:
+            table[0] = 3
+            table[1] = 4
+            table[2] = 5
+            table[3] = 6
+        then let
+            x1 = 10
+            x2 = 20
+        and
+            index = 1
+
+        the result of this method will be:
+            table[0] = 3
+            table[1] = 4 + x1 = 14
+            table[2] = 5 + x2 = 25
+            table[3] = 6
+        
+        and no carry at the end of table[3]
+
+        (of course if there was a carry in table[2](5+20) then 
+        this carry would be passed to the table[3] etc.)
+    */
+    template<uint value_size>
+    uint UInt<value_size>::AddTwoInts(uint x2, uint x1, uint index)
+    {
+    uint b = value_size;
+    uint * p1 = table;
+    uint c;
+
+        TTMATH_ASSERT( index < value_size - 1 )
+
+        #ifndef __GNUC__
+            c = ttmath_addindexed2_x64(p1,b,index,x1,x2);
+        #endif
+
+
+        #ifdef __GNUC__
+        uint dummy, dummy2;
+
+            __asm__ __volatile__(
+            
+                "subq %%rdx, %%rcx                 \n"
+                
+                "addq %%rsi, (%%rbx,%%rdx,8)     \n"
+                "incq %%rdx                        \n"
+                "decq %%rcx                        \n"
+
+            "1:                                    \n"
+                "adcq %%rax, (%%rbx,%%rdx,8)    \n"
+            "jnc 2f                                \n"
+
+                "mov $0, %%rax                    \n"
+                "incq %%rdx                        \n"
+                "decq %%rcx                        \n"
+            "jnz 1b                                \n"
+
+            "2:                                    \n"
+                "setc %%al                        \n"
+                "movzx %%al, %%rax                \n"
+
+                : "=a" (c), "=c" (dummy), "=d" (dummy2)
+                : "0" (x2), "1" (b),      "2" (index), "b" (p1), "S" (x1)
+                : "cc", "memory" );
+
+        #endif
+
+        TTMATH_LOGC("UInt::AddTwoInts", c)
+
+    return c;
+    }
+
+
+
+    /*!
+        this static method addes one vector to the other
+        'ss1' is larger in size or equal to 'ss2'
+
+        ss1 points to the first (larger) vector
+        ss2 points to the second vector
+        ss1_size - size of the ss1 (and size of the result too)
+        ss2_size - size of the ss2
+        result - is the result vector (which has size the same as ss1: ss1_size)
+
+        Example:  ss1_size is 5, ss2_size is 3
+        ss1:      ss2:   result (output):
+          5        1         5+1
+          4        3         4+3
+          2        7         2+7
+          6                  6
+          9                  9
+      of course the carry is propagated and will be returned from the last item
+      (this method is used by the Karatsuba multiplication algorithm)
+    */
+    template<uint value_size>
+    uint UInt<value_size>::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
+    {
+        TTMATH_ASSERT( ss1_size >= ss2_size )
+
+        uint c;
+
+        #ifndef __GNUC__
+             c = ttmath_addvector_x64(ss1, ss2, ss1_size, ss2_size, result);
+        #endif
+
+
+        #ifdef __GNUC__
+        uint dummy1, dummy2, dummy3;    
+        uint rest = ss1_size - ss2_size;
+            
+            //    this part should be compiled with gcc
+        
+            __asm__ __volatile__(
+                "mov %%rdx, %%r8                    \n"
+                "xor %%rdx, %%rdx                    \n"   // rdx = 0, cf = 0
+            "1:                                        \n"
+                "mov (%%rsi,%%rdx,8), %%rax            \n"
+                "adc (%%rbx,%%rdx,8), %%rax            \n"
+                "mov %%rax, (%%rdi,%%rdx,8)            \n"
+
+                "inc %%rdx                            \n"
+                "dec %%rcx                            \n"
+            "jnz 1b                                    \n"
+
+                "adc %%rcx, %%rcx                    \n"   // rcx has the cf state
+
+                "or %%r8, %%r8                        \n"
+                "jz 3f                                \n"
+                
+                "xor %%rbx, %%rbx                    \n"   // ebx = 0
+                "neg %%rcx                            \n"   // setting cf from rcx
+                "mov %%r8, %%rcx                    \n"   // rcx=rest and is != 0
+            "2:                                        \n"
+                "mov (%%rsi, %%rdx, 8), %%rax        \n"
+                "adc %%rbx, %%rax                     \n"
+                "mov %%rax, (%%rdi, %%rdx, 8)        \n"
+
+                "inc %%rdx                            \n"
+                "dec %%rcx                            \n"
+            "jnz 2b                                    \n"
+
+                "adc %%rcx, %%rcx                    \n"
+            "3:                                        \n"
+
+                : "=a" (dummy1), "=b" (dummy2), "=c" (c),       "=d" (dummy3)
+                :                "1" (ss2),     "2" (ss2_size), "3" (rest),   "S" (ss1),  "D" (result)
+                : "%r8", "cc", "memory" );
+
+        #endif
+
+        TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size)
+
+    return c;
+    }
+
+
+
+    /*!
+        this method's subtracting ss2 from the 'this' and subtracting
+        carry if it has been defined
+        (this = this - ss2 - c)
+
+        ***this method is created only on a 64bit platform***
+
+        c must be zero or one (might be a bigger value than 1)
+        function returns carry (1) (if it was)
+    */
+    template<uint value_size>
+    uint UInt<value_size>::Sub(const UInt<value_size> & ss2, uint c)
+    {
+    uint b = value_size;
+    uint * p1 = table;
+    const uint * p2 = ss2.table;
+    
+        // we don't have to use TTMATH_REFERENCE_ASSERT here
+        // this algorithm doesn't require it
+
+        #ifndef __GNUC__
+            c = ttmath_sbb_x64(p1,p2,b,c);
+        #endif
+
+
+        #ifdef __GNUC__
+        uint dummy, dummy2;
+
+            __asm__  __volatile__(
+    
+                "xorq %%rdx, %%rdx                \n"
+                "negq %%rax                        \n"     // CF=1 if rax!=0 , CF=0 if rax==0
+
+            "1:                                    \n"
+                "movq (%%rsi,%%rdx,8), %%rax    \n"
+                "sbbq %%rax, (%%rbx,%%rdx,8)    \n"
+            
+                "incq %%rdx                        \n"
+                "decq %%rcx                        \n"
+            "jnz 1b                                \n"
+
+                "adcq %%rcx, %%rcx                \n"
+
+                : "=c" (c), "=a" (dummy), "=d" (dummy2)
+                : "0" (b),  "1" (c), "b" (p1), "S" (p2)
+                : "cc", "memory" );
+
+        #endif
+
+        TTMATH_LOGC("UInt::Sub", c)
+
+    return c;
+    }
+
+
+
+    /*!
+        this method subtracts one word (at a specific position)
+        and returns a carry (if it was)
+
+        ***this method is created only on a 64bit platform***
+
+        if we've got (value_size=3):
+            table[0] = 10;
+            table[1] = 30;
+            table[2] = 5;    
+        and we call:
+            SubInt(2,1)
+        then it'll be:
+            table[0] = 10;
+            table[1] = 30 - 2;
+            table[2] = 5;
+
+        of course if there was a carry from table[2] it would be returned
+    */
+    template<uint value_size>
+    uint UInt<value_size>::SubInt(uint value, uint index)
+    {
+    uint b = value_size;
+    uint * p1 = table;
+    uint c;
+
+        TTMATH_ASSERT( index < value_size )
+
+        #ifndef __GNUC__
+            c = ttmath_subindexed_x64(p1,b,index,value);
+        #endif
+
+
+        #ifdef __GNUC__
+            uint dummy, dummy2;
+
+            __asm__ __volatile__(
+            
+                "subq %%rdx, %%rcx                 \n"
+
+            "1:                                    \n"
+                "subq %%rax, (%%rbx,%%rdx,8)    \n"
+            "jnc 2f                                \n"
+                
+                "movq $1, %%rax                    \n"
+                "incq %%rdx                        \n"
+                "decq %%rcx                        \n"
+            "jnz 1b                                \n"
+
+            "2:                                    \n"
+                "setc %%al                        \n"
+                "movzx %%al, %%rdx                \n"
+
+                : "=d" (c),    "=a" (dummy), "=c" (dummy2)
+                : "0" (index), "1" (value),  "2" (b), "b" (p1)
+                : "cc", "memory" );
+
+        #endif
+
+        TTMATH_LOGC("UInt::SubInt", c)
+
+    return c;
+    }
+
+
+    /*!
+        this static method subtractes one vector from the other
+        'ss1' is larger in size or equal to 'ss2'
+
+        ss1 points to the first (larger) vector
+        ss2 points to the second vector
+        ss1_size - size of the ss1 (and size of the result too)
+        ss2_size - size of the ss2
+        result - is the result vector (which has size the same as ss1: ss1_size)
+
+        Example:  ss1_size is 5, ss2_size is 3
+        ss1:      ss2:   result (output):
+          5        1         5-1
+          4        3         4-3
+          2        7         2-7
+          6                  6-1  (the borrow from previous item)
+          9                  9
+                       return (carry): 0
+      of course the carry (borrow) is propagated and will be returned from the last item
+      (this method is used by the Karatsuba multiplication algorithm)
+    */
+    template<uint value_size>
+    uint UInt<value_size>::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
+    {
+        TTMATH_ASSERT( ss1_size >= ss2_size )
+
+        uint c;
+
+        #ifndef __GNUC__
+            c = ttmath_subvector_x64(ss1, ss2, ss1_size, ss2_size, result);
+        #endif
+
+
+        #ifdef __GNUC__
+        
+        //    the asm code is nearly the same as in AddVector
+        //    only two instructions 'adc' are changed to 'sbb'
+        
+        uint dummy1, dummy2, dummy3;
+        uint rest = ss1_size - ss2_size;
+
+            __asm__ __volatile__(
+                "mov %%rdx, %%r8                    \n"
+                "xor %%rdx, %%rdx                    \n"   // rdx = 0, cf = 0
+            "1:                                        \n"
+                "mov (%%rsi,%%rdx,8), %%rax            \n"
+                "sbb (%%rbx,%%rdx,8), %%rax            \n"
+                "mov %%rax, (%%rdi,%%rdx,8)            \n"
+
+                "inc %%rdx                            \n"
+                "dec %%rcx                            \n"
+            "jnz 1b                                    \n"
+
+                "adc %%rcx, %%rcx                    \n"   // rcx has the cf state
+
+                "or %%r8, %%r8                        \n"
+                "jz 3f                                \n"
+                
+                "xor %%rbx, %%rbx                    \n"   // ebx = 0
+                "neg %%rcx                            \n"   // setting cf from rcx
+                "mov %%r8, %%rcx                    \n"   // rcx=rest and is != 0
+            "2:                                        \n"
+                "mov (%%rsi, %%rdx, 8), %%rax        \n"
+                "sbb %%rbx, %%rax                     \n"
+                "mov %%rax, (%%rdi, %%rdx, 8)        \n"
+
+                "inc %%rdx                            \n"
+                "dec %%rcx                            \n"
+            "jnz 2b                                    \n"
+
+                "adc %%rcx, %%rcx                    \n"
+            "3:                                        \n"
+
+                : "=a" (dummy1), "=b" (dummy2), "=c" (c),       "=d" (dummy3)
+                :                "1" (ss2),     "2" (ss2_size), "3" (rest),   "S" (ss1),  "D" (result)
+                : "%r8", "cc", "memory" );
+
+        #endif
+
+        TTMATH_VECTOR_LOGC("UInt::SubVector", c, result, ss1_size)
+
+    return c;
+    }
+
+
+    /*!
+        this method moves all bits into the left hand side
+        return value <- this <- c
+
+        the lowest *bit* will be held the 'c' and
+        the state of one additional bit (on the left hand side)
+        will be returned
+
+        for example:
+        let this is 001010000
+        after Rcl2_one(1) there'll be 010100001 and Rcl2_one returns 0
+    
+        ***this method is created only on a 64bit platform***
+    */
+    template<uint value_size>
+    uint UInt<value_size>::Rcl2_one(uint c)
+    {
+    sint b = value_size;
+    uint * p1 = table;
+
+
+        #ifndef __GNUC__
+            c = ttmath_rcl_x64(p1,b,c);
+        #endif
+
+
+        #ifdef __GNUC__
+        uint dummy, dummy2;
+
+        __asm__  __volatile__(
+        
+            "xorq %%rdx, %%rdx            \n"   // rdx=0
+            "negq %%rax                    \n"   // CF=1 if rax!=0 , CF=0 if rax==0
+
+        "1:                                \n"
+            "rclq $1, (%%rbx, %%rdx, 8)    \n"
+
+            "incq %%rdx                    \n"
+            "decq %%rcx                    \n"
+        "jnz 1b                            \n"
+
+            "adcq %%rcx, %%rcx            \n"
+
+            : "=c" (c), "=a" (dummy), "=d" (dummy2)
+            : "0" (b),  "1" (c), "b" (p1)
+            : "cc", "memory" );
+    
+        #endif
+
+        TTMATH_LOGC("UInt::Rcl2_one", c)
+
+    return c;
+    }
+
+
+    /*!
+        this method moves all bits into the right hand side
+        c -> this -> return value
+
+        the highest *bit* will be held the 'c' and
+        the state of one additional bit (on the right hand side)
+        will be returned
+
+        for example:
+        let this is 000000010
+        after Rcr2_one(1) there'll be 100000001 and Rcr2_one returns 0
+
+        ***this method is created only on a 64bit platform***
+    */
+    template<uint value_size>
+    uint UInt<value_size>::Rcr2_one(uint c)
+    {
+    sint b = value_size;
+    uint * p1 = table;
+    
+
+        #ifndef __GNUC__
+            c = ttmath_rcr_x64(p1,b,c);
+        #endif
+
+
+        #ifdef __GNUC__
+        uint dummy;
+
+        __asm__  __volatile__(
+
+            "negq %%rax                        \n"   // CF=1 if rax!=0 , CF=0 if rax==0
+
+        "1:                                    \n"
+            "rcrq $1, -8(%%rbx, %%rcx, 8)    \n"
+
+            "decq %%rcx                        \n"
+        "jnz 1b                                \n"
+
+            "adcq %%rcx, %%rcx                \n"
+
+            : "=c" (c), "=a" (dummy)
+            : "0" (b),  "1" (c), "b" (p1)
+            : "cc", "memory" );
+
+        #endif
+
+        TTMATH_LOGC("UInt::Rcr2_one", c)
+
+    return c;
+    }
+
+
+
+    /*!
+        this method moves all bits into the left hand side
+        return value <- this <- c
+
+        the lowest *bits* will be held the 'c' and
+        the state of one additional bit (on the left hand side)
+        will be returned
+
+        for example:
+        let this is 001010000
+        after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1
+    
+        ***this method is created only on a 64bit platform***
+    */
+    template<uint value_size>
+    uint UInt<value_size>::Rcl2(uint bits, uint c)
+    {
+    TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
+
+    uint b = value_size;
+    uint * p1 = table;
+
+
+        #ifndef __GNUC__
+            c = ttmath_rcl2_x64(p1,b,bits,c);
+        #endif
+
+
+        #ifdef __GNUC__
+        uint dummy, dummy2, dummy3;
+
+        __asm__  __volatile__(
+        
+            "movq %%rcx, %%rsi                \n"
+            "movq $64, %%rcx                \n"
+            "subq %%rsi, %%rcx                \n"
+            "movq $-1, %%rdx                \n"
+            "shrq %%cl, %%rdx                \n"
+            "movq %%rdx, %%r8                 \n"
+            "movq %%rsi, %%rcx                \n"
+
+            "xorq %%rdx, %%rdx                \n"
+            "movq %%rdx, %%rsi                \n"
+            "orq %%rax, %%rax                \n"
+            "cmovnz %%r8, %%rsi                \n"
+
+        "1:                                    \n"
+            "rolq %%cl, (%%rbx,%%rdx,8)        \n"
+
+            "movq (%%rbx,%%rdx,8), %%rax    \n"
+            "andq %%r8, %%rax                \n"
+            "xorq %%rax, (%%rbx,%%rdx,8)    \n"
+            "orq  %%rsi, (%%rbx,%%rdx,8)    \n"
+            "movq %%rax, %%rsi                \n"
+            
+            "incq %%rdx                        \n"
+            "decq %%rdi                        \n"
+        "jnz 1b                                \n"
+            
+            "and $1, %%rax                    \n"
+
+            : "=a" (c), "=D" (dummy), "=S" (dummy2), "=d" (dummy3)
+            : "0" (c),  "1" (b), "b" (p1), "c" (bits)
+            : "%r8", "cc", "memory" );
+
+        #endif
+
+        TTMATH_LOGC("UInt::Rcl2", c)
+
+    return c;
+    }
+
+
+    /*!
+        this method moves all bits into the right hand side
+        C -> this -> return value
+
+        the highest *bits* will be held the 'c' and
+        the state of one additional bit (on the right hand side)
+        will be returned
+
+        for example:
+        let this is 000000010
+        after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1
+
+        ***this method is created only on a 64bit platform***
+    */
+    template<uint value_size>
+    uint UInt<value_size>::Rcr2(uint bits, uint c)
+    {
+    TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
+
+    sint b = value_size;
+    uint * p1 = table;
+
+
+        #ifndef __GNUC__
+            c = ttmath_rcr2_x64(p1,b,bits,c);
+        #endif
+
+
+        #ifdef __GNUC__
+            uint dummy, dummy2, dummy3;
+
+            __asm__  __volatile__(
+
+            "movq %%rcx, %%rsi                \n"
+            "movq $64, %%rcx                \n"
+            "subq %%rsi, %%rcx                \n"
+            "movq $-1, %%rdx                \n"
+            "shlq %%cl, %%rdx                \n"
+            "movq %%rdx, %%R8                \n"
+            "movq %%rsi, %%rcx                \n"
+
+            "xorq %%rdx, %%rdx                \n"
+            "movq %%rdx, %%rsi                \n"
+            "addq %%rdi, %%rdx                \n"
+            "decq %%rdx                        \n"
+            "orq %%rax, %%rax                \n"
+            "cmovnz %%R8, %%rsi                \n"
+
+        "1:                                    \n"
+            "rorq %%cl, (%%rbx,%%rdx,8)        \n"
+
+            "movq (%%rbx,%%rdx,8), %%rax    \n"
+            "andq %%R8, %%rax                \n"
+            "xorq %%rax, (%%rbx,%%rdx,8)    \n"
+            "orq  %%rsi, (%%rbx,%%rdx,8)    \n"
+            "movq %%rax, %%rsi                \n"
+            
+            "decq %%rdx                        \n"
+            "decq %%rdi                        \n"
+        "jnz 1b                                \n"
+            
+            "rolq $1, %%rax                    \n"
+            "andq $1, %%rax                    \n"
+
+            : "=a" (c), "=D" (dummy), "=S" (dummy2), "=d" (dummy3)
+            : "0" (c), "1" (b), "b" (p1), "c" (bits)
+            : "%r8", "cc", "memory" );
+
+        #endif
+
+        TTMATH_LOGC("UInt::Rcr2", c)
+
+    return c;
+    }
+
+
+    /*
+        this method returns the number of the highest set bit in one 64-bit word
+        if the 'x' is zero this method returns '-1'
+
+        ***this method is created only on a 64bit platform***
+    */
+    template<uint value_size>
+    sint UInt<value_size>::FindLeadingBitInWord(uint x)
+    {
+    sint result;
+
+    
+        #ifndef __GNUC__
+
+            unsigned long nIndex = 0;
+
+            if( _BitScanReverse64(&nIndex,x) == 0 )
+                result = -1;
+            else
+                result = nIndex;
+
+        #endif
+
+
+        #ifdef __GNUC__
+        uint dummy;
+
+                __asm__ (
+
+                "movq $-1, %1          \n"
+                "bsrq %2, %0           \n"
+                "cmovz %1, %0          \n"
+
+                : "=r" (result), "=&r" (dummy)
+                : "r" (x)
+                : "cc" );
+
+        #endif
+
+
+    return result;
+    }
+
+
+    /*
+        this method returns the number of the highest set bit in one 64-bit word
+        if the 'x' is zero this method returns '-1'
+
+        ***this method is created only on a 64bit platform***
+    */
+    template<uint value_size>
+    sint UInt<value_size>::FindLowestBitInWord(uint x)
+    {
+    sint result;
+
+    
+        #ifndef __GNUC__
+
+            unsigned long nIndex = 0;
+
+            if( _BitScanForward64(&nIndex,x) == 0 )
+                result = -1;
+            else
+                result = nIndex;
+
+        #endif
+
+
+        #ifdef __GNUC__
+        uint dummy;
+
+                __asm__ (
+
+                "movq $-1, %1          \n"
+                "bsfq %2, %0           \n"
+                "cmovz %1, %0          \n"
+
+                : "=r" (result), "=&r" (dummy)
+                : "r" (x)
+                : "cc" );
+
+        #endif
+
+
+    return result;
+    }
+
+
+    /*!
+        this method sets a special bit in the 'value'
+        and returns the last state of the bit (zero or one)
+
+        ***this method is created only on a 64bit platform***
+
+        bit is from <0,63>
+
+        e.g.
+         uint x = 100;
+         uint bit = SetBitInWord(x, 3);
+         now: x = 108 and bit = 0
+    */
+    template<uint value_size>
+    uint UInt<value_size>::SetBitInWord(uint & value, uint bit)
+    {
+        TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT )
+        
+        uint old_bit;
+        uint v = value;
+
+
+        #ifndef __GNUC__
+            old_bit = _bittestandset64((__int64*)&value,bit) != 0;
+        #endif
+
+
+        #ifdef __GNUC__
+
+            __asm__ (
+
+            "btsq %%rbx, %%rax        \n"
+            "setc %%bl                \n"
+            "movzx %%bl, %%rbx        \n"
+            
+            : "=a" (v), "=b" (old_bit)
+            : "0" (v),  "1" (bit)
+            : "cc" );
+
+        #endif
+
+        value = v;
+
+    return old_bit;
+    }
+
+
+    /*!
+     *
+     * Multiplication
+     *
+     *
+    */
+
+
+    /*!
+        multiplication: result_high:result_low = a * b
+        result_high - higher word of the result
+        result_low  - lower word of the result
+    
+        this methos never returns a carry
+        this method is used in the second version of the multiplication algorithms
+
+        ***this method is created only on a 64bit platform***
+    */
+    template<uint value_size>
+    void UInt<value_size>::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low)
+    {
+    /*
+        we must use these temporary variables in order to inform the compilator
+        that value pointed with result1 and result2 has changed
+
+        this has no effect in visual studio but it's usefull when
+        using gcc and options like -O
+    */
+    uint result1_;
+    uint result2_;
+
+
+        #ifndef __GNUC__
+            result1_ = _umul128(a,b,&result2_);
+        #endif
+
+
+        #ifdef __GNUC__
+
+        __asm__ (
+        
+            "mulq %%rdx            \n"
+
+            : "=a" (result1_), "=d" (result2_)
+            : "0" (a),         "1" (b)
+            : "cc" );
+
+        #endif
+
+
+        *result_low  = result1_;
+        *result_high = result2_;
+    }
+
+
+
+
+    /*!
+     *
+     * Division
+     *
+     *
+    */
+    
+
+    /*!
+        this method calculates 64bits word a:b / 32bits c (a higher, b lower word)
+        r = a:b / c and rest - remainder
+        
+        ***this method is created only on a 64bit platform***
+
+        *
+        * WARNING:
+        * if r (one word) is too small for the result or c is equal zero
+        * there'll be a hardware interruption (0)
+        * and probably the end of your program
+        *
+    */
+    template<uint value_size>
+    void UInt<value_size>::DivTwoWords(uint a,uint b, uint c, uint * r, uint * rest)
+    {
+        uint r_;
+        uint rest_;
+        /*
+            these variables have similar meaning like those in
+            the multiplication algorithm MulTwoWords
+        */
+
+        TTMATH_ASSERT( c != 0 )
+
+
+        #ifndef __GNUC__
+
+            ttmath_div_x64(&a,&b,c);
+            r_    = a;
+            rest_ = b;
+            
+        #endif
+
+
+        #ifdef __GNUC__
+        
+            __asm__ (
+
+            "divq %%rcx                \n"
+
+            : "=a" (r_), "=d" (rest_)
+            : "d" (a), "a" (b), "c" (c)
+            : "cc" );
+
+        #endif
+
+
+        *r = r_;
+        *rest = rest_;
+    }
+
+} //namespace
+
+
+#endif //ifdef TTMATH_PLATFORM64
+#endif //ifndef TTMATH_NOASM
+#endif
+
+
+