home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of A1200
/
World_Of_A1200.iso
/
programs
/
misc
/
eval
/
source
/
src.lha
/
base.c
next >
Wrap
C/C++ Source or Header
|
1993-04-13
|
9KB
|
503 lines
/*
** 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 <float.h>
#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;i<sf;i++)
incbuf((char)'0');
}
addtobuf(obase>14 ? " 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<sf;i++)
{
if (i==1)
dec=1;
if (i>=maxdigits)
nz++;
else
{
f=f*obase;
if (f>=1.)
{
if (dec)
{
incbuf((char)'.');
dec=0;
}
if (nz)
{
for (j=0;j<nz;j++)
incbuf((char)'0');
nz=0;
}
j=f;
incbuf((char)(j<10 ? '0'+j : 'A'+j-10));
f=f-j;
}
else
nz++;
}
}
if (fixed)
{
if (dec)
incbuf((char)'.');
if (nz)
for (j=0;j<nz;j++)
incbuf((char)'0');
}
addtobuf(obase>14 ? " 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;i<dplace;i++)
incbuf((char)'0');
}
return;
}
sn=val>0;
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<iex2)
val=val+pow((double)obase,(double)iex-maxdigits);
f=val/pow((double)obase,ex);
if (f>=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<dplace;j++)
incbuf((char)'0');
}
return;
}
if (iex<=0)
{
incbuf((char)'0');
dec=1;
nz=-iex;
}
for (i=0;fixed || i<sf;i++)
{
f=f*obase;
if (i<maxdigits && f>=1.)
{
if (dec)
{
incbuf((char)'.');
dec=0;
}
if (nz)
{
for (j=0;j<nz;j++)
incbuf((char)'0');
nz=0;
}
j=f;
incbuf((char)(j<10 ? '0'+j : 'A'+j-10));
f=f-j;
}
else
if (k<=0)
nz++;
else
incbuf((char)'0');
k--;
if (fixed && k<=-dplace)
break;
if (k==0)
dec=1;
}
if (k>0)
for (;k>0;k--)
incbuf((char)'0');
if (fixed)
{
if (dec)
incbuf((char)'.');
if (nz)
for (j=0;j<nz;j++)
incbuf((char)'0');
}
}
static void addtobuf(char *s)
{
int i;
for (i=0;s[i]!=EOS;i++)
incbuf((char)s[i]);
}
static int bufindex;
static char *bufptr;
static void initbuf(char *s)
{
bufindex=0;
bufptr=s;
}
static void incbuf(char c)
{
if (bufindex>MAXOUTLEN-50)
return;
if (bufindex==MAXOUTLEN-50)
{
bufindex++;
strcat(bufptr,"*** BUFFER OVERFLOW!");
return;
}
bufptr[bufindex++]=c;
bufptr[bufindex]=EOS;
}