/* ** BASE.C Handles float to ASCII and ASCII to float conversion ** in any number base. ** Will Menninger, 11-14-92, ANSI C ** ** Eval is a floating point expression evaluator. ** This file last updated in version 1.10 ** For the version number, see eval.h ** Copyright (C) 1993 Will Menninger ** ** This program is free software; you can redistribute it and/or modify it ** under the terms of the GNU General Public License as published by the ** Free Software Foundation; either version 2 of the License, or any ** later version. ** ** This program is distributed in the hope that it will be useful, but ** WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** General Public License for more details. ** ** You should have received a copy of the GNU General Public License along ** with this program; if not, write to the Free Software Foundation, Inc., ** 675 Mass Ave, Cambridge, MA 02139, USA. ** ** The author until 9/93 can be contacted at: ** e-mail: willus@ilm.pfc.mit.edu ** U.S. mail: Will Menninger, 45 River St., #2, Boston, MA 02108-1124 ** ** */ #include "eval.h" #include #define SCI 1 #define FREE 3 static int sigfig; static int maxexp; static int fixed; static int sci; static int dplace; static int maxdigits; static int ibase; static int obase; static void sci_out(double val,char *buf); static void intadd(int x); static void free_out(double val,char *buf); static int digval(char c); static int ascii_int(int base,char *s); static void addtobuf(char *s); static void initbuf(char *s); static void incbuf(char c); void baseconv(double val,char *buf) { if (sci) sci_out(val,buf); else free_out(val,buf); } void set_scinote(int val) { sci=val; } void set_sigfig(int val) { sigfig=val; } void set_dplace(int val) { dplace=val; } void set_maxexp(int val) { maxexp=val; } void set_fix(int val) { fixed=val; } void setobase(int base) { obase=base; maxdigits=precision(base); } void setibase(int base) { ibase=base; } int getobase(void) { return(obase); } int getibase(void) { return(ibase); } int get_scinote(void) { return(sci); } int get_fix(void) { return(fixed); } int precision(int base) { return((int)(DBL_MANT_DIG*log(2.)/log((double)base))); } void print_outtype(void) { printf("\nScientific notation: %s\n",sci ? "ON" : "OFF"); printf("Significant digits: "); if (sigfig>0) printf("%d",sigfig); else printf("max"); if (!sci && fixed) printf(" (ignored)"); printf("\n"); printf("Fixed precision: %s",fixed ? "ON" : "OFF"); if (sci) printf(" (trailing zeroes printed.)"); printf("\n"); printf("Digits after the decimal: %d",dplace); if (sci || !fixed) printf(" (ignored)"); printf("\n"); printf("Exponent limit: "); if (maxexp<0) printf("none"); else printf("%d",maxexp); if (sci) printf(" (ignored)"); printf("\n\n"); } double asciiconv(int base,char *s) { double val; int i,div,expc; for (i=0;s[i]!=EOS;i++) s[i]=tolower((int)s[i]); expc= base>14 ? '\\' : 'e'; div=-1; val=0; for (i=0;s[i]!=expc && s[i]!='\\' && s[i]!=EOS;i++) { if (s[i]=='.') { div++; continue; } if (div>=0) div++; val=val*base+digval(s[i]); } if (div<0) div=0; if (s[i]!=EOS) div-=ascii_int(base,&s[i+1]); if (div!=0) val=val/pow((double)base,(double)div); return(val); } static int ascii_int(int base,char *s) { int i,val,sign; val=0; if (s[0]=='-' || s[0]=='+') { sign=(s[0]=='+'); i=1; } else { sign=1; i=0; } for (;s[i]!=EOS;i++) val=base*val+digval(s[i]); return(sign ? val : -val); } static int digval(char c) { c=tolower((int)c); return((int)(c<='9' ? c-'0' : c-'a'+10)); } static void sci_out(double val,char *buf) { double ex,f; int sf,sn,i,j,iex,dec,nz; initbuf(buf); if (sigfig<=0) sf=maxdigits; else sf=sigfig; if (val==0.) { incbuf((char)'0'); if (fixed && sf>1) { incbuf((char)'.'); for (i=1;i14 ? " x 10^0":"e0"); return; } sn=val>0; val=fabs(val); ex=log(val)/log((double)obase); ex=floor(ex)+1.; iex=ex; val=val+(obase/2.)*pow((double)obase,ex-1.-sf); f=val/pow((double)obase,ex); if (f>=1.) { f=f/obase; iex++; } initbuf(buf); dec=0; nz=0; if (!sn) incbuf((char)'-'); for (i=0;i=maxdigits) nz++; else { f=f*obase; if (f>=1.) { if (dec) { incbuf((char)'.'); dec=0; } if (nz) { for (j=0;j14 ? " x 10^" : "e"); intadd(iex-1); } static void intadd(int x) { char temp[100]; int i,j,sn; if (!x) { incbuf((char)'0'); return; } sn=(x>=0); if (x<0) x=-x; for (i=0;x;i++) { j=x%obase; temp[i]=j<10 ? j+'0' : 'A'+j-10; x/=obase; } if (!sn) incbuf((char)'-'); for (j=i-1;j>=0;j--) incbuf((char)temp[j]); } static void free_out(double val,char *buf) { double ex,f; int sf,sn,i,j,k,iex,iex2,nz,dec; initbuf(buf); if (fixed || sigfig<=0) sf=maxdigits; else sf=sigfig; if (val==0.) { incbuf((char)'0'); if (fixed) { if (dplace>0) incbuf((char)'.'); for (i=0;i0; val=fabs(val); ex=log(val)/log((double)obase); ex=floor(ex)+1.; if (maxexp>=0 && fabs(ex)>=maxexp+1) { sci_out(sn ? val : -val,buf); return; } iex=ex; if (fixed) iex2=-1-dplace; else iex2=ex-1-sf; val=val+(obase/2.)*pow((double)obase,(double)iex2); if (iex-maxdigits-1=1.) { f=f/obase; iex++; } k=iex; if (!sn) incbuf((char)'-'); dec=0; nz=0; if (fixed && iex<=-dplace) { incbuf((char)'0'); if (dplace>0) { incbuf((char)'.'); for (j=0;j=1.) { if (dec) { incbuf((char)'.'); dec=0; } if (nz) { for (j=0;j0) for (;k>0;k--) incbuf((char)'0'); if (fixed) { if (dec) incbuf((char)'.'); if (nz) for (j=0;jMAXOUTLEN-50) return; if (bufindex==MAXOUTLEN-50) { bufindex++; strcat(bufptr,"*** BUFFER OVERFLOW!"); return; } bufptr[bufindex++]=c; bufptr[bufindex]=EOS; }