summaryrefslogtreecommitdiff
path: root/float.c
diff options
context:
space:
mode:
Diffstat (limited to 'float.c')
-rw-r--r--float.c509
1 files changed, 256 insertions, 253 deletions
diff --git a/float.c b/float.c
index e7a5fcd..75d68ef 100644
--- a/float.c
+++ b/float.c
@@ -17,89 +17,89 @@
#define TRUE 1
#define FALSE 0
-#define MANT_WORDS 6 /* 64 bits + 32 for accuracy == 96 */
-#define MANT_DIGITS 28 /* 29 digits don't fit in 96 bits */
+#define MANT_WORDS 6 /* 64 bits + 32 for accuracy == 96 */
+#define MANT_DIGITS 28 /* 29 digits don't fit in 96 bits */
/*
* guaranteed top bit of from is set
* => we only have to worry about _one_ bit shift to the left
*/
-static int ieee_multiply(unsigned short *to, unsigned short *from)
+static int ieee_multiply(unsigned short *to, unsigned short *from)
{
- unsigned long temp[MANT_WORDS*2];
- int i, j;
+ unsigned long temp[MANT_WORDS * 2];
+ int i, j;
- for (i=0; i<MANT_WORDS*2; i++)
- temp[i] = 0;
+ for (i = 0; i < MANT_WORDS * 2; i++)
+ temp[i] = 0;
- for (i=0; i<MANT_WORDS; i++)
- for (j=0; j<MANT_WORDS; j++) {
- unsigned long n;
- n = (unsigned long)to[i] * (unsigned long)from[j];
- temp[i+j] += n >> 16;
- temp[i+j+1] += n & 0xFFFF;
- }
+ for (i = 0; i < MANT_WORDS; i++)
+ for (j = 0; j < MANT_WORDS; j++) {
+ unsigned long n;
+ n = (unsigned long)to[i] * (unsigned long)from[j];
+ temp[i + j] += n >> 16;
+ temp[i + j + 1] += n & 0xFFFF;
+ }
- for (i=MANT_WORDS*2; --i ;) {
- temp[i-1] += temp[i] >> 16;
- temp[i] &= 0xFFFF;
+ for (i = MANT_WORDS * 2; --i;) {
+ temp[i - 1] += temp[i] >> 16;
+ temp[i] &= 0xFFFF;
}
if (temp[0] & 0x8000) {
- for (i=0; i<MANT_WORDS; i++)
- to[i] = temp[i] & 0xFFFF;
- return 0;
+ for (i = 0; i < MANT_WORDS; i++)
+ to[i] = temp[i] & 0xFFFF;
+ return 0;
} else {
- for (i=0; i<MANT_WORDS; i++)
- to[i] = (temp[i] << 1) + !!(temp[i+1] & 0x8000);
- return -1;
+ for (i = 0; i < MANT_WORDS; i++)
+ to[i] = (temp[i] << 1) + !!(temp[i + 1] & 0x8000);
+ return -1;
}
}
-static void ieee_flconvert(char *string, unsigned short *mant, long *exponent,
- efunc error)
+static void ieee_flconvert(char *string, unsigned short *mant,
+ long *exponent, efunc error)
{
- char digits[MANT_DIGITS];
- char *p, *q, *r;
+ char digits[MANT_DIGITS];
+ char *p, *q, *r;
unsigned short mult[MANT_WORDS], bit;
- unsigned short * m;
- long tenpwr, twopwr;
- int extratwos, started, seendot;
+ unsigned short *m;
+ long tenpwr, twopwr;
+ int extratwos, started, seendot;
p = digits;
tenpwr = 0;
started = seendot = FALSE;
while (*string && *string != 'E' && *string != 'e') {
- if (*string == '.') {
- if (!seendot)
- seendot = TRUE;
- else {
- error (ERR_NONFATAL,
- "too many periods in floating-point constant");
- return;
- }
- } else if (*string >= '0' && *string <= '9') {
- if (*string == '0' && !started) {
- if (seendot)
- tenpwr--;
- } else {
- started = TRUE;
- if (p < digits+sizeof(digits))
- *p++ = *string - '0';
- if (!seendot)
- tenpwr++;
- }
- } else {
- error (ERR_NONFATAL,
- "floating-point constant: `%c' is invalid character",
- *string);
- return;
- }
- string++;
+ if (*string == '.') {
+ if (!seendot)
+ seendot = TRUE;
+ else {
+ error(ERR_NONFATAL,
+ "too many periods in floating-point constant");
+ return;
+ }
+ } else if (*string >= '0' && *string <= '9') {
+ if (*string == '0' && !started) {
+ if (seendot)
+ tenpwr--;
+ } else {
+ started = TRUE;
+ if (p < digits + sizeof(digits))
+ *p++ = *string - '0';
+ if (!seendot)
+ tenpwr++;
+ }
+ } else {
+ error(ERR_NONFATAL,
+ "floating-point constant: `%c' is invalid character",
+ *string);
+ return;
+ }
+ string++;
}
if (*string) {
- string++; /* eat the E */
- tenpwr += atoi(string);
+ string++; /* eat the E */
+ tenpwr += atoi(string);
}
/*
@@ -111,37 +111,37 @@ static void ieee_flconvert(char *string, unsigned short *mant, long *exponent,
*/
bit = 0x8000;
- for (m=mant; m<mant+MANT_WORDS; m++)
- *m = 0;
+ for (m = mant; m < mant + MANT_WORDS; m++)
+ *m = 0;
m = mant;
q = digits;
started = FALSE;
twopwr = 0;
- while (m < mant+MANT_WORDS) {
- unsigned short carry = 0;
- while (p > q && !p[-1])
- p--;
- if (p <= q)
- break;
- for (r = p; r-- > q ;) {
- int i;
+ while (m < mant + MANT_WORDS) {
+ unsigned short carry = 0;
+ while (p > q && !p[-1])
+ p--;
+ if (p <= q)
+ break;
+ for (r = p; r-- > q;) {
+ int i;
- i = 2 * *r + carry;
- if (i >= 10)
- carry = 1, i -= 10;
- else
- carry = 0;
- *r = i;
- }
- if (carry)
- *m |= bit, started = TRUE;
- if (started) {
- if (bit == 1)
- bit = 0x8000, m++;
- else
- bit >>= 1;
- } else
- twopwr--;
+ i = 2 * *r + carry;
+ if (i >= 10)
+ carry = 1, i -= 10;
+ else
+ carry = 0;
+ *r = i;
+ }
+ if (carry)
+ *m |= bit, started = TRUE;
+ if (started) {
+ if (bit == 1)
+ bit = 0x8000, m++;
+ else
+ bit >>= 1;
+ } else
+ twopwr--;
}
twopwr += tenpwr;
@@ -153,22 +153,22 @@ static void ieee_flconvert(char *string, unsigned short *mant, long *exponent,
*/
if (tenpwr < 0) {
- for (m=mult; m<mult+MANT_WORDS; m++)
- *m = 0xCCCC;
- extratwos = -2;
- tenpwr = -tenpwr;
+ for (m = mult; m < mult + MANT_WORDS; m++)
+ *m = 0xCCCC;
+ extratwos = -2;
+ tenpwr = -tenpwr;
} else if (tenpwr > 0) {
- mult[0] = 0xA000;
- for (m=mult+1; m<mult+MANT_WORDS; m++)
- *m = 0;
- extratwos = 3;
+ mult[0] = 0xA000;
+ for (m = mult + 1; m < mult + MANT_WORDS; m++)
+ *m = 0;
+ extratwos = 3;
} else
- extratwos = 0;
+ extratwos = 0;
while (tenpwr) {
- if (tenpwr & 1)
- twopwr += extratwos + ieee_multiply (mant, mult);
- extratwos = extratwos * 2 + ieee_multiply (mult, mult);
- tenpwr >>= 1;
+ if (tenpwr & 1)
+ twopwr += extratwos + ieee_multiply(mant, mult);
+ extratwos = extratwos * 2 + ieee_multiply(mult, mult);
+ tenpwr >>= 1;
}
/*
@@ -183,29 +183,29 @@ static void ieee_flconvert(char *string, unsigned short *mant, long *exponent,
/*
* Shift a mantissa to the right by i (i < 16) bits.
*/
-static void ieee_shr(unsigned short *mant, int i)
+static void ieee_shr(unsigned short *mant, int i)
{
unsigned short n = 0, m;
- int j;
+ int j;
- for (j=0; j<MANT_WORDS; j++) {
- m = (mant[j] << (16-i)) & 0xFFFF;
- mant[j] = (mant[j] >> i) | n;
- n = m;
+ for (j = 0; j < MANT_WORDS; j++) {
+ m = (mant[j] << (16 - i)) & 0xFFFF;
+ mant[j] = (mant[j] >> i) | n;
+ n = m;
}
}
/*
* Round a mantissa off after i words.
*/
-static int ieee_round(unsigned short *mant, int i)
+static int ieee_round(unsigned short *mant, int i)
{
if (mant[i] & 0x8000) {
- do {
- ++mant[--i];
- mant[i] &= 0xFFFF;
- } while (i > 0 && !mant[i]);
- return !i && !mant[i];
+ do {
+ ++mant[--i];
+ mant[i] &= 0xFFFF;
+ } while (i > 0 && !mant[i]);
+ return !i && !mant[i];
}
return 0;
}
@@ -213,191 +213,194 @@ static int ieee_round(unsigned short *mant, int i)
#define put(a,b) ( (*(a)=(b)), ((a)[1]=(b)>>8) )
static int to_double(char *str, long sign, unsigned char *result,
- efunc error)
+ efunc error)
{
unsigned short mant[MANT_WORDS];
long exponent;
sign = (sign < 0 ? 0x8000L : 0L);
- ieee_flconvert (str, mant, &exponent, error);
+ ieee_flconvert(str, mant, &exponent, error);
if (mant[0] & 0x8000) {
- /*
- * Non-zero.
- */
- exponent--;
- if (exponent >= -1022 && exponent <= 1024) {
- /*
- * Normalised.
- */
- exponent += 1023;
- ieee_shr(mant, 11);
- ieee_round(mant, 4);
- if (mant[0] & 0x20) /* did we scale up by one? */
- ieee_shr(mant, 1), exponent++;
- mant[0] &= 0xF; /* remove leading one */
- put(result+6,(exponent << 4) | mant[0] | sign);
- put(result+4,mant[1]);
- put(result+2,mant[2]);
- put(result+0,mant[3]);
- } else if (exponent < -1022 && exponent >= -1074) {
- /*
- * Denormal.
- */
- int shift = -(exponent+1011);
- int sh = shift % 16, wds = shift / 16;
- ieee_shr(mant, sh);
- if (ieee_round(mant, 4-wds) || (sh>0 && (mant[0]&(0x8000>>(sh-1))))) {
- ieee_shr(mant, 1);
- if (sh==0)
- mant[0] |= 0x8000;
- exponent++;
- }
- put(result+6,(wds == 0 ? mant[0] : 0) | sign);
- put(result+4,(wds <= 1 ? mant[1-wds] : 0));
- put(result+2,(wds <= 2 ? mant[2-wds] : 0));
- put(result+0,(wds <= 3 ? mant[3-wds] : 0));
- } else {
- if (exponent > 0) {
- error(ERR_NONFATAL, "overflow in floating-point constant");
- return 0;
- } else
- memset (result, 0, 8);
- }
+ /*
+ * Non-zero.
+ */
+ exponent--;
+ if (exponent >= -1022 && exponent <= 1024) {
+ /*
+ * Normalised.
+ */
+ exponent += 1023;
+ ieee_shr(mant, 11);
+ ieee_round(mant, 4);
+ if (mant[0] & 0x20) /* did we scale up by one? */
+ ieee_shr(mant, 1), exponent++;
+ mant[0] &= 0xF; /* remove leading one */
+ put(result + 6, (exponent << 4) | mant[0] | sign);
+ put(result + 4, mant[1]);
+ put(result + 2, mant[2]);
+ put(result + 0, mant[3]);
+ } else if (exponent < -1022 && exponent >= -1074) {
+ /*
+ * Denormal.
+ */
+ int shift = -(exponent + 1011);
+ int sh = shift % 16, wds = shift / 16;
+ ieee_shr(mant, sh);
+ if (ieee_round(mant, 4 - wds)
+ || (sh > 0 && (mant[0] & (0x8000 >> (sh - 1))))) {
+ ieee_shr(mant, 1);
+ if (sh == 0)
+ mant[0] |= 0x8000;
+ exponent++;
+ }
+ put(result + 6, (wds == 0 ? mant[0] : 0) | sign);
+ put(result + 4, (wds <= 1 ? mant[1 - wds] : 0));
+ put(result + 2, (wds <= 2 ? mant[2 - wds] : 0));
+ put(result + 0, (wds <= 3 ? mant[3 - wds] : 0));
+ } else {
+ if (exponent > 0) {
+ error(ERR_NONFATAL, "overflow in floating-point constant");
+ return 0;
+ } else
+ memset(result, 0, 8);
+ }
} else {
- /*
- * Zero.
- */
- memset (result, 0, 8);
+ /*
+ * Zero.
+ */
+ memset(result, 0, 8);
}
- return 1; /* success */
+ return 1; /* success */
}
static int to_float(char *str, long sign, unsigned char *result,
- efunc error)
+ efunc error)
{
unsigned short mant[MANT_WORDS];
long exponent;
sign = (sign < 0 ? 0x8000L : 0L);
- ieee_flconvert (str, mant, &exponent, error);
+ ieee_flconvert(str, mant, &exponent, error);
if (mant[0] & 0x8000) {
- /*
- * Non-zero.
- */
- exponent--;
- if (exponent >= -126 && exponent <= 128) {
- /*
- * Normalised.
- */
- exponent += 127;
- ieee_shr(mant, 8);
- ieee_round(mant, 2);
- if (mant[0] & 0x100) /* did we scale up by one? */
- ieee_shr(mant, 1), exponent++;
- mant[0] &= 0x7F; /* remove leading one */
- put(result+2,(exponent << 7) | mant[0] | sign);
- put(result+0,mant[1]);
- } else if (exponent < -126 && exponent >= -149) {
- /*
- * Denormal.
- */
- int shift = -(exponent+118);
- int sh = shift % 16, wds = shift / 16;
- ieee_shr(mant, sh);
- if (ieee_round(mant, 2-wds) || (sh>0 && (mant[0]&(0x8000>>(sh-1))))) {
- ieee_shr(mant, 1);
- if (sh==0)
- mant[0] |= 0x8000;
- exponent++;
- }
- put(result+2,(wds == 0 ? mant[0] : 0) | sign);
- put(result+0,(wds <= 1 ? mant[1-wds] : 0));
- } else {
- if (exponent > 0) {
- error(ERR_NONFATAL, "overflow in floating-point constant");
- return 0;
- } else
- memset (result, 0, 4);
- }
+ /*
+ * Non-zero.
+ */
+ exponent--;
+ if (exponent >= -126 && exponent <= 128) {
+ /*
+ * Normalised.
+ */
+ exponent += 127;
+ ieee_shr(mant, 8);
+ ieee_round(mant, 2);
+ if (mant[0] & 0x100) /* did we scale up by one? */
+ ieee_shr(mant, 1), exponent++;
+ mant[0] &= 0x7F; /* remove leading one */
+ put(result + 2, (exponent << 7) | mant[0] | sign);
+ put(result + 0, mant[1]);
+ } else if (exponent < -126 && exponent >= -149) {
+ /*
+ * Denormal.
+ */
+ int shift = -(exponent + 118);
+ int sh = shift % 16, wds = shift / 16;
+ ieee_shr(mant, sh);
+ if (ieee_round(mant, 2 - wds)
+ || (sh > 0 && (mant[0] & (0x8000 >> (sh - 1))))) {
+ ieee_shr(mant, 1);
+ if (sh == 0)
+ mant[0] |= 0x8000;
+ exponent++;
+ }
+ put(result + 2, (wds == 0 ? mant[0] : 0) | sign);
+ put(result + 0, (wds <= 1 ? mant[1 - wds] : 0));
+ } else {
+ if (exponent > 0) {
+ error(ERR_NONFATAL, "overflow in floating-point constant");
+ return 0;
+ } else
+ memset(result, 0, 4);
+ }
} else {
- memset (result, 0, 4);
+ memset(result, 0, 4);
}
return 1;
}
static int to_ldoub(char *str, long sign, unsigned char *result,
- efunc error)
+ efunc error)
{
unsigned short mant[MANT_WORDS];
long exponent;
sign = (sign < 0 ? 0x8000L : 0L);
- ieee_flconvert (str, mant, &exponent, error);
+ ieee_flconvert(str, mant, &exponent, error);
if (mant[0] & 0x8000) {
- /*
- * Non-zero.
- */
- exponent--;
- if (exponent >= -16383 && exponent <= 16384) {
- /*
- * Normalised.
- */
- exponent += 16383;
- if (ieee_round(mant, 4)) /* did we scale up by one? */
- ieee_shr(mant, 1), mant[0] |= 0x8000, exponent++;
- put(result+8,exponent | sign);
- put(result+6,mant[0]);
- put(result+4,mant[1]);
- put(result+2,mant[2]);
- put(result+0,mant[3]);
- } else if (exponent < -16383 && exponent >= -16446) {
- /*
- * Denormal.
- */
- int shift = -(exponent+16383);
- int sh = shift % 16, wds = shift / 16;
- ieee_shr(mant, sh);
- if (ieee_round(mant, 4-wds) || (sh>0 && (mant[0]&(0x8000>>(sh-1))))) {
- ieee_shr(mant, 1);
- if (sh==0)
- mant[0] |= 0x8000;
- exponent++;
- }
- put(result+8,sign);
- put(result+6,(wds == 0 ? mant[0] : 0));
- put(result+4,(wds <= 1 ? mant[1-wds] : 0));
- put(result+2,(wds <= 2 ? mant[2-wds] : 0));
- put(result+0,(wds <= 3 ? mant[3-wds] : 0));
- } else {
- if (exponent > 0) {
- error(ERR_NONFATAL, "overflow in floating-point constant");
- return 0;
- } else
- memset (result, 0, 10);
- }
+ /*
+ * Non-zero.
+ */
+ exponent--;
+ if (exponent >= -16383 && exponent <= 16384) {
+ /*
+ * Normalised.
+ */
+ exponent += 16383;
+ if (ieee_round(mant, 4)) /* did we scale up by one? */
+ ieee_shr(mant, 1), mant[0] |= 0x8000, exponent++;
+ put(result + 8, exponent | sign);
+ put(result + 6, mant[0]);
+ put(result + 4, mant[1]);
+ put(result + 2, mant[2]);
+ put(result + 0, mant[3]);
+ } else if (exponent < -16383 && exponent >= -16446) {
+ /*
+ * Denormal.
+ */
+ int shift = -(exponent + 16383);
+ int sh = shift % 16, wds = shift / 16;
+ ieee_shr(mant, sh);
+ if (ieee_round(mant, 4 - wds)
+ || (sh > 0 && (mant[0] & (0x8000 >> (sh - 1))))) {
+ ieee_shr(mant, 1);
+ if (sh == 0)
+ mant[0] |= 0x8000;
+ exponent++;
+ }
+ put(result + 8, sign);
+ put(result + 6, (wds == 0 ? mant[0] : 0));
+ put(result + 4, (wds <= 1 ? mant[1 - wds] : 0));
+ put(result + 2, (wds <= 2 ? mant[2 - wds] : 0));
+ put(result + 0, (wds <= 3 ? mant[3 - wds] : 0));
+ } else {
+ if (exponent > 0) {
+ error(ERR_NONFATAL, "overflow in floating-point constant");
+ return 0;
+ } else
+ memset(result, 0, 10);
+ }
} else {
- /*
- * Zero.
- */
- memset (result, 0, 10);
+ /*
+ * Zero.
+ */
+ memset(result, 0, 10);
}
return 1;
}
-int float_const (char *number, long sign, unsigned char *result, int bytes,
- efunc error)
+int float_const(char *number, long sign, unsigned char *result, int bytes,
+ efunc error)
{
if (bytes == 4)
- return to_float (number, sign, result, error);
+ return to_float(number, sign, result, error);
else if (bytes == 8)
- return to_double (number, sign, result, error);
+ return to_double(number, sign, result, error);
else if (bytes == 10)
- return to_ldoub (number, sign, result, error);
+ return to_ldoub(number, sign, result, error);
else {
- error(ERR_PANIC, "strange value %d passed to float_const", bytes);
- return 0;
+ error(ERR_PANIC, "strange value %d passed to float_const", bytes);
+ return 0;
}
}