Game Development Community

dev|Pro Game Development Curriculum

64bit math library for TorqueScript

by Gabriel Notman · 09/26/2007 (12:55 pm) · 2 comments

Download Code File

This resource was developed in response to this thread:
garagegames.com/mg/forums/result.thread.php?qt=66369

Credit should be given to the author of that thread which has paid for this resource to be made available.

This set functions were developed to allow the manipulation of numbers with greater precision then the standard six digits afforded in TorqueScript. Rarely will you need this level of precision, but it some cases it may be required such as in a calculator app.

It allows for double floating point precision and includes the following functionality:
Arithmetic: + - * /
Trigonometry: cos() sin() tan() acos() asin() atan()
Powers: pow() log()

This does not cover the all mathematical functions but these are some of the basic ones.
Note: Sqrt() can be achieve by raising the number to the power of 0.5.

Important note:
You must pass the parameters to these functions as strings not as numbers. Because if you pass them as numbers, they will be truncated to single precision in torque script (before they even reach the function).

eg:
m64Add(1, 1.123456789)

Second parameter above will be truncated to single precision, however the following will not!

m64Add("1", "1.123456789")

Issues:
Floating point operations can be slightly out by +/-0.0000000000000001. The unPad() function has been added to remove any extra trailing zeros, but doesn't work if the float point accuracy is off!

Download it from the link or copy from below, and add to your project (will require a code recompile).

#include "console/simBase.h"
#include "platformWin32/platformWin32.h"
#include "math/mMathFn.h"

F64 dAtof64(const char *str)
{
   // Warning: metrowerks crashes when strange strings are passed in '0x [enter]' for example!
   return (F64)atof(str);
}

void unPad(char* str)
{
	S16 size=dStrlen(str);

	S16 newEnd=size;

	for (U16 i=size-1; i !=0; i--)
	{
		//if its not a zero(48) or a period(46)
		//break
		if ((str[i] != 48) && (str[i] != 46))
			break;

		newEnd=i;
	}

	str[newEnd]=0;
}

ConsoleFunctionGroupBegin(Math64, "Math functions with 64bit percission");

//Arithmetic
ConsoleFunction(m64Add, const char *, 3, 3, "(A,B)\n"
                "Returns A+B")
{
	F64 a;
	F64 b;

	a=dAtof64(argv[1]);
	b=dAtof64(argv[2]);
	
	F64 res=a+b;

	char* buff=Con::getReturnBuffer(64);

	dSprintf(buff, 256, "%.16f", res);

	unPad(buff);

	return buff;
}

ConsoleFunction(m64Sub, const char *, 3, 3, "(A,B)\n"
                "Returns A-B")
{
	F64 a;
	F64 b;

	a=dAtof64(argv[1]);
	b=dAtof64(argv[2]);
	
	F64 res=a-b;

	char* buff=Con::getReturnBuffer(64);

	dSprintf(buff, 256, "%.16f", res);

	unPad(buff);

	return buff;
}

ConsoleFunction(m64Mul, const char *, 3, 3, "(A,B)\n"
                "Returns A*B")
{
	F64 a;
	F64 b;

	a=dAtof64(argv[1]);
	b=dAtof64(argv[2]);
	
	F64 res=a*b;

	char* buff=Con::getReturnBuffer(64);

	dSprintf(buff, 256, "%.16f", res);

	unPad(buff);

	return buff;
}

ConsoleFunction(m64Div, const char *, 3, 3, "(A,B)\n"
                "Returns A/B")
{
	F64 a;
	F64 b;

	a=dAtof64(argv[1]);
	b=dAtof64(argv[2]);
	
	F64 res=a/b;

	char* buff=Con::getReturnBuffer(64);

	dSprintf(buff, 256, "%.16f", res);

	unPad(buff);

	return buff;
}
//Trigonometry 
ConsoleFunction(m64Cos, const char *, 2, 2, "(A)\n"
                "Returns the Cosine of A")
{
	F64 a;
	
	a=dAtof64(argv[1]);
	
	F64 res=mCos(a);

	char* buff=Con::getReturnBuffer(64);

	dSprintf(buff, 256, "%.16f", res);

	unPad(buff);

	return buff;
}

ConsoleFunction(m64Acos, const char *, 2, 2, "(A)\n"
                "Returns the Inverse Cosine of A")
{
	F64 a;
	
	a=dAtof64(argv[1]);
	
	F64 res=mAcos(a);

	char* buff=Con::getReturnBuffer(64);

	dSprintf(buff, 256, "%.16f", res);

	unPad(buff);

	return buff;
}


ConsoleFunction(m64Sin, const char *, 2, 2, "(A)\n"
                "Returns the Sine of A")
{
	F64 a;
	
	a=dAtof64(argv[1]);
	
	F64 res=mSin(a);

	char* buff=Con::getReturnBuffer(64);

	dSprintf(buff, 256, "%.16f", res);

	unPad(buff);

	return buff;
}


ConsoleFunction(m64Asin, const char *, 2, 2, "(A)\n"
                "Returns the Inverse Sine of A")
{
	F64 a;
	
	a=dAtof64(argv[1]);
	
	F64 res=mAsin(a);

	char* buff=Con::getReturnBuffer(64);

	dSprintf(buff, 256, "%.16f", res);

	unPad(buff);

	return buff;
}

ConsoleFunction(m64Tan, const char *, 2, 2, "(A)\n"
                "Returns the Tangent of A")
{
	F64 a;
	
	a=dAtof64(argv[1]);
	
	F64 res=mTan(a);

	char* buff=Con::getReturnBuffer(64);

	dSprintf(buff, 256, "%.16f", res);

	unPad(buff);

	return buff;
}

ConsoleFunction(m64ATan, const char *, 3, 3, "(A, B)\n"
                "Returns the Inverse Tangent of A/B (atan2(a,b))")
{
	F64 a;
	F64 b;
	
	a=dAtof64(argv[1]);
	b=dAtof64(argv[2]);
	
	F64 res=mAtan(a,b);

	char* buff=Con::getReturnBuffer(64);

	dSprintf(buff, 256, "%.16f", res);

	unPad(buff);

	return buff;
}


//Powers etc
ConsoleFunction(m64Pow, const char *, 3, 3, "(A,B)\n"
                "Returns A to the power of B")
{
	F64 a;
	F64 b;

	a=dAtof64(argv[1]);
	b=dAtof64(argv[2]);
	
	F64 res=mPow(a,b);

	char* buff=Con::getReturnBuffer(64);

	dSprintf(buff, 256, "%.16f", res);

	unPad(buff);

	return buff;
}


ConsoleFunction(m64Log, const char *, 2, 2, "(A)\n"
                "Returns the Logarithm of A")
{
	F64 a;
	
	a=dAtof64(argv[1]);
	
	F64 res=mLog(a);

	char* buff=Con::getReturnBuffer(64);

	dSprintf(buff, 256, "%.16f", res);

	unPad(buff);

	return buff;
}

ConsoleFunctionGroupEnd(Math64);