Back to index

tetex-bin  3.0
numbers.c
Go to the documentation of this file.
00001 /*  $Header$
00002 
00003     This is dvipdfm, a DVI to PDF translator.
00004     Copyright (C) 1998, 1999 by Mark A. Wicks
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019     
00020     The author may be contacted via the e-mail address
00021 
00022        mwicks@kettering.edu
00023 */
00024 
00025 #include "system.h"  
00026 #include "error.h"
00027 #include "mfileio.h"
00028 #include "numbers.h"
00029 
00030 UNSIGNED_BYTE get_unsigned_byte (FILE *file)
00031 {
00032   int ch;
00033   if ((ch = fgetc (file)) < 0)
00034     ERROR ("File ended prematurely\n");
00035   return (UNSIGNED_BYTE) ch;
00036 }
00037 
00038 UNSIGNED_BYTE sget_unsigned_byte (char *s)
00039 {
00040   return *((unsigned char *) s);
00041 }
00042 
00043 SIGNED_BYTE get_signed_byte (FILE *file)
00044 {
00045   int byte;
00046   byte = get_unsigned_byte(file);
00047   if (byte >= 0x80) 
00048     byte -= 0x100;
00049   return (SIGNED_BYTE) byte;
00050 }
00051 
00052 UNSIGNED_PAIR get_unsigned_pair (FILE *file)
00053 {
00054   int i;
00055   UNSIGNED_BYTE byte;
00056   UNSIGNED_PAIR pair = 0;
00057   for (i=0; i<2; i++) {
00058     byte = get_unsigned_byte(file);
00059     pair = pair*0x100u + byte;
00060   }
00061   return pair;
00062 }
00063 
00064 UNSIGNED_PAIR sget_unsigned_pair (unsigned char *s)
00065 {
00066   int i;
00067   UNSIGNED_BYTE byte;
00068   UNSIGNED_PAIR pair = 0;
00069   for (i=0; i<2; i++) {
00070     byte = *(s++);
00071     pair = pair*0x100u + byte;
00072   }
00073   return pair;
00074 }
00075 
00076 SIGNED_PAIR get_signed_pair (FILE *file)
00077 {
00078   int i;
00079   long pair = 0;
00080   for (i=0; i<2; i++) {
00081     pair = pair*0x100 + get_unsigned_byte(file);
00082   }
00083   if (pair >= 0x8000) {
00084     pair -= 0x10000l;
00085   }
00086   return (SIGNED_PAIR) pair;
00087 }
00088 
00089 
00090 UNSIGNED_TRIPLE get_unsigned_triple(FILE *file)
00091 {
00092   int i;
00093   long triple = 0;
00094   for (i=0; i<3; i++) {
00095     triple = triple*0x100u + get_unsigned_byte(file);
00096   }
00097   return (UNSIGNED_TRIPLE) triple;
00098 }
00099 
00100 SIGNED_TRIPLE get_signed_triple(FILE *file)
00101 {
00102   int i;
00103   long triple = 0;
00104   for (i=0; i<3; i++) {
00105     triple = triple*0x100 + get_unsigned_byte(file);
00106   }
00107   if (triple >= 0x800000l) 
00108     triple -= 0x1000000l;
00109   return (SIGNED_TRIPLE) triple;
00110 }
00111 
00112 SIGNED_QUAD get_signed_quad(FILE *file)
00113 {
00114   int byte, i;
00115   long quad = 0;
00116 
00117   /* Check sign on first byte before reading others */
00118   byte = get_unsigned_byte(file);
00119   quad = byte;
00120   if (quad >= 0x80) 
00121     quad = byte - 0x100;
00122   for (i=0; i<3; i++) {
00123     quad = quad*0x100 + get_unsigned_byte(file);
00124   }
00125   return (SIGNED_QUAD) quad;
00126 }
00127 
00128 UNSIGNED_QUAD get_unsigned_quad(FILE *file)
00129 {
00130   int i;
00131   unsigned long quad = 0;
00132   for (i=0; i<4; i++) {
00133     quad = quad*0x100u + get_unsigned_byte(file);
00134   }
00135   return (UNSIGNED_QUAD) quad;
00136 }
00137 
00138 SIGNED_QUAD sqxfw (SIGNED_QUAD sq, fixword fw)
00139 {
00140   int sign = 1;
00141   unsigned long a, b, c, d, ad, bd, bc, ac;
00142   unsigned long e, f, g, h, i, j, k;
00143   unsigned long result;
00144   /* Make positive. */
00145   if (sq < 0) {
00146     sign = -sign;
00147     sq = -sq;
00148   }
00149   if (fw < 0) {
00150     sign = -sign;
00151     fw = -fw;
00152   }
00153   a = ((unsigned long) sq) >> 16u;
00154   b = ((unsigned long) sq) & 0xffffu;
00155   c = ((unsigned long) fw) >> 16u;
00156   d = ((unsigned long) fw) & 0xffffu;
00157   ad = a*d; bd = b*d; bc = b*c; ac = a*c;
00158   e = bd >> 16u;
00159   f = ad >> 16u;
00160   g = ad & 0xffffu;
00161   h = bc >> 16u;
00162   i = bc & 0xffffu;
00163   j = ac >> 16u;
00164   k = ac & 0xffffu;
00165   result = (e+g+i + (1<<3)) >> 4u;  /* 1<<3 is for rounding */
00166   result += (f+h+k) << 12u;
00167   result += j << 28u;
00168   return (sign>0)?result:-result;
00169 }
00170 
00171 SIGNED_QUAD axboverc (SIGNED_QUAD n1, SIGNED_QUAD n2, SIGNED_QUAD div)
00172 {
00173   int sign = 1;
00174   unsigned long a, b, c, d, ad, bd, bc, ac, e, f, g, h, i, j, o;
00175   unsigned long high, low;
00176   SIGNED_QUAD result = 0;
00177   /*  Make positive. */
00178   if (n1 < 0) {
00179     sign = -sign;
00180     n1 = -n1;
00181   }
00182   if (n2 < 0) {
00183     sign = -sign;
00184     n2 = -n2;
00185   }
00186   if (div < 0) {
00187     sign = -sign;
00188     div = -div;
00189   }
00190   a = ((unsigned long) n1) >> 16u;
00191   b = ((unsigned long) n1) & 0xffffu;
00192   c = ((unsigned long) n2) >> 16u;
00193   d = ((unsigned long) n2) & 0xffffu;
00194   ad = a*d; bd = b*d; bc = b*c; ac = a*c;
00195   e = bd >> 16u; f = bd & 0xffffu;
00196   g = ad >> 16u; h = ad & 0xffffu;
00197   i = bc >> 16u; j = bc & 0xffffu;
00198   o = e+h+j;
00199   high = g+i+(o>>16u)+ac; o &= 0xffffu;
00200   low = (o << 16) + f;
00201   if (high >= div)
00202     ERROR ("Overflow in axboc");
00203   {
00204     int i;
00205     for (i=0; i<32; i++) {
00206       high *= 2;
00207       result *= 2;
00208       if (low >= 0x80000000) {
00209        low -= 0x80000000;
00210        high += 1;
00211       }
00212       low *= 2;
00213       if (high > div) {
00214        high -= div;
00215        result += 1;
00216       }
00217     }
00218   }
00219   high *= 2;
00220   if (high >= div)
00221     result += 1;
00222   return (sign>0)?result:-result;
00223 }
00224 
00225 /* Create a  private_itoa to be used internally in the
00226    hopes that a good optimizing compiler will use it inline */
00227 static int private_itoa (char *s, long int n, int mindigits)
00228 {
00229    int j, nwhole;
00230    char *p = s;
00231    if (n<0) {
00232       *(p++) = '-';
00233       n = -n;
00234    }
00235    /* Generate at least one digit in reverse order */
00236    nwhole = 0;
00237    do {
00238       p[nwhole++] = n%10 + '0';
00239       n /= 10;
00240    } while (n != 0 || nwhole < mindigits);
00241    /* Reverse the digits */
00242    for (j=0; j<nwhole/2; j++) {
00243       char tmp = p[j];
00244       p[j] = p[nwhole-j-1];
00245       p[nwhole-j-1]=tmp;
00246    }
00247    p += nwhole;
00248    *p = 0;
00249    return (p-s);
00250 }
00251 
00252 int inttoa (char *s, long int i)
00253 {
00254   /* Call the private one */
00255   return private_itoa (s, i, 0);
00256 }
00257 
00258 int centi_u_to_a (char *s, long int n)
00259 {
00260   char *p = s;
00261   unsigned long whole_part;
00262   int frac_part;
00263   if (n<0) {
00264     *(p++) = '-';
00265     n = -n;
00266   }
00267   whole_part = ((unsigned long) n) / 100;
00268   frac_part = ((unsigned long) n) % 100;
00269   /* Print the whole part */
00270   p += private_itoa (p, whole_part, 0);
00271   if (frac_part) {
00272     int mindigits = 2;
00273     *(p++) = '.';
00274     while (!(frac_part % 10)) {
00275       frac_part /= 10;
00276       mindigits -= 1;
00277     }
00278     p += private_itoa (p, frac_part, mindigits);
00279   }
00280   return (p-s);
00281 }
00282 
00283 int fixnumtoa (char *s, long int n)
00284 {
00285    int j, thresh;
00286    char *p = s;
00287    unsigned long whole_part, frac_part;
00288    if (n<0) {
00289       *(p++) = '-';
00290       n = -n;
00291    }
00292    whole_part = ((unsigned long) n) / (65536l);
00293    frac_part = ((unsigned long) n) % 65536l;
00294    /* Print the whole part */
00295    p += private_itoa (p, whole_part, 0);
00296 
00297    #define BASE ((unsigned long)(256*65536l))
00298    frac_part *= 256;
00299    thresh = BASE / 10000;
00300    /* Round last digit */
00301    frac_part += thresh/2;
00302    if (frac_part > thresh) {
00303       *(p++) = '.';
00304    }
00305    for (j=0; j<4 && frac_part> thresh; j++) {
00306       char next_digit;
00307       next_digit = (10*frac_part)/BASE;
00308       frac_part = (10*frac_part)%BASE;
00309       *(p++) = next_digit + '0';
00310       thresh *= 10;
00311    }
00312    *p = 0;
00313    return (p-s);
00314 }
00315 
00316 
00317