<commit_before>
#include "yacasprivate.h"

#include "yacasbase.h"
#include "lispenvironment.h"
#include "standard.h"
#include "lispeval.h"
#include "lispatom.h"
#include "lispparser.h"
#include "stdfileio.h"
#include "stringio.h"
#include "lisperror.h"
#include "infixparser.h"
#include "lispuserfunc.h"
#include "mathuserfunc.h"
#include "platmath.h"
#include "numbers.h"
#include "anumber.h"
#include "arrayclass.h"
#include "patternclass.h"
#include "substitute.h"
#include "errors.h"
#include "patcher.h"
#include "platdll.h"
#include "unipoly.h"

#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#ifdef VERSION
#undef VERSION
#endif //VERSION

//#define VERSION "Windows latest"
#include "version.h"


/*TODO

 - Make a separate Number object, for fast calculations.

 - as an alternative, I *could* implement MathFac ;-)

 - Add Number and CopiedNumber methods to LispObject
 - implement Number and CopiedNumber in LispAtom
 - define a LispNumber that can cache a number. This would already
   speed up twofold.
 - implement at least addition and multiplication so they
   can use these.
 - IsNumber and IsInteger should Check ->Number() before doing ->String()

 

 The trick will obviously be to make sure no conversions are made to
 ascii until needed.

 
 */






#define InternalEval aEnvironment.iEvaluator->Eval



#ifndef NO_USE_BIGFLOAT
void GetNumber(RefPtr<BigNumber>& x, LispEnvironment& aEnvironment, LispPtr& aArguments, LispInt aArgNr)
{
    LispPtr result;
    InternalEval(aEnvironment, result, Argument(aArguments,aArgNr));
    RefPtr<BigNumber> num; num = result.Get()->Number(aEnvironment.Precision());
    CHK_ARG(num.Ptr() != NULL,aArgNr);
    x = num;
}
#endif // USE_BIGFLOAT

//FIXME remove these
void LispArithmetic2(LispEnvironment& aEnvironment, LispPtr& aResult,
                     LispPtr& aArguments,
                     LispStringPtr (*func)(LispCharPtr f1, LispCharPtr f2,LispHashTable& aHashTable,LispInt aPrecision),
                    LispBoolean arbbase=LispFalse);

void LispArithmetic1(LispEnvironment& aEnvironment, LispPtr& aResult,
                     LispPtr& aArguments,
                     LispStringPtr (*func)(LispCharPtr f1, LispHashTable& aHashTable,LispInt aPrecision));






//FIXME remove these
void LispArithmetic1(LispEnvironment& aEnvironment, LispPtr& aResult,
                     LispPtr& aArguments,
                     LispStringPtr (*func)(LispCharPtr f1, LispHashTable& aHashTable,LispInt aPrecision))
{
    TESTARGS(2);

    LispStringPtr str1;

    LispPtr result1;
    InternalEval(aEnvironment, result1, Argument(aArguments,1));

    str1 = result1.Get()->String();
    CHK_ARG(str1 != NULL,1);
    CHK_ARG(IsNumber(str1->String(),LispTrue),1);
    aResult.Set(LispAtom::New(aEnvironment,func(str1->String(),
                                   aEnvironment.HashTable(),
                                   aEnvironment.Precision())));
}


//FIXME remove these
void LispArithmetic2(LispEnvironment& aEnvironment, LispPtr& aResult,
                     LispPtr& aArguments,
                     LispStringPtr (*func)(LispCharPtr f1, LispCharPtr f2,LispHashTable& aHashTable,LispInt aPrecision),
                    LispBoolean arbbase)
{
    TESTARGS(3);

    LispStringPtr str1;
    LispStringPtr str2;

    LispPtr result1;
    LispPtr result2;
    InternalEval(aEnvironment, result1, Argument(aArguments,1));
    InternalEval(aEnvironment, result2, Argument(aArguments,2));

    str1 = result1.Get()->String();
    str2 = result2.Get()->String();
    CHK_ARG(str1 != NULL,1);
    CHK_ARG(str2 != NULL,2);
    if (!arbbase)
    {
        CHK_ARG(IsNumber(str1->String(),LispTrue) ,1);
        CHK_ARG(IsNumber(str2->String(),LispTrue) ,2);
    }

    aResult.Set(LispAtom::New(aEnvironment,func(str1->String(),str2->String(),
                                   aEnvironment.HashTable(),
                                   aEnvironment.Precision())));
}


void LispMultiply(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{
#ifndef NO_USE_BIGFLOAT
      RefPtr<BigNumber> x;
      RefPtr<BigNumber> y;
      GetNumber(x,aEnvironment, aArguments, 1);
      GetNumber(y,aEnvironment, aArguments, 2);
      BigNumber *z = NEW BigNumber(aEnvironment.Precision());
      z->Multiply(*x.Ptr(),*y.Ptr(),aEnvironment.Precision());
      aResult.Set(NEW LispNumber(aEnvironment.HashTable(),z));
      return;
#endif // USE_BIGFLOAT
    LispArithmetic2(aEnvironment, aResult, aArguments, MultiplyFloat);
}

void LispAdd(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{
    LispInt length = InternalListLength(aArguments);
    if (length == 2)
    {
#ifndef NO_USE_BIGFLOAT
      RefPtr<BigNumber> x;
      GetNumber(x,aEnvironment, aArguments, 1);
      aResult.Set(NEW LispNumber(aEnvironment.HashTable(),x.Ptr()));
      return;
#endif
        LispArithmetic1(aEnvironment, aResult, aArguments, PlusFloat);
    }
    else
    {
#ifndef NO_USE_BIGFLOAT
      RefPtr<BigNumber> x;
      RefPtr<BigNumber> y;
      GetNumber(x,aEnvironment, aArguments, 1);
      GetNumber(y,aEnvironment, aArguments, 2);
      BigNumber *z = NEW BigNumber(aEnvironment.Precision());
      z->Add(*x.Ptr(),*y.Ptr(),aEnvironment.Precision());
      aResult.Set(NEW LispNumber(aEnvironment.HashTable(),z));
      return;
#endif // USE_BIGFLOAT

        LispArithmetic2(aEnvironment, aResult, aArguments, AddFloat);
    }
}

void LispSubtract(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{
    LispInt length = InternalListLength(aArguments);
    if (length == 2)
    {
#ifndef NO_USE_BIGFLOAT
      RefPtr<BigNumber> x;
      GetNumber(x,aEnvironment, aArguments, 1);
      BigNumber *z = NEW BigNumber(aEnvironment.Precision());
      z->Negate(*x.Ptr());
      aResult.Set(NEW LispNumber(aEnvironment.HashTable(),z));
      return;
#endif
        LispArithmetic1(aEnvironment, aResult, aArguments, NegateFloat);
    }
    else
    {
#ifndef NO_USE_BIGFLOAT
      RefPtr<BigNumber> x;
      RefPtr<BigNumber> y;
      GetNumber(x,aEnvironment, aArguments, 1);
      GetNumber(y,aEnvironment, aArguments, 2);
      BigNumber yneg;
      yneg.Negate(*y.Ptr());
      BigNumber *z = NEW BigNumber(aEnvironment.Precision());
      z->Add(*x.Ptr(),yneg,aEnvironment.Precision());
      aResult.Set(NEW LispNumber(aEnvironment.HashTable(),z));
      return;
#endif // USE_BIGFLOAT
        LispArithmetic2(aEnvironment, aResult, aArguments, SubtractFloat);
    }
}


void LispDivide(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{
// Serge, what was the deal again with divide, floats and integers mixed in the same function?
//	yes, divide works differently on integers and on floats -- see new.chapt -- Serge
#ifndef NO_USE_BIGFLOAT
      RefPtr<BigNumber> x;
      RefPtr<BigNumber> y;
      GetNumber(x,aEnvironment, aArguments, 1);
      GetNumber(y,aEnvironment, aArguments, 2);
      BigNumber *z = NEW BigNumber(aEnvironment.Precision());
	  // if both arguments are integers, then BigNumber::Divide would perform an integer divide, but we want a float divide here.
	  if (x.Ptr()->IsInt() && y.Ptr()->IsInt())
	  {
		  // why can't we just say BigNumber temp; ?
		  BigNumber *temp = NEW BigNumber(aEnvironment.Precision());
		  temp->SetTo(*x.Ptr());
		  temp->BecomeFloat();	// coerce x to float
     	  z->Divide(*temp, *y.Ptr(),aEnvironment.Precision());
	  }
	  else
	  {
		  z->Divide(*x.Ptr(), *y.Ptr(),aEnvironment.Precision());
	  }
	  aResult.Set(NEW LispNumber(aEnvironment.HashTable(),z));
      return;
#endif // USE_BIGFLOAT
    LispArithmetic2(aEnvironment, aResult, aArguments, DivideFloat);
}


void LispSin(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME move to scripts
    LispArithmetic1(aEnvironment, aResult, aArguments, SinFloat);
}

void LispCos(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME move to scripts
    LispArithmetic1(aEnvironment, aResult, aArguments, CosFloat);
}

void LispTan(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME move to scripts
    LispArithmetic1(aEnvironment, aResult, aArguments, TanFloat);
}

void LispArcSin(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME move to scripts
    LispArithmetic1(aEnvironment, aResult, aArguments, ArcSinFloat);
}

void LispArcCos(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME move to scripts
    LispArithmetic1(aEnvironment, aResult, aArguments, ArcCosFloat);
}

void LispArcTan(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME move to scripts
    LispArithmetic1(aEnvironment, aResult, aArguments, ArcTanFloat);
}

void LispSqrt(LispEnvironment& aEnvironment, LispPtr& aResult,
              LispPtr& aArguments)
{//FIXME move to scripts
    LispArithmetic1(aEnvironment, aResult, aArguments, SqrtFloat);
}


#ifndef NO_USE_BIGFLOAT
#define UNARYFUNCTION(LispName, BigNumName, OldName) \
void LispName(LispEnvironment& aEnvironment, LispPtr& aResult, LispPtr& aArguments) \
{ \
      RefPtr<BigNumber> x; \
      GetNumber(x,aEnvironment, aArguments, 1); \
      BigNumber *z = NEW BigNumber(aEnvironment.Precision()); \
      z->BigNumName(*x.Ptr()); \
      aResult.Set(NEW LispNumber(aEnvironment.HashTable(),z)); \
}
#define BINARYFUNCTION(LispName, BigNumName, OldName) \
void LispName(LispEnvironment& aEnvironment, LispPtr& aResult, LispPtr& aArguments) \
{ \
      RefPtr<BigNumber> x; \
      RefPtr<BigNumber> y; \
      GetNumber(x,aEnvironment, aArguments, 1); \
      GetNumber(y,aEnvironment, aArguments, 2); \
      BigNumber *z = NEW BigNumber(aEnvironment.Precision()); \
      z->BigNumName(*x.Ptr(), *y.Ptr()); \
      aResult.Set(NEW LispNumber(aEnvironment.HashTable(),z)); \
}
#else
#define UNARYFUNCTION(LispName, BigNumName, OldName) \
void LispName(LispEnvironment& aEnvironment, LispPtr& aResult, LispPtr& aArguments) \
{ \
    LispArithmetic1(aEnvironment, aResult, aArguments, OldName); \
}
#define BINARYFUNCTION(LispName, BigNumName, OldName) \
void LispName(LispEnvironment& aEnvironment, LispPtr& aResult, LispPtr& aArguments) \
{ \
    LispArithmetic2(aEnvironment, aResult, aArguments, OldName); \
}
#endif

UNARYFUNCTION(LispFloor, Floor, FloorFloat)
// these functions are not yet in yacasapi.cpp but should be eventually
//UNARYFUNCTION(LispBitCount, BitCount, MathBitCount)
//UNARYFUNCTION(LispSign, Sign, MathSign)
//UNARYFUNCTION(LispNegate, Negate, MathNegate)

/** this produces the following equivalent code for a unary function:
void LispFloor(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{
#ifndef NO_USE_BIGFLOAT
      RefPtr<BigNumber> x;
      GetNumber(x,aEnvironment, aArguments, 1);
      BigNumber *z = NEW BigNumber(aEnvironment.Precision());
      z->Floor(*x.Ptr());
      aResult.Set(NEW LispNumber(aEnvironment.HashTable(),z));
#else
    LispArithmetic1(aEnvironment, aResult, aArguments, FloorFloat);
#endif
}
*/

void LispCeil(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{
#ifndef NO_USE_BIGFLOAT
      RefPtr<BigNumber> x;
      GetNumber(x,aEnvironment, aArguments, 1);
      BigNumber *z = NEW BigNumber(aEnvironment.Precision());
      z->Negate(*x.Ptr());
      z->Floor(*z);
      z->Negate(*z);
      aResult.Set(NEW LispNumber(aEnvironment.HashTable(),z));
#else
   LispArithmetic1(aEnvironment, aResult, aArguments, CeilFloat);
#endif
}

void LispAbs(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{
#ifndef NO_USE_BIGFLOAT
      RefPtr<BigNumber> x;
      GetNumber(x,aEnvironment, aArguments, 1);
      BigNumber *z = NEW BigNumber(aEnvironment.Precision());
      z->SetTo(*x.Ptr());
      if (x.Ptr()->Sign()<0)
	      z->Negate(*x.Ptr());
      aResult.Set(NEW LispNumber(aEnvironment.HashTable(),z));
#else
   LispArithmetic1(aEnvironment, aResult, aArguments, AbsFloat);
#endif
}
BINARYFUNCTION(LispMod, Mod, ModFloat)
/*
void LispMod(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic2(aEnvironment, aResult, aArguments, ModFloat);
}
*/

void LispDiv(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
#ifndef NO_USE_BIGFLOAT
      RefPtr<BigNumber> x;
      RefPtr<BigNumber> y;
      GetNumber(x,aEnvironment, aArguments, 1);
      GetNumber(y,aEnvironment, aArguments, 2);
	  if (x.Ptr()->IsInt() && y.Ptr()->IsInt())
	  {	// both integer, perform integer division
    	  BigNumber *z = NEW BigNumber(aEnvironment.Precision());
    	  z->Divide(*x.Ptr(),*y.Ptr(),aEnvironment.Precision());
    	  aResult.Set(NEW LispNumber(aEnvironment.HashTable(),z));
    	  return;
	  }
	  else
	  {// FIXME: either need to report error that one or both of the arguments are not integer, or coerce them to integers
	  	fprintf(stderr, "LispDiv: error: both arguments must be integer\n");
		  return;
	  }
	  
#endif // USE_BIGFLOAT
    LispArithmetic2(aEnvironment, aResult, aArguments, DivFloat);
}

void LispLog(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME move to scripts
    LispArithmetic1(aEnvironment, aResult, aArguments, LnFloat);
}

void LispExp(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME move to scripts
    LispArithmetic1(aEnvironment, aResult, aArguments, ExpFloat);
}

void LispPower(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME move to scripts
    LispArithmetic2(aEnvironment, aResult, aArguments, PowerFloat);
}



void LispFac(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME move to scripts
    LispArithmetic1(aEnvironment, aResult, aArguments, LispFactorial);
}


// platform functions, taking/returning a platform int/float

void LispFastIsPrime(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic1(aEnvironment, aResult, aArguments, PlatIsPrime);
}



void LispFastSin(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic1(aEnvironment, aResult, aArguments, PlatSin);
}

void LispFastCos(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic1(aEnvironment, aResult, aArguments, PlatCos);
}
void LispFastTan(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic1(aEnvironment, aResult, aArguments, PlatTan);
}

void LispFastArcSin(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic1(aEnvironment, aResult, aArguments, PlatArcSin);
}
void LispFastArcCos(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic1(aEnvironment, aResult, aArguments, PlatArcCos);
}
void LispFastArcTan(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic1(aEnvironment, aResult, aArguments, PlatArcTan);
}
void LispFastExp(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic1(aEnvironment, aResult, aArguments, PlatExp);
}
void LispFastLog(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic1(aEnvironment, aResult, aArguments, PlatLn);
}

void LispFastPower(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic2(aEnvironment, aResult, aArguments, PlatPower);
}

void LispFastSqrt(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic1(aEnvironment, aResult, aArguments, PlatSqrt);
}

void LispFastFloor(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic1(aEnvironment, aResult, aArguments, PlatFloor);
}

void LispFastCeil(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic1(aEnvironment, aResult, aArguments, PlatCeil);
}
void LispFastMod(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic2(aEnvironment, aResult, aArguments, PlatMod);
}

void LispFastAbs(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic1(aEnvironment, aResult, aArguments, PlatAbs);
}


BINARYFUNCTION(LispShiftLeft, ShiftLeft, ShiftLeft)
BINARYFUNCTION(LispShiftRight, ShiftRight, ShiftRight)

BINARYFUNCTION(LispBitAnd, BitAnd, BitAnd)
BINARYFUNCTION(LispBitOr, BitOr, BitOr)
BINARYFUNCTION(LispBitXor, BitXor, BitXor)
// BitNot not yet in yacasapi etc.
//BINARYFUNCTION(LispBitNot, BitNot, BitNot)
/*
void LispShiftLeft(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic2(aEnvironment, aResult, aArguments, ShiftLeft);
}
void LispShiftRight(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic2(aEnvironment, aResult, aArguments, ShiftRight);
}

void LispBitAnd(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic2(aEnvironment, aResult, aArguments, BitAnd);
}
void LispBitOr(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic2(aEnvironment, aResult, aArguments, BitOr);
}
void LispBitXor(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic2(aEnvironment, aResult, aArguments, BitXor);
}
*/
<commit_msg>temporarily undoing the latest changes, to improve stability<commit_after>
#include "yacasprivate.h"

#include "yacasbase.h"
#include "lispenvironment.h"
#include "standard.h"
#include "lispeval.h"
#include "lispatom.h"
#include "lispparser.h"
#include "stdfileio.h"
#include "stringio.h"
#include "lisperror.h"
#include "infixparser.h"
#include "lispuserfunc.h"
#include "mathuserfunc.h"
#include "platmath.h"
#include "numbers.h"
#include "anumber.h"
#include "arrayclass.h"
#include "patternclass.h"
#include "substitute.h"
#include "errors.h"
#include "patcher.h"
#include "platdll.h"
#include "unipoly.h"

#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#ifdef VERSION
#undef VERSION
#endif //VERSION

//#define VERSION "Windows latest"
#include "version.h"


/*TODO

 - Make a separate Number object, for fast calculations.

 - as an alternative, I *could* implement MathFac ;-)

 - Add Number and CopiedNumber methods to LispObject
 - implement Number and CopiedNumber in LispAtom
 - define a LispNumber that can cache a number. This would already
   speed up twofold.
 - implement at least addition and multiplication so they
   can use these.
 - IsNumber and IsInteger should Check ->Number() before doing ->String()

 

 The trick will obviously be to make sure no conversions are made to
 ascii until needed.

 
 */






#define InternalEval aEnvironment.iEvaluator->Eval



#ifndef NO_USE_BIGFLOAT
void GetNumber(RefPtr<BigNumber>& x, LispEnvironment& aEnvironment, LispPtr& aArguments, LispInt aArgNr)
{
    LispPtr result;
    InternalEval(aEnvironment, result, Argument(aArguments,aArgNr));
    RefPtr<BigNumber> num; num = result.Get()->Number(aEnvironment.Precision());
    CHK_ARG(num.Ptr() != NULL,aArgNr);
    x = num;
}
#endif // USE_BIGFLOAT

//FIXME remove these
void LispArithmetic2(LispEnvironment& aEnvironment, LispPtr& aResult,
                     LispPtr& aArguments,
                     LispStringPtr (*func)(LispCharPtr f1, LispCharPtr f2,LispHashTable& aHashTable,LispInt aPrecision),
                    LispBoolean arbbase=LispFalse);

void LispArithmetic1(LispEnvironment& aEnvironment, LispPtr& aResult,
                     LispPtr& aArguments,
                     LispStringPtr (*func)(LispCharPtr f1, LispHashTable& aHashTable,LispInt aPrecision));






//FIXME remove these
void LispArithmetic1(LispEnvironment& aEnvironment, LispPtr& aResult,
                     LispPtr& aArguments,
                     LispStringPtr (*func)(LispCharPtr f1, LispHashTable& aHashTable,LispInt aPrecision))
{
    TESTARGS(2);

    LispStringPtr str1;

    LispPtr result1;
    InternalEval(aEnvironment, result1, Argument(aArguments,1));

    str1 = result1.Get()->String();
    CHK_ARG(str1 != NULL,1);
    CHK_ARG(IsNumber(str1->String(),LispTrue),1);
    aResult.Set(LispAtom::New(aEnvironment,func(str1->String(),
                                   aEnvironment.HashTable(),
                                   aEnvironment.Precision())));
}


//FIXME remove these
void LispArithmetic2(LispEnvironment& aEnvironment, LispPtr& aResult,
                     LispPtr& aArguments,
                     LispStringPtr (*func)(LispCharPtr f1, LispCharPtr f2,LispHashTable& aHashTable,LispInt aPrecision),
                    LispBoolean arbbase)
{
    TESTARGS(3);

    LispStringPtr str1;
    LispStringPtr str2;

    LispPtr result1;
    LispPtr result2;
    InternalEval(aEnvironment, result1, Argument(aArguments,1));
    InternalEval(aEnvironment, result2, Argument(aArguments,2));

    str1 = result1.Get()->String();
    str2 = result2.Get()->String();
    CHK_ARG(str1 != NULL,1);
    CHK_ARG(str2 != NULL,2);
    if (!arbbase)
    {
        CHK_ARG(IsNumber(str1->String(),LispTrue) ,1);
        CHK_ARG(IsNumber(str2->String(),LispTrue) ,2);
    }

    aResult.Set(LispAtom::New(aEnvironment,func(str1->String(),str2->String(),
                                   aEnvironment.HashTable(),
                                   aEnvironment.Precision())));
}


void LispMultiply(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{
#ifndef NO_USE_BIGFLOAT
      RefPtr<BigNumber> x;
      RefPtr<BigNumber> y;
      GetNumber(x,aEnvironment, aArguments, 1);
      GetNumber(y,aEnvironment, aArguments, 2);
      BigNumber *z = NEW BigNumber(aEnvironment.Precision());
      z->Multiply(*x.Ptr(),*y.Ptr(),aEnvironment.Precision());
      aResult.Set(NEW LispNumber(aEnvironment.HashTable(),z));
      return;
#endif // USE_BIGFLOAT
    LispArithmetic2(aEnvironment, aResult, aArguments, MultiplyFloat);
}

void LispAdd(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{
    LispInt length = InternalListLength(aArguments);
    if (length == 2)
    {
#ifndef NO_USE_BIGFLOAT
      RefPtr<BigNumber> x;
      GetNumber(x,aEnvironment, aArguments, 1);
      aResult.Set(NEW LispNumber(aEnvironment.HashTable(),x.Ptr()));
      return;
#endif
        LispArithmetic1(aEnvironment, aResult, aArguments, PlusFloat);
    }
    else
    {
#ifndef NO_USE_BIGFLOAT
      RefPtr<BigNumber> x;
      RefPtr<BigNumber> y;
      GetNumber(x,aEnvironment, aArguments, 1);
      GetNumber(y,aEnvironment, aArguments, 2);
      BigNumber *z = NEW BigNumber(aEnvironment.Precision());
      z->Add(*x.Ptr(),*y.Ptr(),aEnvironment.Precision());
      aResult.Set(NEW LispNumber(aEnvironment.HashTable(),z));
      return;
#endif // USE_BIGFLOAT

        LispArithmetic2(aEnvironment, aResult, aArguments, AddFloat);
    }
}

void LispSubtract(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{
    LispInt length = InternalListLength(aArguments);
    if (length == 2)
    {
#ifndef NO_USE_BIGFLOAT
      RefPtr<BigNumber> x;
      GetNumber(x,aEnvironment, aArguments, 1);
      BigNumber *z = NEW BigNumber(aEnvironment.Precision());
      z->Negate(*x.Ptr());
      aResult.Set(NEW LispNumber(aEnvironment.HashTable(),z));
      return;
#endif
        LispArithmetic1(aEnvironment, aResult, aArguments, NegateFloat);
    }
    else
    {
#ifndef NO_USE_BIGFLOAT
      RefPtr<BigNumber> x;
      RefPtr<BigNumber> y;
      GetNumber(x,aEnvironment, aArguments, 1);
      GetNumber(y,aEnvironment, aArguments, 2);
      BigNumber yneg;
      yneg.Negate(*y.Ptr());
      BigNumber *z = NEW BigNumber(aEnvironment.Precision());
      z->Add(*x.Ptr(),yneg,aEnvironment.Precision());
      aResult.Set(NEW LispNumber(aEnvironment.HashTable(),z));
      return;
#endif // USE_BIGFLOAT
        LispArithmetic2(aEnvironment, aResult, aArguments, SubtractFloat);
    }
}


void LispDivide(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{
// Serge, what was the deal again with divide, floats and integers mixed in the same function?
//	yes, divide works differently on integers and on floats -- see new.chapt -- Serge
#ifndef NO_USE_BIGFLOAT
      RefPtr<BigNumber> x;
      RefPtr<BigNumber> y;
      GetNumber(x,aEnvironment, aArguments, 1);
      GetNumber(y,aEnvironment, aArguments, 2);
      BigNumber *z = NEW BigNumber(aEnvironment.Precision());
	  // if both arguments are integers, then BigNumber::Divide would perform an integer divide, but we want a float divide here.
	  if (x.Ptr()->IsInt() && y.Ptr()->IsInt())
	  {
		  // why can't we just say BigNumber temp; ?
		  BigNumber *temp = NEW BigNumber(aEnvironment.Precision());
		  temp->SetTo(*x.Ptr());
		  temp->BecomeFloat();	// coerce x to float
     	  z->Divide(*temp, *y.Ptr(),aEnvironment.Precision());
	  }
	  else
	  {
		  z->Divide(*x.Ptr(), *y.Ptr(),aEnvironment.Precision());
	  }
	  aResult.Set(NEW LispNumber(aEnvironment.HashTable(),z));
      return;
#endif // USE_BIGFLOAT
    LispArithmetic2(aEnvironment, aResult, aArguments, DivideFloat);
}


void LispSin(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME move to scripts
    LispArithmetic1(aEnvironment, aResult, aArguments, SinFloat);
}

void LispCos(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME move to scripts
    LispArithmetic1(aEnvironment, aResult, aArguments, CosFloat);
}

void LispTan(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME move to scripts
    LispArithmetic1(aEnvironment, aResult, aArguments, TanFloat);
}

void LispArcSin(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME move to scripts
    LispArithmetic1(aEnvironment, aResult, aArguments, ArcSinFloat);
}

void LispArcCos(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME move to scripts
    LispArithmetic1(aEnvironment, aResult, aArguments, ArcCosFloat);
}

void LispArcTan(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME move to scripts
    LispArithmetic1(aEnvironment, aResult, aArguments, ArcTanFloat);
}

void LispSqrt(LispEnvironment& aEnvironment, LispPtr& aResult,
              LispPtr& aArguments)
{//FIXME move to scripts
    LispArithmetic1(aEnvironment, aResult, aArguments, SqrtFloat);
}


#ifndef NO_USE_BIGFLOAT
#define UNARYFUNCTION(LispName, BigNumName, OldName) \
void LispName(LispEnvironment& aEnvironment, LispPtr& aResult, LispPtr& aArguments) \
{ \
      RefPtr<BigNumber> x; \
      GetNumber(x,aEnvironment, aArguments, 1); \
      BigNumber *z = NEW BigNumber(aEnvironment.Precision()); \
      z->BigNumName(*x.Ptr()); \
      aResult.Set(NEW LispNumber(aEnvironment.HashTable(),z)); \
}
#define BINARYFUNCTION(LispName, BigNumName, OldName) \
void LispName(LispEnvironment& aEnvironment, LispPtr& aResult, LispPtr& aArguments) \
{ \
      RefPtr<BigNumber> x; \
      RefPtr<BigNumber> y; \
      GetNumber(x,aEnvironment, aArguments, 1); \
      GetNumber(y,aEnvironment, aArguments, 2); \
      BigNumber *z = NEW BigNumber(aEnvironment.Precision()); \
      z->BigNumName(*x.Ptr(), *y.Ptr()); \
      aResult.Set(NEW LispNumber(aEnvironment.HashTable(),z)); \
}
#else
#define UNARYFUNCTION(LispName, BigNumName, OldName) \
void LispName(LispEnvironment& aEnvironment, LispPtr& aResult, LispPtr& aArguments) \
{ \
    LispArithmetic1(aEnvironment, aResult, aArguments, OldName); \
}
#define BINARYFUNCTION(LispName, BigNumName, OldName) \
void LispName(LispEnvironment& aEnvironment, LispPtr& aResult, LispPtr& aArguments) \
{ \
    LispArithmetic2(aEnvironment, aResult, aArguments, OldName); \
}
#endif

UNARYFUNCTION(LispFloor, Floor, FloorFloat)
// these functions are not yet in yacasapi.cpp but should be eventually
//UNARYFUNCTION(LispBitCount, BitCount, MathBitCount)
//UNARYFUNCTION(LispSign, Sign, MathSign)
//UNARYFUNCTION(LispNegate, Negate, MathNegate)

/** this produces the following equivalent code for a unary function:
void LispFloor(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{
#ifndef NO_USE_BIGFLOAT
      RefPtr<BigNumber> x;
      GetNumber(x,aEnvironment, aArguments, 1);
      BigNumber *z = NEW BigNumber(aEnvironment.Precision());
      z->Floor(*x.Ptr());
      aResult.Set(NEW LispNumber(aEnvironment.HashTable(),z));
#else
    LispArithmetic1(aEnvironment, aResult, aArguments, FloorFloat);
#endif
}
*/

void LispCeil(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{
#ifndef NO_USE_BIGFLOAT
      RefPtr<BigNumber> x;
      GetNumber(x,aEnvironment, aArguments, 1);
      BigNumber *z = NEW BigNumber(aEnvironment.Precision());
      z->Negate(*x.Ptr());
      z->Floor(*z);
      z->Negate(*z);
      aResult.Set(NEW LispNumber(aEnvironment.HashTable(),z));
#else
   LispArithmetic1(aEnvironment, aResult, aArguments, CeilFloat);
#endif
}

void LispAbs(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{
#ifndef NO_USE_BIGFLOAT
      RefPtr<BigNumber> x;
      GetNumber(x,aEnvironment, aArguments, 1);
      BigNumber *z = NEW BigNumber(aEnvironment.Precision());
      z->SetTo(*x.Ptr());
      if (x.Ptr()->Sign()<0)
	      z->Negate(*x.Ptr());
      aResult.Set(NEW LispNumber(aEnvironment.HashTable(),z));
#else
   LispArithmetic1(aEnvironment, aResult, aArguments, AbsFloat);
#endif
}
//BINARYFUNCTION(LispMod, Mod, ModFloat)
/* this will be gone */
void LispMod(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic2(aEnvironment, aResult, aArguments, ModFloat);
}
/**/

void LispDiv(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{
#ifndef NO_USE_BIGFLOAT
      RefPtr<BigNumber> x;
      RefPtr<BigNumber> y;
      GetNumber(x,aEnvironment, aArguments, 1);
      GetNumber(y,aEnvironment, aArguments, 2);
	  if (x.Ptr()->IsInt() && y.Ptr()->IsInt())
	  {	// both integer, perform integer division
    	  BigNumber *z = NEW BigNumber(aEnvironment.Precision());
    	  z->Divide(*x.Ptr(),*y.Ptr(),aEnvironment.Precision());
    	  aResult.Set(NEW LispNumber(aEnvironment.HashTable(),z));
    	  return;
	  }
	  else
	  {// FIXME: either need to report error that one or both of the arguments are not integer, or coerce them to integers
	  	fprintf(stderr, "LispDiv: error: both arguments must be integer\n");
		  return;
	  }
	  
#endif // USE_BIGFLOAT
    LispArithmetic2(aEnvironment, aResult, aArguments, DivFloat);
}

void LispLog(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME move to scripts
    LispArithmetic1(aEnvironment, aResult, aArguments, LnFloat);
}

void LispExp(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME move to scripts
    LispArithmetic1(aEnvironment, aResult, aArguments, ExpFloat);
}

void LispPower(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME move to scripts
    LispArithmetic2(aEnvironment, aResult, aArguments, PowerFloat);
}



void LispFac(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME move to scripts
    LispArithmetic1(aEnvironment, aResult, aArguments, LispFactorial);
}


// platform functions, taking/returning a platform int/float

void LispFastIsPrime(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic1(aEnvironment, aResult, aArguments, PlatIsPrime);
}



void LispFastSin(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic1(aEnvironment, aResult, aArguments, PlatSin);
}

void LispFastCos(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic1(aEnvironment, aResult, aArguments, PlatCos);
}
void LispFastTan(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic1(aEnvironment, aResult, aArguments, PlatTan);
}

void LispFastArcSin(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic1(aEnvironment, aResult, aArguments, PlatArcSin);
}
void LispFastArcCos(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic1(aEnvironment, aResult, aArguments, PlatArcCos);
}
void LispFastArcTan(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic1(aEnvironment, aResult, aArguments, PlatArcTan);
}
void LispFastExp(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic1(aEnvironment, aResult, aArguments, PlatExp);
}
void LispFastLog(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic1(aEnvironment, aResult, aArguments, PlatLn);
}

void LispFastPower(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic2(aEnvironment, aResult, aArguments, PlatPower);
}

void LispFastSqrt(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic1(aEnvironment, aResult, aArguments, PlatSqrt);
}

void LispFastFloor(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic1(aEnvironment, aResult, aArguments, PlatFloor);
}

void LispFastCeil(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic1(aEnvironment, aResult, aArguments, PlatCeil);
}
void LispFastMod(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic2(aEnvironment, aResult, aArguments, PlatMod);
}

void LispFastAbs(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic1(aEnvironment, aResult, aArguments, PlatAbs);
}

/*
BINARYFUNCTION(LispShiftLeft, ShiftLeft, ShiftLeft)
BINARYFUNCTION(LispShiftRight, ShiftRight, ShiftRight)

BINARYFUNCTION(LispBitAnd, BitAnd, BitAnd)
BINARYFUNCTION(LispBitOr, BitOr, BitOr)
BINARYFUNCTION(LispBitXor, BitXor, BitXor)
// BitNot not yet in yacasapi etc.
//BINARYFUNCTION(LispBitNot, BitNot, BitNot)
*/
/* this will be gone */
void LispShiftLeft(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic2(aEnvironment, aResult, aArguments, ShiftLeft);
}
void LispShiftRight(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic2(aEnvironment, aResult, aArguments, ShiftRight);
}

void LispBitAnd(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic2(aEnvironment, aResult, aArguments, BitAnd);
}
void LispBitOr(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic2(aEnvironment, aResult, aArguments, BitOr);
}
void LispBitXor(LispEnvironment& aEnvironment, LispPtr& aResult,
                  LispPtr& aArguments)
{//FIXME
    LispArithmetic2(aEnvironment, aResult, aArguments, BitXor);
}
/**/

{'fraction_non_alphanumeric': 0.1131241593236158, 'fraction_numerical': 0.006039144637514068, 'mean_word_length': 3.6951926794690038, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 113, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1319347', 'n_tokens_mistral': 12306, 'n_tokens_neox': 11719, 'n_words': 2554}