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.10 2010/09/13 18:43:04 asau Exp $
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
52 * Create a floating point constant.
53 * fconstant ( r -"name"- )
56 ficlPrimitiveFConstant(ficlVm
*vm
)
58 ficlDictionary
*dictionary
= ficlVmGetDictionary(vm
);
59 ficlString name
= ficlVmGetWord(vm
);
61 FICL_STACK_CHECK(vm
->floatStack
, 1, 0);
63 ficlDictionaryAppendWord(dictionary
, name
,
64 (ficlPrimitive
)ficlInstructionFConstantParen
, FICL_WORD_DEFAULT
);
65 ficlDictionaryAppendCell(dictionary
, ficlStackPop(vm
->floatStack
));
70 ficlDictionaryAppendFConstant(ficlDictionary
*dictionary
, char *name
,
74 FICL_STRING_SET_FROM_CSTRING(s
, name
);
75 return (ficlDictionaryAppendConstantInstruction(dictionary
, s
,
76 ficlInstructionFConstantParen
, *(ficlInteger
*)(&value
)));
81 ficlDictionarySetFConstant(ficlDictionary
*dictionary
, char *name
,
85 FICL_STRING_SET_FROM_CSTRING(s
, name
);
86 return (ficlDictionarySetConstantInstruction(dictionary
, s
,
87 ficlInstructionFConstantParen
, *(ficlInteger
*)(&value
)));
94 ficlPrimitiveF2Constant(ficlVm
*vm
)
96 ficlDictionary
*dictionary
= ficlVmGetDictionary(vm
);
97 ficlString name
= ficlVmGetWord(vm
);
99 FICL_STACK_CHECK(vm
->floatStack
, 2, 0);
101 ficlDictionaryAppendWord(dictionary
, name
,
102 (ficlPrimitive
)ficlInstructionF2ConstantParen
, FICL_WORD_DEFAULT
);
103 ficlDictionaryAppendCell(dictionary
, ficlStackPop(vm
->floatStack
));
104 ficlDictionaryAppendCell(dictionary
, ficlStackPop(vm
->floatStack
));
108 ficlDictionaryAppendF2Constant(ficlDictionary
*dictionary
, char *name
,
112 FICL_STRING_SET_FROM_CSTRING(s
, name
);
113 return (ficlDictionaryAppend2ConstantInstruction(dictionary
, s
,
114 ficlInstructionF2ConstantParen
, *(ficl2Integer
*)(&value
)));
118 ficlDictionarySetF2Constant(ficlDictionary
*dictionary
, char *name
,
122 FICL_STRING_SET_FROM_CSTRING(s
, name
);
123 return (ficlDictionarySet2ConstantInstruction(dictionary
, s
,
124 ficlInstructionF2ConstantParen
, *(ficl2Integer
*)(&value
)));
128 * Display a float in decimal format.
132 ficlPrimitiveFDot(ficlVm
*vm
)
136 FICL_STACK_CHECK(vm
->floatStack
, 1, 0);
138 f
= ficlStackPopFloat(vm
->floatStack
);
139 sprintf(vm
->pad
, "%#f ", f
);
140 ficlVmTextOut(vm
, vm
->pad
);
144 * Display a float in engineering format.
148 ficlPrimitiveEDot(ficlVm
*vm
)
152 FICL_STACK_CHECK(vm
->floatStack
, 1, 0);
154 f
= ficlStackPopFloat(vm
->floatStack
);
155 sprintf(vm
->pad
, "%#e ", f
);
156 ficlVmTextOut(vm
, vm
->pad
);
160 * d i s p l a y FS t a c k
161 * Display the parameter stack (code for "f.s")
171 ficlFloatStackDisplayCallback(void *c
, ficlCell
*cell
)
173 struct stackContext
*context
= (struct stackContext
*)c
;
176 snprintf(buffer
, sizeof (buffer
), "[0x%016lx %3d] %20e (0x%016lx)\n",
177 (unsigned long) cell
, context
->count
++, cell
->f
, cell
->u
);
179 snprintf(buffer
, sizeof (buffer
), "[0x%08x %3d] %12e (0x%08x)\n",
180 (unsigned)cell
, context
->count
++, cell
->f
, cell
->u
);
182 ficlVmTextOut(context
->vm
, buffer
);
187 ficlVmDisplayFloatStack(ficlVm
*vm
)
189 struct stackContext context
;
192 ficlStackDisplay(vm
->floatStack
, ficlFloatStackDisplayCallback
,
197 * Do float stack depth.
201 ficlPrimitiveFDepth(ficlVm
*vm
)
205 FICL_STACK_CHECK(vm
->dataStack
, 0, 1);
207 i
= ficlStackDepth(vm
->floatStack
);
208 ficlStackPushInteger(vm
->dataStack
, i
);
212 * Compile a floating point literal.
215 ficlPrimitiveFLiteralImmediate(ficlVm
*vm
)
217 ficlDictionary
*dictionary
= ficlVmGetDictionary(vm
);
220 FICL_STACK_CHECK(vm
->floatStack
, 1, 0);
222 cell
= ficlStackPop(vm
->floatStack
);
223 if (cell
.f
== 1.0f
) {
224 ficlDictionaryAppendUnsigned(dictionary
, ficlInstructionF1
);
225 } else if (cell
.f
== 0.0f
) {
226 ficlDictionaryAppendUnsigned(dictionary
, ficlInstructionF0
);
227 } else if (cell
.f
== -1.0f
) {
228 ficlDictionaryAppendUnsigned(dictionary
, ficlInstructionFNeg1
);
230 ficlDictionaryAppendUnsigned(dictionary
,
231 ficlInstructionFLiteralParen
);
232 ficlDictionaryAppendCell(dictionary
, cell
);
237 * F l o a t P a r s e S t a t e
238 * Enum to determine the current segement of a floating point number
244 typedef enum _floatParseState
254 * f i c l P a r s e F l o a t N u m b e r
255 * vm -- Virtual Machine pointer.
256 * s -- String to parse.
257 * Returns 1 if successful, 0 if not.
260 ficlVmParseFloatNumber(ficlVm
*vm
, ficlString s
)
267 ficlFloat accum
= 0.0f
;
268 ficlFloat mant
= 0.1f
;
269 ficlInteger exponent
= 0;
271 FloatParseState estate
= FPS_START
;
273 FICL_STACK_CHECK(vm
->floatStack
, 0, 1);
276 * floating point numbers only allowed in base 10
281 trace
= FICL_STRING_GET_POINTER(s
);
282 length
= FICL_STRING_GET_LENGTH(s
);
284 /* Loop through the string's characters. */
285 while ((length
--) && ((c
= *trace
++) != 0)) {
287 /* At start of the number so look for a sign. */
297 /* Note! Drop through to FPS_ININT */
299 * Converting integer part of number.
300 * Only allow digits, decimal and 'E'.
305 } else if ((c
== 'e') || (c
== 'E')) {
306 estate
= FPS_STARTEXP
;
308 digit
= (unsigned char)(c
- '0');
312 accum
= accum
* 10 + digit
;
316 * Processing the fraction part of number.
317 * Only allow digits and 'E'
320 if ((c
== 'e') || (c
== 'E')) {
321 estate
= FPS_STARTEXP
;
323 digit
= (unsigned char)(c
- '0');
327 accum
+= digit
* mant
;
331 /* Start processing the exponent part of number. */
339 } else if (c
== '+') {
342 /* Note! Drop through to FPS_INEXP */
344 * Processing the exponent part of number.
348 digit
= (unsigned char)(c
- '0');
352 exponent
= exponent
* 10 + digit
;
358 /* If parser never made it to the exponent this is not a float. */
359 if (estate
< FPS_STARTEXP
)
362 /* Set the sign of the number. */
366 /* If exponent is not 0 then adjust number by it. */
368 /* Determine if exponent is negative. */
369 if (flag
& EXPISNEG
) {
370 exponent
= -exponent
;
374 power
= (ficlFloat
)pow(10.0, exponent
);
376 power
= (ficlFloat
)powf(10.0, exponent
);
381 ficlStackPushFloat(vm
->floatStack
, accum
);
382 if (vm
->state
== FICL_VM_STATE_COMPILE
)
383 ficlPrimitiveFLiteralImmediate(vm
);
387 #endif /* FICL_WANT_FLOAT */
391 ficlPrimitiveFLocalParen(ficlVm
*vm
)
393 ficlLocalParen(vm
, 0, 1);
397 ficlPrimitiveF2LocalParen(ficlVm
*vm
)
399 ficlLocalParen(vm
, 1, 1);
401 #endif /* FICL_WANT_LOCALS */
404 * Add float words to a system's dictionary.
405 * system -- Pointer to the Ficl sytem to add float words to.
408 ficlSystemCompileFloat(ficlSystem
*system
)
410 ficlDictionary
*dictionary
= ficlSystemGetDictionary(system
);
411 ficlDictionary
*environment
= ficlSystemGetEnvironment(system
);
416 FICL_SYSTEM_ASSERT(system
, dictionary
);
417 FICL_SYSTEM_ASSERT(system
, environment
);
420 ficlDictionarySetPrimitive(dictionary
, "(flocal)",
421 ficlPrimitiveFLocalParen
, FICL_WORD_COMPILE_ONLY
);
422 ficlDictionarySetPrimitive(dictionary
, "(f2local)",
423 ficlPrimitiveF2LocalParen
, FICL_WORD_COMPILE_ONLY
);
424 #endif /* FICL_WANT_LOCALS */
427 ficlDictionarySetPrimitive(dictionary
, "fconstant",
428 ficlPrimitiveFConstant
, FICL_WORD_DEFAULT
);
429 ficlDictionarySetPrimitive(dictionary
, "fvalue",
430 ficlPrimitiveFConstant
, FICL_WORD_DEFAULT
);
431 ficlDictionarySetPrimitive(dictionary
, "f2constant",
432 ficlPrimitiveF2Constant
, FICL_WORD_DEFAULT
);
433 ficlDictionarySetPrimitive(dictionary
, "f2value",
434 ficlPrimitiveF2Constant
, FICL_WORD_DEFAULT
);
435 ficlDictionarySetPrimitive(dictionary
, "fdepth", ficlPrimitiveFDepth
,
437 ficlDictionarySetPrimitive(dictionary
, "fliteral",
438 ficlPrimitiveFLiteralImmediate
, FICL_WORD_IMMEDIATE
);
439 ficlDictionarySetPrimitive(dictionary
, "f.", ficlPrimitiveFDot
,
441 ficlDictionarySetPrimitive(dictionary
, "f.s", ficlVmDisplayFloatStack
,
443 ficlDictionarySetPrimitive(dictionary
, "fe.", ficlPrimitiveEDot
,
465 ficlDictionarySetConstant(environment
, "max-float", data
.i
);
466 /* not all required words are present */
467 ficlDictionarySetConstant(environment
, "floating", FICL_FALSE
);
468 ficlDictionarySetConstant(environment
, "floating-ext", FICL_FALSE
);
469 ficlDictionarySetConstant(environment
, "floating-stack",
472 ficlDictionarySetConstant(environment
, "floating", FICL_FALSE
);