?? math24f.h
字號:
// *************************************************
// 24 bit basic floating point math operations
// Copyright (c) B Knudsen Data, Norway, 2000 - 2005
// *************************************************
#pragma library 1
/* PROTOTYPES for page definition in application header file:
float24 operator* _fmul24( float24 arg1f24, float24 arg2f24);
float24 operator/ _fdiv24( float24 arg1f24, float24 arg2f24);
float24 operator+ _fadd24( float24 arg1f24, float24 arg2f24);
float24 operator- _fsub24( float24 arg1f24, float24 arg2f24);
float24 operator= _int24ToFloat24( int24 arg1f24);
float24 operator= _int32ToFloat24( int32 arg32);
int24 operator= _float24ToInt24( float24 arg1f24);
bit operator< _f24_LT_f24( float24 arg1f24, float24 arg2f24);
bit operator>= _f24_GE_f24( float24 arg1f24, float24 arg2f24);
bit operator> _f24_GT_f24( float24 arg1f24, float24 arg2f24);
bit operator<= _f24_LE_f24( float24 arg1f24, float24 arg2f24);
*/
// DEFINABLE SYMBOLS (in the application code):
//#define FP_OPTIM_SPEED // optimize for SPEED: default
//#define FP_OPTIM_SIZE // optimize for SIZE
//#define DISABLE_ROUNDING // disable rounding and save code space
#define float24ToIEEE754(a) { a.mid8=rl(a.mid8); a.high8=rr(a.high8);\
a.mid8=rr(a.mid8); }
#define IEEE754ToFloat24(a) { a.mid8=rl(a.mid8); a.high8=rl(a.high8);\
a.mid8=rr(a.mid8); }
/* 24 bit floating point format:
address ID
X a.low8 : LSB, bit 0-7 of mantissa
X+1 a.mid8 : bit 8-14 of mantissa, bit 15 is the sign bit
X+2 a.high8 : MSB, bit 0-7 of exponent, with bias 0x7F
bit 15 of mantissa is a hidden bit, always equal to 1
zero (0.0) : a.high8 = 0 (mantissa & sign ignored)
MSB LSB
7F 00 00 : 1.0 = 1.0 * 2**(0x7F-0x7F) = 1.0 * 1
7F 80 00 : -1.0 = -1.0 * 2**(0x7F-0x7F) = -1.0 * 1
80 00 00 : 2.0 = 1.0 * 2**(0x80-0x7F) = 1.0 * 2
80 40 00 : 3.0 = 1.5 * 2**(0x80-0x7F) = 1.5 * 2
7E 60 00 : 0.875 = 1.75 * 2**(0x7E-0x7F) = 1.75 * 0.5
7F 60 00 : 1.75 = 1.75 * 2**(0x7E-0x7F) = 1.75 * 1
7F 7F FF : 1.999969482
00 7C 5A : 0.0 (mantissa & sign ignored)
01 00 00 : 1.17549435e-38 = 1.0 * 2**(0x01-0x7F)
FE 7F FF : 3.40277175e+38 = 1.999969482 * 2**(0xFE-0x7F)
FF 00 00 : +INF : positive infinity
FF 80 00 : -INF : negative infinity
*/
#define FpBIAS 0x7F
#ifndef FpFlags_defined
#define FpFlags_defined
char FpFlags;
//bit IOV @ FpFlags.0; // integer overflow flag: NOT USED
bit FpOverflow @ FpFlags.1; // floating point overflow flag
bit FpUnderFlow @ FpFlags.2; // floating point underflow flag
bit FpDiv0 @ FpFlags.3; // floating point divide by zero flag
//bit FpNAN @ FpFlags.4; // not-a-number exception flag: NOT USED
bit FpDomainError @ FpFlags.5; // domain error exception flag
bit FpRounding @ FpFlags.6; // floating point rounding flag, 0=truncation
// 1 = unbiased rounding to nearest LSB
//bit FpSaturate @ FpFlags.7; // floating point saturate flag: NOT USED
#pragma floatOverflow FpOverflow
#pragma floatUnderflow FpUnderFlow
#define InitFpFlags() FpFlags = 0x40 /* enable rounding as default */
#endif
#ifdef DISABLE_ROUNDING
#pragma floatRounding 0
#endif
#if __CoreSet__ < 1600
#define genAdd(r,a) W=a; btsc(Carry); W=incsz(a); r+=W;
#define genSub(r,a) W=a; btss(Carry); W=incsz(a); r-=W;
#define genAddW(r,a) W=a; btsc(Carry); W=incsz(a); W=r+W;
#define genSubW(r,a) W=a; btss(Carry); W=incsz(a); W=r-W;
#else
#define genAdd(r,a) W=a; r=addWFC(r);
#define genSub(r,a) W=a; r=subWFB(r);
#define genAddW(r,a) W=a; W=addWFC(r);
#define genSubW(r,a) W=a; W=subWFB(r);
#endif
#if __CoreSet__ == 1700 || __CoreSet__ == 1800
#define hw_mult8x8(a,b) { W = a; multiply(b); }
#define loRES PRODL
#define hiRES PRODH
#endif
#if __CoreSet__ == 2000
#define hw_mult8x8(a,b) { W = a; multiply(b); }
#define loRES W
#define hiRES MULH
#endif
float24 operator* _fmul24( sharedM float24 arg1f24, sharedM float24 arg2f24)
{
uns16 aarg;
W = arg1f24.mid8;
aarg.high8 = W;
// save sign
char sign = arg2f24.mid8 ^ W; // before first overflow test
W = arg1f24.high8;
#if __CoreSet__ / 100 == 17
if (W != 0)
W = arg2f24.high8;
if (W == 0)
goto RES0;
#else
if (!Zero_)
W = arg2f24.high8;
if (Zero_)
goto RES0;
#endif
arg1f24.high8 += W /* arg2f24.high8 */;
W = FpBIAS-1;
if (Carry) {
arg1f24.high8 -= W;
if (Carry)
goto OVERFLOW;
}
else {
arg1f24.high8 -= W;
if (!Carry)
goto UNDERFLOW;
}
aarg.low8 = arg1f24.low8;
aarg.15 = 1;
arg2f24.15 = 1;
#if defined hw_mult8x8 && !defined FP_OPTIM_SIZE
char tmpL;
arg1f24.low16 = 0;
hw_mult8x8( arg2f24.low8, aarg.low8); // p1
tmpL = hiRES;
hw_mult8x8( arg2f24.mid8, aarg.low8); // p2
tmpL += loRES;
genAdd( arg1f24.low8, hiRES);
genAdd( arg1f24.mid8, 0);
hw_mult8x8( arg2f24.low8, aarg.mid8); // p2
tmpL += loRES;
genAdd( arg1f24.low8, hiRES);
genAdd( arg1f24.mid8, 0);
hw_mult8x8( arg2f24.mid8, aarg.mid8); // p3
arg1f24.low8 += loRES;
genAdd( arg1f24.mid8, hiRES);
#undef hw_mult8x8
#undef loRES
#undef hiRES
if (!arg1f24.15) {
tmpL = rl( tmpL);
arg1f24.low16 = rl( arg1f24.low16);
if (arg1f24.high8 == 0)
goto UNDERFLOW;
arg1f24.high8 -= 1;
W = rl( tmpL); // restore bit behind LSB in Carry
}
#else
arg1f24.low16 = 0;
char counter = sizeof(aarg)*8;
do {
aarg = rr( aarg);
if (Carry) {
arg1f24.low8 += arg2f24.low8;
genAdd( arg1f24.mid8, arg2f24.mid8);
}
arg1f24.low16 = rr( arg1f24.low16);
counter = decsz(counter);
} while (1);
if (!arg1f24.15) {
// catch Carry bit that was shifted out previously
arg1f24.low16 = rl( arg1f24.low16);
if (arg1f24.high8 == 0)
goto UNDERFLOW;
arg1f24.high8 -= 1;
W = rl( aarg.high8);
// restore bit behind LSB in Carry
}
#endif
#ifndef DISABLE_ROUNDING
if (FpRounding && Carry) {
arg1f24.low8 += 1;
if (!arg1f24.low8) {
arg1f24.mid8 += 1;
if (!arg1f24.mid8) {
#if __CoreSet__ >= 1700 && __CoreSet__ <= 1800
Carry = 1; // previous INCF changes Carry
#else
// Carry = 1; //OK
#endif
arg1f24.low16 = rr( arg1f24.low16);
arg1f24.high8 += 1;
if (Zero_)
goto OVERFLOW;
}
}
}
#endif
goto SET_SIGN;
UNDERFLOW:
FpUnderFlow = 1;
RES0:
arg1f24.high8 = 0;
goto MANTISSA;
OVERFLOW:
FpOverflow = 1;
arg1f24.high8 = 0xFF;
MANTISSA:
arg1f24.low16 = 0x8000;
SET_SIGN:
if (!(sign & 0x80))
arg1f24.15 = 0;
return arg1f24;
}
float24 operator/ _fdiv24( sharedM float24 arg1f24, sharedM float24 arg2f24)
{
uns16 aarg;
W = arg1f24.mid8;
aarg.high8 = W;
// save sign
char sign = arg2f24.mid8 ^ W; // before first overflow test
#if __CoreSet__ / 100 == 17
if (!arg2f24.high8)
goto Div0;
#else
W = arg2f24.high8;
if (Zero_)
goto Div0;
#endif
if (!arg1f24.high8)
goto RES0;
arg1f24.high8 -= arg2f24.high8;
W = FpBIAS;
if (!Carry) {
arg1f24.high8 += W;
if (!Carry)
goto UNDERFLOW;
}
else {
arg1f24.high8 += W;
if (Carry)
goto OVERFLOW;
}
aarg.low8 = arg1f24.low8;
aarg.15 = 1;
arg2f24.15 = 1;
// division: shift & add
char counter = 16;
arg1f24.low16 = 0; // speedup
#if defined FP_OPTIM_SPEED || !defined FP_OPTIM_SIZE // SPEED
goto START;
TEST_ZERO_L:
W = aarg.low8 - arg2f24.low8;
if (!Carry)
goto SHIFT_IN_CARRY;
aarg.low8 = W;
aarg.high8 = 0;
goto SET_AND_SHIFT_IN_CARRY;
// MAIN LOOP
do {
LOOP:
if (!Carry) {
START:
W = aarg.high8 - arg2f24.mid8;
if (Zero_)
goto TEST_ZERO_L;
if (!Carry)
goto SHIFT_IN_CARRY;
}
aarg.low8 -= arg2f24.low8;
genSub( aarg.high8, arg2f24.mid8);
SET_AND_SHIFT_IN_CARRY:
Carry = 1;
SHIFT_IN_CARRY:
arg1f24.low16 = rl( arg1f24.low16);
// Carry = 0; // ok, speedup
aarg = rl( aarg);
counter = decsz(counter);
} while (1);
#else // SIZE
goto START;
// MAIN LOOP
do {
LOOP:
if (Carry)
goto SUBTRACT;
START:
W = aarg.low8 - arg2f24.low8;
genSubW( aarg.high8, arg2f24.mid8);
if (!Carry)
goto SKIP_SUB;
SUBTRACT:
aarg.low8 -= arg2f24.low8;
genSub( aarg.high8, arg2f24.mid8);
Carry = 1;
SKIP_SUB:
arg1f24.low16 = rl( arg1f24.low16);
// Carry = 0; // ok
aarg = rl( aarg);
counter = decsz(counter);
} while (1);
#endif
if (!arg1f24.15) {
if (!arg1f24.high8)
goto UNDERFLOW;
#if __CoreSet__ >= 1700 && __CoreSet__ <= 1800
sign = rr( sign); // Save Carry
#endif
arg1f24.high8 --;
counter ++;
#if __CoreSet__ >= 1700 && __CoreSet__ <= 1800
sign = rl( sign); // Restore Carry, changed by INCF/DECF
#endif
goto LOOP;
}
#ifndef DISABLE_ROUNDING
if (FpRounding) {
if (Carry)
goto ADD_1;
aarg.low8 -= arg2f24.low8;
genSub( aarg.high8, arg2f24.mid8);
if (Carry) {
ADD_1:
arg1f24.low8 += 1;
if (!arg1f24.low8) {
arg1f24.mid8 ++;
if (!arg1f24.mid8) {
arg1f24.low16 = rr( arg1f24.low16);
arg1f24.high8 ++;
if (!arg1f24.high8)
goto OVERFLOW;
}
}
}
}
#endif
goto SET_SIGN;
Div0:
FpDiv0 = 1;
goto SATURATE;
UNDERFLOW:
FpUnderFlow = 1;
RES0:
arg1f24.high8 = 0;
goto MANTISSA;
OVERFLOW:
FpOverflow = 1;
SATURATE:
arg1f24.high8 = 0xFF;
MANTISSA:
arg1f24.low16 = 0x8000;
SET_SIGN:
if (!(sign & 0x80))
arg1f24.15 = 0;
return arg1f24;
}
float24 operator+ _fadd24( sharedM float24 arg1f24, sharedM float24 arg2f24)
{
char xtra, temp;
char expo = arg1f24.high8 - arg2f24.high8;
if (!Carry) {
expo = -expo;
temp = arg1f24.high8;
arg1f24.high8 = arg2f24.high8;
arg2f24.high8 = temp;
temp = arg1f24.mid8;
arg1f24.mid8 = arg2f24.mid8;
arg2f24.mid8 = temp;
temp = arg1f24.low8;
arg1f24.low8 = arg2f24.low8;
arg2f24.low8 = temp;
}
if (expo > sizeof(arg1f24)*8-7)
goto RETURN;
if (!arg2f24.high8)
goto RETURN; // result is arg1f24
xtra = 0;
W = arg1f24.mid8;
temp = W;
char sign = arg2f24.mid8 ^ W;
arg1f24.15 = 1;
arg2f24.15 = 1;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -