home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2001 Mobile
/
Chip_Mobile_2001.iso
/
palm
/
hobby
/
pdof
/
pdof.EXE
/
pdof.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-11-27
|
16KB
|
607 lines
/*
* PDoF 1.2 Copyright (c) 2000 Matti J. KΣrki
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <PalmOS.h>
#include <FeatureMgr.h>
#include <FloatMgr.h>
#include "pdof.h"
/* Global variables (preferences) */
double gFocalLength = 35.0;
double gAperture = 11.0;
double gDistance = 10.0;
int gCoC = 0;
/****************************************************************************
The beginning of the PrintDouble section.
****************************************************************************/
/*
* The following code is written by Fred Bayer, the author of LispMe and
* modified by Warren Young, the author of f/Calc.
*
* The following section is released as Public Domain. More information
* about the original code can be found here:
* http://www.lispme.de/lispme/gcc/tech.html
*/
#define _DONT_USE_FP_TRAPS_ 1
#include <PalmTypes.h>
#include <PalmCompatibility.h>
#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 = '\0';
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 = '\0';
if (s[-1] == '.')
*--s = '\0';
/*----------------------------------------------------------------*/
/* Append exponent */
/*----------------------------------------------------------------*/
if (sign) {
*s++ = 'e';
*s++ = sign;
StrIToA(s, e);
}
else
*s = '\0';
}
}
/****************************************************************************
The end of the PrintDouble section.
****************************************************************************/
/*
* Calculates a hyper-focal distance. This value is used to
* calculate the near and far edges.
*
* folcaLength - Focal Length in millimeters (for example 35.0).
* aperture - Aperture (for example 22.0).
* coc - CoC value. This is 0.033 for 35mm film.
* 0.06 = 6x6cm film
* 0.15 = 4x5in film
*/
static double CalcHyperfocalDist(double focalLength,
double aperture,
double coc) {
return ((focalLength * focalLength) / (aperture * coc));
}
/*
* Calculates the near edge.
*
* hyperfocalDist - Use the result of CalcHyperfocalDist().
* distOfTarget - Distance of the actual target.
* focalLength - Focal Length (same as in CalcHyperfocalDist()).
*/
static double CalcNearEdge(double hyperfocalDist,
double distOfTarget,
double focalLength) {
return ((hyperfocalDist * distOfTarget) / (hyperfocalDist +
(distOfTarget - focalLength)));
}
/*
* Calculates the far edge.
*
* hyperfocalDist - Use the result of CalcHyperfocalDist().
* distOfTarget - Distance of the actual target.
* focalLength - Focal Length (same as in CalcHyperfocalDist()).
*/
static double CalcFarEdge(double hyperfocalDist,
double distOfTarget,
double focalLength) {
return ((hyperfocalDist * distOfTarget) / (hyperfocalDist -
(distOfTarget - focalLength)));
}
/*
* 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));
}
/*
* The main form event handler.
*/
static Boolean AppFormHandleEvent(EventPtr event) {
FormPtr frmP;
Boolean handled = true;
FieldPtr fieldptr;
char *textptr;
char temp[MAXLEN];
FlpCompDouble value;
double hyp, focal, aperture, dist, coc;
char nearstr[MAXLEN];
char farstr[MAXLEN];
FlpCompDouble near, far;
MemHandle strFocalLength;
MemHandle strAperture;
MemHandle strDistance;
MemPtr pointer;
frmP = FrmGetActiveForm();
/* Keys */
if (event->eType == keyDownEvent) {
switch (event->data.keyDown.chr) {
default:
handled = false;
break;
}
}
/* Controls */
else if (event->eType == ctlSelectEvent) {
switch (event->data.ctlSelect.controlID) {
case PDoFButton1:
fieldptr = GetObjectPtr(frmP, PDoFField1);
textptr = FldGetTextPtr(fieldptr);
if (textptr != NULL) {
StrCopy(temp, textptr);
value.fd = FlpAToF(temp);
focal = value.d;
}
else {
focal = 0.0;
}
fieldptr = GetObjectPtr(frmP, PDoFField2);
textptr = FldGetTextPtr(fieldptr);
if (textptr != NULL) {
StrCopy(temp, textptr);
value.fd = FlpAToF(temp);
aperture = value.d;
}
else {
aperture = 0.0;
}
fieldptr = GetObjectPtr(frmP, PDoFField3);
textptr = FldGetTextPtr(fieldptr);
if (textptr != NULL) {
StrCopy(temp, textptr);
value.fd = FlpAToF(temp);
dist = value.d * 1000.0;
}
else {
dist = 0.0;
}
switch (gCoC) {
case 0:
coc = 0.033;
break;
case 1:
coc = 0.06;
break;
case 2:
coc = 0.15;
break;
default:
coc = 0.033;
}
hyp = CalcHyperfocalDist(focal, aperture, coc);
near.d = CalcNearEdge(hyp, dist, focal) / 1000.0;
far.d = CalcFarEdge(hyp, dist, focal) / 1000.0;
if (near.d < 0) {
StrCopy(nearstr, "[inf]");
}
else {
printDouble(CutDecimals(near.d), nearstr);
}
if (far.d < 0) {
StrCopy(farstr, "[inf]");
}
else {
printDouble(CutDecimals(far.d), farstr);
}
gFocalLength = focal;
gAperture = aperture;
gDistance = dist / 1000.0;
FrmCustomAlert(InformationResults, nearstr, farstr, " ");
handled = true;
break;
default:
handled = false;
break;
}
}
/* Menus */
else if (event->eType == menuEvent) {
switch (event->data.menu.itemID) {
default:
handled = false;
break;
}
}
/* Popup lists */
else if (event->eType == popSelectEvent) {
switch (event->data.popSelect.listID) {
case PDoFList1:
gCoC = event->data.popSelect.selection;
handled = false;
break;
default:
handled = false;
break;
}
}
/* Form open */
else if (event->eType == frmOpenEvent) {
FrmDrawForm(frmP);
strFocalLength = MemHandleNew(MAXLEN);
strAperture = MemHandleNew(MAXLEN);
strDistance = MemHandleNew(MAXLEN);
value.d = CutDecimals(gFocalLength);
printDouble(value.d, temp);
pointer = MemHandleLock(strFocalLength);
StrCopy(pointer, temp);
MemHandleUnlock(strFocalLength);
fieldptr = GetObjectPtr(frmP, PDoFField1);
FldSetText(fieldptr, strFocalLength, 0, MAXLEN);
FldDrawField(fieldptr);
value.d = CutDecimals(gAperture);
printDouble(value.d, temp);
pointer = MemHandleLock(strAperture);
StrCopy(pointer, temp);
MemHandleUnlock(strAperture);
fieldptr = GetObjectPtr(frmP, PDoFField2);
FldSetText(fieldptr, strAperture, 0, MAXLEN);
FldDrawField(fieldptr);
value.d = CutDecimals(gDistance);
printDouble(value.d, temp);
pointer = MemHandleLock(strDistance);
StrCopy(pointer, temp);
MemHandleUnlock(strDistance);
fieldptr = GetObjectPtr(frmP, PDoFField3);
FldSetText(fieldptr, strDistance, 0, MAXLEN);
FldDrawField(fieldptr);
LstSetSelection(GetObjectPtr(frmP, PDoFList1), gCoC);
CtlSetLabel(GetObjectPtr(frmP, PDoFTrigger1),
LstGetSelectionText(GetObjectPtr(frmP, PDoFList1), gCoC));
}
/* Form close */
else if (event->eType == frmCloseEvent) {
handled = false;
}
else {
handled = false;
}
return handled;
}
/*
* Application event handler.
*/
static Boolean AppHandleEvent(EventPtr event) {
Boolean eventHandled = true;
FormPtr frm;
if (event->eType == frmLoadEvent) {
frm = FrmInitForm(event->data.frmLoad.formID);
FrmSetActiveForm(frm);
switch (event->data.frmLoad.formID) {
case PDoFForm:
FrmSetEventHandler(frm, AppFormHandleEvent);
break;
default:
eventHandled = false;
break;
}
}
else {
eventHandled = false;
}
return eventHandled;
}
/*
* Application event loop.
*/
static void AppEventLoop() {
UInt16 error;
EventType event;
do {
EvtGetEvent(&event, evtWaitForever);
if (!SysHandleEvent(&event)) {
if (!MenuHandleEvent(NULL, &event, &error)) {
if (!AppHandleEvent(&event)) {
FrmDispatchEvent(&event);
}
}
}
} while (event.eType != appStopEvent);
}
/*
* Start-up function.
*/
static UInt16 StartApplication() {
UInt16 size;
size = sizeof(double);
PrefGetAppPreferences(CreatorID, 0, &gFocalLength, &size, true);
PrefGetAppPreferences(CreatorID, 1, &gAperture, &size, true);
PrefGetAppPreferences(CreatorID, 2, &gDistance, &size, true);
size = sizeof(int);
PrefGetAppPreferences(CreatorID, 3, &gCoC, &size, true);
return 0;
}
/*
* Shutdown function.
*/
static void StopApplication() {
PrefSetAppPreferences(CreatorID, 0, 1, &gFocalLength, sizeof(double), true);
PrefSetAppPreferences(CreatorID, 1, 1, &gAperture, sizeof(double), true);
PrefSetAppPreferences(CreatorID, 2, 1, &gDistance, sizeof(double), true);
PrefSetAppPreferences(CreatorID, 3, 1, &gCoC, sizeof(int), true);
FrmCloseAllForms();
}
/*
* The main function.
*/
UInt32 PilotMain(UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags) {
UInt16 error;
UInt32 romVersion;
FtrGet(sysFtrCreator, sysFtrNumROMVersion, &romVersion);
if (romVersion < VERSION) {
return sysErrRomIncompatible;
}
if (cmd == sysAppLaunchCmdNormalLaunch) {
error = StartApplication();
if (error) {
return error;
}
FrmGotoForm(PDoFForm);
AppEventLoop();
StopApplication();
}
return 0;
}