This code has been declared by its author to be Public Domain code.
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()
// 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 );
}
}
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)
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.