📄 ext_comp.c
字号:
/* (c) copyright 1989 by the Vrije Universiteit, Amsterdam, The Netherlands. See the copyright notice in the ACK home directory, in the file "Copyright".*//* $Id: ext_comp.c,v 1.10 1994/06/24 11:53:36 ceriel Exp $ *//* extended precision arithmetic for the strtod() and cvt() routines *//* This may require some more work when long doubles get bigger than 8 bytes. In this case, these routines may become obsolete. ???*/#include "ext_fmt.h"#include <float.h>#include <errno.h>#include <ctype.h>static int b64_add(struct mantissa *e1, struct mantissa *e2);static b64_sft(struct mantissa *e1, int n);staticmul_ext(struct EXTEND *e1, struct EXTEND *e2, struct EXTEND *e3){ /* Multiply the extended numbers e1 and e2, and put the result in e3. */ register int i,j; /* loop control */ unsigned short mp[4]; unsigned short mc[4]; unsigned short result[8]; /* result */ register unsigned short *pres; /* first save the sign (XOR) */ e3->sign = e1->sign ^ e2->sign; /* compute new exponent */ e3->exp = e1->exp + e2->exp + 1; /* check for overflow/underflow ??? */ /* 128 bit multiply of mantissas */ /* assign unknown long formats */ /* to known unsigned word formats */ mp[0] = e1->m1 >> 16; mp[1] = (unsigned short) e1->m1; mp[2] = e1->m2 >> 16; mp[3] = (unsigned short) e1->m2; mc[0] = e2->m1 >> 16; mc[1] = (unsigned short) e2->m1; mc[2] = e2->m2 >> 16; mc[3] = (unsigned short) e2->m2; for (i = 8; i--;) { result[i] = 0; } /* * fill registers with their components */ for(i=4, pres = &result[4];i--;pres--) if (mp[i]) { unsigned short k = 0; unsigned long mpi = mp[i]; for(j=4;j--;) { unsigned long tmp = (unsigned long)pres[j] + k; if (mc[j]) tmp += mpi * mc[j]; pres[j] = tmp; k = tmp >> 16; } pres[-1] = k; } if (! (result[0] & 0x8000)) { e3->exp--; for (i = 0; i <= 3; i++) { result[i] <<= 1; if (result[i+1]&0x8000) result[i] |= 1; } result[4] <<= 1; } /* * combine the registers to a total */ e3->m1 = ((unsigned long)(result[0]) << 16) + result[1]; e3->m2 = ((unsigned long)(result[2]) << 16) + result[3]; if (result[4] & 0x8000) { if (++e3->m2 == 0) { if (++e3->m1 == 0) { e3->m1 = 0x80000000; e3->exp++; } } }}staticadd_ext(struct EXTEND *e1, struct EXTEND *e2, struct EXTEND *e3){ /* Add two extended numbers e1 and e2, and put the result in e3 */ struct EXTEND ce2; int diff; if ((e2->m1 | e2->m2) == 0L) { *e3 = *e1; return; } if ((e1->m1 | e1->m2) == 0L) { *e3 = *e2; return; } ce2 = *e2; *e3 = *e1; e1 = &ce2; /* adjust mantissas to equal power */ diff = e3->exp - e1->exp; if (diff < 0) { diff = -diff; e3->exp += diff; b64_sft(&(e3->mantissa), diff); } else if (diff > 0) { e1->exp += diff; b64_sft(&(e1->mantissa), diff); } if (e1->sign != e3->sign) { /* e3 + e1 = e3 - (-e1) */ if (e1->m1 > e3->m1 || (e1->m1 == e3->m1 && e1->m2 > e3->m2)) { /* abs(e1) > abs(e3) */ if (e3->m2 > e1->m2) { e1->m1 -= 1; /* carry in */ } e1->m1 -= e3->m1; e1->m2 -= e3->m2; *e3 = *e1; } else { if (e1->m2 > e3->m2) e3->m1 -= 1; /* carry in */ e3->m1 -= e1->m1; e3->m2 -= e1->m2; } } else { if (b64_add(&e3->mantissa,&e1->mantissa)) {/* addition carry */ b64_sft(&e3->mantissa,1);/* shift mantissa one bit RIGHT */ e3->m1 |= 0x80000000L; /* set max bit */ e3->exp++; /* increase the exponent */ } } if ((e3->m2 | e3->m1) != 0L) { /* normalize */ if (e3->m1 == 0L) { e3->m1 = e3->m2; e3->m2 = 0L; e3->exp -= 32; } if (!(e3->m1 & 0x80000000)) { unsigned long l = 0x40000000; int cnt = -1; while (! (l & e3->m1)) { l >>= 1; cnt--; } e3->exp += cnt; b64_sft(&(e3->mantissa), cnt); } }}static intcmp_ext(struct EXTEND *e1, struct EXTEND *e2){ struct EXTEND tmp; e2->sign = ! e2->sign; add_ext(e1, e2, &tmp); e2->sign = ! e2->sign; if (tmp.m1 == 0 && tmp.m2 == 0) return 0; if (tmp.sign) return -1; return 1;}staticb64_sft(struct mantissa *e1, int n){ if (n > 0) { if (n > 63) { e1->l_32 = 0; e1->h_32 = 0; return; } if (n >= 32) { e1->l_32 = e1->h_32; e1->h_32 = 0; n -= 32; } if (n > 0) { e1->l_32 >>= n; if (e1->h_32 != 0) { e1->l_32 |= (e1->h_32 << (32 - n)); e1->h_32 >>= n; } } return; } n = -n; if (n > 0) { if (n > 63) { e1->l_32 = 0; e1->h_32 = 0; return; } if (n >= 32) { e1->h_32 = e1->l_32; e1->l_32 = 0; n -= 32; } if (n > 0) { e1->h_32 <<= n; if (e1->l_32 != 0) { e1->h_32 |= (e1->l_32 >> (32 - n)); e1->l_32 <<= n; } } }}static intb64_add(struct mantissa *e1, struct mantissa *e2) /* * pointers to 64 bit 'registers' */{ register int overflow; int carry; /* add higher pair of 32 bits */ overflow = ((unsigned long) 0xFFFFFFFF - e1->h_32 < e2->h_32); e1->h_32 += e2->h_32; /* add lower pair of 32 bits */ carry = ((unsigned long) 0xFFFFFFFF - e1->l_32 < e2->l_32); e1->l_32 += e2->l_32; if ((carry) && (++e1->h_32 == 0)) return(1); /* had a 64 bit overflow */ else return(overflow); /* return status from higher add */}/* The following tables can be computed with the following bc(1) program:obase=16scale=0define t(x){ auto a, b, c a=2;b=1;c=2^32;n=1 while(a<x) { b=a;n+=n;a*=a } n/=2 a=b while(b<x) { a=b;b*=c;n+=32 } n-=32 b=a while(a<x) { b=a;a+=a;n+=1 } n-=1 x*=16^16 b=x%a x/=a if(a<=(2*b)) x+=1 obase=10 n obase=16 return(x)}for (i=1;i<28;i++) { t(10^i)}0for (i=1;i<20;i++) { t(10^(28*i))}0define r(x){ auto a, b, c a=2;b=1;c=2^32;n=1 while(a<x) { b=a;n+=n;a*=a } n/=2 a=b while(b<x) { a=b;b*=c;n+=32 } n-=32 b=a while(a<x) { b=a;a+=a;n+=1 } a=b a*=16^16 b=a%x a/=x if(x<=(2*b)) a+=1 obase=10 -n obase=16 return(a)}for (i=1;i<28;i++) { r(10^i)}0for (i=1;i<20;i++) { r(10^(28*i))}0*/static struct EXTEND ten_powers[] = { /* representation of 10 ** i */ { 0, 0, 0x80000000, 0 }, { 0, 3, 0xA0000000, 0 }, { 0, 6, 0xC8000000, 0 }, { 0, 9, 0xFA000000, 0 }, { 0, 13, 0x9C400000, 0 }, { 0, 16, 0xC3500000, 0 }, { 0, 19, 0xF4240000, 0 }, { 0, 23, 0x98968000, 0 }, { 0, 26, 0xBEBC2000, 0 }, { 0, 29, 0xEE6B2800, 0 }, { 0, 33, 0x9502F900, 0 }, { 0, 36, 0xBA43B740, 0 }, { 0, 39, 0xE8D4A510, 0 }, { 0, 43, 0x9184E72A, 0 }, { 0, 46, 0xB5E620F4, 0x80000000 }, { 0, 49, 0xE35FA931, 0xA0000000 }, { 0, 53, 0x8E1BC9BF, 0x04000000 }, { 0, 56, 0xB1A2BC2E, 0xC5000000 }, { 0, 59, 0xDE0B6B3A, 0x76400000 }, { 0, 63, 0x8AC72304, 0x89E80000 }, { 0, 66, 0xAD78EBC5, 0xAC620000 }, { 0, 69, 0xD8D726B7, 0x177A8000 }, { 0, 73, 0x87867832, 0x6EAC9000 }, { 0, 76, 0xA968163F, 0x0A57B400 }, { 0, 79, 0xD3C21BCE, 0xCCEDA100 }, { 0, 83, 0x84595161, 0x401484A0 }, { 0, 86, 0xA56FA5B9, 0x9019A5C8 }, { 0, 89, 0xCECB8F27, 0xF4200F3A }};static struct EXTEND big_ten_powers[] = { /* representation of 10 ** (28*i) */ { 0, 0, 0x80000000, 0 }, { 0, 93, 0x813F3978, 0xF8940984 }, { 0, 186, 0x82818F12, 0x81ED44A0 }, { 0, 279, 0x83C7088E, 0x1AAB65DB }, { 0, 372, 0x850FADC0, 0x9923329E }, { 0, 465, 0x865B8692, 0x5B9BC5C2 }, { 0, 558, 0x87AA9AFF, 0x79042287 }, { 0, 651, 0x88FCF317, 0xF22241E2 }, { 0, 744, 0x8A5296FF, 0xE33CC930 }, { 0, 837, 0x8BAB8EEF, 0xB6409C1A }, { 0, 930, 0x8D07E334, 0x55637EB3 }, { 0, 1023, 0x8E679C2F, 0x5E44FF8F }, { 0, 1116, 0x8FCAC257, 0x558EE4E6 }, { 0, 1209, 0x91315E37, 0xDB165AA9 }, { 0, 1302, 0x929B7871, 0xDE7F22B9 },
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -