Multi-Precision Arithmetic by C++ with no use of assembler

SN library Copyright (C) 1999-2018 K.Tsuru

Elementary directions
Here I shall explain the fundamental usage of this library.
About specification statements, overloaded operators and upper limit of digits
You can easily translate a conventional C++ program into a "SN" one by replacing "long" with "SLong" and "double" with "SDouble". Allowing time and memory the default maximum length is about four million(=106) digits for 32 bit system or about several billion(=109) digits for 64 bit system.
A number of four million figures occupies a memory 2MB. In my library many recursive functions are used. It costs much memory and stack. Considering the speed of CPU and memory in present personal computer I think that it is not feasible over the above value. How do you think? More in the real functions uses the series in which division by "unsigned long" is used. The divisor must be less than ULONG_MAX/radix for the speed. Then for a large significant figures the series will not converge within this value.
See also "sn32-64/doc/cputime.txt".

Firstly I show some examples.
Sample program 1
--------------------------------------------------------------

#include "sn.h"  // SN library's header file
int main()
{
    SLong f;	// declaration of multi-precision integer
    SDouble pi;	// declaration of multi-precision real number
    f = Fact(10000000);	//calculate a factorial 10,000,000! (18 sec)and substitute to lhs
    cout << a << endl;  //output using iostream operator 65,657,053 digits. It takes much time.
    pi = Pi();	//calculate pi in default significant figures(*)
    cout << pi << endl;  //output
}
---------------------------------------------------------------
(*)The default significant figures is about 240.
At the same time declaration and initialization can be done. As the rhs the multi-precision variable, double value(15 figures), integer and string can be used. But zero must be written such as "0.0", namely "0" causes a compile error. Because the compiler cannot decide whether "0" is a pointer of char* or a number zero.
I show an example.
    // SDouble a(0);	/* error */
    SDouble a(0.0), b(10), c(b), e("1.0e-500"), f; // initialize
    SLong g;
    cin >> g;  // input any long integer by keyboard
...............
    f="0.12345678901234567890123456789e10000";
    g="1.5e200";
    cout << f*g  << endl;
Sample program 2
--------------------------------------------------------------
    SFraction f, g, r;    // declaration of multi-precision fraction
    f = "1009/99799811";    g = "997/99819757";    //set values by strings
    //f.Set(1009L, 99799811L); can be used
    r = f+g;    cout << f << '+' << g << '=' << r << endl;
    r = f-g;    cout << f << '-' << g << '=' << r << endl;
    r = f*g;    cout << f << '*' << g << '=' << r << endl;
    r = f/g;    cout << f << '/' << g << '=' << r << endl;
--------------------------------------------------------------      
"SFraction" class has decimal radix(10000). "SRational" class whose radix is binary (32768) can also be used. As shown the above usual operators '+', '-', '*' and '/' can be used.
A substitution "SFraction" variable into "SDouble" one can be used. But the reverse is forbidden. I show an example.

    SFraction f(1, 3);	// f=1/3
    SDouble a;
    a=f;          //Ok, a = 0.33333....
    f=a;          //error, not convert to 1/3

Sample program 3
---------------------------------------------------------------------
RealSize C; // Only one object is permitted. C.SetEffFig(250); //change the number of significant figures into 250*4=1000 digits SDouble pi; pi=Pi(); cout << pi << endl; // C.SetEffFig(500); /* error */ C.SetEffFig(0); //put back to previous value C.SetEffFig(500); //Ok. "500" is near to and within 2 to the 9th power 512. ---------------------------------------------------------------------
notice "SDouble" object cannot call the function "SetEffFig()", i.e. "pi.SetEffFig(500)" causes an error. It is desirable to take the number of significant figures near and smaller a little the power of two(2n), because the efficiency of FFT multiplication and memory size are good.

About speed of calculation including square
A statement
 y = a *(x *x );
is faster than
 y = a *x *x;
because in the (x*x ) an optimization can be done for SLong or SDouble numbers e.g. in a multiplication
 xy = (aR + b )(cR + d ) = acR 2+(ad +bc )R +bd  (R is power of radix)
when x== y (i.e. &x == &y ), ad == bc, then one multiplication can be reduced.