/** 
    -- The No-FP-Stack Floating-Point Word Set
   
    Copyright (C) Krishna Myneni and Guido Draheim, 2002
  
    @see     GNU LGPL
    @author  Krishna Myneni        @(#) %derived_by: guidod %
    @version %version: 32.12 %
      (%date_modified: Wed Oct 16 14:54:57 2002 %)
  
    @description
           The No-FP-Stack Floating-Point Wordset is not usually
           used on embedded platforms. This Module implements
           the floating-point words but expects and puts the
           floating-point values on the forth parameter-stack.
 */
/*@{*/
#if defined(__version_control__) && defined(__GNUC__)
static char* id __attribute__((unused)) = 
"@(#) $Id: %full_filespec:  fpnostack-ext.c~32.12:csrc:bln_mpt1!1 % $";
#endif

#define _P4_SOURCE 1
#define _GNU_SOURCE 1            /* glibc's pow10 */

#if !defined P4_NO_FP

#include <pfe/pfe-base.h>
#include <pfe/def-xtra.h>

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <float.h>
#include <math.h>

#include <pfe/option-ext.h>
#include <pfe/def-comp.h>
#include <pfe/double-sub.h>
#include <pfe/logging.h>
#include <pfe/_missing.h>

#define CELLBITS	BITSOF (p4cell)
#define FSPINC  SP++; SP++
#define FSPDEC  SP--; SP--
#define FSP  ((double*) SP)

/* ------------------------------------------------------------------ 
   static helper routines for missing functionality.
 */
#if !defined PFE_HAVE_ACOSH /* Simple acosh(), asinh(), atanh() for those unfortunates who don't have them. These are oversimplified routines (no error or boundry checking). !!! DONT TRUST THESE ROUTINES !!! */ #include <math.h>
static double acosh (double n) 
{ 
    return log (n + sqrt (n * n - 1)); 
}
static double asinh (double n) 
{ 
    return (n < 0 ? -1.0 : 1.0) 
	* log (fabs (n) + sqrt (n * n + 1)); 
}
static double atanh (double n) 
{ 
    return log (1.0 + ((2.0 * n) / (1.0 - n))) * 0.5; 
}
#endif #if !defined HAVE_POW10 && !defined PFE_HAVE_POW10 #define pow10(X) pow(10.0,(X)) #endif
/* ------------------------------------------------------------------ */
/**
   return double float-aligned address
 */
_export p4cell
p4_nofp_dfaligned (p4cell n)	
{
    while (!P4_DFALIGNED (n))
        n++;
    return n;
}
/**
    used in engine
 */
_export int
p4_nofp_to_float (char *p, p4cell n, double *r)
{
# if defined USE_STRTOD		/* most systems have good strtod */

    char buf[80], *q;
  
    if (!*p) return 0; 
    /* strtod does crash on vxworks being empty non-null *gud*/

    p4_store_c_string (p, n, buf, sizeof buf);
    if (tolower (buf[n - 1]) == 'e')
        buf[n++] = '0';
    buf[n] = '\0';
    *r = strtod (buf, &q);
    if (q == NULL)
        return 1;
    while (isspace (*q))
        q++;
    return *q == '\0';

# else				/* but some haven't */

    enum state 			/* states of the state machine */
    
{
        bpn,			/* before point, maybe sign */
        bp,			/* before point, no more sign (had one) */
        ap,			/* after point */
        exn,			/* exponent, maybe sign */
        ex,			/* exponent, no more sign, yet no digit */
        exd			/* exponent, no more sign, had one digit */
    }
; enum state state = bpn; int sign = 1; /* sign of mantissa */ long double mant = 0; /* the mantissa */ int esign = 1; /* sign of exponent */ int exp = 0; /* the exponent */ int bdigs = 0; /* digits before point */ int scale = 0; /* number of digits after point */ while (--n >= 0)
{
        p4char c = *p++;

        switch (state)
	
{
         case bpn:
             switch (c)
             
{
              case '-':
                  sign = -1;
              case '+':
                  state = bp;
                  continue;
              case '.':
                  state = ap;
                  continue;
              default:
                  if (isspace (c))
                      continue;
                  if (isdigit (c))
                  
{
                      bdigs = 1;
                      mant = c - '0';
                      state = bp;
                      continue;
                  }
}
return 0; case bp: switch (c)
{
              case '.':
                  state = ap;
                  continue;
#            if 0
              case '-':
                  esign = -1;
              case '+':
                  state = ex;
                  continue;
#            endif
              case 'e':
              case 'E':
                  state = exn;
                  continue;
              default:
                  if (isdigit (c))
                  
{
                      bdigs++;
                      mant *= 10;
                      mant += c - '0';
                      continue;
                  }
}
return 0; case ap: switch (c)
{
              case '-':
                  esign = -1;
              case '+':
                  state = ex;
                  continue;
              case 'e':
              case 'E':
                  state = exn;
                  continue;
              default:
                  if (isdigit (c))
                  
{
                      mant *= 10;
                      mant += c - '0';
                      scale--;
                      continue;
                  }
}
return 0; case exn: state = ex; switch (c)
{
              case '-':
                  esign = -1;
              case '+':
                  continue;
              default: ;
             }
case ex: if (isdigit (c))
{
                 exp = c - '0';
                 state = exd;
                 continue;
             }
return 0; case exd: if (isdigit (c))
{
                 exp *= 10;
                 exp += c - '0';
                 continue;
             }
return 0; }
}
*r = sign * mant * pow10 (scale + esign * exp); return bdigs - scale > 0; # endif }
/** */ FCode (p4_nofp_d_f_align); #if defined USE_SSCANF /* define this if you fully trust your scanf */
/*
   This is a working solution on most machines.
   Unfortunately it relies on pretty obscure features of sscanf()
   which are not truly implemented everywhere.
 */
FCode (p4_nofp_to_float)		
{
    char *p, buf[80];
    static char *fmt[] =
    
{
        "%lf%n %n%d%n$",
        "%lf%*1[DdEe]%n %n%d%n$",
    }
; int i, n, exp, n1, n2, n3; double r; p = (char *) SP[1]; n = p4_dash_trailing (p, *SP); if (n == 0)
{
        *FSP = 0.;
	--SP; *SP = P4_TRUE;
        return;
    }
p4_store_c_string (p, n, buf, sizeof buf); strcat (buf, "$"); # if defined SYS_EMX /* emx' sscanf(), %lf conversion, doesn't read past 0E accepting the * "0" as good number when no exponent follows. Therefore we change * the 'E' to 'D', ugly hack but helps. */ p4_upper (buf, n); if (strchr (buf, 'E')) *strchr (buf, 'E') = 'D'; # endif if (1 == sscanf (buf, "%lf%n$", &r, &n1) && n == n1)
{
	*FSP = r;
	--SP; *SP = P4_TRUE;
        return;
    }
for (i = 0; i < DIM (fmt); i++)
{
        switch (sscanf (buf, fmt[i], &r, &n1, &n2, &exp, &n3))
        
{
         case 1:
             if (n < n2)
                 break;

	     *FSP = r;
	     --SP; *SP = P4_TRUE;
             return;
         case 2:
             if (n1 != n2 || n < n3)
                 break;

	     *FSP = r * pow10 (exp);
	     --SP; *SP = P4_TRUE;
             return;
        }
}
*FSP = 0; --SP; *SP = P4_FALSE; }
#else
FCode (p4_nofp_to_float)	
/*
   This is an implementation based on a simple state machine.
   Uses nothing but simple character manipulation and floating point math.
 */
{
    enum state			/* states of the state machine */
    
{
        bpn,			/* before point, maybe sign */
        bp,			/* before point, no more sign (had one) */
        ap,			/* after point */
        exn,			/* exponent, maybe sign */
        ex,			/* exponent, no more sign */
        ts			/* trailing space */
    }
; enum state state = bpn; int sign = 1; /* sign of mantissa */ long double mant = 0; /* the mantissa */ int esign = 1; /* sign of exponent */ int exp = 0; /* the exponent */ int scale = 0; /* number of digits after point */ int n = *SP; /* string length */ char *p = (char *) *(SP+1); /* points to string */ while (--n >= 0)
{
        p4char c = *p++;

        switch (state)
	
{
         case bpn:
             switch (c)
             
{
              case '-':
                  sign = -1;
              case '+':
                  state = bp;
                  continue;
              case '.':
                  state = ap;
                  continue;
              default:
                  if (isspace (c))
                      continue;
                  if (isdigit (c))
                  
{
                      mant = c - '0';
                      state = bp;
                      continue;
                  }
}
goto bad; case bp: switch (c)
{
              case '.':
                  state = ap;
                  continue;
              case '-':
                  esign = -1;
              case '+':
                  state = ex;
                  continue;
              case 'D':
              case 'd':
              case 'E':
              case 'e':
                  state = exn;
                  continue;
              default:
                  if (isspace (c))
                  
{
                      state = ts;
                      continue;
                  }
if (isdigit (c))
{
                      mant *= 10;
                      mant += c - '0';
                      continue;
                  }
}
goto bad; case ap: switch (c)
{
              case '-':
                  esign = -1;
              case '+':
                  state = ex;
                  continue;
              case 'D':
              case 'd':
              case 'E':
              case 'e':
                  state = exn;
                  continue;
              default:
                  if (isspace (c))
                  
{
                      state = ts;
                      continue;
                  }
if (isdigit (c))
{
                      mant *= 10;
                      mant += c - '0';
                      scale--;
                      continue;
                  }
}
goto bad; case exn: switch (c)
{
              case '-':
                  esign = -1;
              case '+':
                  state = ex;
                  continue;
              default:
                  if (isspace (c))
                  
{
                      state = ts;
                      continue;
                  }
if (isdigit (c))
{
                      exp = c - '0';
                      state = ex;
                      continue;
                  }
}
goto bad; case ex: if (isspace (c))
{
                 state = ts;
                 continue;
             }
if (isdigit (c))
{
                 exp *= 10;
                 exp += c - '0';
                 continue;
             }
goto bad; case ts: if (isspace (c)) continue; goto bad; }
}
*FSP = sign * mant * pow10 (scale + esign * exp); --SP; *SP = P4_TRUE; return; bad: *FSP = 0.; --SP; *SP = P4_FALSE; return; }
#endif
FCode (p4_nofp_d_to_f)
{
    int sign;
    double res;
    
    if (SP[0] < 0)
        sign = 1, dnegate ((p4dcell *) &SP[0]);
    else
        sign = 0;
#if Linux /*FIXME:*/
    /* slackware 2.2.0.1 (at least) has a bug in ldexp()  */
    res = (p4ucell) SP[0] * ((double)(1<<31) * 2) + (p4ucell) SP[1];
#else
    res = ldexp ((p4ucell) SP[0], CELLBITS) + (p4ucell) SP[1];
#endif

    *FSP = sign ? -res : res;
}
FCode (p4_nofp_f_store)
{
    *((double *) *SP) = *((double*) (SP+1));
    SP++;
    FSPINC;
}
FCode (p4_nofp_f_star)
{
    FSP[1] *= FSP[0];
    FSPINC;
}
FCode (p4_nofp_f_plus)
{
    FSP[1] += FSP[0];
    FSPINC;
}
FCode (p4_nofp_f_minus)
{
    FSP[1] -= FSP[0];
    FSPINC;
}
FCode (p4_nofp_f_slash)
{
    FSP[1] /= FSP[0];
    FSPINC;
}
FCode (p4_nofp_f_zero_less)
{
    *(SP+1) = P4_FLAG (*FSP < 0);
    SP++;
}
FCode (p4_nofp_f_zero_equal)
{
    *(SP+1) = P4_FLAG (*FSP == 0); 
    SP++;
}
FCode (p4_nofp_f_equal)
{
    int flag;
    flag = P4_FLAG (FSP[1] == FSP[0]);
    FSPINC;
    *++SP = flag;
}
FCode (p4_nofp_f_not_equal)
{
    int flag;
    flag = P4_FLAG (FSP[1] != FSP[0]);
    FSPINC;
    *++SP = flag;
}
FCode (p4_nofp_f_less_than)
{
    int flag;
    flag = P4_FLAG (FSP[1] < FSP[0]);
    FSPINC; 
    *++SP = flag;
}
FCode (p4_nofp_f_greater_than)
{
    int flag;
    flag = P4_FLAG (FSP[1] > FSP[0]);
    FSPINC; 
    *++SP = flag;
}
FCode (p4_nofp_f_less_than_or_equal)
{
    int flag;
    flag = P4_FLAG (FSP[1] <= FSP[0]);
    FSPINC; 
    *++SP = flag;
}
FCode (p4_nofp_f_greater_than_or_equal)
{
    int flag;
    flag = P4_FLAG (FSP[1] >= FSP[0]);
    FSPINC; 
    *++SP = flag;
}
FCode (p4_nofp_f_to_d)
{
    double a, hi, lo;
    int sign;
    
    if ((a = *FSP) < 0)
        sign = 1, a = -a;
    else
        sign = 0;
    lo = modf (ldexp (a, -CELLBITS), &hi);
    SP[0] = (p4ucell) hi;
    SP[1] = (p4ucell) ldexp (lo, CELLBITS);
    if (sign)
        dnegate ((p4dcell *) &SP[0]);
}
FCode (p4_nofp_f_fetch)
{
    *((double*) (SP-1)) = *((double*) *SP); SP--;
}
FCode_RT (p4_nofp_f_constant_RT)
{
    FX_USE_BODY_ADDR;
    FSPDEC;
    *FSP = *(double *) p4_nofp_dfaligned ((p4cell) FX_POP_BODY_ADDR);
}
FCode (p4_nofp_f_constant)
{
    FX_RUNTIME_HEADER;
    FX_RUNTIME1 (p4_nofp_f_constant);
    FX (p4_nofp_d_f_align);
    FX_FCOMMA (*FSP);
    FSPINC;
}
P4RUNTIME1(p4_nofp_f_constant, p4_nofp_f_constant_RT);
FCode (p4_nofp_f_depth)
{
    *--SP = (p4_S0 - SP)/2;
}
FCode (p4_nofp_f_drop)
{
    FSPINC;
}
FCode (p4_nofp_f_dup)
{
    FSPDEC;
    FSP[0] = FSP[1];
}
/* originally P4_SKIPS_FLOAT */
p4xt* 
p4_lit_nofp_float_SEE (p4xt* ip, char* p, p4_Semant* s)
{
# if PFE_ALIGNOF_DFLOAT > PFE_ALIGNOF_CELL
    if (!P4_DFALIGNED (ip))
        ip++;
# endif
    sprintf (p, "%e ", *(double *) ip);
    P4_INC (ip, double);
    
    return ip;
}
FCode_XE (p4_nofp_f_literal_execution)
{
    FX_USE_CODE_ADDR;
    FSPDEC;
    *FSP= P4_POP_ (double, IP);
    FX_USE_CODE_EXIT;
}
FCode (p4_nofp_f_literal)
{
    _FX_STATESMART_Q_COMP;
    if (STATESMART)
    
{
#if PFE_ALIGNOF_DFLOAT > PFE_ALIGNOF_CELL
        if (P4_DFALIGNED (DP))
            FX_COMPILE2 (p4_nofp_f_literal);
#endif
        FX_COMPILE1 (p4_nofp_f_literal);
        FX_FCOMMA (*FSP);
	FSPINC;
    }
}
P4COMPILES2 (p4_nofp_f_literal, p4_nofp_f_literal_execution, p4_noop, p4_lit_nofp_float_SEE, P4_DEFAULT_STYLE);
FCode (p4_nofp_floor)
{
  *FSP = floor (*FSP);
}
FCode (p4_nofp_f_max)
{
    if (FSP[0] > FSP[1])
        FSP[1] = FSP[0];
    FSPINC;
}
FCode (p4_nofp_f_min)
{
    if (FSP[0] < FSP[1])
        FSP[1] = FSP[0];
    FSPINC;
}
FCode (p4_nofp_f_negate)
{
    *FSP = -*FSP;
}
FCode (p4_nofp_f_over)
{
    FSPDEC;
    FSP[0] = FSP[2];
}
FCode (p4_nofp_f_rot)
{
    double h = FSP[2];
    
    FSP[2] = FSP[1];
    FSP[1] = FSP[0];
    FSP[0] = h;
}
#ifndef FROUND_FLOOR /* same user.config as in floating-ext! */ #define FROUND_FLOOR 0 /* FROUND identical with floor(fp+0.5) ? */ #endif
FCode (p4_nofp_f_round)
{
#  if defined HAVE_RINT || defined PFE_HAVE_RINT
    /* correct and fast */
    *FSP = rint (*FSP);
#  elif FROUND_FLOOR
    /* incorrect but fast */
    *FSP = floor (*FSP + 0.5); 
#  else
    /* correct but slow */
    double whole, frac, offset;
 
    frac = fabs(modf(*FSP, &whole));
    *FSP = whole;
    FX(p4_nofp_f_to_d);  /* execute F>D */
    offset = (*SP < 0) ? -1. : 1.;
    
    if (*(SP+1) & 1)  /* check even or odd */
    
{
	if (frac >= 0.5) whole += offset;
    }
else
{
	if (frac > 0.5) whole += offset;
    }
*FSP = whole; # endif }
FCode (p4_nofp_f_swap)
{
    double h = FSP[1];
    
    FSP[1] = FSP[0];
    FSP[0] = h;
}
FCode_RT (p4_nofp_f_variable_RT)
{
    FX_USE_BODY_ADDR;
    FX_PUSH_SP = p4_nofp_dfaligned ((p4cell) FX_POP_BODY_ADDR);
}
FCode (p4_nofp_f_variable)
{
    FX_RUNTIME_HEADER;
    FX_RUNTIME1 (p4_nofp_f_variable);
    FX (p4_nofp_d_f_align);
    FX_FCOMMA (0.);
}
P4RUNTIME1(p4_nofp_f_variable, p4_nofp_f_variable_RT);
FCode (p4_nofp_represent)		/* with help from Lennart Benshop */
{
    char *p, buf[0x80];
    int u, log, sign;
    double f;
    
    f = FSP[1];
    p = (char *) SP[1];
    u = SP[0];
    SP++;
    
    if (f < 0)
        sign = P4_TRUE, f = -f;
    else
        sign = P4_FALSE;
    if (f != 0)
    
{
        log = (int) floor (log10 (f)) + 1;
        f *= pow10 (-log);
        if (f + 0.5 * pow10 (-u) >= 1)
            f /= 10, log++;
    }
else log = 0; sprintf (buf, "%0.*f", u, f); memcpy (p, buf + 2, u); SP[2] = log; SP[1] = sign; SP[0] = P4_TRUE; }
/* ********************************************************************** */ /* Floating point extension words: */
/* ********************************************************************** */
FCode (p4_nofp_d_f_align)
{
    while (!P4_DFALIGNED (DP))
        *DP++ = 0;
}
FCode (p4_nofp_d_f_aligned)
{
    SP[0] = p4_nofp_dfaligned (SP[0]);
}
FCode (p4_nofp_d_float_plus)
{
    *SP += sizeof (double);
}
FCode (p4_nofp_d_floats)
{
    *SP *= sizeof (double);
}
FCode (p4_nofp_f_star_star)
{
    FSP[1] = pow (FSP[1], FSP[0]);
    FSPINC;
}
FCode (p4_nofp_f_dot)
{
    p4_outf ("%.*f ", PRECISION, *FSP);
    FSPINC;
}
FCode (p4_nofp_f_abs)
{
    if (*FSP < 0)
        *FSP = -*FSP;
}
FCode (p4_nofp_f_e_dot)			/* with help from Lennart Benshop */
{
    double f = fabs (*FSP);
    double h = 0.5 * pow10 (-PRECISION);
    int n;

    if (f == 0)
        n = 0;
    else if (f < 1)
    
{
        h = 1 - h;
        for (n = 3; f * pow10 (n) < h; n += 3);
    }
else
{
        h = 1000 - h;
        for (n = 0; h <= f * pow10 (n); n -= 3);
    }
p4_outf ("%+*.*fE%+03d ", PRECISION + 5, PRECISION, *FSP * pow10 (n), -n); FSPINC; }
FCode (p4_nofp_f_s_dot)
{
    p4_outf ("%.*E ", PRECISION, *FSP); FSPINC;
}
FCode (p4_nofp_f_proximate)
{
    double a, b, c;

    a = FSP[2];
    b = FSP[1];
    c = FSP[0];
    FSPINC; FSPINC; SP++;
# if 0
    if (c > 0)
        *SP = P4_FLAG (fabs (a - b) < c);
    else if (c < 0)
        *SP = P4_FLAG (fabs (a - b) < -c * (fabs (a) + fabs (b)));
    else
        *SP = P4_FLAG (memcmp (&a, &b, sizeof (double)) == 0);
    
# else
    *SP = P4_FLAG
        (c > 0 
          ? fabs (a - b) < c 
          : c < 0 
          ? fabs (a - b) < -c * (fabs (a) + fabs (b))
          : a == b);
# endif
}
FCode (p4_nofp_set_precision)
{
    PRECISION = *SP++;
}
FCode (p4_nofp_s_f_store)
{
    *(float *) *SP = *((double*) (SP+1));
    SP += 3;
}
FCode (p4_nofp_s_f_fetch)
{
    *((double*)(SP-1)) = *(float *) *SP;
    --SP;
}
FCode (p4_nofp_s_float_plus)
{
    *SP += sizeof (float);
}
FCode (p4_nofp_s_floats)
{
    *SP *= sizeof (float);
}
/*-- simple mappings to the ANSI-C library  --*/
FCode (p4_nofp_f_acos)	
{ *FSP = acos (*FSP); }
FCode (p4_nofp_f_acosh)	
{ *FSP = acosh (*FSP); }
FCode (p4_nofp_f_alog)	
{ *FSP = pow10 (*FSP); }
FCode (p4_nofp_f_asin)	
{ *FSP = asin (*FSP); }
FCode (p4_nofp_f_asinh)	
{ *FSP = asinh (*FSP); }
FCode (p4_nofp_f_atan)	
{ *FSP = atan (*FSP); }
FCode (p4_nofp_f_atan2)	
{ FSP [1] = atan2 (FSP [1], FSP [0]); FSPINC; }
FCode (p4_nofp_f_atanh)	
{ *FSP = atanh (*FSP); }
FCode (p4_nofp_f_cos)	
{ *FSP = cos (*FSP); }
FCode (p4_nofp_f_cosh)	
{ *FSP = cosh (*FSP); }
FCode (p4_nofp_f_exp)	
{ *FSP = exp (*FSP); }
FCode (p4_nofp_f_expm1)	
{ *FSP = exp (*FSP) - 1.0; }
FCode (p4_nofp_f_ln)	
{ *FSP = log (*FSP); }
FCode (p4_nofp_f_lnp1)	
{ *FSP = log (*FSP + 1.0); }
FCode (p4_nofp_f_log)	
{ *FSP = log10 (*FSP); }
FCode (p4_nofp_f_sin)	
{ *FSP = sin (*FSP); }
FCode (p4_nofp_f_sincos)
{ FSPDEC; FSP[0]=cos(FSP[1]); FSP[1]=sin(FSP[1]);}
FCode (p4_nofp_f_sinh)	
{ *FSP = sinh (*FSP); }
FCode (p4_nofp_f_sqrt)	
{ *FSP = sqrt (*FSP); }
FCode (p4_nofp_f_tan)	
{ *FSP = tan (*FSP); }
FCode (p4_nofp_f_tanh)	
{ *FSP = tanh (*FSP); }
/* environment queries */
static FCode (p__nofp_max_float)
{
    FSPDEC;
    *FSP = DBL_MAX;
}
/* words not from the ansi'94 forth standard  */
/* ================= INTERPRET =================== */
#ifndef DOUBLE_ALIGNED #if defined HOST_ARCH_SPARC || defined __target_arch_sparc #define DOUBLE_ALIGNED 1 #elif defined HOST_ARCH_POWERPC || defined __target_arch_powerpc #define DOUBLE_ALIGNED 1 #else #define DOUBLE_ALIGNED 0 #endif #endif
static p4ucell FXCode (interpret_float) /*hereclean*/
{
    /* scanned word sits at PFE.word. (not at HERE) */
# ifndef P4_NO_FP
    if (! BASE == 10 || ! FLOAT_INPUT) return 0; /* quick path */

    
{
	double f;
	/* WORD-string is at HERE */
	if (! p4_nofp_to_float (PFE.word.ptr, PFE.word.len, &f)) 
	    return 0; /* quick path */
	
	if (STATE)
	
{
#          if PFE_ALIGNOF_DFLOAT > PFE_ALIGNOF_CELL
	    if (P4_DFALIGNED (DP))
		FX_COMPILE2 (p4_nofp_f_literal);
#          endif
	    FX_COMPILE1 (p4_nofp_f_literal);
	    FX_FCOMMA (f);
	}
else
{
	    FSPDEC;
#          if DOUBLE_ALIGNED
            if (((long)(void*)SP)&7) 
{ SP--; P4_fail("auto dfaligned SP"); }
# endif *FSP = f; }
return 1; }
# else return 0; # endif }
static int decompile_floating (char* nfa, p4xt xt)
{
    if (*P4_TO_CODE(xt) == PFX (p4_nofp_f_constant_RT))          
    
{
        p4_outf ("%g FCONSTANT ( fpnostack )", 
          *(double *) p4_nofp_dfaligned ((p4cell) P4_TO_BODY (xt)));
        p4_dot_name (nfa);
        return 1;
    }
else if (*P4_TO_CODE(xt) == PFX (p4_nofp_f_variable_RT))
{
        p4_outf ("%g FVARIABLE ( fpnostack )", 
          *(double *) p4_nofp_dfaligned ((p4cell) P4_TO_BODY (xt)));
        p4_dot_name (nfa);
        return 1;
    }
return 0; }
/* slot 1 == p4_interpret_smart slot 2 == p4_interpret_floating */ #ifndef FPNOSTACK_INTERPRET_SLOT /* USER-CONFIG: */ #define FPNOSTACK_INTERPRET_SLOT 2 /* 1 == smart-ext / 2 == floating-ext */ #endif
static FCode_RT(fpnostack_deinit)
{
    FX_USE_BODY_ADDR; 
    FX_POP_BODY_ADDR_UNUSED;
    PFE.decompile[FPNOSTACK_INTERPRET_SLOT] = 0;
    PFE.interpret[FPNOSTACK_INTERPRET_SLOT] = 0;
}
static FCode(fpnostack_init)
{
    PFE.interpret[FPNOSTACK_INTERPRET_SLOT] = PFX (interpret_float);
    PFE.decompile[FPNOSTACK_INTERPRET_SLOT] = decompile_floating;
    p4_forget_word ("deinit:fpnostack:%i", FPNOSTACK_INTERPRET_SLOT, 
		    PFX(fpnostack_deinit), FPNOSTACK_INTERPRET_SLOT);
}
P4_LISTWORDS (fpnostack) =
{
    P4_INTO ("EXTENSIONS", 0),
    P4_FXco (">FLOAT",		 p4_nofp_to_float),
    P4_FXco ("D>F",		 p4_nofp_d_to_f),
    P4_FXco ("F!",		 p4_nofp_f_store),
    P4_FXco ("F*",		 p4_nofp_f_star),
    P4_FXco ("F+",		 p4_nofp_f_plus),
    P4_FXco ("F-",		 p4_nofp_f_minus),
    P4_FXco ("F/",		 p4_nofp_f_slash),
    P4_FXco ("F0<",		 p4_nofp_f_zero_less),
    P4_FXco ("F0=",		 p4_nofp_f_zero_equal),
    P4_FXco ("F<",		 p4_nofp_f_less_than),
    P4_FXco ("F>",               p4_nofp_f_greater_than),
    P4_FXco ("F=",               p4_nofp_f_equal),
    P4_FXco ("F<>",              p4_nofp_f_not_equal),
    P4_FXco ("F<=",              p4_nofp_f_less_than_or_equal),
    P4_FXco ("F>=",              p4_nofp_f_greater_than_or_equal),
    P4_FXco ("F>D",		 p4_nofp_f_to_d),
    P4_FXco ("F@",		 p4_nofp_f_fetch),
    P4_FXco ("FALIGN",		 p4_nofp_d_f_align),
    P4_FXco ("FALIGNED",	 p4_nofp_d_f_aligned),
    P4_RTco ("FCONSTANT",	 p4_nofp_f_constant),
    P4_FXco ("FDEPTH",		 p4_nofp_f_depth),
    P4_FXco ("FDROP",		 p4_nofp_f_drop),
    P4_FXco ("FDUP",		 p4_nofp_f_dup),
    P4_SXco ("FLITERAL",	 p4_nofp_f_literal),
    P4_FXco ("FLOAT+",		 p4_nofp_d_float_plus),
    P4_FXco ("FLOATS",		 p4_nofp_d_floats),
    P4_FXco ("FLOOR",		 p4_nofp_floor),
    P4_FXco ("FMAX",		 p4_nofp_f_max),
    P4_FXco ("FMIN",		 p4_nofp_f_min),
    P4_FXco ("FNEGATE",		 p4_nofp_f_negate),
    P4_FXco ("FOVER",		 p4_nofp_f_over),
    P4_FXco ("FROT",		 p4_nofp_f_rot),
    P4_FXco ("FROUND",		 p4_nofp_f_round),
    P4_FXco ("FSWAP",		 p4_nofp_f_swap),
    P4_RTco ("FVARIABLE",	 p4_nofp_f_variable),
    P4_FXco ("REPRESENT",	 p4_nofp_represent),
    /* floating point extension words */
    P4_FXco ("DF!",		 p4_nofp_f_store),
    P4_FXco ("DF@",		 p4_nofp_f_fetch),
    P4_FXco ("DFALIGN",		 p4_nofp_d_f_align),
    P4_FXco ("DFALIGNED",	 p4_nofp_d_f_aligned),
    P4_FXco ("DFLOAT+",		 p4_nofp_d_float_plus),
    P4_FXco ("DFLOATS",		 p4_nofp_d_floats),
    P4_FXco ("F**",		 p4_nofp_f_star_star),
    P4_FXco ("F.",		 p4_nofp_f_dot),
    P4_FXco ("FABS",		 p4_nofp_f_abs),
    P4_FXco ("FACOS",		 p4_nofp_f_acos),
    P4_FXco ("FACOSH",		 p4_nofp_f_acosh),
    P4_FXco ("FALOG",		 p4_nofp_f_alog),
    P4_FXco ("FASIN",		 p4_nofp_f_asin),
    P4_FXco ("FASINH",		 p4_nofp_f_asinh),
    P4_FXco ("FATAN",		 p4_nofp_f_atan),
    P4_FXco ("FATAN2",		 p4_nofp_f_atan2),
    P4_FXco ("FATANH",		 p4_nofp_f_atanh),
    P4_FXco ("FCOS",		 p4_nofp_f_cos),
    P4_FXco ("FCOSH",		 p4_nofp_f_cosh),
    P4_FXco ("FE.",		 p4_nofp_f_e_dot),
    P4_FXco ("FEXP",		 p4_nofp_f_exp),
    P4_FXco ("FEXPM1",		 p4_nofp_f_expm1),
    P4_FXco ("FLN",		 p4_nofp_f_ln),
    P4_FXco ("FLNP1",		 p4_nofp_f_lnp1),
    P4_FXco ("FLOG",		 p4_nofp_f_log),
    P4_FXco ("FS.",		 p4_nofp_f_s_dot),
    P4_FXco ("FSIN",		 p4_nofp_f_sin),
    P4_FXco ("FSINCOS",		 p4_nofp_f_sincos),
    P4_FXco ("FSINH",		 p4_nofp_f_sinh),
    P4_FXco ("FSQRT",		 p4_nofp_f_sqrt),
    P4_FXco ("FTAN",		 p4_nofp_f_tan),
    P4_FXco ("FTANH",		 p4_nofp_f_tanh),
    P4_FXco ("F~",		 p4_nofp_f_proximate),
    P4_DVaL ("PRECISION",	 precision),
    P4_FXco ("SET-PRECISION",	 p4_nofp_set_precision),
    P4_FXco ("SF!",		 p4_nofp_s_f_store),
    P4_FXco ("SF@",		 p4_nofp_s_f_fetch),
    P4_FXco ("SFALIGN",		 p4_align), /* alias cell-aligned */
    P4_FXco ("SFALIGNED",	 p4_aligned),
    P4_FXco ("SFLOAT+",		 p4_nofp_s_float_plus),
    P4_FXco ("SFLOATS",		 p4_nofp_s_floats),

    P4_INTO ("ENVIRONMENT", 0 ),
    P4_OCoN ("FLOATING",         1994 ),
    P4_OCoN ("FPNOSTACK-EXT",	 1994 ),
    P4_FXco ("MAX-FLOAT",	 p__nofp_max_float ),
    P4_XXco ("FPNOSTACK-LOADED",  fpnostack_init),
}
; P4_COUNTWORDS (fpnostack, "FpNoStack Floating point + extensions"); /* if !defined P4_NO_FP */ #endif /*@}*/
/* 
   Local variables:
   c-file-style: "stroustrup"
   End:
 */