%mathpiper,def="NumberToRep"

//Retract("NumberToRep",*);


10 # NumberToRep( N_IsNumber ) <--
[
    //If(InVerboseMode(),Tell(NumberToRep,N));
    Local(oldPrec,sgn,assoc,typ,val,prec,rep);
    oldPrec  := BuiltinPrecisionGet();
    BuiltinPrecisionSet(300);
    /*   NOTE: the above arbitrary 'magic number' is used because it is 
     *   currently necessary to set BuiltinPrecision to a value large 
     *   enough to handle any forseeable input.  Of course, even 300
     *   might not be enough!  I am looking for a way to base the 
     *   setting directly on the input number itself.                   */
     
    sgn      := Sign(N); 
    assoc    := DumpNumber(Abs(N));
    //If(InVerboseMode(),[ Tell("   ",assoc); Tell("   ",sgn); ]);
    typ := Assoc("type",assoc)[2];
    //If(InVerboseMode(),Tell("   ",typ));
    If( typ = "BigDecimal",
       [
          rep := { sgn*Assoc("unscaledValue",assoc)[2],
                   Assoc("precision",    assoc)[2],
                   Assoc("scale",        assoc)[2] 
                 };
       ],
       [
          Local(val,prec);
          val  := Assoc("value",assoc)[2];
          prec := Length(ExpressionToString(val));
          rep := { sgn*val, prec };
       ]
    );
    //If(InVerboseMode(),Tell("   ",rep));
    BuiltinPrecisionSet(oldPrec);
    rep;
];



12 # NumberToRep( N_IsComplex ) <-- 
[
    If(IsZero(Re(N)),
        {NumberToRep(0.0),NumberToRep(Im(N))},
        {NumberToRep(Re(N)),NumberToRep(Im(N))}
    );
];

%/mathpiper

    %output,preserve="false"
      Result: True
.   %/output

    





%mathpiper_docs,name="NumberToRep",categories="Programmer Functions;Numerical (Arbitrary Precision)"
*CMD NumberToRep --- returns a List showing MathPiper's internal representation of a number
*STD
*CALL
	NumberToRep(number)
	
*PARMS

{number} -- an Integer, Decimal, or Complex number


*DESC

Internally, MathPiper represents {arbitrary precision} numbers as Java BigIntegers or
BigDecimals.  Java code handles calculations using such numbers.

All the information needed to correctly understand the precision attached to a number,
and the rounding and comparison thereof, is contained in the Java structure.

For a Decimal number (essentially anything with a decimal point), the representation
consists of an arbitrary-precision integer containing {all} the significant digits of
the number, and a {scale factor} telling where the implied decimal point is supposed to
be placed with respect to the end of the integer.  The {precision} of the number is
just the number of digits in the integer.

The three components of the List returned for a decimal number are, respectively,
{{BigInteger (unscaled), Precision, ScaleFactor}}.
Note that the second of these is redundent: only the BigInteger and the ScaleFactor
are needed to completely define the number.

For an Integer number, the integer is its own representation, and again, the number of
its digits gives its precision.

For a Complex number, this function returns a List containing the representations of
the Real and Imaginary parts of the number.

The best way to {consistently} deal with precision and rounding issues is by making use
of the information given by this function.

*E.G.
    
In> NumberToRep(123.45678)
Result: {12345678,8,5}
    
In> NumberToRep(34700)
Result: {34700,5}
    
In> NumberToRep(1.5+6.75*I)
Result: {{150,3,2},{675,3,2}}
    
In> NumberToRep(123.45678E-10)
Result: {12345678,8,15}
   
In> NumberToRep(123.45678E+10)
Result: {12345678,8,-5}
    
NOTICE that the first, fourth, and fifth of these have the same 
BigInteger representation, and hence the same precision, namely 8.  
The ScaleFactor tells how many places the decimal point must be 
moved {leftward} from the {end} of the integer.  A negative 
ScaleFactor says to move the decimal point to the right -- 
i.e., effectively, add terminal zeros. However, if the number had 
originally been written as 1234567800000., it would actually have
a different representation, namely {1234567800000,13,0}.  That is
because, if we write those terminal zeros explicitly, they are assumed
to be "significant", and so the number is shown with precision 13.
Exponential notation must be used if the precision really is 8.

*SEE RepToNumber, DumpNumber
%/mathpiper_docs

    %output,preserve="false"
      
.   %/output


