Home | History | Annotate | Line # | Download | only in gdtoa
dmisc.c revision 1.1
      1  1.1  kleink /* $NetBSD: dmisc.c,v 1.1 2006/01/25 15:18:40 kleink Exp $ */
      2  1.1  kleink 
      3  1.1  kleink /****************************************************************
      4  1.1  kleink 
      5  1.1  kleink The author of this software is David M. Gay.
      6  1.1  kleink 
      7  1.1  kleink Copyright (C) 1998 by Lucent Technologies
      8  1.1  kleink All Rights Reserved
      9  1.1  kleink 
     10  1.1  kleink Permission to use, copy, modify, and distribute this software and
     11  1.1  kleink its documentation for any purpose and without fee is hereby
     12  1.1  kleink granted, provided that the above copyright notice appear in all
     13  1.1  kleink copies and that both that the copyright notice and this
     14  1.1  kleink permission notice and warranty disclaimer appear in supporting
     15  1.1  kleink documentation, and that the name of Lucent or any of its entities
     16  1.1  kleink not be used in advertising or publicity pertaining to
     17  1.1  kleink distribution of the software without specific, written prior
     18  1.1  kleink permission.
     19  1.1  kleink 
     20  1.1  kleink LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     21  1.1  kleink INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
     22  1.1  kleink IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
     23  1.1  kleink SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     24  1.1  kleink WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
     25  1.1  kleink IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
     26  1.1  kleink ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
     27  1.1  kleink THIS SOFTWARE.
     28  1.1  kleink 
     29  1.1  kleink ****************************************************************/
     30  1.1  kleink 
     31  1.1  kleink /* Please send bug reports to David M. Gay (dmg at acm dot org,
     32  1.1  kleink  * with " at " changed at "@" and " dot " changed to ".").	*/
     33  1.1  kleink 
     34  1.1  kleink #include "gdtoaimp.h"
     35  1.1  kleink 
     36  1.1  kleink #ifndef MULTIPLE_THREADS
     37  1.1  kleink  char *dtoa_result;
     38  1.1  kleink #endif
     39  1.1  kleink 
     40  1.1  kleink  char *
     41  1.1  kleink #ifdef KR_headers
     42  1.1  kleink rv_alloc(i) int i;
     43  1.1  kleink #else
     44  1.1  kleink rv_alloc(int i)
     45  1.1  kleink #endif
     46  1.1  kleink {
     47  1.1  kleink 	int j, k, *r;
     48  1.1  kleink 
     49  1.1  kleink 	j = sizeof(ULong);
     50  1.1  kleink 	for(k = 0;
     51  1.1  kleink 		sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= i;
     52  1.1  kleink 		j <<= 1)
     53  1.1  kleink 			k++;
     54  1.1  kleink 	r = (int*)Balloc(k);
     55  1.1  kleink 	*r = k;
     56  1.1  kleink 	return
     57  1.1  kleink #ifndef MULTIPLE_THREADS
     58  1.1  kleink 	dtoa_result =
     59  1.1  kleink #endif
     60  1.1  kleink 		(char *)(r+1);
     61  1.1  kleink 	}
     62  1.1  kleink 
     63  1.1  kleink  char *
     64  1.1  kleink #ifdef KR_headers
     65  1.1  kleink nrv_alloc(s, rve, n) char *s, **rve; int n;
     66  1.1  kleink #else
     67  1.1  kleink nrv_alloc(char *s, char **rve, int n)
     68  1.1  kleink #endif
     69  1.1  kleink {
     70  1.1  kleink 	char *rv, *t;
     71  1.1  kleink 
     72  1.1  kleink 	t = rv = rv_alloc(n);
     73  1.1  kleink 	while((*t = *s++) !=0)
     74  1.1  kleink 		t++;
     75  1.1  kleink 	if (rve)
     76  1.1  kleink 		*rve = t;
     77  1.1  kleink 	return rv;
     78  1.1  kleink 	}
     79  1.1  kleink 
     80  1.1  kleink /* freedtoa(s) must be used to free values s returned by dtoa
     81  1.1  kleink  * when MULTIPLE_THREADS is #defined.  It should be used in all cases,
     82  1.1  kleink  * but for consistency with earlier versions of dtoa, it is optional
     83  1.1  kleink  * when MULTIPLE_THREADS is not defined.
     84  1.1  kleink  */
     85  1.1  kleink 
     86  1.1  kleink  void
     87  1.1  kleink #ifdef KR_headers
     88  1.1  kleink freedtoa(s) char *s;
     89  1.1  kleink #else
     90  1.1  kleink freedtoa(char *s)
     91  1.1  kleink #endif
     92  1.1  kleink {
     93  1.1  kleink 	Bigint *b = (Bigint *)((int *)s - 1);
     94  1.1  kleink 	b->maxwds = 1 << (b->k = *(int*)b);
     95  1.1  kleink 	Bfree(b);
     96  1.1  kleink #ifndef MULTIPLE_THREADS
     97  1.1  kleink 	if (s == dtoa_result)
     98  1.1  kleink 		dtoa_result = 0;
     99  1.1  kleink #endif
    100  1.1  kleink 	}
    101  1.1  kleink 
    102  1.1  kleink  int
    103  1.1  kleink quorem
    104  1.1  kleink #ifdef KR_headers
    105  1.1  kleink 	(b, S) Bigint *b, *S;
    106  1.1  kleink #else
    107  1.1  kleink 	(Bigint *b, Bigint *S)
    108  1.1  kleink #endif
    109  1.1  kleink {
    110  1.1  kleink 	int n;
    111  1.1  kleink 	ULong *bx, *bxe, q, *sx, *sxe;
    112  1.1  kleink #ifdef ULLong
    113  1.1  kleink 	ULLong borrow, carry, y, ys;
    114  1.1  kleink #else
    115  1.1  kleink 	ULong borrow, carry, y, ys;
    116  1.1  kleink #ifdef Pack_32
    117  1.1  kleink 	ULong si, z, zs;
    118  1.1  kleink #endif
    119  1.1  kleink #endif
    120  1.1  kleink 
    121  1.1  kleink 	n = S->wds;
    122  1.1  kleink #ifdef DEBUG
    123  1.1  kleink 	/*debug*/ if (b->wds > n)
    124  1.1  kleink 	/*debug*/	Bug("oversize b in quorem");
    125  1.1  kleink #endif
    126  1.1  kleink 	if (b->wds < n)
    127  1.1  kleink 		return 0;
    128  1.1  kleink 	sx = S->x;
    129  1.1  kleink 	sxe = sx + --n;
    130  1.1  kleink 	bx = b->x;
    131  1.1  kleink 	bxe = bx + n;
    132  1.1  kleink 	q = *bxe / (*sxe + 1);	/* ensure q <= true quotient */
    133  1.1  kleink #ifdef DEBUG
    134  1.1  kleink 	/*debug*/ if (q > 9)
    135  1.1  kleink 	/*debug*/	Bug("oversized quotient in quorem");
    136  1.1  kleink #endif
    137  1.1  kleink 	if (q) {
    138  1.1  kleink 		borrow = 0;
    139  1.1  kleink 		carry = 0;
    140  1.1  kleink 		do {
    141  1.1  kleink #ifdef ULLong
    142  1.1  kleink 			ys = *sx++ * (ULLong)q + carry;
    143  1.1  kleink 			carry = ys >> 32;
    144  1.1  kleink 			y = *bx - (ys & 0xffffffffUL) - borrow;
    145  1.1  kleink 			borrow = y >> 32 & 1UL;
    146  1.1  kleink 			*bx++ = y & 0xffffffffUL;
    147  1.1  kleink #else
    148  1.1  kleink #ifdef Pack_32
    149  1.1  kleink 			si = *sx++;
    150  1.1  kleink 			ys = (si & 0xffff) * q + carry;
    151  1.1  kleink 			zs = (si >> 16) * q + (ys >> 16);
    152  1.1  kleink 			carry = zs >> 16;
    153  1.1  kleink 			y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
    154  1.1  kleink 			borrow = (y & 0x10000) >> 16;
    155  1.1  kleink 			z = (*bx >> 16) - (zs & 0xffff) - borrow;
    156  1.1  kleink 			borrow = (z & 0x10000) >> 16;
    157  1.1  kleink 			Storeinc(bx, z, y);
    158  1.1  kleink #else
    159  1.1  kleink 			ys = *sx++ * q + carry;
    160  1.1  kleink 			carry = ys >> 16;
    161  1.1  kleink 			y = *bx - (ys & 0xffff) - borrow;
    162  1.1  kleink 			borrow = (y & 0x10000) >> 16;
    163  1.1  kleink 			*bx++ = y & 0xffff;
    164  1.1  kleink #endif
    165  1.1  kleink #endif
    166  1.1  kleink 			}
    167  1.1  kleink 			while(sx <= sxe);
    168  1.1  kleink 		if (!*bxe) {
    169  1.1  kleink 			bx = b->x;
    170  1.1  kleink 			while(--bxe > bx && !*bxe)
    171  1.1  kleink 				--n;
    172  1.1  kleink 			b->wds = n;
    173  1.1  kleink 			}
    174  1.1  kleink 		}
    175  1.1  kleink 	if (cmp(b, S) >= 0) {
    176  1.1  kleink 		q++;
    177  1.1  kleink 		borrow = 0;
    178  1.1  kleink 		carry = 0;
    179  1.1  kleink 		bx = b->x;
    180  1.1  kleink 		sx = S->x;
    181  1.1  kleink 		do {
    182  1.1  kleink #ifdef ULLong
    183  1.1  kleink 			ys = *sx++ + carry;
    184  1.1  kleink 			carry = ys >> 32;
    185  1.1  kleink 			y = *bx - (ys & 0xffffffffUL) - borrow;
    186  1.1  kleink 			borrow = y >> 32 & 1UL;
    187  1.1  kleink 			*bx++ = y & 0xffffffffUL;
    188  1.1  kleink #else
    189  1.1  kleink #ifdef Pack_32
    190  1.1  kleink 			si = *sx++;
    191  1.1  kleink 			ys = (si & 0xffff) + carry;
    192  1.1  kleink 			zs = (si >> 16) + (ys >> 16);
    193  1.1  kleink 			carry = zs >> 16;
    194  1.1  kleink 			y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
    195  1.1  kleink 			borrow = (y & 0x10000) >> 16;
    196  1.1  kleink 			z = (*bx >> 16) - (zs & 0xffff) - borrow;
    197  1.1  kleink 			borrow = (z & 0x10000) >> 16;
    198  1.1  kleink 			Storeinc(bx, z, y);
    199  1.1  kleink #else
    200  1.1  kleink 			ys = *sx++ + carry;
    201  1.1  kleink 			carry = ys >> 16;
    202  1.1  kleink 			y = *bx - (ys & 0xffff) - borrow;
    203  1.1  kleink 			borrow = (y & 0x10000) >> 16;
    204  1.1  kleink 			*bx++ = y & 0xffff;
    205  1.1  kleink #endif
    206  1.1  kleink #endif
    207  1.1  kleink 			}
    208  1.1  kleink 			while(sx <= sxe);
    209  1.1  kleink 		bx = b->x;
    210  1.1  kleink 		bxe = bx + n;
    211  1.1  kleink 		if (!*bxe) {
    212  1.1  kleink 			while(--bxe > bx && !*bxe)
    213  1.1  kleink 				--n;
    214  1.1  kleink 			b->wds = n;
    215  1.1  kleink 			}
    216  1.1  kleink 		}
    217  1.1  kleink 	return q;
    218  1.1  kleink 	}
    219