1 /*******************************************************************
3 ** Forth Inspired Command Language
4 ** ANS Forth FLOAT word-set written in C
5 ** Author: Guy Carver & John Sadler (john_sadler@alum.mit.edu)
7 ** $Id: float.c,v 1.8 2001/12/05 07:21:34 jsadler Exp $
8 *******************************************************************/
10 ** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
11 ** All rights reserved.
13 ** Get the latest Ficl release at http://ficl.sourceforge.net
15 ** I am interested in hearing from anyone who uses ficl. If you have
16 ** a problem, a success story, a defect, an enhancement request, or
17 ** if you would like to contribute to the ficl release, please
18 ** contact me by email at the address above.
20 ** L I C E N S E and D I S C L A I M E R
22 ** Redistribution and use in source and binary forms, with or without
23 ** modification, are permitted provided that the following conditions
25 ** 1. Redistributions of source code must retain the above copyright
26 ** notice, this list of conditions and the following disclaimer.
27 ** 2. Redistributions in binary form must reproduce the above copyright
28 ** notice, this list of conditions and the following disclaimer in the
29 ** documentation and/or other materials provided with the distribution.
31 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
32 ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34 ** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
35 ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39 ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
40 ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 /* $FreeBSD: src/sys/boot/ficl/float.c,v 1.2 2007/03/23 22:26:01 jkim Exp $
46 * $DragonFly: src/sys/boot/ficl/float.c,v 1.2 2008/03/29 23:31:07 swildner Exp $
58 /*******************************************************************
59 ** Do float addition r1 + r2.
61 *******************************************************************/
62 static void Fadd(FICL_VM
*pVM
)
67 vmCheckFStack(pVM
, 2, 1);
75 /*******************************************************************
76 ** Do float subtraction r1 - r2.
78 *******************************************************************/
79 static void Fsub(FICL_VM
*pVM
)
84 vmCheckFStack(pVM
, 2, 1);
92 /*******************************************************************
93 ** Do float multiplication r1 * r2.
95 *******************************************************************/
96 static void Fmul(FICL_VM
*pVM
)
101 vmCheckFStack(pVM
, 2, 1);
109 /*******************************************************************
110 ** Do float negation.
111 ** fnegate ( r -- r )
112 *******************************************************************/
113 static void Fnegate(FICL_VM
*pVM
)
118 vmCheckFStack(pVM
, 1, 1);
125 /*******************************************************************
126 ** Do float division r1 / r2.
128 *******************************************************************/
129 static void Fdiv(FICL_VM
*pVM
)
134 vmCheckFStack(pVM
, 2, 1);
142 /*******************************************************************
143 ** Do float + integer r + n.
145 *******************************************************************/
146 static void Faddi(FICL_VM
*pVM
)
151 vmCheckFStack(pVM
, 1, 1);
152 vmCheckStack(pVM
, 1, 0);
155 f
= (FICL_FLOAT
)POPINT();
160 /*******************************************************************
161 ** Do float - integer r - n.
163 *******************************************************************/
164 static void Fsubi(FICL_VM
*pVM
)
169 vmCheckFStack(pVM
, 1, 1);
170 vmCheckStack(pVM
, 1, 0);
174 f
-= (FICL_FLOAT
)POPINT();
178 /*******************************************************************
179 ** Do float * integer r * n.
181 *******************************************************************/
182 static void Fmuli(FICL_VM
*pVM
)
187 vmCheckFStack(pVM
, 1, 1);
188 vmCheckStack(pVM
, 1, 0);
191 f
= (FICL_FLOAT
)POPINT();
196 /*******************************************************************
197 ** Do float / integer r / n.
199 *******************************************************************/
200 static void Fdivi(FICL_VM
*pVM
)
205 vmCheckFStack(pVM
, 1, 1);
206 vmCheckStack(pVM
, 1, 0);
210 f
/= (FICL_FLOAT
)POPINT();
214 /*******************************************************************
215 ** Do integer - float n - r.
217 *******************************************************************/
218 static void isubf(FICL_VM
*pVM
)
223 vmCheckFStack(pVM
, 1, 1);
224 vmCheckStack(pVM
, 1, 0);
227 f
= (FICL_FLOAT
)POPINT();
232 /*******************************************************************
233 ** Do integer / float n / r.
235 *******************************************************************/
236 static void idivf(FICL_VM
*pVM
)
241 vmCheckFStack(pVM
, 1,1);
242 vmCheckStack(pVM
, 1, 0);
245 f
= (FICL_FLOAT
)POPINT();
250 /*******************************************************************
251 ** Do integer to float conversion.
252 ** int>float ( n -- r )
253 *******************************************************************/
254 static void itof(FICL_VM
*pVM
)
259 vmCheckStack(pVM
, 1, 0);
260 vmCheckFStack(pVM
, 0, 1);
267 /*******************************************************************
268 ** Do float to integer conversion.
269 ** float>int ( r -- n )
270 *******************************************************************/
271 static void Ftoi(FICL_VM
*pVM
)
276 vmCheckStack(pVM
, 0, 1);
277 vmCheckFStack(pVM
, 1, 0);
280 i
= (FICL_INT
)POPFLOAT();
284 /*******************************************************************
285 ** Floating point constant execution word.
286 *******************************************************************/
287 void FconstantParen(FICL_VM
*pVM
)
289 FICL_WORD
*pFW
= pVM
->runningWord
;
292 vmCheckFStack(pVM
, 0, 1);
295 PUSHFLOAT(pFW
->param
[0].f
);
298 /*******************************************************************
299 ** Create a floating point constant.
300 ** fconstant ( r -"name"- )
301 *******************************************************************/
302 static void Fconstant(FICL_VM
*pVM
)
304 FICL_DICT
*dp
= vmGetDict(pVM
);
305 STRINGINFO si
= vmGetWord(pVM
);
308 vmCheckFStack(pVM
, 1, 0);
311 dictAppendWord2(dp
, si
, FconstantParen
, FW_DEFAULT
);
312 dictAppendCell(dp
, stackPop(pVM
->fStack
));
315 /*******************************************************************
316 ** Display a float in decimal format.
318 *******************************************************************/
319 static void FDot(FICL_VM
*pVM
)
324 vmCheckFStack(pVM
, 1, 0);
328 sprintf(pVM
->pad
,"%#f ",f
);
329 vmTextOut(pVM
, pVM
->pad
, 0);
332 /*******************************************************************
333 ** Display a float in engineering format.
335 *******************************************************************/
336 static void EDot(FICL_VM
*pVM
)
341 vmCheckFStack(pVM
, 1, 0);
345 sprintf(pVM
->pad
,"%#e ",f
);
346 vmTextOut(pVM
, pVM
->pad
, 0);
349 /**************************************************************************
350 d i s p l a y FS t a c k
351 ** Display the parameter stack (code for "f.s")
353 **************************************************************************/
354 static void displayFStack(FICL_VM
*pVM
)
356 int d
= stackDepth(pVM
->fStack
);
360 vmCheckFStack(pVM
, 0, 0);
362 vmTextOut(pVM
, "F:", 0);
365 vmTextOut(pVM
, "[0]", 0);
368 ltoa(d
, &pVM
->pad
[1], pVM
->base
);
370 strcat(pVM
->pad
,"] ");
371 vmTextOut(pVM
,pVM
->pad
,0);
373 pCell
= pVM
->fStack
->sp
- d
;
374 for (i
= 0; i
< d
; i
++)
376 sprintf(pVM
->pad
,"%#f ",(*pCell
++).f
);
377 vmTextOut(pVM
,pVM
->pad
,0);
382 /*******************************************************************
383 ** Do float stack depth.
385 *******************************************************************/
386 static void Fdepth(FICL_VM
*pVM
)
391 vmCheckStack(pVM
, 0, 1);
394 i
= stackDepth(pVM
->fStack
);
398 /*******************************************************************
399 ** Do float stack drop.
401 *******************************************************************/
402 static void Fdrop(FICL_VM
*pVM
)
405 vmCheckFStack(pVM
, 1, 0);
411 /*******************************************************************
412 ** Do float stack 2drop.
414 *******************************************************************/
415 static void FtwoDrop(FICL_VM
*pVM
)
418 vmCheckFStack(pVM
, 2, 0);
424 /*******************************************************************
425 ** Do float stack dup.
427 *******************************************************************/
428 static void Fdup(FICL_VM
*pVM
)
431 vmCheckFStack(pVM
, 1, 2);
437 /*******************************************************************
438 ** Do float stack 2dup.
439 ** f2dup ( r1 r2 -- r1 r2 r1 r2 )
440 *******************************************************************/
441 static void FtwoDup(FICL_VM
*pVM
)
444 vmCheckFStack(pVM
, 2, 4);
451 /*******************************************************************
452 ** Do float stack over.
453 ** fover ( r1 r2 -- r1 r2 r1 )
454 *******************************************************************/
455 static void Fover(FICL_VM
*pVM
)
458 vmCheckFStack(pVM
, 2, 3);
464 /*******************************************************************
465 ** Do float stack 2over.
466 ** f2over ( r1 r2 r3 -- r1 r2 r3 r1 r2 )
467 *******************************************************************/
468 static void FtwoOver(FICL_VM
*pVM
)
471 vmCheckFStack(pVM
, 4, 6);
478 /*******************************************************************
479 ** Do float stack pick.
481 *******************************************************************/
482 static void Fpick(FICL_VM
*pVM
)
487 vmCheckFStack(pVM
, c
.i
+1, c
.i
+2);
493 /*******************************************************************
494 ** Do float stack ?dup.
496 *******************************************************************/
497 static void FquestionDup(FICL_VM
*pVM
)
502 vmCheckFStack(pVM
, 1, 2);
510 /*******************************************************************
511 ** Do float stack roll.
513 *******************************************************************/
514 static void Froll(FICL_VM
*pVM
)
520 vmCheckFStack(pVM
, i
+1, i
+1);
526 /*******************************************************************
527 ** Do float stack -roll.
529 *******************************************************************/
530 static void FminusRoll(FICL_VM
*pVM
)
536 vmCheckFStack(pVM
, i
+1, i
+1);
542 /*******************************************************************
543 ** Do float stack rot.
544 ** frot ( r1 r2 r3 -- r2 r3 r1 )
545 *******************************************************************/
546 static void Frot(FICL_VM
*pVM
)
549 vmCheckFStack(pVM
, 3, 3);
555 /*******************************************************************
556 ** Do float stack -rot.
557 ** f-rot ( r1 r2 r3 -- r3 r1 r2 )
558 *******************************************************************/
559 static void Fminusrot(FICL_VM
*pVM
)
562 vmCheckFStack(pVM
, 3, 3);
568 /*******************************************************************
569 ** Do float stack swap.
570 ** fswap ( r1 r2 -- r2 r1 )
571 *******************************************************************/
572 static void Fswap(FICL_VM
*pVM
)
575 vmCheckFStack(pVM
, 2, 2);
581 /*******************************************************************
582 ** Do float stack 2swap
583 ** f2swap ( r1 r2 r3 r4 -- r3 r4 r1 r2 )
584 *******************************************************************/
585 static void FtwoSwap(FICL_VM
*pVM
)
588 vmCheckFStack(pVM
, 4, 4);
595 /*******************************************************************
596 ** Get a floating point number from a variable.
598 *******************************************************************/
599 static void Ffetch(FICL_VM
*pVM
)
604 vmCheckFStack(pVM
, 0, 1);
605 vmCheckStack(pVM
, 1, 0);
608 pCell
= (CELL
*)POPPTR();
612 /*******************************************************************
613 ** Store a floating point number into a variable.
615 *******************************************************************/
616 static void Fstore(FICL_VM
*pVM
)
621 vmCheckFStack(pVM
, 1, 0);
622 vmCheckStack(pVM
, 1, 0);
625 pCell
= (CELL
*)POPPTR();
626 pCell
->f
= POPFLOAT();
629 /*******************************************************************
630 ** Add a floating point number to contents of a variable.
632 *******************************************************************/
633 static void FplusStore(FICL_VM
*pVM
)
638 vmCheckStack(pVM
, 1, 0);
639 vmCheckFStack(pVM
, 1, 0);
642 pCell
= (CELL
*)POPPTR();
643 pCell
->f
+= POPFLOAT();
646 /*******************************************************************
647 ** Floating point literal execution word.
648 *******************************************************************/
649 static void fliteralParen(FICL_VM
*pVM
)
652 vmCheckStack(pVM
, 0, 1);
655 PUSHFLOAT(*(float*)(pVM
->ip
));
656 vmBranchRelative(pVM
, 1);
659 /*******************************************************************
660 ** Compile a floating point literal.
661 *******************************************************************/
662 static void fliteralIm(FICL_VM
*pVM
)
664 FICL_DICT
*dp
= vmGetDict(pVM
);
665 FICL_WORD
*pfLitParen
= ficlLookup(pVM
->pSys
, "(fliteral)");
668 vmCheckFStack(pVM
, 1, 0);
671 dictAppendCell(dp
, LVALUEtoCELL(pfLitParen
));
672 dictAppendCell(dp
, stackPop(pVM
->fStack
));
675 /*******************************************************************
676 ** Do float 0= comparison r = 0.0.
678 *******************************************************************/
679 static void FzeroEquals(FICL_VM
*pVM
)
684 vmCheckFStack(pVM
, 1, 0); /* Make sure something on float stack. */
685 vmCheckStack(pVM
, 0, 1); /* Make sure room for result. */
688 c
.i
= FICL_BOOL(POPFLOAT() == 0);
692 /*******************************************************************
693 ** Do float 0< comparison r < 0.0.
695 *******************************************************************/
696 static void FzeroLess(FICL_VM
*pVM
)
701 vmCheckFStack(pVM
, 1, 0); /* Make sure something on float stack. */
702 vmCheckStack(pVM
, 0, 1); /* Make sure room for result. */
705 c
.i
= FICL_BOOL(POPFLOAT() < 0);
709 /*******************************************************************
710 ** Do float 0> comparison r > 0.0.
712 *******************************************************************/
713 static void FzeroGreater(FICL_VM
*pVM
)
718 vmCheckFStack(pVM
, 1, 0);
719 vmCheckStack(pVM
, 0, 1);
722 c
.i
= FICL_BOOL(POPFLOAT() > 0);
726 /*******************************************************************
727 ** Do float = comparison r1 = r2.
728 ** f= ( r1 r2 -- T/F )
729 *******************************************************************/
730 static void FisEqual(FICL_VM
*pVM
)
735 vmCheckFStack(pVM
, 2, 0);
736 vmCheckStack(pVM
, 0, 1);
741 PUSHINT(FICL_BOOL(x
== y
));
744 /*******************************************************************
745 ** Do float < comparison r1 < r2.
746 ** f< ( r1 r2 -- T/F )
747 *******************************************************************/
748 static void FisLess(FICL_VM
*pVM
)
753 vmCheckFStack(pVM
, 2, 0);
754 vmCheckStack(pVM
, 0, 1);
759 PUSHINT(FICL_BOOL(x
< y
));
762 /*******************************************************************
763 ** Do float > comparison r1 > r2.
764 ** f> ( r1 r2 -- T/F )
765 *******************************************************************/
766 static void FisGreater(FICL_VM
*pVM
)
771 vmCheckFStack(pVM
, 2, 0);
772 vmCheckStack(pVM
, 0, 1);
777 PUSHINT(FICL_BOOL(x
> y
));
781 /*******************************************************************
782 ** Move float to param stack (assumes they both fit in a single CELL)
784 *******************************************************************/
785 static void FFrom(FICL_VM
*pVM
)
790 vmCheckFStack(pVM
, 1, 0);
791 vmCheckStack(pVM
, 0, 1);
794 c
= stackPop(pVM
->fStack
);
795 stackPush(pVM
->pStack
, c
);
799 static void ToF(FICL_VM
*pVM
)
804 vmCheckFStack(pVM
, 0, 1);
805 vmCheckStack(pVM
, 1, 0);
808 c
= stackPop(pVM
->pStack
);
809 stackPush(pVM
->fStack
, c
);
814 /**************************************************************************
815 F l o a t P a r s e S t a t e
816 ** Enum to determine the current segement of a floating point number
818 **************************************************************************/
822 typedef enum _floatParseState
831 /**************************************************************************
832 f i c l P a r s e F l o a t N u m b e r
833 ** pVM -- Virtual Machine pointer.
834 ** si -- String to parse.
835 ** Returns 1 if successful, 0 if not.
836 **************************************************************************/
837 int ficlParseFloatNumber( FICL_VM
*pVM
, STRINGINFO si
)
839 unsigned char ch
, digit
;
845 FICL_INT exponent
= 0;
847 FloatParseState estate
= FPS_START
;
850 vmCheckFStack(pVM
, 0, 1);
854 ** floating point numbers only allowed in base 10
861 count
= (FICL_COUNT
)SI_COUNT(si
);
863 /* Loop through the string's characters. */
864 while ((count
--) && ((ch
= *cp
++) != 0))
868 /* At start of the number so look for a sign. */
881 } /* Note! Drop through to FPS_ININT */
883 **Converting integer part of number.
884 ** Only allow digits, decimal and 'E'.
892 else if ((ch
== 'e') || (ch
== 'E'))
894 estate
= FPS_STARTEXP
;
898 digit
= (unsigned char)(ch
- '0');
902 accum
= accum
* 10 + digit
;
908 ** Processing the fraction part of number.
909 ** Only allow digits and 'E'
913 if ((ch
== 'e') || (ch
== 'E'))
915 estate
= FPS_STARTEXP
;
919 digit
= (unsigned char)(ch
- '0');
923 accum
+= digit
* mant
;
928 /* Start processing the exponent part of number. */
943 } /* Note! Drop through to FPS_INEXP */
945 ** Processing the exponent part of number.
946 ** Only allow digits.
950 digit
= (unsigned char)(ch
- '0');
954 exponent
= exponent
* 10 + digit
;
961 /* If parser never made it to the exponent this is not a float. */
962 if (estate
< FPS_STARTEXP
)
965 /* Set the sign of the number. */
969 /* If exponent is not 0 then adjust number by it. */
972 /* Determine if exponent is negative. */
975 exponent
= -exponent
;
978 power
= (float)pow(10.0, exponent
);
983 if (pVM
->state
== COMPILE
)
989 #endif /* FICL_WANT_FLOAT */
991 /**************************************************************************
992 ** Add float words to a system's dictionary.
993 ** pSys -- Pointer to the FICL sytem to add float words to.
994 **************************************************************************/
995 void ficlCompileFloat(FICL_SYSTEM
*pSys
)
997 FICL_DICT
*dp
= pSys
->dp
;
1001 dictAppendWord(dp
, ">float", ToF
, FW_DEFAULT
);
1003 dictAppendWord(dp
, "f!", Fstore
, FW_DEFAULT
);
1004 dictAppendWord(dp
, "f*", Fmul
, FW_DEFAULT
);
1005 dictAppendWord(dp
, "f+", Fadd
, FW_DEFAULT
);
1006 dictAppendWord(dp
, "f-", Fsub
, FW_DEFAULT
);
1007 dictAppendWord(dp
, "f/", Fdiv
, FW_DEFAULT
);
1008 dictAppendWord(dp
, "f0<", FzeroLess
, FW_DEFAULT
);
1009 dictAppendWord(dp
, "f0=", FzeroEquals
, FW_DEFAULT
);
1010 dictAppendWord(dp
, "f<", FisLess
, FW_DEFAULT
);
1014 dictAppendWord(dp
, "f@", Ffetch
, FW_DEFAULT
);
1019 dictAppendWord(dp
, "fconstant", Fconstant
, FW_DEFAULT
);
1020 dictAppendWord(dp
, "fdepth", Fdepth
, FW_DEFAULT
);
1021 dictAppendWord(dp
, "fdrop", Fdrop
, FW_DEFAULT
);
1022 dictAppendWord(dp
, "fdup", Fdup
, FW_DEFAULT
);
1023 dictAppendWord(dp
, "fliteral", fliteralIm
, FW_IMMEDIATE
);
1031 dictAppendWord(dp
, "f?dup", FquestionDup
, FW_DEFAULT
);
1032 dictAppendWord(dp
, "f=", FisEqual
, FW_DEFAULT
);
1033 dictAppendWord(dp
, "f>", FisGreater
, FW_DEFAULT
);
1034 dictAppendWord(dp
, "f0>", FzeroGreater
, FW_DEFAULT
);
1035 dictAppendWord(dp
, "f2drop", FtwoDrop
, FW_DEFAULT
);
1036 dictAppendWord(dp
, "f2dup", FtwoDup
, FW_DEFAULT
);
1037 dictAppendWord(dp
, "f2over", FtwoOver
, FW_DEFAULT
);
1038 dictAppendWord(dp
, "f2swap", FtwoSwap
, FW_DEFAULT
);
1039 dictAppendWord(dp
, "f+!", FplusStore
, FW_DEFAULT
);
1040 dictAppendWord(dp
, "f+i", Faddi
, FW_DEFAULT
);
1041 dictAppendWord(dp
, "f-i", Fsubi
, FW_DEFAULT
);
1042 dictAppendWord(dp
, "f*i", Fmuli
, FW_DEFAULT
);
1043 dictAppendWord(dp
, "f/i", Fdivi
, FW_DEFAULT
);
1044 dictAppendWord(dp
, "int>float", itof
, FW_DEFAULT
);
1045 dictAppendWord(dp
, "float>int", Ftoi
, FW_DEFAULT
);
1046 dictAppendWord(dp
, "f.", FDot
, FW_DEFAULT
);
1047 dictAppendWord(dp
, "f.s", displayFStack
, FW_DEFAULT
);
1048 dictAppendWord(dp
, "fe.", EDot
, FW_DEFAULT
);
1049 dictAppendWord(dp
, "fover", Fover
, FW_DEFAULT
);
1050 dictAppendWord(dp
, "fnegate", Fnegate
, FW_DEFAULT
);
1051 dictAppendWord(dp
, "fpick", Fpick
, FW_DEFAULT
);
1052 dictAppendWord(dp
, "froll", Froll
, FW_DEFAULT
);
1053 dictAppendWord(dp
, "frot", Frot
, FW_DEFAULT
);
1054 dictAppendWord(dp
, "fswap", Fswap
, FW_DEFAULT
);
1055 dictAppendWord(dp
, "i-f", isubf
, FW_DEFAULT
);
1056 dictAppendWord(dp
, "i/f", idivf
, FW_DEFAULT
);
1058 dictAppendWord(dp
, "float>", FFrom
, FW_DEFAULT
);
1060 dictAppendWord(dp
, "f-roll", FminusRoll
, FW_DEFAULT
);
1061 dictAppendWord(dp
, "f-rot", Fminusrot
, FW_DEFAULT
);
1062 dictAppendWord(dp
, "(fliteral)", fliteralParen
, FW_COMPILE
);
1064 ficlSetEnv(pSys
, "floating", FICL_FALSE
); /* not all required words are present */
1065 ficlSetEnv(pSys
, "floating-ext", FICL_FALSE
);
1066 ficlSetEnv(pSys
, "floating-stack", FICL_DEFAULT_STACK
);