Code archives/User Libs/Blitz Double

This code has been declared by its author to be Public Domain code.

Download source code

Blitz Double by Abram2007
For all of you that finds the accuracy of the Blitz float not sufficient I have made a dll that includes many functions to operate on doubles.

Unfortunately I had no place to upload a compiled dll but hopefully someone that reads this can compile a dll and add a link. Otherwise I can always mail a compiled version.
Save the following in you userlibs as "blitzdouble.decls"

.lib "blitzdouble.dll"
DoubleMultiply(A,B,Out) : "_DoubleMultiply@12"
DoubleDivide(A,B,Out) : "_DoubleDivide@12"
DoubleAdd(A,B,Out) : "_DoubleAdd@12"
DoubleSubtract(A,B,Out) : "_DoubleSubtract@12"
Double2Float#(A) : "_Double2Float@4"
Double2Int%(A) : "_Double2Int@4"
DoubleAssignFromString(Out,B$) : "_DoubleAssignFromString@8"
DoubleAssignFromFloat(Out,B#) : "_DoubleAssignFromFloat@8"
DoubleAssignFromInt(Out,B) : "_DoubleAssignFromInt@8"
DoubleAssign(Out,B) : "_DoubleAssign@8"
Double2String$(A) : "_Double2String@4"
DoubleSqrt(A,Out) : "_DoubleSqrt@8"
DoubleSin(A,Out) : "_DoubleSin@8"
DoubleCos(A,Out) : "_DoubleCos@8"
DoubleASin(A,Out) : "_DoubleASin@8"
DoubleACos(A,Out) : "_DoubleACos@8"
DoubleATan(A,Out) : "_DoubleATan@8"
DoubleATan2(A,B,Out) : "_DoubleATan2@12"
DoubleTan(A,Out) : "_DoubleTan@8"
DoubleAbs(A,Out) : "_DoubleAbs@8"
DoubleLog(A,Out) : "_DoubleLog@8"
DoubleLog10(A,Out) : "_DoubleLog10@8"
DoublePow(A,B,Out) : "_DoublePow@12"
DoubleExp(A,Out) : "_DoubleExp@8"
DoubleCeiling(A,Out) : "_DoubleCeiling@8"
DoubleFloor(A,Out) : "_DoubleFloor@8"
DoubleSinh(A,Out) : "_DoubleSinh@8"
DoubleCosh(A,Out) : "_DoubleCosh@8"
DoubleSign%(A) : "_DoubleSign@4"
DoubleEqualLessThan%(A,B) : "_DoubleEqualLessThan@8"
DoubleLessThan%(A,B) : "_DoubleLessThan@8"
DoubleEqualTo%(A,B) : "_DoubleEqualTo@8"
DoubleEqualBiggerThan%(A,B) : "_DoubleEqualBiggerThan@8"
DoubleBiggerThan%(A,B) : "_DoubleBiggerThan@8"
DoubleSetFPUDoubleMode() : "_DoubleSetFPUDoubleMode@0"
DoubleSetFPUSingleMode() : "_DoubleSetFPUSingleMode@0"

Comments

Abram2007
Example Code:

; Create some banks to store the double variables
Local MyDouble_1 = CreateBank(8)
Local MyDouble_2 = CreateBank(8)
Local MyDouble_3 = CreateBank(8)
Local MyDouble_4 = CreateBank(8)
Local MyDouble_5 = CreateBank(8)

Print "Assign from string"
DoubleAssignFromString(MyDouble_5,"3.2361567664646")
DoubleAssignFromString(MyDouble_3,"36337.58583466")
DoubleAssignFromString(MyDouble_4,"4792.94923023755")
Print Double2String(MyDouble_5)
Print Double2String(MyDouble_4)
Print Double2String(MyDouble_3)

; Normally Blitz Basic has the processor set to single precision,
; DoubleSetFPUDoubleMode sets the processor to double precision calculations,
; as long as you only use BlitzDouble calculations it should be safe to let
; it stay in double precision mode... but it seems to be no problems also to
; let Blitz Basic floats operate in Double Mode, but that needs to be tested
; alot more than I have done...

DoubleMultiply(MyDouble_3,MyDouble_4,MyDouble_1)
Print: Print "Multiply (without setting FPU to double mode)"
Print "Double: "+Double2String(MyDouble_1)
Print "Float: "+(36337.58583466*4792.94923023755)

DoubleSetFPUDoubleMode()

DoubleMultiply(MyDouble_3,MyDouble_4,MyDouble_1)
Print: Print "Multiply (after FPU in double mode)"
Print "Double: "+Double2String(MyDouble_1)
Print "Float: "+(36337.58583466*4792.94923023755)


DoubleDivide(MyDouble_3,MyDouble_4,MyDouble_1)
Print : Print "Divide"
Print "Double: "+Double2String(MyDouble_1)
Print "Float: "+(36337.58583466/4792.94923023755)

WaitKey
Print : Print "Add"
DoubleAdd(MyDouble_3,MyDouble_4,MyDouble_1)
Print "Double: "+Double2String(MyDouble_1)
Print "Float: "+(36337.58583466+4792.94923023755)

Print : Print "Substract"
DoubleSubtract(MyDouble_3,MyDouble_4,MyDouble_1)
Print "Double: "+Double2String(MyDouble_1)
Print "Float: "+ (36337.58583466-4792.94923023755)

Print : Print "Assign from float"
Local TestaFloat# = 1.4369736
DoubleAssignFromFloat(MyDouble_1,TestaFloat#)
Print "Double: " + Double2Float(MyDouble_1)
Print "Float: " + TestaFloat#

Print : Print "Pow"
DoubleAssignFromString(MyDouble_3,"2")
DoubleAssignFromString(MyDouble_4,"4.005")
DoublePow(MyDouble_3,MyDouble_4,MyDouble_1)
Print "Double: "+Double2String(MyDouble_1)

Print : Print "Sinus"
DoubleAssignFromString(MyDouble_3,"0.156782")
DoubleSin(MyDouble_3,MyDouble_1)
Print "Double: "+Double2String(MyDouble_1)
Print "Float: " + Sin(0.156782*180/Pi)

Print : Print "Cosinus"
DoubleAssignFromString(MyDouble_3,"0.156782")
DoubleCos(MyDouble_3,MyDouble_1)
Print "Double: "+Double2String(MyDouble_1)
Print "Float: " + Cos(0.156782*180/Pi)

Local Loops = 10000000
Print : Print "Speed Test ("+Loops+" Divisions)"
DoubleAssignFromString(MyDouble_3,"1.01234")
DoubleAssignFromString(MyDouble_4,"0.99999888")
Local Var1# = 1.01234
Local Var2# = 0.99999888
Local Var3# = -1;
Local StartTime=MilliSecs()
For i=1 To Loops
DoubleDivide(MyDouble_3,MyDouble_4,MyDouble_3)
Next
Local EndTime=MilliSecs()
Print "Double took: "+(EndTime-StartTime)+"ms with result: "+Double2String(MyDouble_3)
StartTime=MilliSecs()
For i=1 To Loops
Var1 = Var1/Var2
Next
EndTime=MilliSecs()
Print "Float took: "+(EndTime-StartTime)+"ms with result: "+Var1

Print : Print "Speed Test ("+Loops+" Multiplications)"
DoubleAssignFromString(MyDouble_3,"1.01234")
DoubleAssignFromString(MyDouble_4,"0.99999888")
Var1# = 1.01234
Var2# = 0.99999888
Var3# = -1;
StartTime=MilliSecs()
For i=1 To Loops
DoubleMultiply(MyDouble_3,MyDouble_4,MyDouble_3)
Next
EndTime=MilliSecs()
Print "Double took: "+(EndTime-StartTime)+"ms with result: "+Double2String(MyDouble_3)

StartTime=MilliSecs()
For i=1 To Loops
Var1 = Var1*Var2
Next
EndTime=MilliSecs()
Print "Float took: "+(EndTime-StartTime)+"ms with result: "+Var1

Print : Print "Sign"
DoubleAssignFromInt(MyDouble_3,0)
Print "Sign: "+Double2String(MyDouble_3)+" is "+DoubleSign(MyDouble_3)
DoubleAssignFromInt(MyDouble_3,-4)
Print "Sign: "+Double2String(MyDouble_3)+" is "+DoubleSign(MyDouble_3)
DoubleAssignFromInt(MyDouble_3,9)
Print "Sign: "+Double2String(MyDouble_3)+" is "+DoubleSign(MyDouble_3)

Print : Print "Sign"
DoubleAssignFromInt(MyDouble_3,0)
Print "Sign of "+Double2String(MyDouble_3)+" is "+DoubleSign(MyDouble_3)
DoubleAssignFromInt(MyDouble_3,-4)
Print "Sign of "+Double2String(MyDouble_3)+" is "+DoubleSign(MyDouble_3)
DoubleAssignFromInt(MyDouble_3,9)
Print "Sign of "+Double2String(MyDouble_3)+" is "+DoubleSign(MyDouble_3)

DoubleAssignFromFloat(MyDouble_3,2.468764)
DoubleCeiling(MyDouble_3,MyDouble_1)
DoubleFloor(MyDouble_3,MyDouble_2)
Print "Ceiling of "+Double2String(MyDouble_3)+" is "+Double2String(MyDouble_1)
Print "Floor of "+Double2String(MyDouble_3)+" is "+Double2String(MyDouble_2)

DoubleAssignFromFloat(MyDouble_3,-2.468764)
DoubleCeiling(MyDouble_3,MyDouble_1)
DoubleFloor(MyDouble_3,MyDouble_2)
Print "Ceiling of "+Double2String(MyDouble_3)+" is "+Double2String(MyDouble_1)
Print "Floor of "+Double2String(MyDouble_3)+" is "+Double2String(MyDouble_2)

WaitKey()


Abram2007
// Blitz double. Made by Örjan Abramsson 2007-03-16.
// Feel free to make any improvements that you find necessary.
// Code will be faster if it is compiled with SIZECHECK 0 which
// will disable the security check of the banksize, but if you know how to
// use the dll, this check is not necessary :)
// Just dont hold me responsible for any program crashes if this check is
// disabled... and also not when the check is enabled... Just to
// be on the safe side :)
// Have fun with the code

#include <afxwin.h>
#include <float.h>
#include "stdafx.h"
#include "math.h"
#define BBDECL extern "C" _declspec(dllexport)
#define BBCALL _stdcall
#define CONVERTDOUBLE(A) *(double *)(*(int *)((char *)(A)+4))

unsigned int _TheOrginalFPUMode=0;
#define ALWAYS_SET_DOUBLEPRECISION 0
// To be used if the FPU mode shall be set to double just before
// calculations and back to Blitz Basic Mode afterwards.
// That way should be 100% secure... letting it stay in double
// mode might perhaps have unknown effects in Blitz 3D?
// Try to set this flag to 0 at your own risk, but if you do
// remember to also call DoubleSetFPUDoubleMode, otherwise the
// double calculations will not work. DoubleSetFPUDoubleMode is not
// needed when this flag is set to 1.

#define SIZECHECK 0 // If you know that you will not send banks with sizes different than 8
// define SIZECHECK to 0 and the dll will compile without the check
// and thus improve the speed of the dll. Then you can also remove
// #include <afxwin.h> since the check is the only place for AfxMessageBox

// Bank Information:
// When receiving a bank from blitz basic the adress to the
// memory is stored in an offset of +4. The Size of the bank
// is stored at +8 as an integer

// Type Casting explanation for CONVERTDOUBLE(A) (double *)(*(int *)((char *)(A)+4))
// A + 4 is the adress to the memory where the bank is stored
// therefore (char *)A + 4, in order to have the adress of the bank.
// To be able to interpret this as an adress this is casted to an integerpointer
// therefore (int *)((char *)A+4). This is then a pointer to a memory adress.
// In order to read the adress we check what the pointer is pointing at with
// *(int *)((char *)A+4), which returns an integer which we interpret as the adress
// to a double with (double *)(*(int *)((char *)A+4)), which finally gives the adress
// where we can work with our double. The last step with *(double *)(*(int *)((char *)A+4))
// is so that we work with the value and not the pointer of the double.
// Explaination is just as confusing as the line when I read it myself... sorry.


#if SIZECHECK
inline bool CheckBankSize(void *Bank)
{
int BankSize=*(int *)((char *)Bank+8);
if(BankSize!=8) // Bank size shall be 8 for a double
{
char Buffer[200];
sprintf(Buffer,"Blitz Double Bank Size Error\nBank size is: %d should be 8",BankSize);
AfxMessageBox(Buffer,MB_ICONSTOP|MB_OK);
return false;
}
return true;
}
#endif

BBDECL void BBCALL DoubleMultiply(void *A,void *B,void *Out)
{
#if SIZECHECK
if( CheckBankSize(A)==false || CheckBankSize(B)==false || CheckBankSize(Out)==false )
return;
#endif
#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif

CONVERTDOUBLE(Out)= (CONVERTDOUBLE(A)) * (CONVERTDOUBLE(B));

#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
}

BBDECL void BBCALL DoubleDivide(void *A,void *B,void *Out)
{
#if SIZECHECK
if( CheckBankSize(A)==false || CheckBankSize(B)==false || CheckBankSize(Out)==false )
return;
#endif
#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif

CONVERTDOUBLE(Out)= (CONVERTDOUBLE(A)) / (CONVERTDOUBLE(B));

#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
}

BBDECL void BBCALL DoubleAdd(void *A,void *B,void *Out)
{

#if SIZECHECK
if( CheckBankSize(A)==false || CheckBankSize(B)==false || CheckBankSize(Out)==false )
return;
#endif
#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif

CONVERTDOUBLE(Out)= (CONVERTDOUBLE(A)) + (CONVERTDOUBLE(B));

#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
}

BBDECL void BBCALL DoubleSubtract(void *A,void *B,void *Out)
{
#if SIZECHECK
if( CheckBankSize(A)==false || CheckBankSize(B)==false || CheckBankSize(Out)==false )
return;
#endif
#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif

CONVERTDOUBLE(Out)= (CONVERTDOUBLE(A)) - (CONVERTDOUBLE(B));

#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif

}

BBDECL float BBCALL Double2Float(void *A)
{
#if SIZECHECK
if( CheckBankSize(A)==false )
return 0;
#endif
#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif

float TheData=(float)CONVERTDOUBLE(A);

#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif

return TheData;
}

BBDECL int BBCALL Double2Int(void *A)
{
#if SIZECHECK
if( CheckBankSize(A)==false )
return 0;
#endif
#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif

int TheData=(int)CONVERTDOUBLE(A);

#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif

return TheData;

}

BBDECL void BBCALL DoubleAssignFromString(void *Out,char *B)
{

#if SIZECHECK
if( CheckBankSize(Out)==false )
return;
#endif

#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif

CONVERTDOUBLE(Out)=atof(B);

#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
}

BBDECL void BBCALL DoubleAssignFromFloat(void *Out,float B)
{

#if SIZECHECK
if( CheckBankSize(Out)==false )
return;
#endif
#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif

CONVERTDOUBLE(Out)=(double)B;

#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
}

BBDECL void BBCALL DoubleAssignFromInt(void *Out,int B)
{

#if SIZECHECK
if( CheckBankSize(Out)==false )
return;
#endif
#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif

CONVERTDOUBLE(Out)=(double)B;

#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
}

BBDECL void BBCALL DoubleAssign(void *Out,void *B)
{

#if SIZECHECK
if( CheckBankSize(B)==false || CheckBankSize(Out)==false )
return;
#endif

#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif

CONVERTDOUBLE(Out)=CONVERTDOUBLE(B);

#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
}

BBDECL const char* BBCALL Double2String(void *A)
{

#if SIZECHECK
if( CheckBankSize(A)==false )
return "Bank Size Error";
#endif
#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif

static char _buf[30];
sprintf(_buf,"%.20g",CONVERTDOUBLE(A));

#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
return _buf;
}

BBDECL void BBCALL DoubleSqrt(void *A,void *Out)
{
#if SIZECHECK
if( CheckBankSize(A)==false || CheckBankSize(Out)==false )
return;
#endif
#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif

CONVERTDOUBLE(Out)=sqrt(CONVERTDOUBLE(A));

#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif

}

BBDECL void BBCALL DoubleSin(void *A,void *Out)
{
#if SIZECHECK
if( CheckBankSize(A)==false || CheckBankSize(Out)==false )
return;
#endif
#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif

CONVERTDOUBLE(Out)=sin(CONVERTDOUBLE(A));

#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
}

BBDECL void BBCALL DoubleCos(void *A,void *Out)
{
#if SIZECHECK
if( CheckBankSize(A)==false || CheckBankSize(Out)==false )
return;
#endif

#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif

CONVERTDOUBLE(Out)=cos(CONVERTDOUBLE(A));

#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
}

BBDECL void BBCALL DoubleASin(void *A,void *Out)
{
#if SIZECHECK
if( CheckBankSize(A)==false || CheckBankSize(Out)==false )
return;
#endif

#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif

CONVERTDOUBLE(Out)=asin(CONVERTDOUBLE(A));

#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
}

BBDECL void BBCALL DoubleACos(void *A,void *Out)
{
#if SIZECHECK
if( CheckBankSize(A)==false || CheckBankSize(Out)==false )
return;
#endif

#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif

CONVERTDOUBLE(Out)=acos(CONVERTDOUBLE(A));

#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
}

BBDECL void BBCALL DoubleATan(void *A,void *Out)
{
#if SIZECHECK
if( CheckBankSize(A)==false || CheckBankSize(Out)==false )
return;
#endif

#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif

CONVERTDOUBLE(Out)=atan(CONVERTDOUBLE(A));

#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
}

BBDECL void BBCALL DoubleATan2(void *A,void *B,void *Out)
{
#if SIZECHECK
if( CheckBankSize(A)==false || CheckBankSize(B)==false || CheckBankSize(Out)==false )
return;
#endif

#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif

CONVERTDOUBLE(Out)=atan2(CONVERTDOUBLE(A),CONVERTDOUBLE(B));

#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
}

BBDECL void BBCALL DoubleTan(void *A,void *Out)
{
#if SIZECHECK
if( CheckBankSize(A)==false || CheckBankSize(Out)==false )
return;
#endif

#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif

CONVERTDOUBLE(Out)=tan(CONVERTDOUBLE(A));

#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
}

BBDECL void BBCALL DoubleAbs(void *A,void *Out)
{
#if SIZECHECK
if( CheckBankSize(A)==false || CheckBankSize(Out)==false )
return;
#endif

#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif

CONVERTDOUBLE(Out)=abs(CONVERTDOUBLE(A));

#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
}

BBDECL void BBCALL DoubleLog(void *A,void *Out)
{
#if SIZECHECK
if( CheckBankSize(A)==false || CheckBankSize(Out)==false )
return;
#endif

#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif

CONVERTDOUBLE(Out)=log(CONVERTDOUBLE(A));

#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
}

BBDECL void BBCALL DoubleLog10(void *A,void *Out)
{
#if SIZECHECK
if( CheckBankSize(A)==false || CheckBankSize(Out)==false )
return;
#endif

#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif

CONVERTDOUBLE(Out)=log10(CONVERTDOUBLE(A));

#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
}

BBDECL void BBCALL DoublePow(void *A,void *B,void *Out)
{
#if SIZECHECK
if( CheckBankSize(A)==false || CheckBankSize(B)==false || CheckBankSize(Out)==false )
return;
#endif

#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif

CONVERTDOUBLE(Out)=pow(CONVERTDOUBLE(A),CONVERTDOUBLE(B));

#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
}

BBDECL void BBCALL DoubleExp(void *A,void *Out)
{
#if SIZECHECK
if( CheckBankSize(A)==false || CheckBankSize(Out)==false )
return;
#endif
#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif
CONVERTDOUBLE(Out)=exp(CONVERTDOUBLE(A));
#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
}

BBDECL void BBCALL DoubleCeiling(void *A,void *Out)
{
#if SIZECHECK
if( CheckBankSize(A)==false || CheckBankSize(Out)==false )
return;
#endif
#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif
CONVERTDOUBLE(Out)=ceil(CONVERTDOUBLE(A));
#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
}

BBDECL void BBCALL DoubleFloor(void *A,void *Out)
{
#if SIZECHECK
if( CheckBankSize(A)==false || CheckBankSize(Out)==false )
return;
#endif
#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif
CONVERTDOUBLE(Out)=floor(CONVERTDOUBLE(A));
#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
}

BBDECL void BBCALL DoubleSinh(void *A,void *Out)
{
#if SIZECHECK
if( CheckBankSize(A)==false || CheckBankSize(Out)==false )
return;
#endif
#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif
CONVERTDOUBLE(Out)=sinh(CONVERTDOUBLE(A));
#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
}

BBDECL void BBCALL DoubleCosh(void *A,void *Out)
{
#if SIZECHECK
if( CheckBankSize(A)==false || CheckBankSize(Out)==false )
return;
#endif
#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif
CONVERTDOUBLE(Out)=cosh(CONVERTDOUBLE(A));
#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
}

BBDECL int BBCALL DoubleSign(void *A)
{
#if SIZECHECK
if( CheckBankSize(A)==false )
return 0;
#endif
#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif
int TheSign= (CONVERTDOUBLE(A) > 0) - (CONVERTDOUBLE(A) < 0);
#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
return TheSign;
}

BBDECL int BBCALL DoubleEqualLessThan(void *A,void *B)
{
#if SIZECHECK
if( CheckBankSize(A)==false || CheckBankSize(B)==false )
return 0;
#endif
#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif
int TheResult= (CONVERTDOUBLE(A)) <= (CONVERTDOUBLE(B));
#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
return TheResult;
}

BBDECL int BBCALL DoubleLessThan(void *A,void *B)
{
#if SIZECHECK
if( CheckBankSize(A)==false || CheckBankSize(B)==false )
return 0;
#endif
#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif
int TheResult= (CONVERTDOUBLE(A)) < (CONVERTDOUBLE(B));
#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
return TheResult;
}

BBDECL int BBCALL DoubleEqualTo(void *A,void *B)
{
#if SIZECHECK
if( CheckBankSize(A)==false || CheckBankSize(B)==false )
return 0;
#endif
#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif
int TheResult= (CONVERTDOUBLE(A)) == (CONVERTDOUBLE(B));
#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
return TheResult;
}

BBDECL int BBCALL DoubleEqualBiggerThan(void *A,void *B)
{
#if SIZECHECK
if( CheckBankSize(A)==false || CheckBankSize(B)==false )
return 0;
#endif
#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif
int TheResult= (CONVERTDOUBLE(A)) >= (CONVERTDOUBLE(B));
#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
return TheResult;
}

BBDECL int BBCALL DoubleBiggerThan(void *A,void *B)
{
#if SIZECHECK
if( CheckBankSize(A)==false || CheckBankSize(B)==false )
return 0;
#endif
#if ALWAYS_SET_DOUBLEPRECISION
unsigned int OrginalMode = _controlfp( 0, 0 );
_controlfp( _CW_DEFAULT, 0xfffff );
#endif
int TheResult= (CONVERTDOUBLE(A)) > (CONVERTDOUBLE(B));
#if ALWAYS_SET_DOUBLEPRECISION
_controlfp( OrginalMode, 0xfffff );
#endif
return TheResult;
}

BBDECL void BBCALL DoubleSetFPUDoubleMode(void)
{
if(_TheOrginalFPUMode==0)
{
_TheOrginalFPUMode = _controlfp( 0, 0 );
}
_controlfp( _CW_DEFAULT, 0xfffff );
}

BBDECL void BBCALL DoubleSetFPUSingleMode(void)
{
if(_TheOrginalFPUMode!=0)
{
_controlfp( _TheOrginalFPUMode, 0xfffff );
}
}


humanspacecraft2007
Thanks Abram, this was urgently needed!
Doubelfun with floats can be downloaded from:

http://www.electricdesire.com/blitz/blitzdouble.rar


humanspacecraft2007
--


Abram2007
Happy to be of help, glad that you find it useful.


jfk EO-111102007
Very nice addition, thanks a lot!


RGR2007
Did no-one check if the results are exact? See the following:
http://www.blitzbasic.com/Community/posts.php?topic=58849

Doubles in a dll don't work with Blitz3D! Everything after the 7th digit is wrong

I wrote about that many month ago:
http://www.blitzbasic.com/Community/posts.php?topic=58828#654531


Abram2007
Updated code where also the results are correct is now available..... Double precision in Blitz3D is really possible :)

Sorry about having such a major bug... but at least it is gone now. Just got blind of when I saw that more decimals were available at first.

Have updated the code on this page, make sure your downloaded code matched the one presented here, otherwise it will not work.


RGR2007
Hi, great work :-)
Thanks for the quick fix and delivery by mail.
Ralph


humanspacecraft2007
The updated version is now also available here:
www.electricdesire.com/blitz/blitzdouble.rar


Abram2007
Updated once again, got a request for a lot of functions that I had not included in the dll. Functions to compare doubles and some more maths functions. Also made an option to set the FPU to double mode only in the start of the program, which increases the speed of the dll a lot... Just remember to set it to single mode after the calculations are done, otherwise I have no idea if there will be secondary effects in other parts of your programs..
Or you can use compile with the ALWAYS_SET_DOUBLEPRECISION set to 1 and this will not be a problem.
Hope this will be the last update for a long while :)
(Code once again mailed to humanspacecraft, thanks a lot for hosting)


humanspacecraft2007
Here the freshly extended version:
http://www.electricdesire.com/blitz/blitzdoubleXL.rar


Loktar2007
This is pretty cool... so does this mean i could finally make a space game with realistic distances between planets :) ?


Graythe2007
Thanks Abram, bloody marvellous!


AD2007
I downloaded the zip files and the exe files work fine - however when I try to edit and run/compile the .bb file in BB2D v1.68 it keeps saying "function not found", also there is no "userlibs" folder in my version of BB2D.

Please explain how to use this Double function as I am eager to use it!


Abram2007
I am not sure which version of Blitz that first introduced userlibs, but you should upgrade to the latest version of Blitz Basic and you will have a folder that is named userlibs. With your current version I do not think it will work... sorry. The exe files are compiled with version 1.98, and I guess that is why you do not get it to work.


AD2007
That's a shame. I have the Blitz Basic free version that came with a magazine (IDE: v1.68, Linker v1.24, Runtime v1.68)

I do have BlitzMax, but still aren't used to using it.

Oh well, thank you for at least attempting to beat the double issue with BB2D.


Code Archives Forum