Geek@Paris

palm编程的浮点运算太复杂了,贴一些资料在这里

2007-11-03
the following code is written by Fred Bayer, the author of LispMe and
modified by Warren Young, the author of f/Calc.(tbird. comment)
u can modify it as u need, hope it helps.

#include <PalmOS.h>
#include <PalmTypes.h>
#include <PalmCompatibility.h>
#include <FloatMgr.h>
#include <FeatureMgr.h>

#define _DONT_USE_FP_TRAPS_ 1
#include <CoreTraps.h>
#include <StringMgr.h>

void SysTrapFlpLToF(FlpDouble *, Long) SYS_TRAP(sysTrapFlpEmDispatch);

/* convert a long to double */
double longToDouble(long l) {
FlpCompDouble fcd;
asm("moveq.l %0,%%d2": : "i"(sysFloatEm_d_itod):"d2");
SysTrapFlpLToF(&fcd.fd, l);
return fcd.d;
}

Long SysTrapFlpFToL(FlpDouble) SYS_TRAP(sysTrapFlpEmDispatch);

/* convert a double to long */
long doubleToLong(double d) {
FlpCompDouble fcd;
fcd.d = d;
asm("moveq.l %0,%%d2": : "i"(sysFloatEm_d_dtoi):"d2");
return SysTrapFlpFToL(fcd.fd);
}

void SysTrapBinOp(FlpDouble *, FlpDouble, FlpDouble) SYS_TRAP(sysTrapFlpEmDispatch);

/* the same interface is used for all basic arithmetic operations */
double genericDoubleOp(double a, double b, long opcode) {
FlpCompDouble fcda, fcdb, fcds;
fcda.d = a;
fcdb.d = b;
asm("move.l %0,%%d2": : "g"(opcode):"d2");
SysTrapBinOp(&fcds.fd, fcda.fd, fcdb.fd);
return fcds.d;
}

/* basic arithmetic operations */
#define addDouble(a,b) genericDoubleOp(a,b,sysFloatEm_d_add)
#define subDouble(a,b) genericDoubleOp(a,b,sysFloatEm_d_sub)
#define mulDouble(a,b) genericDoubleOp(a,b,sysFloatEm_d_mul)
#define divDouble(a,b) genericDoubleOp(a,b,sysFloatEm_d_div)

SDWord SysTrapCompare(FlpDouble, FlpDouble) SYS_TRAP(sysTrapFlpEmDispatch);

/* compare 2 doubles for equality */
Boolean eqDouble(double a, double b) {
FlpCompDouble fcda, fcdb;
fcda.d = a;
fcdb.d = b;
asm("moveq.l %0,%%d2": : "i"(sysFloatEm_d_feq):"d2");
return SysTrapCompare(fcda.fd, fcdb.fd);
}

/* compare 2 doubles for less or equal */
Boolean leqDouble(double a, double b) {
FlpCompDouble fcda, fcdb;
fcda.d = a;
fcdb.d = b;
asm("moveq.l %0,%%d2": : "i"(sysFloatEm_d_fle):"d2");
return SysTrapCompare(fcda.fd, fcdb.fd);
}

/**********************************************************************/
/* Formatting parameters */
/**********************************************************************/
#define NUM_DIGITS 15
#define MIN_FLOAT 4
#define ROUND_FACTOR 1.0000000000000005 /* NUM_DIGITS zeros */

/**********************************************************************/
/* FP conversion constants */
/**********************************************************************/
static double pow1[] = {
1e256, 1e128, 1e064,
1e032, 1e016, 1e008,
1e004, 1e002, 1e001
};

static double pow2[] = {
1e-256, 1e-128, 1e-064,
1e-032, 1e-016, 1e-008,
1e-004, 1e-002, 1e-001
};

void printDouble(double x, char *s) {
FlpCompDouble fcd;
short e, e1, i;
double *pd, *pd1;
char sign = ”;
short dec = 0;

/*——————————————————————*/
/* Round to desired precision */
/* (this doesn’t always provide a correct last digit!) */
/*——————————————————————*/
x = mulDouble(x, ROUND_FACTOR);

/*——————————————————————*/
/* check for NAN, +INF, -INF, 0 */
/*——————————————————————*/
fcd.d = x;
if ((fcd.ul[0] & 0x7ff00000) == 0x7ff00000)
if (fcd.fdb.manH == 0 && fcd.fdb.manL == 0)
if (fcd.fdb.sign)
StrCopy(s, "[-inf]");
else
StrCopy(s, "[inf]");
else
StrCopy(s, "[nan]");
else if (FlpIsZero(fcd))
StrCopy(s, "0");
else {
/*—————————————————————-*/
/* Make positive and store sign */
/*—————————————————————-*/
if (FlpGetSign(fcd)) {
*s++ = ‘-‘;
FlpSetPositive(fcd);
}

if ((unsigned) fcd.fdb.exp < 0x3ff) { /* meaning x < 1.0 */
/*————————————————————–*/
/* Build negative exponent */
/*————————————————————–*/
for (e = 1, e1 = 256, pd = pow1, pd1 = pow2; e1;
e1 >>= 1, ++pd, ++pd1)
if (!leqDouble(*pd1, fcd.d)) {
e += e1;
fcd.d = mulDouble(fcd.d, *pd);
}
fcd.d = mulDouble(fcd.d, 10.0);

/*————————————————————–*/
/* Only print big exponents */
/*————————————————————–*/
if (e <= MIN_FLOAT) {
*s++ = ‘0’;
*s++ = ‘.’;
dec = -1;
while (–e)
*s++ = ‘0’;
}
else
sign = ‘-‘;
}
else {
/*————————————————————–*/
/* Build positive exponent */
/*————————————————————–*/
for (e = 0, e1 = 256, pd = pow1, pd1 = pow2; e1;
e1 >>= 1, ++pd, ++pd1)
if (leqDouble(*pd, fcd.d)) {
e += e1;
fcd.d = mulDouble(fcd.d, *pd1);
}
if (e < NUM_DIGITS)
dec = e;
else
sign = ‘+’;
}

/*—————————————————————-*/
/* Extract decimal digits of mantissa */
/*—————————————————————-*/
for (i = 0; i < NUM_DIGITS; ++i, –dec) {
Long d = doubleToLong(fcd.d);
*s++ = d + ‘0’;
if (!dec)
*s++ = ‘.’;
fcd.d = subDouble(fcd.d, longToDouble(d));
fcd.d = mulDouble(fcd.d, 10.0);
}

/*—————————————————————-*/
/* Remove trailing zeros and decimal point */
/*—————————————————————-*/
while (s[-1] == ‘0’)
*–s = ”;
if (s[-1] == ‘.’)
*–s = ”;

/*—————————————————————-*/
/* Append exponent */
/*—————————————————————-*/
if (sign) {
*s++ = ‘e’;
*s++ = sign;
StrIToA(s, e);
}
else
*s = ”;
}
}

/****************************************************************************
The end of the PrintDouble section.
****************************************************************************/

/*
* This will cut the decimals. No roundings.
*/

double CutDecimals(double d) {
long l;

l = (long) (d * 1000.0);
return (double) l / 1000.0;
}

/*
* Returns pointer to the object by pointer ID from the given form.
*/
static void* GetObjectPtr(FormPtr formP, UInt16 objectID)
{
FormPtr frmP;

if (formP != NULL) {
frmP = formP;
}
else {
frmP = FrmGetActiveForm();
}

return FrmGetObjectPtr(frmP, FrmGetObjectIndex(frmP, objectID)
);
}

// Code is in the public domain, per this snippet from an email from David Bray <dbray@twcny.rr.com>:
// Str to double begin.
// This code is here because the internal function has limitations.
// Check it yourself at Bray’s page

#if defined(USELIBGLUE)
#include <Libraries/PalmOSGlue/TxtGlue.h>
#define PalmIsDigit TxtGlueCharIsDigit
#else
#define PalmIsDigit TxtCharIsDigit
#endif

double strToDouble(char* str)
{
Int start, length, punctPos;
double result, sign, fractPart;
char temp[30];
UInt32 i;
result = fractPart = 0.0;
length = punctPos = StrLen(str);
start = 0;
sign = 1.0;
if (str[0] == ‘-‘) {
sign = -1.0;
start = 1;
}

for (i = start; i < length; i++) // parse the string from left to right converting the integer part
{
if (str[i] != ‘.’) {
if (PalmIsDigit(str[i]))
{result = result * 10.0 + (double) (str[i] – 48);
printDouble(result, temp);}
else {
return 0.0;
}
}
else {
punctPos = i;
break;
}
}

if (str[punctPos] == ‘.’) // parse the string from the end to the ‘.’ converting the fractional part
{
for (i = length – 1; i > punctPos; i–) {
if (PalmIsDigit(str[i]))
fractPart = fractPart / 10.0 + (double) (str[i] – 48);
else {
return 0.0;
}
}
result += fractPart / 10.0;
}

return result * sign; // correcting the sign
}

// Set text to Field start
static FieldPtr SetTextFromHandle(Word fieldID, Handle txtH)
{
Handle oldTxtH;
FormPtr frm=FrmGetActiveForm();
FieldPtr fldP;

fldP=GetObjectPtr(frm, fieldID);
ErrNonFatalDisplayIf(!fldP, "missing field");
oldTxtH = FldGetTextHandle(fldP);

FldSetTextHandle(fldP, txtH);
FldDrawField(fldP);

if (oldTxtH)//Free the old text pointer
MemHandleFree( (VoidHand) oldTxtH);
return fldP;
}

static FieldPtr SetTxtFld(Word fieldID, CharPtr strP)
{
Handle txtH;
txtH = (Handle) MemHandleNew(StrLen(strP)+1);
if (!txtH)
return NULL;
StrCopy(MemHandleLock((VoidHand) txtH), strP);
MemHandleUnlock( (VoidHand) txtH);
return SetTextFromHandle(fieldID, txtH);
}
//Set text to field End

//Get text from field start
static CharPtr GetTxtFld(Word fieldID)
{
CharPtr temp;
FormPtr frmP = FrmGetActiveForm();
FieldPtr fldP=GetObjectPtr(frmP, fieldID);
temp=FldGetTextPtr(fldP);
if (temp==NULL) temp="";
return temp;
}
//Get text from field end

// Initial setting
static void mainFormInit(FormPtr frmP)
{
//

//
}

// Menu begin
static Boolean doMenu(FormPtr frmP, Word command)
{
Boolean handled = false;
switch (command) {
case Item001 :
FrmAlert(Alertbox001);
handled = true;
break;}
return handled;
}
// Menu end

// button Manager begin
static Boolean doButton(FormPtr frmP, Word command)
{
char* temp;
char t[30];
double inputnumber, result;
Boolean handled = false;
//
temp = GetTxtFld(Field001); //get input number
StrCopy(t, temp);
inputnumber = strToDouble(t);
result = inputnumber * 0.333;
printDouble(CutDecimals(result), t); // double to string
SetTxtFld(Field002, t); //Set the solution to the field
//
handled = true;
return handled;
}

//button end

static
Boolean mainFormEventHandler(EventPtr eventP)
{
Boolean handled = false;
FormPtr frmP = FrmGetActiveForm();
switch (eventP->eType) {
case frmOpenEvent:
FrmDrawForm(frmP);
mainFormInit(frmP);
handled = true;
break;
case menuEvent:
handled = doMenu(frmP, eventP->data.menu.itemID);
break;
case ctlSelectEvent:
handled = doButton(frmP, eventP->data.ctlEnter.controlID);
break;
}
return handled;
}

void stopApp()
{

}

Boolean appHandleEvent(EventPtr event)
{
FormPtr frm;
Int formId;
Boolean handled = false;
if (event->eType == frmLoadEvent) {
formId = event->data.frmLoad.formID;
frm = FrmInitForm(formId);
FrmSetActiveForm(frm);
if (formId == Form001)
FrmSetEventHandler (frm, mainFormEventHandler);
handled = true;
}
return handled;
}

// Main() start
DWord PilotMain(Word cmd, Ptr cmdPBP, Word launchFlags)
{
EventType event;
UInt16 error;
if (cmd == sysAppLaunchCmdNormalLaunch) {
FrmGotoForm(Form001);
do {
EvtGetEvent(&event, evtWaitForever);
if (!SysHandleEvent(&event))
if (!MenuHandleEvent(0, &event, &error))
if (!appHandleEvent(&event))
FrmDispatchEvent(&event);
} while (event.eType != appStopEvent);
stopApp();
FrmCloseAllForms();
}
return 0;
}
// Main() end

Author:admin | Categories:PDA | Tags:

2 Comments

  1. 蒙柯 says:

    是C语言,不过函数主要都是palm里特有的

  2. 林峰 says:

    是c语言吗

Leave a Reply

Your email address will not be published. Required fields are marked *


Clickcha - The One-Click Captcha