📄 calc.c
字号:
/* * M_APM - calc.c * * Copyright (C) 1999 Michael C. Ring * * Permission to use, copy, and distribute this software and its * documentation for any purpose with or without fee is hereby granted, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. * * Permission to modify the software is granted, but not the right to * distribute the modified code. Modifications are to be distributed * as patches to released version. * * This software is provided "as is" without express or implied warranty. *//* * $Id: calc.c,v 1.6 1999/07/05 15:06:04 mike Exp $ * * RPN Calculator : demo of the MAPM math library * * This file contains the validation test program. It compares * the M_APM library to the standard C lbrary math functions. * * $Log: calc.c,v $ * Revision 1.6 1999/07/05 15:06:04 mike * added DUP operator * * Revision 1.5 1999/06/01 02:35:00 mike * fix isdigit call with cast * * Revision 1.4 1999/05/28 21:17:11 mike * break up usage into 2 printf so dos compile doesnt choke * * Revision 1.3 1999/05/19 02:29:44 mike * added version of calc to usage line * * Revision 1.2 1999/05/19 02:18:33 mike * added check for stack under-flow * * Revision 1.1 1999/05/19 02:01:02 mike * Initial revision */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include "m_apm.h"/* prototypes for functions in this file */void calc_reciprocal(M_APM, int, M_APM);void calc_square(M_APM, int, M_APM);void calc_pi(M_APM, int);char *lowercase(char *);char *out_buffer;char in_buffer[4096];#define STACK_SIZE 96M_APM calc_stack_data[STACK_SIZE];#define NUM_OPERATOR_ENTRIES 27 /* number of operators *//* calling convention for various MAPM library functions ... */#define MMM 0x0A01 /* ( MAPM, MAPM, MAPM ) */#define MiMM 0x0A02 /* ( MAPM, int, MAPM, MAPM ) */#define MiM 0x0A03 /* ( MAPM, int, MAPM ) */#define Mi 0x0A04 /* ( MAPM, int ) */#define MM 0x0A05 /* ( MAPM, MAPM ) */#define MXY 0x0A80 /* special for x <> y */#define MDUP 0x0A81 /* special for dup */#define M_END 0x0AFF /* end of table flag */struct opstr { char operator[16]; int calling_convention; void (*funcname)();};struct opstr operator_lookup[NUM_OPERATOR_ENTRIES] = { { "+", MMM, m_apm_add, /* 0 */ }, { "-", MMM, m_apm_subtract, /* 1 */ }, { "*", MMM, m_apm_multiply, /* 2 */ }, { "x", MMM, m_apm_multiply, /* 3 */ }, { "/", MiMM, m_apm_divide, /* 4 */ }, { "\\", MMM, m_apm_integer_divide, /* 5 */ }, { "i", MMM, m_apm_integer_divide, /* 6 */ }, { "!", MM, m_apm_factorial, /* 7 */ }, { "s", MiM, m_apm_sin, /* 8 */ }, { "c", MiM, m_apm_cos, /* 9 */ }, { "t", MiM, m_apm_tan, /* 10 */ }, { "q", MiM, m_apm_sqrt, /* 11 */ }, { "as", MiM, m_apm_arcsin, /* 12 */ }, { "ac", MiM, m_apm_arccos, /* 13 */ }, { "at", MiM, m_apm_arctan, /* 14 */ }, { "at2", MiMM, m_apm_arctan2, /* 15 */ }, { "lg", MiM, m_apm_log, /* 16 */ }, { "lg10", MiM, m_apm_log10, /* 17 */ }, { "e", MiM, m_apm_exp, /* 18 */ }, { "p", MiMM, m_apm_pow, /* 19 */ }, { "h", MM, m_apm_negate, /* 20 */ }, { "xy", MXY, NULL, /* 21 */ }, { "d", MDUP, NULL, /* 22 */ }, { "r", MiM, calc_reciprocal, /* 23 */ }, { "x2", MiM, calc_square, /* 24 */ }, { "pi", Mi, calc_pi, /* 25 */ }, { "ZZZ", M_END, NULL /* 26 */ } }; int main(argc, argv)int argc; char *argv[];{void (*fp)();char *cp;int ii, ilow, stack_pointer, decimal_places, k;M_APM apmtmp;M_APM arg1; M_APM arg2;if (argc < 2) { fprintf(stderr,"calc [-d##] <numbers,operators>\t\t\t\t[Version 1.1]\n"); fprintf(stderr," -d : specify decimal places, default = 20\n\n"); fprintf(stderr,"operators : + : add s : sin\n\ - : subtract c : cos\n\ x : multiply (*) t : tan\n\ / : divide q : sqrt\n\ \\ : integer divide (i) as : arc-sin\n\ ! : factorial ac : arc-cos\n"); fprintf(stderr," x2 : x ^ 2 at : arc-tan\n\ r : 1 / x at2 : arc-tan2 (y,x)\n\ lg : log e : e ^ x\n\ lg10 : log10 p : y ^ x\n\ xy : x<>y (exchange x,y) h : +/- (change sign)\n\ d : dup pi : 3.14159.. \n\"); exit(2); }/* leave arg1, arg2 uninitialized on purpose *//* *//* analagous to : int *arg1, buffer[NN]; *//* arg1 = buffer; */apmtmp = m_apm_init();for (k=0; k < STACK_SIZE; k++) calc_stack_data[k] = m_apm_init();/* * normally, stack_pointer would be 0 and we would * check all operations on it to verify it never * went < 0. since this is a just demo program and not * a 'real' application, we will just warn the user * at the end if a potential stack underflow occurred. * we can likely force a run-time core dump with 16 * math operations with no numbers to work with : * i.e. -> calc + + + + ... 16 times */stack_pointer = 16;decimal_places = 20;ilow = 1;strcpy(in_buffer, argv[1]);lowercase(in_buffer);if ((cp = strstr(in_buffer,"-d")) != NULL) { ilow++; cp += 2; decimal_places = atoi(cp); if (decimal_places < 2) decimal_places = 2; }for (ii=ilow; ii < argc; ii++) { strcpy(in_buffer, argv[ii]); lowercase(in_buffer); k = 0; while (1) { /* * if we reached the end of the table or the first * char is a digit, we assume this is a number */ if (operator_lookup[k].calling_convention == M_END || isdigit((int)*in_buffer)) { stack_pointer++; m_apm_set_string(calc_stack_data[stack_pointer], in_buffer); break; } if (strcmp(operator_lookup[k].operator, in_buffer) == 0) { /* * we found an operator, so do it */ if (operator_lookup[k].calling_convention == Mi) { fp = operator_lookup[k].funcname; (*fp)(apmtmp, decimal_places); m_apm_copy(calc_stack_data[++stack_pointer], apmtmp); } if (operator_lookup[k].calling_convention == MXY) { arg2 = calc_stack_data[stack_pointer - 1]; arg1 = calc_stack_data[stack_pointer]; m_apm_copy(apmtmp, arg1); m_apm_copy(arg1, arg2); m_apm_copy(arg2, apmtmp); } if (operator_lookup[k].calling_convention == MDUP) { arg1 = calc_stack_data[stack_pointer]; m_apm_copy(calc_stack_data[++stack_pointer], arg1); } if (operator_lookup[k].calling_convention == MMM) { fp = operator_lookup[k].funcname; arg2 = calc_stack_data[stack_pointer]; arg1 = calc_stack_data[--stack_pointer]; (*fp)(apmtmp, arg1, arg2); m_apm_copy(arg1, apmtmp); } if (operator_lookup[k].calling_convention == MiMM) { fp = operator_lookup[k].funcname; arg2 = calc_stack_data[stack_pointer]; arg1 = calc_stack_data[--stack_pointer]; (*fp)(apmtmp, decimal_places, arg1, arg2); m_apm_copy(arg1, apmtmp); } if (operator_lookup[k].calling_convention == MM) { fp = operator_lookup[k].funcname; arg1 = calc_stack_data[stack_pointer]; (*fp)(apmtmp, arg1); m_apm_copy(arg1, apmtmp); } if (operator_lookup[k].calling_convention == MiM) { fp = operator_lookup[k].funcname; arg1 = calc_stack_data[stack_pointer]; (*fp)(apmtmp, decimal_places, arg1); m_apm_copy(arg1, apmtmp); } break; } k++; } }if ((out_buffer = (char *)malloc(decimal_places + 16)) == NULL) { fprintf(stderr,"out of memory\n"); exit(6); }if (stack_pointer <= 16) { fprintf(stderr,"Warning!, stack under-flow, result is unreliable\n"); }arg1 = calc_stack_data[stack_pointer];m_apm_round(apmtmp, decimal_places, arg1);m_apm_to_string(out_buffer, -1, apmtmp);printf("%s\n",out_buffer);for (k=0; k < STACK_SIZE; k++) m_apm_free(calc_stack_data[k]);m_apm_free(apmtmp);free(out_buffer);exit(0);}/***********************************************************************/void calc_reciprocal(rr, p, xx)M_APM rr, xx;int p;{m_apm_divide(rr, p, MM_One, xx);}/***********************************************************************/void calc_square(rr, p, xx)M_APM rr, xx;int p;{m_apm_multiply(rr, xx, xx);}/***********************************************************************/void calc_pi(rr, p)M_APM rr;int p;{m_apm_round(rr, p, MM_PI);}/***********************************************************************/char *lowercase(s)char *s;{register char *p;p = s;while (1) { if (*p >= 'A' && *p <= 'Z') *p += 'a' - 'A'; if (*p++ == 0) break; }return(s);}/***********************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -