home *** CD-ROM | disk | FTP | other *** search
/ Fractal Creations (Second Edition) / FRACTALS_2E.iso / frasrc.exe / PARSERFP.C < prev    next >
C/C++ Source or Header  |  1993-07-13  |  36KB  |  1,202 lines

  1. /* */
  2. /* PARSERFP.C  -- Part of FRACTINT fractal drawer. */
  3. /* */
  4. /*   By Chuck Ebbert  CompuServe [76306,1226] */
  5. /*                     internet: 76306.1226@compuserve.com  */
  6. /* */
  7. /* Fast floating-point parser code.  The functions beginning with */
  8. /*    "fStk" are in PARSERA.ASM.  PARSER.C calls this code after */
  9. /*    it has parsed the formula. */
  10. /* */
  11. /*   Converts the function pointers/load pointers/store pointers */
  12. /*       built by parsestr() into an optimized array of function */
  13. /*       pointer/operand pointer pairs. */
  14. /* */
  15. /* ******************************************************************* */
  16. /*                                                                     */
  17. /*  Copyright (C) 1992, 1993 Chuck Ebbert.  All rights reserved.       */
  18. /*                                                                     */
  19. /*    This code may be freely distributed and used in non-commercial   */
  20. /*    programs provided the author is credited either during program   */
  21. /*    execution or in the documentation, and this copyright notice     */
  22. /*    is left intact.  Sale of this code, or its use in any commercial */
  23. /*    product requires permission from the author.  Nominal            */
  24. /*    distribution and handling fees may be charged by shareware and   */
  25. /*    freeware distributors.                                           */
  26. /*                                                                     */
  27. /*       Chuck Ebbert                                                  */
  28. /*       1915 Blust Ln.                                                */
  29. /*       Enola, PA  17025                                              */
  30. /*                                                                     */
  31. /* ******************************************************************* */
  32. /* */
  33. /* Revised 12 July 1993 (for v18.1) by CAE to fix optimizer bug  */
  34. /* */
  35. /* Revised 22 MAR 1993 (for Fractint v18.0)  */
  36. /* */
  37. /* Uncomment the next line to enable debug. */
  38. /*      #define TESTFP 1  */
  39. /* */
  40.  
  41. #include <string.h>
  42. #include <ctype.h>
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <float.h>
  46. #include <time.h>
  47. #include "mpmath.h"
  48. #include "prototyp.h"
  49.  
  50. extern union Arg *Arg1, *Arg2;
  51. /* Some of these variables should be renamed for safety */
  52. extern union Arg s[20], far * far *Store, far * far *Load;
  53. extern int StoPtr, LodPtr, OpPtr;
  54. extern int debugflag;
  55. extern unsigned vsp, LastOp;
  56. extern struct ConstArg far *v;
  57. extern int inside;         /* "inside" color to use    */
  58. extern int outside;        /* "outside" color to use   */
  59. extern int potflag;        /* potential enabled? */
  60. extern char useinitorbit;
  61. extern int InitLodPtr, InitStoPtr, InitOpPtr, LastInitOp;
  62. extern void (far * far *f)(void);
  63.  
  64. struct fls { /* function, load, store pointers  CAE fp */
  65.    void (near *function)(void);
  66.    union Arg near *operand;
  67. } far *pfls = (struct fls far *)0;
  68.  
  69. void  StkLod(void);
  70. void  StkClr(void);
  71. void  dStkAdd(void);
  72. void  dStkSub(void);
  73. void  dStkMul(void);
  74. void  dStkDiv(void);
  75. void  StkSto(void);
  76. void  dStkSqr(void);
  77. void  EndInit(void);
  78. void  dStkMod(void);
  79. void  dStkLTE(void);
  80. void  dStkSin(void);
  81. void  dStkCos(void);
  82. void  dStkSinh(void);
  83. void  dStkCosh(void);
  84. void  dStkCosXX(void);
  85. void  dStkTan(void);
  86. void  dStkTanh(void);
  87. void  dStkCoTan(void);
  88. void  dStkCoTanh(void);
  89. void  dStkLog(void);
  90. void  dStkExp(void);
  91. void  dStkPwr(void);
  92. void  dStkLT(void);
  93. void  dStkFlip(void);
  94. void  dStkReal(void);
  95. void  dStkImag(void);
  96. void  dStkConj(void);
  97. void  dStkNeg(void);
  98. void  dStkAbs(void);
  99. void  dStkRecip(void);
  100. void  StkIdent(void);
  101. void  dStkGT(void);
  102. void  dStkGTE(void);
  103. void  dStkNE(void);
  104. void  dStkEQ(void);
  105. void  dStkAND(void);
  106. void  dStkOR(void);
  107.  
  108. #define fgf(x) pfls[(x)].function
  109. #define opp(x) pfls[(x)].operand
  110. #define NO_OPERAND (void near *)0
  111. #define LastSqr v[4].a
  112. #define MAX_ARGS 100
  113. #define MAX_STACK 8
  114. #define TWO_FREE 6
  115.  
  116. #ifndef XFRACT
  117.  
  118. void (near fStkPull2 )(void); /* pull up fpu stack from 2 to 4 */
  119. void (near fStkPush2 )(void); /* push down fpu stack from 8 to 6 */
  120. void (near fStkPush2a )(void); /* push down fpu stack from 6 to 4 */
  121. void (near fStkPush4 )(void); /* push down fpu stack from 8 to 4 */
  122. void (near fStkLodDup )(void); /* lod, dup */
  123. void (near fStkLodSqr )(void); /* lod, sqr, dont save magnitude */
  124. void (near fStkLodSqr2 )(void); /* lod, sqr, save magnitude */
  125. void (near fStkStoDup )(void); /* store, duplicate */
  126. void (near fStkStoSqr )(void); /* store, sqr, save lastsqr */
  127. void (near fStkStoSqr0 )(void); /* store, sqr, dont save lastsqr */
  128. void (near fStkLodDbl )(void); /* load, double */
  129. void (near fStkStoDbl )(void); /* store, double */
  130. void (near fStkReal2 )(void); /* fast ver. of real */
  131. void (near fStkSqr )(void); /* sqr, save magnitude in lastsqr */
  132. void (near fStkSqr0 )(void); /* sqr, no save magnitude */
  133. void (near fStkClr1 )(void); /* clear fpu */
  134. void (near fStkClr2 )(void); /* test stack top, clear fpu */
  135. void (near fStkStoClr1 )(void); /* store, clr1 */
  136. void (near fStkAdd )(void);
  137. void (near fStkSub )(void);
  138. void (near fStkSto )(void);
  139. void (near fStkSto2 )(void); /* fast ver. of sto */
  140. void (near fStkLod )(void);
  141. void (near fStkEndInit )(void);
  142. void (near fStkMod )(void);
  143. void (near fStkMod2 )(void);
  144. void (near fStkLodMod2 )(void);
  145. void (near fStkStoMod2 )(void);
  146. void (near fStkLTE )(void);
  147. void (near fStkLodLTEMul )(void);
  148. void (near fStkLTE2 )(void);
  149. void (near fStkLodLTE )(void);
  150. void (near fStkLodLTE2 )(void);
  151. void (near fStkLodLTEAnd2 )(void);
  152. void (near fStkLT )(void);
  153. void (near fStkLodLTMul )(void);
  154. void (near fStkLT2 )(void);
  155. void (near fStkLodLT )(void);
  156. void (near fStkLodLT2 )(void);
  157. void (near fStkGTE )(void);
  158. void (near fStkLodGTE )(void);
  159. void (near fStkLodGTE2 )(void);
  160. void (near fStkGT )(void);
  161. void (near fStkGT2 )(void);
  162. void (near fStkLodGT )(void);
  163. void (near fStkLodGT2 )(void);
  164. void (near fStkEQ )(void);
  165. void (near fStkLodEQ )(void);
  166. void (near fStkNE )(void);
  167. void (near fStkLodNE )(void);
  168. void (near fStkAND )(void);
  169. void (near fStkANDClr2 )(void);
  170. void (near fStkOR )(void);
  171. void (near fStkSin )(void);
  172. void (near fStkSinh )(void);
  173. void (near fStkCos )(void);
  174. void (near fStkCosXX )(void);
  175. void (near fStkCosh )(void);
  176. void (near fStkTan )(void);
  177. void (near fStkTanh )(void);
  178. void (near fStkCoTan )(void);
  179. void (near fStkCoTanh )(void);
  180. void (near fStkLog )(void);
  181. void (near fStkExp )(void);
  182. void (near fStkPwr )(void);
  183. void (near fStkMul )(void);
  184. void (near fStkDiv )(void);
  185. void (near fStkFlip )(void);
  186. void (near fStkReal )(void);
  187. void (near fStkImag )(void);
  188. void (near fStkRealFlip )(void);
  189. void (near fStkImagFlip )(void);
  190. void (near fStkConj )(void);
  191. void (near fStkNeg )(void);
  192. void (near fStkAbs )(void);
  193. void (near fStkRecip )(void);
  194. void (near fStkLodReal )(void);
  195. void (near fStkLodRealC )(void);
  196. void (near fStkLodImag )(void);
  197. void (near fStkLodRealFlip )(void);
  198. void (near fStkLodRealAbs )(void);
  199. void (near fStkLodRealMul )(void);
  200. void (near fStkLodRealAdd )(void);
  201. void (near fStkLodRealSub )(void);
  202. void (near fStkLodImagFlip )(void);
  203. void (near fStkLodImagAbs )(void);
  204. void (near fStkLodConj )(void);
  205. void (near fStkLodAdd )(void);
  206. void (near fStkLodSub )(void);
  207. void (near fStkLodSubMod )(void);
  208. void (near fStkLodMul )(void);
  209. void (near fStkPLodAdd )(void);
  210. void (near fStkPLodSub )(void);
  211. void (near Img_Setup )(void);
  212.  
  213.  
  214. static void (near *prevfptr )(void);
  215. static int stkcnt, prevstkcnt, cvtptrx, prevlodptr, lastsqrused;
  216.  
  217. static void CvtFptr(void (near * ffptr)(void), int MinStk, int MaxStk,
  218.       int Delta )
  219. /* (MinStk <= 4, MaxStk >= TWO_FREE) */
  220. {
  221.    char testconst = 0;
  222.  
  223.    if (stkcnt < MinStk ) { /* not enough operands on fpu stack */
  224. #ifdef TESTFP
  225.       stopmsg(0, "Inserted pull." );
  226. #endif
  227.       opp(cvtptrx) = NO_OPERAND;
  228.       fgf(cvtptrx++) = fStkPull2;  /* so adjust the stack, pull operand */
  229.       stkcnt += 2;
  230.    }
  231.    else if (stkcnt > MaxStk ) { /* too many operands */
  232. #ifdef TESTFP
  233.       stopmsg(0, "Inserted push." );
  234. #endif
  235.       opp(cvtptrx) = NO_OPERAND;
  236.       fgf(cvtptrx++) = fStkPush2;  /* push operand to adjust stack */
  237.       stkcnt -= 2;
  238.    }
  239.  
  240.    /* set the operand pointer here */
  241.    if (ffptr == fStkSto ){ /* this must be before test for load */
  242.       opp(cvtptrx) = (void near *)(Store[StoPtr++]);
  243.    }
  244.    else if (ffptr == fStkLod && debugflag == 322 ){
  245.       /* if disabling optimizer, set load pointer here */
  246.       opp(cvtptrx) = (void near *)(Load[LodPtr++]);
  247.    }
  248.    else {
  249.       opp(cvtptrx) = NO_OPERAND;
  250.    }
  251.  
  252.    if (debugflag == 322 ){
  253.       goto SkipOptimizer;
  254.    } /* --------------------------  begin optimizer  -------------- */
  255.  
  256.    /* For the following: */
  257.    /*   * == cvtptrx points to this */
  258.    /*  () == this is about to be added to the array */
  259.  
  260.    if (ffptr == fStkLod) { /* we are about to add Lod to the array */
  261.       if (prevfptr == fStkLod && Load[LodPtr-1] == Load[LodPtr] ) {
  262.          /* previous non-adjust operator was Lod of same operand */
  263.          /* i.e. found {? lodx ? (*lodx) } */
  264.          if (fgf(--cvtptrx) == fStkPush2 ){ /* prev fn was push */
  265.             /* {? lod *push (lod) } */
  266.             --cvtptrx; /* found {? *lod push (lod) } */
  267.             if (fgf(cvtptrx-1) == fStkPush2){ /* always more ops here */
  268. #ifdef TESTFP
  269.                stopmsg(0, "push *lod push (lod) -> push4 (*loddup)" );
  270. #endif
  271.                fgf(cvtptrx-1) = fStkPush4;
  272.             }
  273.             else { /* prev op not push */
  274. #ifdef TESTFP
  275.                stopmsg(0, "op *lod push (lod) -> op pusha(p=0) (*loddup)" );
  276. #endif
  277.                opp(cvtptrx) = NO_OPERAND; /* use 'alternate' push fn. */
  278.                fgf(cvtptrx++) = fStkPush2a; /* push with TWO_FREE on stack */
  279.                /* operand ptr will be set below */
  280.             }
  281.          }
  282.          else {  /* never {push *lod (lod) } so must be */
  283. #ifdef TESTFP
  284.             stopmsg(0, "op *lod (lod) -> op (*loddup)" );
  285. #endif
  286.          }
  287.          ffptr = fStkLodDup;
  288.       }
  289.       else if (prevfptr == fStkSto2
  290.                && Store[StoPtr-1] == Load[LodPtr] ){
  291.          /* store, load of same value */
  292.          /* only one operand on stack here when prev oper is Sto2 */
  293.          --cvtptrx;
  294. #ifdef TESTFP
  295.          stopmsg(0, "*sto2 (lod) -> (*stodup)" );
  296. #endif
  297.          ffptr = fStkStoDup;
  298.       }
  299.       /* This may cause roundoff problems when later operators */
  300.       /*  use the rounded value that was stored here, while the next */
  301.       /*  operator uses the more accurate internal value. */
  302.       else if (prevfptr == fStkStoClr1 && prevstkcnt == 2
  303.                && Store[StoPtr-1] == Load[LodPtr] ){
  304.          /* store, clear, load same value found */
  305.          /* only one operand was on stack so this is safe */
  306.          --cvtptrx;
  307. #ifdef TESTFP
  308.          stopmsg (0, "*StoClr1 (Lod) -> (*Sto2)" );
  309. #endif
  310.          ffptr = fStkSto2; /* use different Sto fn */
  311.       }
  312.       else {
  313.          /* the really awful hack below gets the first char of the name */
  314.          /*    of the variable being loaded */
  315.          testconst = **(((char * far *)Load[LodPtr] ) - 2 );
  316.          if ( !isalpha(testconst) && Load[LodPtr]->d.y == 0.0 ){
  317.             /* if first character not alpha, the var is a constant */
  318. #ifdef TESTFP
  319.             stopmsg (0, "(*lod) -> (*lodrealc)" );
  320. #endif
  321.             ffptr = fStkLodRealC; /* a real const is being loaded */
  322.          }
  323.       }
  324.       /* set the operand ptr here */
  325.       opp(cvtptrx) = (void near *)(Load[LodPtr++]);
  326.    }
  327.    else if (ffptr == fStkAdd ){
  328.       if (prevfptr == fStkLodDup ){ /* there is never a push before add */
  329.          --cvtptrx; /* found {? *loddup (add) } */
  330.          if (cvtptrx>0 && fgf(cvtptrx-1) == fStkPush2a ){
  331.             /* because {push lod lod } impossible so is {push loddup } */
  332. #ifdef TESTFP
  333.             stopmsg (0, "pusha *loddup (add) -> (*loddbl),stk+=2" );
  334. #endif
  335.             --cvtptrx;
  336.             opp(cvtptrx) = opp(cvtptrx+1); /* fix opptr */
  337.             stkcnt += 2;
  338.          }
  339.          else if (cvtptrx>0 && fgf(cvtptrx-1) == fStkPush4 ){
  340. #ifdef TESTFP
  341.             stopmsg (0, "push4 *loddup (add) -> push2 (*loddbl),stk+=2" );
  342. #endif
  343.             fgf(cvtptrx-1) = fStkPush2;
  344.             stkcnt += 2;  /*  CAE added 12 July 1993 to fix bug  */
  345.          }
  346.          else {
  347. #ifdef TESTFP
  348.             stopmsg (0, "op *loddup (add) -> {op (*loddbl)" );
  349. #endif
  350.          }
  351.          ffptr = fStkLodDbl;
  352.       }
  353.       else if (prevfptr == fStkStoDup ){
  354. #ifdef TESTFP
  355.          stopmsg (0, "stodup (add) -> (stodbl)" );
  356. #endif
  357.          /* there are always exactly 4 on stack here */
  358.          --cvtptrx;
  359.          ffptr = fStkStoDbl;
  360.       }
  361.       else if (prevfptr == fStkLod ){ /* have found {lod (*add) } */
  362.          --cvtptrx;    /* {? *lod (add) } */
  363.          if (fgf(cvtptrx-1) == fStkPush2 ){
  364. #ifdef TESTFP
  365.             stopmsg (0, "*push load (add) -> (*plodadd),stk+=2" );
  366. #endif
  367.             --cvtptrx;
  368.             stkcnt += 2; /* eliminated a push */
  369.             opp(cvtptrx) = opp(cvtptrx+1); /* fix opptrs */
  370.             ffptr = fStkPLodAdd;
  371.          }
  372.          else {
  373. #ifdef TESTFP
  374.             stopmsg (0, "op *lod (add) -> op (*lodadd)" );
  375. #endif
  376.             ffptr = fStkLodAdd;
  377.          }
  378.       }
  379.       else if (prevfptr == fStkLodReal || prevfptr == fStkLodRealC ){
  380.          --cvtptrx; /* found {? *lodreal (add) } */
  381.          if (fgf(cvtptrx-1) == fStkPush2 ){
  382. #ifdef TESTFP
  383.          stopmsg (0, "*push lodreal (add) -> (*lodrealadd),stk+=2" );
  384. #endif
  385.             --cvtptrx;
  386.             stkcnt += 2;    /* push eliminated */
  387.             opp(cvtptrx) = opp(cvtptrx+1); /* fix opptrs */
  388.          }
  389.          else {
  390. #ifdef TESTFP
  391.             stopmsg (0, "*lodreal (add) -> (*lodrealadd)" );
  392. #endif
  393.          }
  394.          ffptr = fStkLodRealAdd;
  395.       }
  396.    }
  397.    else if (ffptr == fStkSub ){
  398.       if (prevfptr == fStkLod ){
  399.          /* found {lod (*sub) } */
  400.          --cvtptrx; /* {*lod (sub) } */
  401.          /* there is never a sequence (lod push sub ) */
  402.          if (fgf(cvtptrx-1) == fStkPush2 ){
  403. #ifdef TESTFP
  404.             stopmsg (0, "*push lod (sub) -> (*plodsub),stk+=2" );
  405. #endif
  406.             --cvtptrx;
  407.             opp(cvtptrx) = opp(cvtptrx+1); /* fix opptrs */
  408.             stkcnt += 2; /* push was deleted so adj. stkcnt */
  409.             ffptr = fStkPLodSub;
  410.          }
  411.          else {
  412. #ifdef TESTFP
  413.             stopmsg (0, "*lod (sub) -> (*lodsub)" );
  414. #endif
  415.             ffptr = fStkLodSub;
  416.          }
  417.       }
  418.       else if (prevfptr == fStkLodReal || prevfptr == fStkLodRealC ){
  419.          --cvtptrx; /* {? *lodreal (sub) } */
  420.          if (fgf(cvtptrx-1) == fStkPush2 ){
  421. #ifdef TESTFP
  422.             stopmsg (0, "*push lodreal (sub) -> (*lodrealsub),stk+=2" );
  423. #endif
  424.             --cvtptrx;
  425.             stkcnt += 2;    /* push eliminated */
  426.             opp(cvtptrx) = opp(cvtptrx+1); /* fix opptrs */
  427.          }
  428.          else {
  429. #ifdef TESTFP
  430.             stopmsg (0, "*lodreal (sub) -> (*lodrealsub)" );
  431. #endif
  432.          }
  433.          ffptr = fStkLodRealSub;
  434.       }
  435.    }
  436.    else if (ffptr == fStkMul ){
  437.       if (prevfptr == fStkLodDup ){
  438.          /* found {loddup ? (*mul) } */
  439.          if (fgf(--cvtptrx) == fStkPush2 ){
  440. #ifdef TESTFP
  441.             stopmsg (0, "loddup *push (mul) -> (*lodsqr),stk+=2" );
  442. #endif
  443.             stkcnt += 2; /* eliminate this push */
  444.             --cvtptrx;    /* prev is a LodDup */
  445.          }
  446.          else {
  447. #ifdef TESTFP
  448.             stopmsg (0, "*loddup (mul) -> (*lodsqr)" );
  449. #endif
  450.          }
  451.          ffptr = fStkLodSqr;
  452.       }
  453.       else if (prevfptr == fStkStoDup ){ /* no pushes here, 4 on stk. */
  454. #ifdef TESTFP
  455.          stopmsg (0, "stodup (mul) -> (*stosqr0)" );
  456. #endif
  457.          --cvtptrx;
  458.          ffptr = fStkStoSqr0; /* dont save lastsqr here ever */
  459.       }
  460.       else if (prevfptr == fStkLod ){
  461.          --cvtptrx; /* {lod *? (mul) } */
  462.          if (fgf(cvtptrx) == fStkPush2 ){ /* {lod *push (mul) } */
  463.             --cvtptrx; /* {? *lod push (mul) } */
  464.             if(fgf(cvtptrx-1) == fStkPush2 ){
  465. #ifdef TESTFP
  466.                stopmsg (0, "push *lod push (mul) -> push4 (*lodmul)" );
  467. #endif
  468.                fgf(cvtptrx-1) = fStkPush4;
  469.             }
  470.             else {
  471. #ifdef TESTFP
  472.                stopmsg (0, "op *lod push (mul) -> op pusha (*lodmul)" );
  473. #endif
  474.                opp(cvtptrx+1) = opp(cvtptrx); /* fix operand ptr */
  475.                fgf(cvtptrx) = fStkPush2a;
  476.                opp(cvtptrx++) = NO_OPERAND;
  477.             }
  478.          }
  479.          else {
  480. #ifdef TESTFP
  481.             stopmsg (0, "*lod (mul) -> (*lodmul)" );
  482. #endif
  483.          }
  484.          ffptr = fStkLodMul;
  485.       }
  486.       else if (prevfptr == fStkLodReal || prevfptr == fStkLodRealC ){
  487.          --cvtptrx; /* found {lodreal *? (mul) } */
  488.          if (fgf(cvtptrx) == fStkPush2 ){
  489. #ifdef TESTFP
  490.             stopmsg (0, "lodreal *push2 (mul) -> (*lodrealmul),stk+=2" );
  491. #endif
  492.             --cvtptrx;
  493.             stkcnt += 2;    /* stack ends with TWO_FREE, not 4 */
  494.          }
  495.          else {
  496. #ifdef TESTFP
  497.             stopmsg (0, "*lodreal (mul) }-> {(*lodrealmul)" );
  498. #endif
  499.          }
  500.          ffptr = fStkLodRealMul;
  501.       }
  502.       else if (prevfptr == fStkLodLT && fgf(cvtptrx-1) != fStkPull2 ){
  503.          /* this shortcut fails if {Lod LT Pull Mul } found */
  504. #ifdef TESTFP
  505.          stopmsg (0, "LodLT (*Mul) -> (*LodLTMul)" );
  506. #endif
  507.          --cvtptrx; /* never { lod LT Push Mul } here */
  508.          ffptr = fStkLodLTMul;
  509.       }
  510.       else if (prevfptr == fStkLodLTE && fgf(cvtptrx-1) != fStkPull2 ){
  511. #ifdef TESTFP
  512.          stopmsg (0, "LodLTE (*mul) -> (*LodLTEmul)" );
  513. #endif
  514.          --cvtptrx;
  515.          ffptr = fStkLodLTEMul;
  516.       }
  517.    }
  518.    else if (ffptr == fStkClr1 && prevfptr == fStkSto ){
  519. #ifdef TESTFP
  520.          stopmsg (0, "sto (*clr1) -> (*stoclr1)" );
  521. #endif
  522.       --cvtptrx;
  523.       ffptr = fStkStoClr1;
  524.    }
  525.    else if (ffptr == fStkDiv ){
  526.       if (prevfptr == fStkLodRealC && vsp < MAX_ARGS - 1 ){
  527.          /* have found a divide by a real constant */
  528.          /*  and there is space to create a new one */
  529.          /* {lodrealc ? (*div) } */
  530.          --cvtptrx; /* change '/ const' to '* 1/const' */
  531.          if (fgf(cvtptrx) == fStkPush2 ){
  532. #ifdef TESTFP
  533.             stopmsg (0, "lodrealc *push (div) -> (*lodrealmul),stk+=2" );
  534. #endif
  535.             --cvtptrx;
  536.             stkcnt += 2;
  537.          }
  538.          else {
  539. #ifdef TESTFP
  540.             stopmsg (0, "*lodrealc (div) -> {(*lodrealmul)" );
  541. #endif
  542.          }
  543.          v[vsp].s = (void near *)0; /* this constant has no name */
  544.          v[vsp].len = 0;
  545.          v[vsp].a.d.x = 1.0 / Load[LodPtr-1]->d.x;
  546.          v[vsp].a.d.y = 0.0;
  547.          opp(cvtptrx) = (void near *)&v[vsp++].a; /* isn't C fun! */
  548.          ffptr = fStkLodRealMul;
  549.       }
  550.    }
  551.    else if (ffptr == fStkReal ){
  552.       if (prevfptr == fStkLod ){
  553. #ifdef TESTFP
  554.          stopmsg (0, "lod (*real) -> (*lodreal)" );
  555. #endif
  556.          --cvtptrx;
  557.          ffptr = fStkLodReal;
  558.       }
  559.       else if (stkcnt < MAX_STACK ){
  560. #ifdef TESTFP
  561.          stopmsg (0, "(*real) -> (*real2)" );
  562. #endif
  563.          ffptr = fStkReal2;
  564.       }
  565.    }
  566.    else if (ffptr == fStkImag && prevfptr == fStkLod ){
  567. #ifdef TESTFP
  568.          stopmsg (0, "lod (*imag) -> lodimag" );
  569. #endif
  570.       --cvtptrx;
  571.       ffptr = fStkLodImag;
  572.    }
  573.    else if (ffptr == fStkConj && prevfptr == fStkLod ){
  574. #ifdef TESTFP
  575.          stopmsg (0, "lod (*conj) -> (*lodconj)" );
  576. #endif
  577.       --cvtptrx;
  578.       ffptr = fStkLodConj;
  579.    }
  580.    else if (ffptr == fStkMod && stkcnt < MAX_STACK ){
  581. #ifdef TESTFP
  582.       stopmsg (0, "(*mod) -> (*mod2)" );
  583. #endif
  584.       ffptr = fStkMod2; /* use faster version if room on stack */
  585.       if (prevfptr == fStkLod ){
  586. #ifdef TESTFP
  587.          stopmsg (0, "lod (*mod2) -> (*lodmod2)" );
  588. #endif
  589.          --cvtptrx;
  590.          ffptr = fStkLodMod2;
  591.       }
  592.       else if (prevfptr == fStkSto || prevfptr == fStkSto2 ){
  593. #ifdef TESTFP
  594.          stopmsg (0, "sto (*mod2) -> (*stomod2)" );
  595. #endif
  596.          --cvtptrx;
  597.          ffptr = fStkStoMod2;
  598.       }
  599.       else if (prevfptr == fStkLodSub ){
  600. #ifdef TESTFP
  601.          stopmsg (0, "lodsub (*mod2) -> (*lodsubmod)" );
  602. #endif
  603.          --cvtptrx;
  604.          ffptr = fStkLodSubMod;
  605.       }
  606.    }
  607.    else if (ffptr == fStkFlip ){
  608.       if (prevfptr == fStkReal || prevfptr == fStkReal2 ){
  609. #ifdef TESTFP
  610.          stopmsg (0, "real (*flip) -> (*realflip)" );
  611. #endif
  612.          --cvtptrx;
  613.          ffptr = fStkRealFlip;
  614.       }
  615.       else if (prevfptr == fStkImag ){
  616. #ifdef TESTFP
  617.          stopmsg (0, "imag (*flip) -> (*imagflip)" );
  618. #endif
  619.          --cvtptrx;
  620.          ffptr = fStkImagFlip;
  621.       }
  622.       else if (prevfptr == fStkLodReal ){
  623. #ifdef TESTFP
  624.          stopmsg (0, "lodreal (*flip) -> (*lodrealflip)" );
  625. #endif
  626.          --cvtptrx;
  627.          ffptr = fStkLodRealFlip;
  628.       }
  629.       else if (prevfptr == fStkLodImag ){
  630. #ifdef TESTFP
  631.          stopmsg (0, "lodimag (*flip) -> (*lodimagflip)" );
  632. #endif
  633.          --cvtptrx;
  634.          ffptr = fStkLodImagFlip;
  635.       }
  636.    }
  637.    else if (ffptr == fStkAbs ){
  638.       if (prevfptr == fStkLodReal ){
  639. #ifdef TESTFP
  640.          stopmsg (0, "lodreal (*abs) -> (*lodrealabs)" );
  641. #endif
  642.          --cvtptrx;
  643.          ffptr = fStkLodRealAbs;
  644.       }
  645.       else if (prevfptr == fStkLodImag ){
  646. #ifdef TESTFP
  647.          stopmsg (0, "lodimag (*abs) -> (*lodimagabs)" );
  648. #endif
  649.          --cvtptrx;
  650.          ffptr = fStkLodImagAbs;
  651.       }
  652.    }
  653.    else if (ffptr == fStkSqr ){
  654.       if (prevfptr == fStkLod && fgf(cvtptrx-1) != fStkPush2 ){
  655. #ifdef TESTFP
  656.          stopmsg (0, "lod (*sqr) -> (*lodsqr)" );
  657. #endif
  658.          --cvtptrx;
  659.          ffptr = fStkLodSqr; /* assume no need to save lastsqr */
  660.          if (lastsqrused) {
  661. #ifdef TESTFP
  662.             stopmsg (0, "(*lodsqr) -> (*lodsqr2)" );
  663. #endif
  664.             ffptr = fStkLodSqr2; /* lastsqr is being used */
  665.          }
  666.       }
  667.       else if (prevfptr == fStkSto2 ){
  668. #ifdef TESTFP
  669.          stopmsg (0, "sto2 (*sqr) -> (*stosqr0)" );
  670. #endif
  671.          --cvtptrx;
  672.          ffptr = fStkStoSqr0; /* assume no need to save lastsqr */
  673.          if (lastsqrused) {
  674. #ifdef TESTFP
  675.             stopmsg (0, "(*stosqr0) -> (*stosqr)" );
  676. #endif
  677.             ffptr = fStkStoSqr; /* save lastsqr */
  678.          }
  679.       }
  680.       else {
  681.          if (!lastsqrused) {
  682. #ifdef TESTFP
  683.             stopmsg (0, "(*sqr) -> (*sqr0)" );
  684. #endif
  685.             ffptr = fStkSqr0; /* don't save lastsqr */
  686.          }
  687.       }
  688.    }
  689.    else if (ffptr == fStkLTE && ( prevfptr == fStkLod
  690.          || prevfptr == fStkLodReal || prevfptr == fStkLodRealC ) ){
  691. #ifdef TESTFP
  692.       stopmsg(0, "Lod (*LTE) -> (*LodLTE)" );
  693. #endif
  694.       --cvtptrx;
  695.       ffptr = fStkLodLTE;
  696.    }
  697.    else if (ffptr == fStkLT && ( prevfptr == fStkLod
  698.          || prevfptr == fStkLodReal || prevfptr == fStkLodRealC ) ){
  699. #ifdef TESTFP
  700.       stopmsg(0, "Lod (*LT) -> (*LodLT)" );
  701. #endif
  702.       --cvtptrx;
  703.       ffptr = fStkLodLT;
  704.    }
  705.    else if (ffptr == fStkGT && ( prevfptr == fStkLod
  706.          || prevfptr == fStkLodReal || prevfptr == fStkLodRealC ) ){
  707. #ifdef TESTFP
  708.       stopmsg(0, "Lod (*GT) -> (*LodGT)" );
  709. #endif
  710.       --cvtptrx;
  711.       ffptr = fStkLodGT;
  712.    }
  713.    else if (ffptr == fStkGTE && ( prevfptr == fStkLod
  714.          || prevfptr == fStkLodReal || prevfptr == fStkLodRealC ) ){
  715. #ifdef TESTFP
  716.       stopmsg(0, "Lod (*GTE) -> (*LodGTE)" );
  717. #endif
  718.       --cvtptrx;
  719.       ffptr = fStkLodGTE;
  720.    }
  721.    else if (ffptr == fStkNE && ( prevfptr == fStkLod
  722.          || prevfptr == fStkLodReal || prevfptr == fStkLodRealC ) ){
  723. #ifdef TESTFP
  724.       stopmsg(0, "Lod (*NE) -> (*LodNE)" );
  725. #endif
  726.       --cvtptrx;
  727.       ffptr = fStkLodNE;
  728.    }
  729.    else if (ffptr == fStkEQ && ( prevfptr == fStkLod
  730.          || prevfptr == fStkLodReal || prevfptr == fStkLodRealC ) ){
  731. #ifdef TESTFP
  732.       stopmsg(0, "Lod (*EQ) -> (*LodEQ)" );
  733. #endif
  734.       --cvtptrx;
  735.       ffptr = fStkLodEQ;
  736.    }
  737.  
  738. SkipOptimizer:  /* -----------  end of optimizer code  ------------ */
  739.  
  740.    fgf(cvtptrx++) = prevfptr = ffptr;
  741.    prevstkcnt = stkcnt;
  742.  
  743.    if (Delta == 999 ){
  744.       stkcnt = 0;
  745.    }
  746.    else {
  747.       stkcnt += Delta;
  748.    }
  749.    return;
  750. }
  751.  
  752. int CvtStk() {    /* convert the array of ptrs */
  753.    extern int fform_per_pixel(void);    /* these fns are in parsera.asm */
  754.    extern int fFormula(void);
  755.    extern int BadFormula(void);
  756.    extern char FormName[];
  757.    void (far *ftst)(void);
  758.    void (near *ntst)(void);
  759.  
  760. #ifdef TESTFP
  761.    if (debugflag == 322) {
  762.       stopmsg(0, "Skipping optimizer." );
  763.    }
  764. #endif
  765.  
  766.    for (OpPtr = LodPtr = lastsqrused = 0; OpPtr < LastOp; OpPtr++) {
  767.       ftst = f[OpPtr];
  768.       if (ftst == StkLod && Load[LodPtr++] == &LastSqr ){
  769.          lastsqrused = 1; /* lastsqr is being used in the formula */
  770.       }
  771.       if (  ftst != StkLod  /* these are the supported parser fns */
  772.             && ftst != StkClr
  773.             && ftst != dStkAdd
  774.             && ftst != dStkSub
  775.             && ftst != dStkMul
  776.             && ftst != dStkDiv
  777.             && ftst != StkSto
  778.             && ftst != dStkSqr
  779.             && ftst != EndInit
  780.             && ftst != dStkMod
  781.             && ftst != dStkLTE
  782.             && ftst != dStkSin
  783.             && ftst != dStkCos
  784.             && ftst != dStkSinh
  785.             && ftst != dStkCosh
  786.             && ftst != dStkCosXX
  787.             && ftst != dStkTan
  788.             && ftst != dStkTanh
  789.             && ftst != dStkCoTan
  790.             && ftst != dStkCoTanh
  791.             && ftst != dStkLog
  792.             && ftst != dStkExp
  793.             && ftst != dStkPwr
  794.             && ftst != dStkLT
  795.             && ftst != dStkFlip
  796.             && ftst != dStkReal
  797.             && ftst != dStkImag
  798.             && ftst != dStkConj
  799.             && ftst != dStkNeg
  800.             && ftst != dStkAbs
  801.             && ftst != dStkRecip
  802.             && ftst != StkIdent
  803.             && ftst != dStkGT
  804.             && ftst != dStkGTE
  805.             && ftst != dStkNE
  806.             && ftst != dStkEQ
  807.             && ftst != dStkAND
  808.             && ftst != dStkOR ){
  809.          stopmsg(0, "Fast failure, using old code" );
  810.          return 1; /* Use old code */
  811.       }
  812.    }
  813.  
  814. #ifdef TESTFP
  815.    if (lastsqrused) {
  816.       stopmsg(0, "LastSqr used" );
  817.    }
  818.    else {
  819.       stopmsg(0, "LastSqr not used" );
  820.    }
  821. #endif
  822.  
  823.    if (f[LastOp-1] != StkClr ){ /* some formulas don't clear at the end! */
  824. #ifdef TESTFP
  825.       stopmsg (0, "clr added at end" );
  826. #endif
  827.       f[LastOp++] = StkClr;
  828.    }
  829.    prevfptr = (void (near *)(void))0;
  830.    prevstkcnt = 999; /* there was not previous stk cnt */
  831.    stkcnt = cvtptrx = 0;
  832.  
  833.    for (OpPtr = LodPtr = StoPtr = 0; OpPtr < LastOp; OpPtr++) {
  834.       ftst = f[OpPtr];
  835.       if (ftst == StkLod ) {
  836. #ifdef TESTFP
  837.          stopmsg(0, "lod,0,TWO_FREE,2" );
  838. #endif
  839.          CvtFptr(fStkLod, 0, TWO_FREE, 2 );
  840.          continue;
  841.       }
  842.       if (ftst == StkClr ) {
  843.          if (OpPtr == LastOp - 1 ){
  844. #ifdef TESTFP
  845.             stopmsg(0, "clr2,0,MAX_STACK,999" );
  846. #endif
  847.             CvtFptr(fStkClr2, 0, MAX_STACK, 999 );
  848.          } else {
  849. #ifdef TESTFP
  850.             stopmsg(0, "clr1,0,MAX_STACK,999" );
  851. #endif
  852.             CvtFptr(fStkClr1, 0, MAX_STACK, 999 );
  853.          }
  854.          continue;
  855.       }
  856.       if (ftst == dStkAdd ) {
  857. #ifdef TESTFP
  858.          stopmsg(0, "add,4,MAX_STACK,-2" );
  859. #endif
  860.          CvtFptr(fStkAdd, 4, MAX_STACK, -2 );
  861.          continue;
  862.       }
  863.       if (ftst == dStkSub ) {
  864. #ifdef TESTFP
  865.          stopmsg(0, "sub,4,MAX_STACK,-2" );
  866. #endif
  867.          CvtFptr(fStkSub, 4, MAX_STACK, -2 );
  868.          continue;
  869.       }
  870.       if (ftst == dStkDiv ) {
  871. #ifdef TESTFP
  872.          stopmsg(0, "div,4,TWO_FREE,-2" );
  873. #endif
  874.          CvtFptr(fStkDiv, 4, TWO_FREE, -2 );
  875.          continue;
  876.       }
  877.       if (ftst == dStkMul ) {
  878. #ifdef TESTFP
  879.          stopmsg(0, "mul,4,TWO_FREE,-2" );
  880. #endif
  881.          CvtFptr(fStkMul, 4, TWO_FREE, -2 );
  882.          continue;
  883.       }
  884.       if (ftst == StkSto ) {
  885. #ifdef TESTFP
  886.          stopmsg(0, "sto,2,MAX_STACK,0" );
  887. #endif
  888.          CvtFptr(fStkSto, 2, MAX_STACK, 0 );
  889.          continue;
  890.       }
  891.       if (ftst == dStkSqr ) {
  892. #ifdef TESTFP
  893.          stopmsg(0, "sqr,2,TWO_FREE,0" );
  894. #endif
  895.          CvtFptr(fStkSqr, 2, TWO_FREE, 0 );
  896.          continue;
  897.       }
  898.       if (ftst == EndInit) {
  899. #ifdef TESTFP
  900.          stopmsg(0, "endinit,0,MAX_STACK,999" );
  901. #endif
  902.          CvtFptr(fStkEndInit, 0, MAX_STACK, 999 );
  903.          continue;
  904.       }
  905.       if (ftst == dStkMod ) {
  906. #ifdef TESTFP
  907.          stopmsg(0, "mod,2,MAX_STACK,0" );
  908. #endif
  909.          CvtFptr(fStkMod, 2, MAX_STACK, 0 );
  910.          continue;
  911.       }
  912.       if (ftst == dStkLTE ) {
  913. #ifdef TESTFP
  914.          stopmsg(0, "LTE,4,MAX_STACK,-2" );
  915. #endif
  916.          CvtFptr(fStkLTE, 4, MAX_STACK, -2 );
  917.          continue;
  918.       }
  919.       if (ftst == dStkSin ) {
  920. #ifdef TESTFP
  921.          stopmsg(0, "sin,2,TWO_FREE,0" );
  922. #endif
  923.          CvtFptr(fStkSin, 2, TWO_FREE, 0 );
  924.          continue;
  925.       }
  926.       if (ftst == dStkCos ) {
  927. #ifdef TESTFP
  928.          stopmsg(0, "cos,2,TWO_FREE,0" );
  929. #endif
  930.          CvtFptr(fStkCos, 2, TWO_FREE, 0 );
  931.          continue;
  932.       }
  933.       if (ftst == dStkSinh ) {
  934. #ifdef TESTFP
  935.          stopmsg(0, "sinh,2,TWO_FREE,0" );
  936. #endif
  937.          CvtFptr(fStkSinh, 2, TWO_FREE, 0 );
  938.          continue;
  939.       }
  940.       if (ftst == dStkCosh ) {
  941. #ifdef TESTFP
  942.          stopmsg(0, "cosh,2,TWO_FREE,0" );
  943. #endif
  944.          CvtFptr(fStkCosh, 2, TWO_FREE, 0 );
  945.          continue;
  946.       }
  947.       if (ftst == dStkCosXX ) {
  948. #ifdef TESTFP
  949.          stopmsg(0, "cosxx,2,TWO_FREE,0" );
  950. #endif
  951.          CvtFptr(fStkCosXX, 2, TWO_FREE, 0 );
  952.          continue;
  953.       }
  954.       if (ftst == dStkTan ) {
  955. #ifdef TESTFP
  956.          stopmsg(0, "tan,2,TWO_FREE,0" );
  957. #endif
  958.          CvtFptr(fStkTan, 2, TWO_FREE, 0 );
  959.          continue;
  960.       }
  961.       if (ftst == dStkTanh ) {
  962. #ifdef TESTFP
  963.          stopmsg(0, "tanh,2,TWO_FREE,0" );
  964. #endif
  965.          CvtFptr(fStkTanh, 2, TWO_FREE, 0 );
  966.          continue;
  967.       }
  968.       if (ftst == dStkCoTan ) {
  969. #ifdef TESTFP
  970.          stopmsg(0, "cotan,2,TWO_FREE,0" );
  971. #endif
  972.          CvtFptr(fStkCoTan, 2, TWO_FREE, 0 );
  973.          continue;
  974.       }
  975.       if (ftst == dStkCoTanh ) {
  976. #ifdef TESTFP
  977.          stopmsg(0, "cotanh,2,TWO_FREE,0" );
  978. #endif
  979.          CvtFptr(fStkCoTanh, 2, TWO_FREE, 0 );
  980.          continue;
  981.       }
  982.       if (ftst == dStkExp ) {
  983. #ifdef TESTFP
  984.          stopmsg(0, "exp,2,TWO_FREE,0" );
  985. #endif
  986.          CvtFptr(fStkExp, 2, TWO_FREE, 0 );
  987.          continue;
  988.       }
  989.       if (ftst == dStkLog ) {
  990. #ifdef TESTFP
  991.          stopmsg(0, "log,2,TWO_FREE,0" );
  992. #endif
  993.          CvtFptr(fStkLog, 2, TWO_FREE, 0 );
  994.          continue;
  995.       }
  996.       if (ftst == dStkPwr ) {
  997. #ifdef TESTFP
  998.          stopmsg(0, "pwr,4,TWO_FREE,-2" );
  999. #endif
  1000.          CvtFptr(fStkPwr, 4, TWO_FREE, -2 );
  1001.          continue;
  1002.       }
  1003.       if (ftst == dStkLT ) {
  1004. #ifdef TESTFP
  1005.          stopmsg(0, "LT,4,MAX_STACK,-2" );
  1006. #endif
  1007.          CvtFptr(fStkLT, 4, MAX_STACK, -2 );
  1008.          continue;
  1009.       }
  1010.       if (ftst == dStkFlip ) {
  1011. #ifdef TESTFP
  1012.          stopmsg(0, "flip,2,MAX_STACK,0" );
  1013. #endif
  1014.          CvtFptr(fStkFlip, 2, MAX_STACK, 0 );
  1015.          continue;
  1016.       }
  1017.       if (ftst == dStkReal ) {
  1018. #ifdef TESTFP
  1019.          stopmsg(0, "real,2,MAX_STACK,0" );
  1020. #endif
  1021.          CvtFptr(fStkReal, 2, MAX_STACK, 0 );
  1022.          continue;
  1023.       }
  1024.       if (ftst == dStkImag ) {
  1025. #ifdef TESTFP
  1026.          stopmsg(0, "imag,2,MAX_STACK,0" );
  1027. #endif
  1028.          CvtFptr(fStkImag, 2, MAX_STACK, 0 );
  1029.          continue;
  1030.       }
  1031.       if (ftst == dStkConj ) {
  1032. #ifdef TESTFP
  1033.          stopmsg(0, "conj,2,MAX_STACK,0" );
  1034. #endif
  1035.          CvtFptr(fStkConj, 2, MAX_STACK, 0 );
  1036.          continue;
  1037.       }
  1038.       if (ftst == dStkNeg ) {
  1039. #ifdef TESTFP
  1040.          stopmsg(0, "neg,2,MAX_STACK,0" );
  1041. #endif
  1042.          CvtFptr(fStkNeg, 2, MAX_STACK, 0 );
  1043.          continue;
  1044.       }
  1045.       if (ftst == dStkAbs ) {
  1046. #ifdef TESTFP
  1047.          stopmsg(0, "abs,2,MAX_STACK,0" );
  1048. #endif
  1049.          CvtFptr(fStkAbs, 2, MAX_STACK, 0 );
  1050.          continue;
  1051.       }
  1052.       if (ftst == dStkRecip ) {
  1053. #ifdef TESTFP
  1054.          stopmsg(0, "recip,2,TWO_FREE,0" );
  1055. #endif
  1056.          CvtFptr(fStkRecip, 2, TWO_FREE, 0 );
  1057.          continue;
  1058.       }
  1059.       if (ftst == StkIdent ) {
  1060. #ifdef TESTFP
  1061.          stopmsg(0, "ident skipped" );
  1062. #endif
  1063.          /* don't bother converting this one */
  1064.          continue;
  1065.       }
  1066.       if (ftst == dStkGT ) {
  1067. #ifdef TESTFP
  1068.          stopmsg(0, "GT,4,MAX_STACK,-2" );
  1069. #endif
  1070.          CvtFptr(fStkGT, 4, MAX_STACK, -2 );
  1071.          continue;
  1072.       }
  1073.       if (ftst == dStkGTE ) {
  1074. #ifdef TESTFP
  1075.          stopmsg(0, "GTE,4,MAX_STACK,-2" );
  1076. #endif
  1077.          CvtFptr(fStkGTE, 4, MAX_STACK, -2 );
  1078.          continue;
  1079.       }
  1080.       if (ftst == dStkEQ ) {
  1081. #ifdef TESTFP
  1082.          stopmsg(0, "EQ,4,MAX_STACK,-2" );
  1083. #endif
  1084.          CvtFptr(fStkEQ, 4, MAX_STACK, -2 );
  1085.          continue;
  1086.       }
  1087.       if (ftst == dStkNE ) {
  1088. #ifdef TESTFP
  1089.          stopmsg(0, "NE,4,MAX_STACK,-2" );
  1090. #endif
  1091.          CvtFptr(fStkNE, 4, MAX_STACK, -2 );
  1092.          continue;
  1093.       }
  1094.       if (ftst == dStkOR ) {
  1095. #ifdef TESTFP
  1096.          stopmsg(0, "OR,4,MAX_STACK,-2" );
  1097. #endif
  1098.          CvtFptr(fStkOR, 4, MAX_STACK, -2 );
  1099.          continue;
  1100.       }
  1101.       if (ftst == dStkAND ) {
  1102. #ifdef TESTFP
  1103.          stopmsg(0, "AND,4,MAX_STACK,-2" );
  1104. #endif
  1105.          CvtFptr(fStkAND, 4, MAX_STACK, -2 );
  1106.          continue;
  1107.       }
  1108.       stopmsg(0, "Fast failure, using old code." );
  1109.       return 1; /* this should never happen but is not fatal now */
  1110.    }
  1111.  
  1112.    if (debugflag == 322 ){
  1113.       /* skip these optimizations too */
  1114.       goto skipfinalopt;
  1115.    } /* ---------------------------------- final optimizations ---- */
  1116.  
  1117.    ntst = fgf(cvtptrx-2 ); /* cvtptrx -> one past last operator (clr2) */
  1118.    if (ntst == fStkLT ){
  1119. #ifdef TESTFP
  1120.       stopmsg (0, "LT Clr2 -> LT2" );
  1121. #endif
  1122.       --cvtptrx;
  1123.       fgf(cvtptrx-1) = fStkLT2;
  1124.    }
  1125.    else if (ntst == fStkLodLT ){
  1126. #ifdef TESTFP
  1127.       stopmsg (0, "LodLT Clr2 -> LodLT2" );
  1128. #endif
  1129.       --cvtptrx;
  1130.       fgf(cvtptrx-1) = fStkLodLT2;
  1131.    }
  1132.    else if (ntst == fStkLTE ){
  1133. #ifdef TESTFP
  1134.       stopmsg (0, "LTE Clr2 -> LTE2" );
  1135. #endif
  1136.       --cvtptrx;
  1137.       fgf(cvtptrx-1) = fStkLTE2;
  1138.    }
  1139.    else if (ntst == fStkLodLTE ){
  1140. #ifdef TESTFP
  1141.       stopmsg (0, "LodLTE Clr2 -> LodLTE2" );
  1142. #endif
  1143.       --cvtptrx;
  1144.       fgf(cvtptrx-1) = fStkLodLTE2;
  1145.    }
  1146.    else if (ntst == fStkGT ){
  1147. #ifdef TESTFP
  1148.       stopmsg (0, "GT Clr2 -> GT2" );
  1149. #endif
  1150.       --cvtptrx;
  1151.       fgf(cvtptrx-1) = fStkGT2;
  1152.    }
  1153.    else if (ntst == fStkLodGT ){
  1154. #ifdef TESTFP
  1155.       stopmsg (0, "LodGT Clr2 -> LodGT2" );
  1156. #endif
  1157.       --cvtptrx;
  1158.       fgf(cvtptrx-1) = fStkLodGT2;
  1159.    }
  1160.    else if (ntst == fStkLodGTE ){
  1161. #ifdef TESTFP
  1162.       stopmsg (0, "LodGTE Clr2 -> LodGTE2" );
  1163. #endif
  1164.       --cvtptrx;
  1165.       fgf(cvtptrx-1) = fStkLodGTE2;
  1166.    }
  1167.    else if (fgf(cvtptrx-2 ) == fStkAND ){
  1168. #ifdef TESTFP
  1169.       stopmsg (0, "AND Clr2 -> ANDClr2" );
  1170. #endif
  1171.       --cvtptrx;
  1172.       fgf(cvtptrx-1) = fStkANDClr2;
  1173.       ntst = fgf(cvtptrx-2);
  1174.       if (ntst == fStkLodLTE ){
  1175. #ifdef TESTFP
  1176.          stopmsg (0, "LodLTE ANDClr2 -> LodLTEAnd2" );
  1177. #endif
  1178.          --cvtptrx;
  1179.          fgf(cvtptrx-1) = fStkLodLTEAnd2;
  1180.       }
  1181.    }
  1182.  
  1183. skipfinalopt: /* ---------------- end of final optimizations ----- */
  1184.  
  1185.    LastOp = cvtptrx; /* save the new operator count */
  1186.    LastSqr.d.y = 0.0; /* do this once per image */
  1187.  
  1188.    /* now change the pointers */
  1189.    if (FormName[0] != 0 ){ /* but only if parse succeeded */
  1190.       curfractalspecific->per_pixel = fform_per_pixel;
  1191.       curfractalspecific->orbitcalc = fFormula;
  1192.    }
  1193.    else {
  1194.       curfractalspecific->per_pixel = BadFormula;
  1195.       curfractalspecific->orbitcalc = BadFormula;
  1196.    }
  1197.    Img_Setup(); /* call assembler setup code */
  1198.    return 1;
  1199. }
  1200.  
  1201. #endif  /*  XFRACT  */
  1202.