"Fossies" - the Fresh Open Source Software Archive 
Member "mapm_4.9.5a/calc.c" (21 Feb 2010, 15790 Bytes) of package /linux/misc/old/mapm-4.9.5a.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "calc.c" see the
Fossies "Dox" file reference documentation.
1
2 /*
3 * M_APM - calc.c
4 *
5 * Copyright (C) 1999 - 2007 Michael C. Ring
6 *
7 * Permission to use, copy, and distribute this software and its
8 * documentation for any purpose with or without fee is hereby granted,
9 * provided that the above copyright notice appear in all copies and
10 * that both that copyright notice and this permission notice appear
11 * in supporting documentation.
12 *
13 * Permission to modify the software is granted. Permission to distribute
14 * the modified code is granted. Modifications are to be distributed by
15 * using the file 'license.txt' as a template to modify the file header.
16 * 'license.txt' is available in the official MAPM distribution.
17 *
18 * This software is provided "as is" without express or implied warranty.
19 */
20
21 /*
22 * $Id: calc.c,v 1.25 2007/12/03 02:04:04 mike Exp $
23 *
24 * RPN Calculator : demo of the MAPM math library
25 *
26 * $Log: calc.c,v $
27 * Revision 1.25 2007/12/03 02:04:04 mike
28 * update version
29 *
30 * Revision 1.24 2007/12/03 01:16:21 mike
31 * Update license
32 *
33 * Revision 1.23 2004/05/31 22:47:55 mike
34 * added MOD operator
35 *
36 * Revision 1.22 2003/05/31 22:44:19 mike
37 * update version for display
38 *
39 * Revision 1.21 2003/05/15 21:21:16 mike
40 * add MAPM version to output
41 *
42 * Revision 1.20 2002/11/03 22:59:11 mike
43 * Updated function parameters to use the modern style
44 *
45 * Revision 1.19 2001/09/03 17:20:45 mike
46 * make new fixpt string call more intuitive
47 *
48 * Revision 1.18 2001/08/26 22:55:58 mike
49 * use fixed point format if the exponent of the result is -4 -> +6
50 *
51 * Revision 1.17 2001/07/16 18:51:42 mike
52 * add call to free_all_mem
53 *
54 * Revision 1.16 2001/07/15 21:00:58 mike
55 * add GCD and LCM
56 *
57 * Revision 1.15 2001/03/25 21:59:20 mike
58 * add floor and ceil functions
59 *
60 * Revision 1.14 2001/02/06 21:52:54 mike
61 * use internal reciprocal function now
62 *
63 * Revision 1.13 2000/08/04 00:37:39 mike
64 * remove unneeded int from calc_square
65 *
66 * Revision 1.12 2000/08/03 18:05:12 mike
67 * add help for new memory commands
68 *
69 * Revision 1.11 2000/08/03 17:56:38 mike
70 * add memory capability
71 *
72 * Revision 1.10 2000/07/11 23:20:19 mike
73 * calculate 'pi' using the new AGM library function
74 *
75 * Revision 1.9 2000/05/05 20:21:14 mike
76 * compute PI on the fly if more than 115 decimal
77 * places are asked for.
78 *
79 * Revision 1.8 2000/04/03 18:51:25 mike
80 * added operators cube root and hyperbolic sin, cos, tan
81 * with their inverses
82 *
83 * Revision 1.7 2000/02/03 22:43:03 mike
84 * calculate a few extra decimal places on the
85 * intermediate results so all answers on the
86 * final output stay consistent
87 *
88 * Revision 1.6 1999/07/05 15:06:04 mike
89 * added DUP operator
90 *
91 * Revision 1.5 1999/06/01 02:35:00 mike
92 * fix isdigit call with cast
93 *
94 * Revision 1.4 1999/05/28 21:17:11 mike
95 * break up usage into 2 printf so dos compile doesnt choke
96 *
97 * Revision 1.3 1999/05/19 02:29:44 mike
98 * added version of calc to usage line
99 *
100 * Revision 1.2 1999/05/19 02:18:33 mike
101 * added check for stack under-flow
102 *
103 * Revision 1.1 1999/05/19 02:01:02 mike
104 * Initial revision
105 */
106
107 #include <stdio.h>
108 #include <stdlib.h>
109 #include <string.h>
110 #include <ctype.h>
111 #include "m_apm.h"
112
113 /* prototypes for functions in this file */
114
115 void calc_square(M_APM, M_APM);
116 void calc_mod(M_APM, M_APM, M_APM);
117 void calc_pi(M_APM, int);
118 char *lowercase(char *);
119
120 char *out_buffer;
121 char in_buffer[8192];
122
123 #define STACK_SIZE 96
124
125 M_APM calc_stack_data[STACK_SIZE];
126 M_APM memory_data[36];
127
128 #define NUM_OPERATOR_ENTRIES 41 /* number of operators */
129
130 /* calling convention for various MAPM library functions ... */
131
132 #define MMM 0x0A01 /* ( MAPM, MAPM, MAPM ) */
133 #define MiMM 0x0A02 /* ( MAPM, int, MAPM, MAPM ) */
134 #define MiM 0x0A03 /* ( MAPM, int, MAPM ) */
135 #define Mi 0x0A04 /* ( MAPM, int ) */
136 #define MM 0x0A05 /* ( MAPM, MAPM ) */
137 #define MXY 0x0A80 /* special for x <> y */
138 #define MDUP 0x0A81 /* special for dup */
139 #define M_END 0x0AFF /* end of table flag */
140
141 struct opstr {
142 char operator[16];
143 int calling_convention;
144 void (*funcname)();
145 };
146
147 struct opstr operator_lookup[NUM_OPERATOR_ENTRIES] = {
148 { "+", MMM, m_apm_add, /* 0 */ },
149 { "-", MMM, m_apm_subtract, /* 1 */ },
150 { "*", MMM, m_apm_multiply, /* 2 */ },
151 { "x", MMM, m_apm_multiply, /* 3 */ },
152 { "/", MiMM, m_apm_divide, /* 4 */ },
153 { "\\", MMM, m_apm_integer_divide, /* 5 */ },
154 { "i", MMM, m_apm_integer_divide, /* 6 */ },
155 { "!", MM, m_apm_factorial, /* 7 */ },
156 { "s", MiM, m_apm_sin, /* 8 */ },
157 { "c", MiM, m_apm_cos, /* 9 */ },
158 { "t", MiM, m_apm_tan, /* 10 */ },
159 { "q", MiM, m_apm_sqrt, /* 11 */ },
160 { "as", MiM, m_apm_asin, /* 12 */ },
161 { "ac", MiM, m_apm_acos, /* 13 */ },
162 { "at", MiM, m_apm_atan, /* 14 */ },
163 { "at2", MiMM, m_apm_atan2, /* 15 */ },
164 { "lg", MiM, m_apm_log, /* 16 */ },
165 { "lg10", MiM, m_apm_log10, /* 17 */ },
166 { "e", MiM, m_apm_exp, /* 18 */ },
167 { "p", MiMM, m_apm_pow, /* 19 */ },
168 { "h", MM, m_apm_negate, /* 20 */ },
169 { "n", MM, m_apm_negate, /* 21 */ },
170 { "xy", MXY, NULL, /* 22 */ },
171 { "d", MDUP, NULL, /* 23 */ },
172 { "r", MiM, m_apm_reciprocal, /* 24 */ },
173 { "x2", MM, calc_square, /* 25 */ },
174 { "pi", Mi, calc_pi, /* 26 */ },
175 { "hs", MiM, m_apm_sinh, /* 27 */ },
176 { "hc", MiM, m_apm_cosh, /* 28 */ },
177 { "ht", MiM, m_apm_tanh, /* 29 */ },
178 { "has", MiM, m_apm_asinh, /* 30 */ },
179 { "hac", MiM, m_apm_acosh, /* 31 */ },
180 { "hat", MiM, m_apm_atanh, /* 32 */ },
181 { "b", MiM, m_apm_cbrt, /* 33 */ },
182 { "f", MM, m_apm_floor, /* 34 */ },
183 { "cl", MM, m_apm_ceil, /* 35 */ },
184 { "gcd", MMM, m_apm_gcd, /* 36 */ },
185 { "lcm", MMM, m_apm_lcm, /* 37 */ },
186 { "mod", MMM, calc_mod, /* 38 */ },
187 { "%", MMM, calc_mod, /* 39 */ },
188 { "ZZZ", M_END, NULL /* 40 */ }
189 };
190
191
192 int main(int argc, char *argv[])
193 {
194 void (*fp)();
195 char ch0, ch1, *cp, version_info[80];
196 int ii, ilow, stack_pointer, decimal_places, k,
197 index, len, memory_ref[36];
198 M_APM apmtmp;
199 M_APM arg1;
200 M_APM arg2;
201
202 if (argc < 2)
203 {
204 m_apm_lib_short_version(version_info);
205
206 fprintf(stderr,"calc [-d##] <numbers,operators>\t\t\t\t[Version 2.3]\n");
207 fprintf(stderr,
208 " -d : specify decimal places, default = 30\t\t[MAPM Version %s]\n\n",
209 version_info);
210
211 fprintf(stderr,
212 "operators : + : add s : sin\n\
213 - : subtract c : cos\n\
214 x : multiply (*) t : tan\n\
215 / : divide q : sqrt\n\
216 \\ : integer divide (i) as : arc-sin\n\
217 ! : factorial ac : arc-cos\n");
218
219 fprintf(stderr,
220 " x2 : x ^ 2 at : arc-tan\n\
221 r : 1 / x at2 : arc-tan2 (y,x)\n\
222 lg : log e : e ^ x\n\
223 lg10 : log10 p : y ^ x\n\
224 xy : x<>y (exchange x,y) n : +/- (negate (h))\n");
225
226 fprintf(stderr,
227 " hs : sinh has : arc-sinh\n\
228 hc : cosh hac : arc-cosh\n\
229 ht : tanh hat : arc-tanh\n\
230 b : cube root d : dup (HP-Enter)\n");
231
232 fprintf(stderr,
233 " f : floor cl : ceil\n\
234 gcd : GCD lcm : LCM\n\
235 s# : save memory, # = 0-9,a-z r# : recall memory, # = 0-9,a-z\n\
236 pi : 3.14159.. mod : modulus (%%)\n");
237
238 exit(2);
239 }
240
241 /* leave arg1, arg2 uninitialized on purpose */
242 /* */
243 /* analagous to : int *arg1, buffer[NN]; */
244 /* arg1 = buffer; */
245
246 apmtmp = m_apm_init();
247
248 for (k=0; k < STACK_SIZE; k++)
249 calc_stack_data[k] = m_apm_init();
250
251 for (k=0; k < 36; k++)
252 {
253 memory_data[k] = m_apm_init();
254 memory_ref[k] = 0;
255 }
256
257 /*
258 * normally, stack_pointer would be 0 and we would
259 * check all operations on it to verify it never
260 * went < 0. since this is a just demo program and not
261 * a 'real' application, we will just warn the user
262 * at the end if a potential stack underflow occurred.
263 * we can likely force a run-time core dump with 16
264 * math operations with no numbers to work with :
265 * i.e. -> calc + + + + ... 16 times
266 */
267
268 stack_pointer = 16;
269 decimal_places = 30;
270 ilow = 1;
271
272 strcpy(in_buffer, argv[1]);
273 lowercase(in_buffer);
274 if ((cp = strstr(in_buffer,"-d")) != NULL)
275 {
276 ilow++;
277 cp += 2;
278 decimal_places = atoi(cp);
279 if (decimal_places < 2)
280 decimal_places = 2;
281 }
282
283 for (ii=ilow; ii < argc; ii++)
284 {
285 strcpy(in_buffer, argv[ii]);
286 lowercase(in_buffer);
287 k = 0;
288
289 while (1)
290 {
291 /*
292 * if the first char is a digit, we assume this is a number
293 */
294
295 if (k == 0)
296 {
297 if (isdigit((int)*in_buffer))
298 {
299 stack_pointer++;
300 m_apm_set_string(calc_stack_data[stack_pointer], in_buffer);
301 break;
302 }
303 }
304
305 /*
306 * at end of operator table ?? if so, see if we have
307 * a memory operator. if not, assume this is a number.
308 */
309
310 if (operator_lookup[k].calling_convention == M_END)
311 {
312 /*
313 * see if we have a 'memory' operator
314 */
315
316 len = strlen(in_buffer);
317 ch0 = in_buffer[0];
318 ch1 = in_buffer[1];
319
320 if (ch0 == 's' || ch0 == 'r')
321 {
322 /* s[0-9,a-z] or r[0-9,a-z] */
323
324 index = -1;
325
326 if (ch1 >= '0' && ch1 <= '9')
327 index = (int)ch1 - '0';
328
329 if (ch1 >= 'a' && ch1 <= 'z')
330 index = (int)ch1 + 10 - 'a';
331
332 if (len == 2 && index >= 0)
333 {
334 if (ch0 == 'r') /* re-call memory */
335 {
336 if (memory_ref[index] != 0)
337 {
338 stack_pointer++;
339 arg1 = memory_data[index];
340 m_apm_copy(calc_stack_data[stack_pointer], arg1);
341 }
342 else
343 {
344 fprintf(stderr,
345 "Warning!, Using un-initialized memory location : \'%c\'\n",ch1);
346 }
347 }
348 else /* store memory */
349 {
350 arg1 = memory_data[index];
351 m_apm_copy(arg1, calc_stack_data[stack_pointer]);
352 memory_ref[index] = 1;
353 }
354 }
355 else
356 {
357 fprintf(stderr,
358 "Error!, Memory command error : Syntax s[0-9,a-z] or r[0-9,a-z]\n");
359 exit(4);
360 }
361 }
362 else /* assume this is a number */
363 {
364 stack_pointer++;
365 m_apm_set_string(calc_stack_data[stack_pointer], in_buffer);
366 }
367
368 break;
369 }
370
371 if (strcmp(operator_lookup[k].operator, in_buffer) == 0)
372 {
373 /*
374 * we found an operator, so do it
375 */
376
377 if (operator_lookup[k].calling_convention == Mi)
378 {
379 fp = operator_lookup[k].funcname;
380 (*fp)(apmtmp, (decimal_places + 6));
381 m_apm_copy(calc_stack_data[++stack_pointer], apmtmp);
382 }
383
384 if (operator_lookup[k].calling_convention == MXY)
385 {
386 arg2 = calc_stack_data[stack_pointer - 1];
387 arg1 = calc_stack_data[stack_pointer];
388
389 m_apm_copy(apmtmp, arg1);
390 m_apm_copy(arg1, arg2);
391 m_apm_copy(arg2, apmtmp);
392 }
393
394 if (operator_lookup[k].calling_convention == MDUP)
395 {
396 arg1 = calc_stack_data[stack_pointer];
397 m_apm_copy(calc_stack_data[++stack_pointer], arg1);
398 }
399
400 if (operator_lookup[k].calling_convention == MMM)
401 {
402 fp = operator_lookup[k].funcname;
403 arg2 = calc_stack_data[stack_pointer];
404 arg1 = calc_stack_data[--stack_pointer];
405 (*fp)(apmtmp, arg1, arg2);
406 m_apm_copy(arg1, apmtmp);
407 }
408
409 if (operator_lookup[k].calling_convention == MiMM)
410 {
411 fp = operator_lookup[k].funcname;
412 arg2 = calc_stack_data[stack_pointer];
413 arg1 = calc_stack_data[--stack_pointer];
414 (*fp)(apmtmp, (decimal_places + 6), arg1, arg2);
415 m_apm_copy(arg1, apmtmp);
416 }
417
418 if (operator_lookup[k].calling_convention == MM)
419 {
420 fp = operator_lookup[k].funcname;
421 arg1 = calc_stack_data[stack_pointer];
422 (*fp)(apmtmp, arg1);
423 m_apm_copy(arg1, apmtmp);
424 }
425
426 if (operator_lookup[k].calling_convention == MiM)
427 {
428 fp = operator_lookup[k].funcname;
429 arg1 = calc_stack_data[stack_pointer];
430 (*fp)(apmtmp, (decimal_places + 6), arg1);
431 m_apm_copy(arg1, apmtmp);
432 }
433
434 break;
435 }
436
437 k++;
438 }
439 }
440
441 if (stack_pointer <= 16)
442 {
443 fprintf(stderr,"Warning!, stack under-flow, result is unreliable\n");
444 }
445
446 arg1 = calc_stack_data[stack_pointer];
447 m_apm_round(apmtmp, decimal_places, arg1);
448
449 /*
450 * if the exponent is >= -4 && <= 6,
451 * use the fixed point format
452 */
453
454 k = m_apm_exponent(apmtmp);
455 if (k >= -4 && k <= 6)
456 {
457 out_buffer = m_apm_to_fixpt_stringexp(-1, apmtmp, '.', 0, 0);
458 }
459 else
460 {
461 out_buffer = (char *)malloc(decimal_places + 16);
462
463 if (out_buffer != NULL)
464 {
465 m_apm_to_string(out_buffer, -1, apmtmp);
466 }
467 }
468
469 if (out_buffer == NULL)
470 {
471 fprintf(stderr,"calc: out of memory\n");
472 exit(4);
473 }
474
475 printf("%s\n",out_buffer);
476
477 for (k=0; k < STACK_SIZE; k++)
478 m_apm_free(calc_stack_data[k]);
479
480 for (k=0; k < 36; k++)
481 m_apm_free(memory_data[k]);
482
483 m_apm_free(apmtmp);
484 m_apm_free_all_mem();
485
486 free(out_buffer);
487
488 exit(0);
489 }
490 /***********************************************************************/
491 void calc_square(M_APM rr, M_APM xx)
492 {
493 m_apm_multiply(rr, xx, xx);
494 }
495 /***********************************************************************/
496 void calc_mod(M_APM mm, M_APM aa, M_APM bb)
497 {
498 M_APM qq;
499
500 qq = m_apm_init();
501
502 m_apm_integer_div_rem(qq, mm, aa, bb);
503
504 m_apm_free(qq);
505 }
506 /***********************************************************************/
507 void calc_pi(M_APM rr, int p)
508 {
509 M_APM aa;
510
511 if (p > 115)
512 {
513 aa = m_apm_init();
514
515 /* compute : PI = 2 * asin(1) */
516
517 m_apm_asin(aa, (p + 2), MM_One);
518 m_apm_add(rr, aa, aa);
519
520 m_apm_free(aa);
521 }
522 else
523 m_apm_round(rr, p, MM_PI);
524 }
525 /***********************************************************************/
526 char *lowercase(char *s)
527 {
528 char *p;
529
530 p = s;
531 while (1)
532 {
533 if (*p >= 'A' && *p <= 'Z') *p += 'a' - 'A';
534 if (*p++ == 0) break;
535 }
536 return(s);
537 }
538 /***********************************************************************/