Category : C Source Code
Archive   : FRASRC18.ZIP
Filename : PARSERFP.C

 
Output of file : PARSERFP.C contained in archive : FRASRC18.ZIP
/* */
/* PARSERFP.C -- Part of FRACTINT fractal drawer. */
/* */
/* By Chuck Ebbert CompuServe [76306,1226] */
/* internet: [email protected] */
/* */
/* Fast floating-point parser code. The functions beginning with */
/* "fStk" are in PARSERA.ASM. PARSER.C calls this code after */
/* it has parsed the formula. */
/* */
/* Converts the function pointers/load pointers/store pointers */
/* built by parsestr() into an optimized array of function */
/* pointer/operand pointer pairs. */
/* */
/* ******************************************************************* */
/* */
/* (C) 1992, 1993 Chuck Ebbert. All rights reserved. */
/* */
/* This code may be freely distributed and used in non-commercial */
/* programs provided the author is credited either during program */
/* execution or in the documentation, and this copyright notice */
/* is left intact. Sale of this code, or its use in any commercial */
/* product requires permission from the author. Nominal */
/* distribution and handling fees may be charged by shareware and */
/* freeware distributors. */
/* */
/* Chuck Ebbert */
/* 1915 Blust Ln. */
/* Enola, PA 17025 */
/* */
/* ******************************************************************* */
/* */
/* Revised 22 MAR 1993 */
/* */
/* Uncomment the next line to enable debug. */
/* #define TESTFP 1 */
/* */

#include
#include
#include
#include
#include
#include
#include "mpmath.h"
#include "prototyp.h"

extern union Arg *Arg1, *Arg2;
/* Some of these variables should be renamed for safety */
extern union Arg s[20], far * far *Store, far * far *Load;
extern int StoPtr, LodPtr, OpPtr;
extern int debugflag;
extern unsigned vsp, LastOp;
extern struct ConstArg far *v;
extern int inside; /* "inside" color to use */
extern int outside; /* "outside" color to use */
extern int potflag; /* potential enabled? */
extern char useinitorbit;
extern int InitLodPtr, InitStoPtr, InitOpPtr, LastInitOp;
extern void (far * far *f)(void);

struct fls { /* function, load, store pointers CAE fp */
void (near *function)(void);
union Arg near *operand;
} far *pfls = (struct fls far *)0;

void StkLod(void);
void StkClr(void);
void dStkAdd(void);
void dStkSub(void);
void dStkMul(void);
void dStkDiv(void);
void StkSto(void);
void dStkSqr(void);
void EndInit(void);
void dStkMod(void);
void dStkLTE(void);
void dStkSin(void);
void dStkCos(void);
void dStkSinh(void);
void dStkCosh(void);
void dStkCosXX(void);
void dStkTan(void);
void dStkTanh(void);
void dStkCoTan(void);
void dStkCoTanh(void);
void dStkLog(void);
void dStkExp(void);
void dStkPwr(void);
void dStkLT(void);
void dStkFlip(void);
void dStkReal(void);
void dStkImag(void);
void dStkConj(void);
void dStkNeg(void);
void dStkAbs(void);
void dStkRecip(void);
void StkIdent(void);
void dStkGT(void);
void dStkGTE(void);
void dStkNE(void);
void dStkEQ(void);
void dStkAND(void);
void dStkOR(void);

#define fgf(x) pfls[(x)].function
#define opp(x) pfls[(x)].operand
#define NO_OPERAND (void near *)0
#define LastSqr v[4].a
#define MAX_ARGS 100
#define MAX_STACK 8
#define TWO_FREE 6

#ifndef XFRACT

void (near fStkPull2 )(void); /* pull up fpu stack from 2 to 4 */
void (near fStkPush2 )(void); /* push down fpu stack from 8 to 6 */
void (near fStkPush2a )(void); /* push down fpu stack from 6 to 4 */
void (near fStkPush4 )(void); /* push down fpu stack from 8 to 4 */
void (near fStkLodDup )(void); /* lod, dup */
void (near fStkLodSqr )(void); /* lod, sqr, dont save magnitude */
void (near fStkLodSqr2 )(void); /* lod, sqr, save magnitude */
void (near fStkStoDup )(void); /* store, duplicate */
void (near fStkStoSqr )(void); /* store, sqr, save lastsqr */
void (near fStkStoSqr0 )(void); /* store, sqr, dont save lastsqr */
void (near fStkLodDbl )(void); /* load, double */
void (near fStkStoDbl )(void); /* store, double */
void (near fStkReal2 )(void); /* fast ver. of real */
void (near fStkSqr )(void); /* sqr, save magnitude in lastsqr */
void (near fStkSqr0 )(void); /* sqr, no save magnitude */
void (near fStkClr1 )(void); /* clear fpu */
void (near fStkClr2 )(void); /* test stack top, clear fpu */
void (near fStkStoClr1 )(void); /* store, clr1 */
void (near fStkAdd )(void);
void (near fStkSub )(void);
void (near fStkSto )(void);
void (near fStkSto2 )(void); /* fast ver. of sto */
void (near fStkLod )(void);
void (near fStkEndInit )(void);
void (near fStkMod )(void);
void (near fStkMod2 )(void);
void (near fStkLodMod2 )(void);
void (near fStkStoMod2 )(void);
void (near fStkLTE )(void);
void (near fStkLodLTEMul )(void);
void (near fStkLTE2 )(void);
void (near fStkLodLTE )(void);
void (near fStkLodLTE2 )(void);
void (near fStkLodLTEAnd2 )(void);
void (near fStkLT )(void);
void (near fStkLodLTMul )(void);
void (near fStkLT2 )(void);
void (near fStkLodLT )(void);
void (near fStkLodLT2 )(void);
void (near fStkGTE )(void);
void (near fStkLodGTE )(void);
void (near fStkLodGTE2 )(void);
void (near fStkGT )(void);
void (near fStkGT2 )(void);
void (near fStkLodGT )(void);
void (near fStkLodGT2 )(void);
void (near fStkEQ )(void);
void (near fStkLodEQ )(void);
void (near fStkNE )(void);
void (near fStkLodNE )(void);
void (near fStkAND )(void);
void (near fStkANDClr2 )(void);
void (near fStkOR )(void);
void (near fStkSin )(void);
void (near fStkSinh )(void);
void (near fStkCos )(void);
void (near fStkCosXX )(void);
void (near fStkCosh )(void);
void (near fStkTan )(void);
void (near fStkTanh )(void);
void (near fStkCoTan )(void);
void (near fStkCoTanh )(void);
void (near fStkLog )(void);
void (near fStkExp )(void);
void (near fStkPwr )(void);
void (near fStkMul )(void);
void (near fStkDiv )(void);
void (near fStkFlip )(void);
void (near fStkReal )(void);
void (near fStkImag )(void);
void (near fStkRealFlip )(void);
void (near fStkImagFlip )(void);
void (near fStkConj )(void);
void (near fStkNeg )(void);
void (near fStkAbs )(void);
void (near fStkRecip )(void);
void (near fStkLodReal )(void);
void (near fStkLodRealC )(void);
void (near fStkLodImag )(void);
void (near fStkLodRealFlip )(void);
void (near fStkLodRealAbs )(void);
void (near fStkLodRealMul )(void);
void (near fStkLodRealAdd )(void);
void (near fStkLodRealSub )(void);
void (near fStkLodImagFlip )(void);
void (near fStkLodImagAbs )(void);
void (near fStkLodConj )(void);
void (near fStkLodAdd )(void);
void (near fStkLodSub )(void);
void (near fStkLodSubMod )(void);
void (near fStkLodMul )(void);
void (near fStkPLodAdd )(void);
void (near fStkPLodSub )(void);
void (near Img_Setup )(void);


static void (near *prevfptr )(void);
static int stkcnt, prevstkcnt, cvtptrx, prevlodptr, lastsqrused;

static void CvtFptr(void (near * ffptr)(void), int MinStk, int MaxStk,
int Delta )
/* (MinStk <= 4, MaxStk >= TWO_FREE) */
{
char testconst = 0;

if (stkcnt < MinStk ) { /* not enough operands on fpu stack */
#ifdef TESTFP
stopmsg(0, "Inserted pull." );
#endif
opp(cvtptrx) = NO_OPERAND;
fgf(cvtptrx++) = fStkPull2; /* so adjust the stack, pull operand */
stkcnt += 2;
}
else if (stkcnt > MaxStk ) { /* too many operands */
#ifdef TESTFP
stopmsg(0, "Inserted push." );
#endif
opp(cvtptrx) = NO_OPERAND;
fgf(cvtptrx++) = fStkPush2; /* push operand to adjust stack */
stkcnt -= 2;
}

/* set the operand pointer here */
if (ffptr == fStkSto ){ /* this must be before test for load */
opp(cvtptrx) = (void near *)(Store[StoPtr++]);
}
else if (ffptr == fStkLod && debugflag == 322 ){
/* if disabling optimizer, set load pointer here */
opp(cvtptrx) = (void near *)(Load[LodPtr++]);
}
else {
opp(cvtptrx) = NO_OPERAND;
}

if (debugflag == 322 ){
goto SkipOptimizer;
} /* -------------------------- begin optimizer -------------- */

/* For the following: */
/* * == cvtptrx points to this */
/* () == this is about to be added to the array */

if (ffptr == fStkLod) { /* we are about to add Lod to the array */
if (prevfptr == fStkLod && Load[LodPtr-1] == Load[LodPtr] ) {
/* previous non-adjust operator was Lod of same operand */
/* i.e. found {? lodx ? (*lodx) } */
if (fgf(--cvtptrx) == fStkPush2 ){ /* prev fn was push */
/* {? lod *push (lod) } */
--cvtptrx; /* found {? *lod push (lod) } */
if (fgf(cvtptrx-1) == fStkPush2){ /* always more ops here */
#ifdef TESTFP
stopmsg(0, "push *lod push (lod) -> push4 (*loddup)" );
#endif
fgf(cvtptrx-1) = fStkPush4;
}
else { /* prev op not push */
#ifdef TESTFP
stopmsg(0, "op *lod push (lod) -> op pusha(p=0) (*loddup)" );
#endif
opp(cvtptrx) = NO_OPERAND; /* use 'alternate' push fn. */
fgf(cvtptrx++) = fStkPush2a; /* push with TWO_FREE on stack */
/* operand ptr will be set below */
}
}
else { /* never {push *lod (lod) } so must be */
#ifdef TESTFP
stopmsg(0, "op *lod (lod) -> op (*loddup)" );
#endif
}
ffptr = fStkLodDup;
}
else if (prevfptr == fStkSto2
&& Store[StoPtr-1] == Load[LodPtr] ){
/* store, load of same value */
/* only one operand on stack here when prev oper is Sto2 */
--cvtptrx;
#ifdef TESTFP
stopmsg(0, "*sto2 (lod) -> (*stodup)" );
#endif
ffptr = fStkStoDup;
}
/* This may cause roundoff problems when later operators */
/* use the rounded value that was stored here, while the next */
/* operator uses the more accurate internal value. */
else if (prevfptr == fStkStoClr1 && prevstkcnt == 2
&& Store[StoPtr-1] == Load[LodPtr] ){
/* store, clear, load same value found */
/* only one operand was on stack so this is safe */
--cvtptrx;
#ifdef TESTFP
stopmsg (0, "*StoClr1 (Lod) -> (*Sto2)" );
#endif
ffptr = fStkSto2; /* use different Sto fn */
}
else {
/* the really awful hack below gets the first char of the name */
/* of the variable being loaded */
testconst = **(((char * far *)Load[LodPtr] ) - 2 );
if ( !isalpha(testconst) && Load[LodPtr]->d.y == 0.0 ){
/* if first character not alpha, the var is a constant */
#ifdef TESTFP
stopmsg (0, "(*lod) -> (*lodrealc)" );
#endif
ffptr = fStkLodRealC; /* a real const is being loaded */
}
}
/* set the operand ptr here */
opp(cvtptrx) = (void near *)(Load[LodPtr++]);
}
else if (ffptr == fStkAdd ){
if (prevfptr == fStkLodDup ){ /* there is never a push before add */
--cvtptrx; /* found {? *loddup (add) } */
if (cvtptrx>0 && fgf(cvtptrx-1) == fStkPush2a ){
/* because {push lod lod } impossible so is {push loddup } */
#ifdef TESTFP
stopmsg (0, "pusha *loddup (add) -> (*loddbl),stk+=2" );
#endif
--cvtptrx;
opp(cvtptrx) = opp(cvtptrx+1); /* fix opptr */
stkcnt += 2;
}
else if (cvtptrx>0 && fgf(cvtptrx-1) == fStkPush4 ){
#ifdef TESTFP
stopmsg (0, "push4 *loddup (add) -> push2 (*loddbl)" );
#endif
fgf(cvtptrx-1) = fStkPush2;
}
else {
#ifdef TESTFP
stopmsg (0, "op *loddup (add) -> {op (*loddbl)" );
#endif
}
ffptr = fStkLodDbl;
}
else if (prevfptr == fStkStoDup ){
#ifdef TESTFP
stopmsg (0, "stodup (add) -> (stodbl)" );
#endif
/* there are always exactly 4 on stack here */
--cvtptrx;
ffptr = fStkStoDbl;
}
else if (prevfptr == fStkLod ){ /* have found {lod (*add) } */
--cvtptrx; /* {? *lod (add) } */
if (fgf(cvtptrx-1) == fStkPush2 ){
#ifdef TESTFP
stopmsg (0, "*push load (add) -> (*plodadd),stk+=2" );
#endif
--cvtptrx;
stkcnt += 2; /* eliminated a push */
opp(cvtptrx) = opp(cvtptrx+1); /* fix opptrs */
ffptr = fStkPLodAdd;
}
else {
#ifdef TESTFP
stopmsg (0, "op *lod (add) -> op (*lodadd)" );
#endif
ffptr = fStkLodAdd;
}
}
else if (prevfptr == fStkLodReal || prevfptr == fStkLodRealC ){
--cvtptrx; /* found {? *lodreal (add) } */
if (fgf(cvtptrx-1) == fStkPush2 ){
#ifdef TESTFP
stopmsg (0, "*push lodreal (add) -> (*lodrealadd),stk+=2" );
#endif
--cvtptrx;
stkcnt += 2; /* push eliminated */
opp(cvtptrx) = opp(cvtptrx+1); /* fix opptrs */
}
else {
#ifdef TESTFP
stopmsg (0, "*lodreal (add) -> (*lodrealadd)" );
#endif
}
ffptr = fStkLodRealAdd;
}
}
else if (ffptr == fStkSub ){
if (prevfptr == fStkLod ){
/* found {lod (*sub) } */
--cvtptrx; /* {*lod (sub) } */
/* there is never a sequence (lod push sub ) */
if (fgf(cvtptrx-1) == fStkPush2 ){
#ifdef TESTFP
stopmsg (0, "*push lod (sub) -> (*plodsub),stk+=2" );
#endif
--cvtptrx;
opp(cvtptrx) = opp(cvtptrx+1); /* fix opptrs */
stkcnt += 2; /* push was deleted so adj. stkcnt */
ffptr = fStkPLodSub;
}
else {
#ifdef TESTFP
stopmsg (0, "*lod (sub) -> (*lodsub)" );
#endif
ffptr = fStkLodSub;
}
}
else if (prevfptr == fStkLodReal || prevfptr == fStkLodRealC ){
--cvtptrx; /* {? *lodreal (sub) } */
if (fgf(cvtptrx-1) == fStkPush2 ){
#ifdef TESTFP
stopmsg (0, "*push lodreal (sub) -> (*lodrealsub),stk+=2" );
#endif
--cvtptrx;
stkcnt += 2; /* push eliminated */
opp(cvtptrx) = opp(cvtptrx+1); /* fix opptrs */
}
else {
#ifdef TESTFP
stopmsg (0, "*lodreal (sub) -> (*lodrealsub)" );
#endif
}
ffptr = fStkLodRealSub;
}
}
else if (ffptr == fStkMul ){
if (prevfptr == fStkLodDup ){
/* found {loddup ? (*mul) } */
if (fgf(--cvtptrx) == fStkPush2 ){
#ifdef TESTFP
stopmsg (0, "loddup *push (mul) -> (*lodsqr),stk+=2" );
#endif
stkcnt += 2; /* eliminate this push */
--cvtptrx; /* prev is a LodDup */
}
else {
#ifdef TESTFP
stopmsg (0, "*loddup (mul) -> (*lodsqr)" );
#endif
}
ffptr = fStkLodSqr;
}
else if (prevfptr == fStkStoDup ){ /* no pushes here, 4 on stk. */
#ifdef TESTFP
stopmsg (0, "stodup (mul) -> (*stosqr0)" );
#endif
--cvtptrx;
ffptr = fStkStoSqr0; /* dont save lastsqr here ever */
}
else if (prevfptr == fStkLod ){
--cvtptrx; /* {lod *? (mul) } */
if (fgf(cvtptrx) == fStkPush2 ){ /* {lod *push (mul) } */
--cvtptrx; /* {? *lod push (mul) } */
if(fgf(cvtptrx-1) == fStkPush2 ){
#ifdef TESTFP
stopmsg (0, "push *lod push (mul) -> push4 (*lodmul)" );
#endif
fgf(cvtptrx-1) = fStkPush4;
}
else {
#ifdef TESTFP
stopmsg (0, "op *lod push (mul) -> op pusha (*lodmul)" );
#endif
opp(cvtptrx+1) = opp(cvtptrx); /* fix operand ptr */
fgf(cvtptrx) = fStkPush2a;
opp(cvtptrx++) = NO_OPERAND;
}
}
else {
#ifdef TESTFP
stopmsg (0, "*lod (mul) -> (*lodmul)" );
#endif
}
ffptr = fStkLodMul;
}
else if (prevfptr == fStkLodReal || prevfptr == fStkLodRealC ){
--cvtptrx; /* found {lodreal *? (mul) } */
if (fgf(cvtptrx) == fStkPush2 ){
#ifdef TESTFP
stopmsg (0, "lodreal *push2 (mul) -> (*lodrealmul),stk+=2" );
#endif
--cvtptrx;
stkcnt += 2; /* stack ends with TWO_FREE, not 4 */
}
else {
#ifdef TESTFP
stopmsg (0, "*lodreal (mul) }-> {(*lodrealmul)" );
#endif
}
ffptr = fStkLodRealMul;
}
else if (prevfptr == fStkLodLT && fgf(cvtptrx-1) != fStkPull2 ){
/* this shortcut fails if {Lod LT Pull Mul } found */
#ifdef TESTFP
stopmsg (0, "LodLT (*Mul) -> (*LodLTMul)" );
#endif
--cvtptrx; /* never { lod LT Push Mul } here */
ffptr = fStkLodLTMul;
}
else if (prevfptr == fStkLodLTE && fgf(cvtptrx-1) != fStkPull2 ){
#ifdef TESTFP
stopmsg (0, "LodLTE (*mul) -> (*LodLTEmul)" );
#endif
--cvtptrx;
ffptr = fStkLodLTEMul;
}
}
else if (ffptr == fStkClr1 && prevfptr == fStkSto ){
#ifdef TESTFP
stopmsg (0, "sto (*clr1) -> (*stoclr1)" );
#endif
--cvtptrx;
ffptr = fStkStoClr1;
}
else if (ffptr == fStkDiv ){
if (prevfptr == fStkLodRealC && vsp < MAX_ARGS - 1 ){
/* have found a divide by a real constant */
/* and there is space to create a new one */
/* {lodrealc ? (*div) } */
--cvtptrx; /* change '/ const' to '* 1/const' */
if (fgf(cvtptrx) == fStkPush2 ){
#ifdef TESTFP
stopmsg (0, "lodrealc *push (div) -> (*lodrealmul),stk+=2" );
#endif
--cvtptrx;
stkcnt += 2;
}

else {
#ifdef TESTFP
stopmsg (0, "*lodrealc (div) -> {(*lodrealmul)" );
#endif
}
v[vsp].s = (void near *)0; /* this constant has no name */
v[vsp].len = 0;
v[vsp].a.d.x = 1.0 / Load[LodPtr-1]->d.x;
v[vsp].a.d.y = 0.0;
opp(cvtptrx) = (void near *)&v[vsp++].a; /* isn't C fun! */
ffptr = fStkLodRealMul;
}
}
else if (ffptr == fStkReal ){
if (prevfptr == fStkLod ){
#ifdef TESTFP
stopmsg (0, "lod (*real) -> (*lodreal)" );
#endif
--cvtptrx;
ffptr = fStkLodReal;
}
else if (stkcnt < MAX_STACK ){
#ifdef TESTFP
stopmsg (0, "(*real) -> (*real2)" );
#endif
ffptr = fStkReal2;
}
}
else if (ffptr == fStkImag && prevfptr == fStkLod ){
#ifdef TESTFP
stopmsg (0, "lod (*imag) -> lodimag" );
#endif
--cvtptrx;
ffptr = fStkLodImag;
}
else if (ffptr == fStkConj && prevfptr == fStkLod ){
#ifdef TESTFP
stopmsg (0, "lod (*conj) -> (*lodconj)" );
#endif
--cvtptrx;
ffptr = fStkLodConj;
}
else if (ffptr == fStkMod && stkcnt < MAX_STACK ){
#ifdef TESTFP
stopmsg (0, "(*mod) -> (*mod2)" );
#endif
ffptr = fStkMod2; /* use faster version if room on stack */
if (prevfptr == fStkLod ){
#ifdef TESTFP
stopmsg (0, "lod (*mod2) -> (*lodmod2)" );
#endif
--cvtptrx;
ffptr = fStkLodMod2;
}
else if (prevfptr == fStkSto || prevfptr == fStkSto2 ){
#ifdef TESTFP
stopmsg (0, "sto (*mod2) -> (*stomod2)" );
#endif
--cvtptrx;
ffptr = fStkStoMod2;
}
else if (prevfptr == fStkLodSub ){
#ifdef TESTFP
stopmsg (0, "lodsub (*mod2) -> (*lodsubmod)" );
#endif
--cvtptrx;
ffptr = fStkLodSubMod;
}
}
else if (ffptr == fStkFlip ){
if (prevfptr == fStkReal || prevfptr == fStkReal2 ){
#ifdef TESTFP
stopmsg (0, "real (*flip) -> (*realflip)" );
#endif
--cvtptrx;
ffptr = fStkRealFlip;
}
else if (prevfptr == fStkImag ){
#ifdef TESTFP
stopmsg (0, "imag (*flip) -> (*imagflip)" );
#endif
--cvtptrx;
ffptr = fStkImagFlip;
}
else if (prevfptr == fStkLodReal ){
#ifdef TESTFP
stopmsg (0, "lodreal (*flip) -> (*lodrealflip)" );
#endif
--cvtptrx;
ffptr = fStkLodRealFlip;
}
else if (prevfptr == fStkLodImag ){
#ifdef TESTFP
stopmsg (0, "lodimag (*flip) -> (*lodimagflip)" );
#endif
--cvtptrx;
ffptr = fStkLodImagFlip;
}
}
else if (ffptr == fStkAbs ){
if (prevfptr == fStkLodReal ){
#ifdef TESTFP
stopmsg (0, "lodreal (*abs) -> (*lodrealabs)" );
#endif
--cvtptrx;
ffptr = fStkLodRealAbs;
}
else if (prevfptr == fStkLodImag ){
#ifdef TESTFP
stopmsg (0, "lodimag (*abs) -> (*lodimagabs)" );
#endif
--cvtptrx;
ffptr = fStkLodImagAbs;
}
}
else if (ffptr == fStkSqr ){
if (prevfptr == fStkLod && fgf(cvtptrx-1) != fStkPush2 ){
#ifdef TESTFP
stopmsg (0, "lod (*sqr) -> (*lodsqr)" );
#endif
--cvtptrx;
ffptr = fStkLodSqr; /* assume no need to save lastsqr */
if (lastsqrused) {
#ifdef TESTFP
stopmsg (0, "(*lodsqr) -> (*lodsqr2)" );
#endif
ffptr = fStkLodSqr2; /* lastsqr is being used */
}
}
else if (prevfptr == fStkSto2 ){
#ifdef TESTFP
stopmsg (0, "sto2 (*sqr) -> (*stosqr0)" );
#endif
--cvtptrx;
ffptr = fStkStoSqr0; /* assume no need to save lastsqr */
if (lastsqrused) {
#ifdef TESTFP
stopmsg (0, "(*stosqr0) -> (*stosqr)" );
#endif
ffptr = fStkStoSqr; /* save lastsqr */
}
}
else {
if (!lastsqrused) {
#ifdef TESTFP
stopmsg (0, "(*sqr) -> (*sqr0)" );
#endif
ffptr = fStkSqr0; /* don't save lastsqr */
}
}
}
else if (ffptr == fStkLTE && ( prevfptr == fStkLod
|| prevfptr == fStkLodReal || prevfptr == fStkLodRealC ) ){
#ifdef TESTFP
stopmsg(0, "Lod (*LTE) -> (*LodLTE)" );
#endif
--cvtptrx;
ffptr = fStkLodLTE;
}
else if (ffptr == fStkLT && ( prevfptr == fStkLod
|| prevfptr == fStkLodReal || prevfptr == fStkLodRealC ) ){
#ifdef TESTFP
stopmsg(0, "Lod (*LT) -> (*LodLT)" );
#endif
--cvtptrx;
ffptr = fStkLodLT;
}
else if (ffptr == fStkGT && ( prevfptr == fStkLod
|| prevfptr == fStkLodReal || prevfptr == fStkLodRealC ) ){
#ifdef TESTFP
stopmsg(0, "Lod (*GT) -> (*LodGT)" );
#endif
--cvtptrx;
ffptr = fStkLodGT;
}
else if (ffptr == fStkGTE && ( prevfptr == fStkLod
|| prevfptr == fStkLodReal || prevfptr == fStkLodRealC ) ){
#ifdef TESTFP
stopmsg(0, "Lod (*GTE) -> (*LodGTE)" );
#endif
--cvtptrx;
ffptr = fStkLodGTE;
}
else if (ffptr == fStkNE && ( prevfptr == fStkLod
|| prevfptr == fStkLodReal || prevfptr == fStkLodRealC ) ){
#ifdef TESTFP
stopmsg(0, "Lod (*NE) -> (*LodNE)" );
#endif
--cvtptrx;
ffptr = fStkLodNE;
}
else if (ffptr == fStkEQ && ( prevfptr == fStkLod
|| prevfptr == fStkLodReal || prevfptr == fStkLodRealC ) ){
#ifdef TESTFP
stopmsg(0, "Lod (*EQ) -> (*LodEQ)" );
#endif
--cvtptrx;
ffptr = fStkLodEQ;
}

SkipOptimizer: /* ----------- end of optimizer code ------------ */

fgf(cvtptrx++) = prevfptr = ffptr;
prevstkcnt = stkcnt;

if (Delta == 999 ){
stkcnt = 0;
}
else {
stkcnt += Delta;
}
return;
}

int CvtStk() { /* convert the array of ptrs */
extern int fform_per_pixel(void); /* these fns are in parsera.asm */
extern int fFormula(void);
extern int BadFormula(void);
extern char FormName[];
void (far *ftst)(void);
void (near *ntst)(void);

#ifdef TESTFP
if (debugflag == 322) {
stopmsg(0, "Skipping optimizer." );
}
#endif

for (OpPtr = LodPtr = lastsqrused = 0; OpPtr < LastOp; OpPtr++) {
ftst = f[OpPtr];
if (ftst == StkLod && Load[LodPtr++] == &LastSqr ){
lastsqrused = 1; /* lastsqr is being used in the formula */
}
if ( ftst != StkLod /* these are the supported parser fns */
&& ftst != StkClr
&& ftst != dStkAdd
&& ftst != dStkSub
&& ftst != dStkMul
&& ftst != dStkDiv
&& ftst != StkSto
&& ftst != dStkSqr
&& ftst != EndInit
&& ftst != dStkMod
&& ftst != dStkLTE
&& ftst != dStkSin
&& ftst != dStkCos
&& ftst != dStkSinh
&& ftst != dStkCosh
&& ftst != dStkCosXX
&& ftst != dStkTan
&& ftst != dStkTanh
&& ftst != dStkCoTan
&& ftst != dStkCoTanh
&& ftst != dStkLog
&& ftst != dStkExp
&& ftst != dStkPwr
&& ftst != dStkLT
&& ftst != dStkFlip
&& ftst != dStkReal
&& ftst != dStkImag
&& ftst != dStkConj
&& ftst != dStkNeg
&& ftst != dStkAbs
&& ftst != dStkRecip
&& ftst != StkIdent
&& ftst != dStkGT
&& ftst != dStkGTE
&& ftst != dStkNE
&& ftst != dStkEQ
&& ftst != dStkAND
&& ftst != dStkOR ){
stopmsg(0, "Fast failure, using old code" );
return 1; /* Use old code */
}
}

#ifdef TESTFP
if (lastsqrused) {
stopmsg(0, "LastSqr used" );
}
else {
stopmsg(0, "LastSqr not used" );
}
#endif

if (f[LastOp-1] != StkClr ){ /* some formulas don't clear at the end! */
#ifdef TESTFP
stopmsg (0, "clr added at end" );
#endif
f[LastOp++] = StkClr;
}
prevfptr = (void (near *)(void))0;
prevstkcnt = 999; /* there was not previous stk cnt */
stkcnt = cvtptrx = 0;

for (OpPtr = LodPtr = StoPtr = 0; OpPtr < LastOp; OpPtr++) {
ftst = f[OpPtr];
if (ftst == StkLod ) {
#ifdef TESTFP
stopmsg(0, "lod,0,TWO_FREE,2" );
#endif
CvtFptr(fStkLod, 0, TWO_FREE, 2 );
continue;
}
if (ftst == StkClr ) {
if (OpPtr == LastOp - 1 ){
#ifdef TESTFP
stopmsg(0, "clr2,0,MAX_STACK,999" );
#endif
CvtFptr(fStkClr2, 0, MAX_STACK, 999 );
} else {
#ifdef TESTFP
stopmsg(0, "clr1,0,MAX_STACK,999" );
#endif
CvtFptr(fStkClr1, 0, MAX_STACK, 999 );
}
continue;
}
if (ftst == dStkAdd ) {
#ifdef TESTFP
stopmsg(0, "add,4,MAX_STACK,-2" );
#endif
CvtFptr(fStkAdd, 4, MAX_STACK, -2 );
continue;
}
if (ftst == dStkSub ) {
#ifdef TESTFP
stopmsg(0, "sub,4,MAX_STACK,-2" );
#endif
CvtFptr(fStkSub, 4, MAX_STACK, -2 );
continue;
}
if (ftst == dStkDiv ) {
#ifdef TESTFP
stopmsg(0, "div,4,TWO_FREE,-2" );
#endif
CvtFptr(fStkDiv, 4, TWO_FREE, -2 );
continue;
}
if (ftst == dStkMul ) {
#ifdef TESTFP
stopmsg(0, "mul,4,TWO_FREE,-2" );
#endif
CvtFptr(fStkMul, 4, TWO_FREE, -2 );
continue;
}
if (ftst == StkSto ) {
#ifdef TESTFP
stopmsg(0, "sto,2,MAX_STACK,0" );
#endif
CvtFptr(fStkSto, 2, MAX_STACK, 0 );
continue;
}
if (ftst == dStkSqr ) {
#ifdef TESTFP
stopmsg(0, "sqr,2,TWO_FREE,0" );
#endif
CvtFptr(fStkSqr, 2, TWO_FREE, 0 );
continue;
}
if (ftst == EndInit) {
#ifdef TESTFP
stopmsg(0, "endinit,0,MAX_STACK,999" );
#endif
CvtFptr(fStkEndInit, 0, MAX_STACK, 999 );
continue;
}
if (ftst == dStkMod ) {
#ifdef TESTFP
stopmsg(0, "mod,2,MAX_STACK,0" );
#endif
CvtFptr(fStkMod, 2, MAX_STACK, 0 );
continue;
}
if (ftst == dStkLTE ) {
#ifdef TESTFP
stopmsg(0, "LTE,4,MAX_STACK,-2" );
#endif
CvtFptr(fStkLTE, 4, MAX_STACK, -2 );
continue;
}
if (ftst == dStkSin ) {
#ifdef TESTFP
stopmsg(0, "sin,2,TWO_FREE,0" );
#endif
CvtFptr(fStkSin, 2, TWO_FREE, 0 );
continue;
}
if (ftst == dStkCos ) {
#ifdef TESTFP
stopmsg(0, "cos,2,TWO_FREE,0" );
#endif
CvtFptr(fStkCos, 2, TWO_FREE, 0 );
continue;
}
if (ftst == dStkSinh ) {
#ifdef TESTFP
stopmsg(0, "sinh,2,TWO_FREE,0" );
#endif
CvtFptr(fStkSinh, 2, TWO_FREE, 0 );
continue;
}
if (ftst == dStkCosh ) {
#ifdef TESTFP
stopmsg(0, "cosh,2,TWO_FREE,0" );
#endif
CvtFptr(fStkCosh, 2, TWO_FREE, 0 );
continue;
}
if (ftst == dStkCosXX ) {
#ifdef TESTFP
stopmsg(0, "cosxx,2,TWO_FREE,0" );
#endif
CvtFptr(fStkCosXX, 2, TWO_FREE, 0 );
continue;
}
if (ftst == dStkTan ) {
#ifdef TESTFP
stopmsg(0, "tan,2,TWO_FREE,0" );
#endif
CvtFptr(fStkTan, 2, TWO_FREE, 0 );
continue;
}
if (ftst == dStkTanh ) {
#ifdef TESTFP
stopmsg(0, "tanh,2,TWO_FREE,0" );
#endif
CvtFptr(fStkTanh, 2, TWO_FREE, 0 );
continue;
}
if (ftst == dStkCoTan ) {
#ifdef TESTFP
stopmsg(0, "cotan,2,TWO_FREE,0" );
#endif
CvtFptr(fStkCoTan, 2, TWO_FREE, 0 );
continue;
}
if (ftst == dStkCoTanh ) {
#ifdef TESTFP
stopmsg(0, "cotanh,2,TWO_FREE,0" );
#endif
CvtFptr(fStkCoTanh, 2, TWO_FREE, 0 );
continue;
}
if (ftst == dStkExp ) {
#ifdef TESTFP
stopmsg(0, "exp,2,TWO_FREE,0" );
#endif
CvtFptr(fStkExp, 2, TWO_FREE, 0 );
continue;
}
if (ftst == dStkLog ) {
#ifdef TESTFP
stopmsg(0, "log,2,TWO_FREE,0" );
#endif
CvtFptr(fStkLog, 2, TWO_FREE, 0 );
continue;
}
if (ftst == dStkPwr ) {
#ifdef TESTFP
stopmsg(0, "pwr,4,TWO_FREE,-2" );
#endif
CvtFptr(fStkPwr, 4, TWO_FREE, -2 );
continue;
}
if (ftst == dStkLT ) {
#ifdef TESTFP
stopmsg(0, "LT,4,MAX_STACK,-2" );
#endif
CvtFptr(fStkLT, 4, MAX_STACK, -2 );
continue;
}
if (ftst == dStkFlip ) {
#ifdef TESTFP
stopmsg(0, "flip,2,MAX_STACK,0" );
#endif
CvtFptr(fStkFlip, 2, MAX_STACK, 0 );
continue;
}
if (ftst == dStkReal ) {
#ifdef TESTFP
stopmsg(0, "real,2,MAX_STACK,0" );
#endif
CvtFptr(fStkReal, 2, MAX_STACK, 0 );
continue;
}
if (ftst == dStkImag ) {
#ifdef TESTFP
stopmsg(0, "imag,2,MAX_STACK,0" );
#endif
CvtFptr(fStkImag, 2, MAX_STACK, 0 );
continue;
}
if (ftst == dStkConj ) {
#ifdef TESTFP
stopmsg(0, "conj,2,MAX_STACK,0" );
#endif
CvtFptr(fStkConj, 2, MAX_STACK, 0 );
continue;
}
if (ftst == dStkNeg ) {
#ifdef TESTFP
stopmsg(0, "neg,2,MAX_STACK,0" );
#endif
CvtFptr(fStkNeg, 2, MAX_STACK, 0 );
continue;
}
if (ftst == dStkAbs ) {
#ifdef TESTFP
stopmsg(0, "abs,2,MAX_STACK,0" );
#endif
CvtFptr(fStkAbs, 2, MAX_STACK, 0 );
continue;
}
if (ftst == dStkRecip ) {
#ifdef TESTFP
stopmsg(0, "recip,2,TWO_FREE,0" );
#endif
CvtFptr(fStkRecip, 2, TWO_FREE, 0 );
continue;
}
if (ftst == StkIdent ) {
#ifdef TESTFP
stopmsg(0, "ident skipped" );
#endif
/* don't bother converting this one */
continue;
}
if (ftst == dStkGT ) {
#ifdef TESTFP
stopmsg(0, "GT,4,MAX_STACK,-2" );
#endif
CvtFptr(fStkGT, 4, MAX_STACK, -2 );
continue;
}
if (ftst == dStkGTE ) {
#ifdef TESTFP
stopmsg(0, "GTE,4,MAX_STACK,-2" );
#endif
CvtFptr(fStkGTE, 4, MAX_STACK, -2 );
continue;
}
if (ftst == dStkEQ ) {
#ifdef TESTFP
stopmsg(0, "EQ,4,MAX_STACK,-2" );
#endif
CvtFptr(fStkEQ, 4, MAX_STACK, -2 );
continue;
}
if (ftst == dStkNE ) {
#ifdef TESTFP
stopmsg(0, "NE,4,MAX_STACK,-2" );
#endif
CvtFptr(fStkNE, 4, MAX_STACK, -2 );
continue;
}
if (ftst == dStkOR ) {
#ifdef TESTFP
stopmsg(0, "OR,4,MAX_STACK,-2" );
#endif
CvtFptr(fStkOR, 4, MAX_STACK, -2 );
continue;
}
if (ftst == dStkAND ) {
#ifdef TESTFP
stopmsg(0, "AND,4,MAX_STACK,-2" );
#endif
CvtFptr(fStkAND, 4, MAX_STACK, -2 );
continue;
}
stopmsg(0, "Fast failure, using old code." );
return 1; /* this should never happen but is not fatal now */
}

if (debugflag == 322 ){
/* skip these optimizations too */
goto skipfinalopt;
} /* ---------------------------------- final optimizations ---- */

ntst = fgf(cvtptrx-2 ); /* cvtptrx -> one past last operator (clr2) */
if (ntst == fStkLT ){
#ifdef TESTFP
stopmsg (0, "LT Clr2 -> LT2" );
#endif
--cvtptrx;
fgf(cvtptrx-1) = fStkLT2;
}
else if (ntst == fStkLodLT ){
#ifdef TESTFP
stopmsg (0, "LodLT Clr2 -> LodLT2" );
#endif
--cvtptrx;
fgf(cvtptrx-1) = fStkLodLT2;
}
else if (ntst == fStkLTE ){
#ifdef TESTFP
stopmsg (0, "LTE Clr2 -> LTE2" );
#endif
--cvtptrx;
fgf(cvtptrx-1) = fStkLTE2;
}
else if (ntst == fStkLodLTE ){
#ifdef TESTFP
stopmsg (0, "LodLTE Clr2 -> LodLTE2" );
#endif
--cvtptrx;
fgf(cvtptrx-1) = fStkLodLTE2;
}
else if (ntst == fStkGT ){
#ifdef TESTFP
stopmsg (0, "GT Clr2 -> GT2" );
#endif
--cvtptrx;
fgf(cvtptrx-1) = fStkGT2;
}
else if (ntst == fStkLodGT ){
#ifdef TESTFP
stopmsg (0, "LodGT Clr2 -> LodGT2" );
#endif
--cvtptrx;
fgf(cvtptrx-1) = fStkLodGT2;
}
else if (ntst == fStkLodGTE ){
#ifdef TESTFP
stopmsg (0, "LodGTE Clr2 -> LodGTE2" );
#endif
--cvtptrx;
fgf(cvtptrx-1) = fStkLodGTE2;
}
else if (fgf(cvtptrx-2 ) == fStkAND ){
#ifdef TESTFP
stopmsg (0, "AND Clr2 -> ANDClr2" );
#endif
--cvtptrx;
fgf(cvtptrx-1) = fStkANDClr2;
ntst = fgf(cvtptrx-2);
if (ntst == fStkLodLTE ){
#ifdef TESTFP
stopmsg (0, "LodLTE ANDClr2 -> LodLTEAnd2" );
#endif
--cvtptrx;
fgf(cvtptrx-1) = fStkLodLTEAnd2;
}
}

skipfinalopt: /* ---------------- end of final optimizations ----- */

LastOp = cvtptrx; /* save the new operator count */
LastSqr.d.y = 0.0; /* do this once per image */

/* now change the pointers */
if (FormName[0] != 0 ){ /* but only if parse succeeded */
curfractalspecific->per_pixel = fform_per_pixel;
curfractalspecific->orbitcalc = fFormula;
}
else {
curfractalspecific->per_pixel = BadFormula;
curfractalspecific->orbitcalc = BadFormula;
}
Img_Setup(); /* call assembler setup code */
return 1;
}

#endif


  3 Responses to “Category : C Source Code
Archive   : FRASRC18.ZIP
Filename : PARSERFP.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/