1 /****************************************************************
3 The author of this software is David M. Gay.
5 Copyright (C) 1998, 1999 by Lucent Technologies
8 Permission to use, copy, modify, and distribute this software and
9 its documentation for any purpose and without fee is hereby
10 granted, provided that the above copyright notice appear in all
11 copies and that both that the copyright notice and this
12 permission notice and warranty disclaimer appear in supporting
13 documentation, and that the name of Lucent or any of its entities
14 not be used in advertising or publicity pertaining to
15 distribution of the software without specific, written prior
18 LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
20 IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
21 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
23 IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
24 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
27 ****************************************************************/
29 /* Please send bug reports to David M. Gay (dmg at acm dot org,
30 * with " at " changed at "@" and " dot " changed to "."). */
33 #define Omit_Private_Memory
37 #endif /* GDTOA_TSD */
41 static pthread_key_t gdtoa_tsd_key
= (pthread_key_t
)-1;
42 static pthread_mutex_t gdtoa_tsd_lock
= PTHREAD_MUTEX_INITIALIZER
;
43 #else /* !GDTOA_TSD */
44 static Bigint
*freelist
[Kmax
+1];
45 #endif /* GDTOA_TSD */
46 #ifndef Omit_Private_Memory
48 #define PRIVATE_MEM 2304
50 #define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
51 static double private_mem
[PRIVATE_mem
], *pmem_next
= private_mem
;
56 gdtoa_freelist_free(void *x
)
60 Bigint
**fl
= (Bigint
**)x
;
63 for(i
= 0; i
< Kmax
+1; fl
++, i
++) {
65 for(cur
= *fl
; cur
; cur
= next
) {
72 #endif /* GDTOA_TSD */
84 #ifndef Omit_Private_Memory
90 if (gdtoa_tsd_key
== (pthread_key_t
)-1) {
91 pthread_mutex_lock(&gdtoa_tsd_lock
);
92 if (gdtoa_tsd_key
== (pthread_key_t
)-1) {
93 gdtoa_tsd_key
= __LIBC_PTHREAD_KEY_GDTOA_BIGINT
;
94 pthread_key_init_np(gdtoa_tsd_key
, gdtoa_freelist_free
);
96 pthread_mutex_unlock(&gdtoa_tsd_lock
);
98 if ((freelist
= (Bigint
**)pthread_getspecific(gdtoa_tsd_key
)) == NULL
) {
99 freelist
= (Bigint
**)MALLOC((Kmax
+1) * sizeof(Bigint
*));
100 bzero(freelist
, (Kmax
+1) * sizeof(Bigint
*));
101 pthread_setspecific(gdtoa_tsd_key
, freelist
);
103 #else /* !GDTOA_TSD */
104 ACQUIRE_DTOA_LOCK(0);
105 #endif /* GDTOA_TSD */
106 if (k
<= Kmax
&& (rv
= freelist
[k
]) !=0) {
107 freelist
[k
] = rv
->next
;
111 #ifdef Omit_Private_Memory
112 rv
= (Bigint
*)MALLOC(sizeof(Bigint
) + (x
-1)*sizeof(ULong
));
114 len
= (sizeof(Bigint
) + (x
-1)*sizeof(ULong
) + sizeof(double) - 1)
116 if (k
<= Kmax
&& pmem_next
- private_mem
+ len
<= PRIVATE_mem
) {
117 rv
= (Bigint
*)pmem_next
;
121 rv
= (Bigint
*)MALLOC(len
*sizeof(double));
128 #endif /* GDTOA_TSD */
129 rv
->sign
= rv
->wds
= 0;
146 Bigint
**freelist
= (Bigint
**)pthread_getspecific(gdtoa_tsd_key
);
147 #else /* !GDTOA_TSD */
148 ACQUIRE_DTOA_LOCK(0);
149 #endif /* GDTOA_TSD */
150 v
->next
= freelist
[v
->k
];
154 #endif /* GDTOA_TSD */
168 register ULong x
= *y
;
210 (b
, m
, a
) Bigint
*b
; int m
, a
;
212 (Bigint
*b
, int m
, int a
) /* multiply by m and add a */
233 y
= *x
* (ULLong
)m
+ carry
;
235 *x
++ = y
& 0xffffffffUL
;
239 y
= (xi
& 0xffff) * m
+ carry
;
240 z
= (xi
>> 16) * m
+ (y
>> 16);
242 *x
++ = (z
<< 16) + (y
& 0xffff);
252 if (wds
>= b
->maxwds
) {
267 (x
) register ULong x
;
274 if (!(x
& 0xffff0000)) {
278 if (!(x
& 0xff000000)) {
282 if (!(x
& 0xf0000000)) {
286 if (!(x
& 0xc0000000)) {
290 if (!(x
& 0x80000000)) {
292 if (!(x
& 0x40000000))
317 (a
, b
) Bigint
*a
, *b
;
319 (Bigint
*a
, Bigint
*b
)
324 ULong
*x
, *xa
, *xae
, *xb
, *xbe
, *xc
, *xc0
;
335 if (a
->wds
< b
->wds
) {
347 for(x
= c
->x
, xa
= x
+ wc
; x
< xa
; x
++)
355 for(; xb
< xbe
; xc0
++) {
356 if ( (y
= *xb
++) !=0) {
361 z
= *x
++ * (ULLong
)y
+ *xc
+ carry
;
363 *xc
++ = z
& 0xffffffffUL
;
371 for(; xb
< xbe
; xb
++, xc0
++) {
372 if ( (y
= *xb
& 0xffff) !=0) {
377 z
= (*x
& 0xffff) * y
+ (*xc
& 0xffff) + carry
;
379 z2
= (*x
++ >> 16) * y
+ (*xc
>> 16) + carry
;
386 if ( (y
= *xb
>> 16) !=0) {
392 z
= (*x
& 0xffff) * y
+ (*xc
>> 16) + carry
;
395 z2
= (*x
++ >> 16) * y
+ (*xc
& 0xffff) + carry
;
403 for(; xb
< xbe
; xc0
++) {
404 if ( (y
= *xb
++) !=0) {
409 z
= *x
++ * y
+ *xc
+ carry
;
419 for(xc0
= c
->x
, xc
= xc0
+ wc
; wc
> 0 && !*--xc
; --wc
) ;
429 (b
, k
) Bigint
*b
; int k
;
434 Bigint
*b1
, *p5
, *p51
;
436 static int p05
[3] = { 5, 25, 125 };
438 if ( (i
= k
& 3) !=0)
439 b
= multadd(b
, p05
[i
-1], 0);
443 if ((p5
= p5s
) == 0) {
445 #ifdef MULTIPLE_THREADS
446 ACQUIRE_DTOA_LOCK(1);
465 if ((p51
= p5
->next
) == 0) {
466 #ifdef MULTIPLE_THREADS
467 ACQUIRE_DTOA_LOCK(1);
468 if (!(p51
= p5
->next
)) {
469 p51
= p5
->next
= mult(p5
,p5
);
474 p51
= p5
->next
= mult(p5
,p5
);
486 (b
, k
) Bigint
*b
; int k
;
493 ULong
*x
, *x1
, *xe
, z
;
498 for(i
= b
->maxwds
; n1
> i
; i
<<= 1)
502 for(i
= 0; i
< n
; i
++)
521 *x1
++ = *x
<< k
& 0xffff | z
;
540 (a
, b
) Bigint
*a
, *b
;
542 (Bigint
*a
, Bigint
*b
)
545 ULong
*xa
, *xa0
, *xb
, *xb0
;
551 if (i
> 1 && !a
->x
[i
-1])
552 Bug("cmp called with a->x[a->wds-1] == 0");
553 if (j
> 1 && !b
->x
[j
-1])
554 Bug("cmp called with b->x[b->wds-1] == 0");
564 return *xa
< *xb
? -1 : 1;
574 (a
, b
) Bigint
*a
, *b
;
576 (Bigint
*a
, Bigint
*b
)
581 ULong
*xa
, *xae
, *xb
, *xbe
, *xc
;
618 y
= (ULLong
)*xa
++ - *xb
++ - borrow
;
619 borrow
= y
>> 32 & 1UL;
620 *xc
++ = y
& 0xffffffffUL
;
625 borrow
= y
>> 32 & 1UL;
626 *xc
++ = y
& 0xffffffffUL
;
631 y
= (*xa
& 0xffff) - (*xb
& 0xffff) - borrow
;
632 borrow
= (y
& 0x10000) >> 16;
633 z
= (*xa
++ >> 16) - (*xb
++ >> 16) - borrow
;
634 borrow
= (z
& 0x10000) >> 16;
639 y
= (*xa
& 0xffff) - borrow
;
640 borrow
= (y
& 0x10000) >> 16;
641 z
= (*xa
++ >> 16) - borrow
;
642 borrow
= (z
& 0x10000) >> 16;
647 y
= *xa
++ - *xb
++ - borrow
;
648 borrow
= (y
& 0x10000) >> 16;
654 borrow
= (y
& 0x10000) >> 16;
668 (a
, e
) Bigint
*a
; int *e
;
673 ULong
*xa
, *xa0
, w
, y
, z
;
687 if (!y
) Bug("zero y in b2d");
693 d0
= Exp_1
| y
>> Ebits
- k
;
694 w
= xa
> xa0
? *--xa
: 0;
695 d1
= y
<< (32-Ebits
) + k
| w
>> Ebits
- k
;
698 z
= xa
> xa0
? *--xa
: 0;
700 d0
= Exp_1
| y
<< k
| z
>> 32 - k
;
701 y
= xa
> xa0
? *--xa
: 0;
702 d1
= z
<< k
| y
>> 32 - k
;
709 if (k
< Ebits
+ 16) {
710 z
= xa
> xa0
? *--xa
: 0;
711 d0
= Exp_1
| y
<< k
- Ebits
| z
>> Ebits
+ 16 - k
;
712 w
= xa
> xa0
? *--xa
: 0;
713 y
= xa
> xa0
? *--xa
: 0;
714 d1
= z
<< k
+ 16 - Ebits
| w
<< k
- Ebits
| y
>> 16 + Ebits
- k
;
717 z
= xa
> xa0
? *--xa
: 0;
718 w
= xa
> xa0
? *--xa
: 0;
720 d0
= Exp_1
| y
<< k
+ 16 | z
<< k
| w
>> 16 - k
;
721 y
= xa
> xa0
? *--xa
: 0;
722 d1
= w
<< k
+ 16 | y
<< k
;
726 word0(d
) = d0
>> 16 | d0
<< 16;
727 word1(d
) = d1
>> 16 | d1
<< 16;
737 (d
, e
, bits
) double d
; int *e
, *bits
;
739 (double d
, int *e
, int *bits
)
743 #ifndef Sudden_Underflow
750 d0
= word0(d
) >> 16 | word0(d
) << 16;
751 d1
= word1(d
) >> 16 | word1(d
) << 16;
765 d0
&= 0x7fffffff; /* clear sign bit, which we ignore */
766 #ifdef Sudden_Underflow
767 de
= (int)(d0
>> Exp_shift
);
772 if ( (de
= (int)(d0
>> Exp_shift
)) !=0)
777 if ( (k
= lo0bits(&y
)) !=0) {
778 x
[0] = y
| z
<< 32 - k
;
783 #ifndef Sudden_Underflow
786 b
->wds
= (x
[1] = z
) !=0 ? 2 : 1;
791 Bug("Zero passed to d2b");
795 #ifndef Sudden_Underflow
803 if ( (k
= lo0bits(&y
)) !=0)
805 x
[0] = y
| z
<< 32 - k
& 0xffff;
806 x
[1] = z
>> k
- 16 & 0xffff;
812 x
[1] = y
>> 16 | z
<< 16 - k
& 0xffff;
813 x
[2] = z
>> k
& 0xffff;
828 Bug("Zero passed to d2b");
846 #ifndef Sudden_Underflow
850 *e
= (de
- Bias
- (P
-1) << 2) + k
;
851 *bits
= 4*P
+ 8 - k
- hi0bits(word0(d
) & Frac_mask
);
853 *e
= de
- Bias
- (P
-1) + k
;
856 #ifndef Sudden_Underflow
859 *e
= de
- Bias
- (P
-1) + 1 + k
;
861 *bits
= 32*i
- hi0bits(x
[i
-1]);
863 *bits
= (i
+2)*16 - hi0bits(x
[i
]);
874 bigtens
[] = { 1e16
, 1e32
, 1e64
, 1e128
, 1e256
};
875 CONST
double tinytens
[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256
879 bigtens
[] = { 1e16
, 1e32
, 1e64
};
880 CONST
double tinytens
[] = { 1e-16, 1e-32, 1e-64 };
882 bigtens
[] = { 1e16
, 1e32
};
883 CONST
double tinytens
[] = { 1e-16, 1e-32 };
889 1e0
, 1e1
, 1e2
, 1e3
, 1e4
, 1e5
, 1e6
, 1e7
, 1e8
, 1e9
,
890 1e10
, 1e11
, 1e12
, 1e13
, 1e14
, 1e15
, 1e16
, 1e17
, 1e18
, 1e19
,
899 strcp_D2A(a
, b
) char *a
; char *b
;
901 strcp_D2A(char *a
, CONST
char *b
)
913 memcpy_D2A(a
, b
, len
) Char
*a
; Char
*b
; size_t len
;
915 memcpy_D2A(void *a1
, void *b1
, size_t len
)
918 register char *a
= (char*)a1
, *ae
= a
+ len
;
919 register char *b
= (char*)b1
, *a0
= a
;
925 #endif /* NO_STRING_H */