Code archives/User Libs/Blitz Double
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
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
| ||
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 ); } } |
| ||
Thanks Abram, this was urgently needed! Doubelfun with floats can be downloaded from: http://www.electricdesire.com/blitz/blitzdouble.rar |
| ||
-- |
| ||
Happy to be of help, glad that you find it useful. |
| ||
Very nice addition, thanks a lot! |
| ||
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 |
| ||
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. |
| ||
Hi, great work :-) Thanks for the quick fix and delivery by mail. Ralph |
| ||
The updated version is now also available here: www.electricdesire.com/blitz/blitzdouble.rar |
| ||
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) |
| ||
Here the freshly extended version: http://www.electricdesire.com/blitz/blitzdoubleXL.rar |
| ||
This is pretty cool... so does this mean i could finally make a space game with realistic distances between planets :) ? |
| ||
Thanks Abram, bloody marvellous! |
| ||
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! |
| ||
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. |
| ||
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