/* $NetBSD: misc.c,v 1.3.12.1 2008/04/08 21:10:55 jdc Exp $ */
/****************************************************************
The author of this software is David M. Gay.
Copyright (C) 1998, 1999 by Lucent Technologies
All Rights Reserved
Permission to use, copy, modify, and distribute this software and
its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of Lucent or any of its entities
not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
****************************************************************/
/* Please send bug reports to David M. Gay (dmg at acm dot org,
* with " at " changed at "@" and " dot " changed to "."). */
#include <LibConfig.h>
#include "gdtoaimp.h"
#if defined(_MSC_VER)
// Disable warnings about assignment within conditional expressions.
#endif
#ifndef Omit_Private_Memory
#ifndef PRIVATE_MEM
#endif
#endif
Bigint *
#ifdef KR_headers
(k) int k;
#else
(int k)
#endif
{
int x;
#ifndef Omit_Private_Memory
unsigned int len;
#endif
}
else {
x = 1 << k;
#ifdef Omit_Private_Memory
#else
/sizeof(double);
}
else
#endif
return NULL;
rv->k = k;
}
FREE_DTOA_LOCK(0);
return rv;
}
void
#ifdef KR_headers
(v) Bigint *v;
#else
(Bigint *v)
#endif
{
if (v) {
freelist[v->k] = v;
FREE_DTOA_LOCK(0);
}
}
int
#ifdef KR_headers
(y) ULong *y;
#else
(ULong *y)
#endif
{
int k;
ULong x = *y;
if (x & 7) {
if (x & 1)
return 0;
if (x & 2) {
*y = x >> 1;
return 1;
}
*y = x >> 2;
return 2;
}
k = 0;
if (!(x & 0xffff)) {
k = 16;
x >>= 16;
}
if (!(x & 0xff)) {
k += 8;
x >>= 8;
}
if (!(x & 0xf)) {
k += 4;
x >>= 4;
}
if (!(x & 0x3)) {
k += 2;
x >>= 2;
}
if (!(x & 1)) {
k++;
x >>= 1;
if (!x)
return 32;
}
*y = x;
return k;
}
Bigint *
#ifdef KR_headers
(b, m, a) Bigint *b; int m, a;
#else
(Bigint *b, int m, int a) /* multiply by m and add a */
#endif
{
int i, wds;
#ifdef ULLong
ULong *x;
#else
#ifdef Pack_32
#endif
#endif
x = b->x;
i = 0;
carry = a;
do {
#ifdef ULLong
carry = y >> 32;
/* LINTED conversion */
*x++ = (uint32_t)(y & 0xffffffffUL);
#else
#ifdef Pack_32
xi = *x;
carry = z >> 16;
*x++ = (z << 16) + (y & 0xffff);
#else
y = *x * m + carry;
carry = y >> 16;
*x++ = y & 0xffff;
#endif
#endif
}
while(++i < wds);
if (carry) {
Bfree(b);
return NULL;
}
Bfree(b);
b = b1;
}
/* LINTED conversion */
}
return b;
}
int
#ifdef KR_headers
(x) ULong x;
#else
(ULong x)
#endif
{
int k = 0;
if (!(x & 0xffff0000)) {
k = 16;
x <<= 16;
}
if (!(x & 0xff000000)) {
k += 8;
x <<= 8;
}
if (!(x & 0xf0000000)) {
k += 4;
x <<= 4;
}
if (!(x & 0xc0000000)) {
k += 2;
x <<= 2;
}
if (!(x & 0x80000000)) {
k++;
if (!(x & 0x40000000))
return 32;
}
return k;
}
Bigint *
#ifdef KR_headers
(i) int i;
#else
(int i)
#endif
{
Bigint *b;
b = Balloc(1);
if (b == NULL)
return NULL;
b->x[0] = i;
b->wds = 1;
return b;
}
Bigint *
#ifdef KR_headers
(a, b) Bigint *a, *b;
#else
#endif
{
Bigint *c;
ULong y;
#ifdef ULLong
#else
#ifdef Pack_32
#endif
#endif
c = a;
a = b;
b = c;
}
k = a->k;
k++;
c = Balloc(k);
if (c == NULL)
return NULL;
*x = 0;
xa = a->x;
xb = b->x;
xc0 = c->x;
#ifdef ULLong
if ( (y = *xb++) !=0) {
x = xa;
carry = 0;
do {
carry = z >> 32;
/* LINTED conversion */
}
while(x < xae);
/* LINTED conversion */
}
}
#else
#ifdef Pack_32
if ( (y = *xb & 0xffff) !=0) {
x = xa;
carry = 0;
do {
carry = z >> 16;
}
while(x < xae);
}
if ( (y = *xb >> 16) !=0) {
x = xa;
carry = 0;
do {
carry = z >> 16;
}
while(x < xae);
}
}
#else
if ( (y = *xb++) !=0) {
x = xa;
carry = 0;
do {
carry = z >> 16;
*xc++ = z & 0xffff;
}
while(x < xae);
}
}
#endif
#endif
return c;
}
Bigint *
#ifdef KR_headers
(b, k) Bigint *b; int k;
#else
(Bigint *b, int k)
#endif
{
int i;
if ( (i = k & 3) !=0) {
if (b == NULL)
return NULL;
}
if ((k = (unsigned int)k >> 2) == 0)
return b;
/* first time */
#ifdef MULTIPLE_THREADS
return NULL;
}
FREE_DTOA_LOCK(1);
#else
return NULL;
#endif
}
for(;;) {
if (k & 1) {
return NULL;
b = b1;
}
if ((k = (unsigned int)k >> 1) == 0)
break;
#ifdef MULTIPLE_THREADS
return NULL;
}
FREE_DTOA_LOCK(1);
#else
return NULL;
#endif
}
}
return b;
}
Bigint *
#ifdef KR_headers
(b, k) Bigint *b; int k;
#else
(Bigint *b, int k)
#endif
{
n = (unsigned int)k >> kshift;
k1 = b->k;
k1++;
return NULL;
for(i = 0; i < n; i++)
*x1++ = 0;
x = b->x;
if (k &= kmask) {
#ifdef Pack_32
k1 = 32 - k;
z = 0;
do {
*x1++ = *x << k | z;
z = *x++ >> k1;
}
while(x < xe);
if ((*x1 = z) !=0)
++n1;
#else
k1 = 16 - k;
z = 0;
do {
*x1++ = *x << k & 0xffff | z;
z = *x++ >> k1;
}
while(x < xe);
if (*x1 = z)
++n1;
#endif
}
else do
*x1++ = *x++;
while(x < xe);
Bfree(b);
return b1;
}
int
#ifdef KR_headers
(a, b) Bigint *a, *b;
#else
#endif
{
int i, j;
i = a->wds;
j = b->wds;
#ifdef DEBUG
if (i > 1 && !a->x[i-1])
Bug("cmp called with a->x[a->wds-1] == 0");
if (j > 1 && !b->x[j-1])
Bug("cmp called with b->x[b->wds-1] == 0");
#endif
if (i -= j)
return i;
xa0 = a->x;
xb0 = b->x;
for(;;) {
break;
}
return 0;
}
Bigint *
#ifdef KR_headers
(a, b) Bigint *a, *b;
#else
#endif
{
Bigint *c;
#ifdef ULLong
#else
#ifdef Pack_32
ULong z;
#endif
#endif
i = cmp(a,b);
if (!i) {
c = Balloc(0);
if (c == NULL)
return NULL;
c->wds = 1;
c->x[0] = 0;
return c;
}
if (i < 0) {
c = a;
a = b;
b = c;
i = 1;
}
else
i = 0;
c = Balloc(a->k);
if (c == NULL)
return NULL;
c->sign = i;
xa = a->x;
xb = b->x;
xc = c->x;
borrow = 0;
#ifdef ULLong
do {
/* LINTED conversion */
}
/* LINTED conversion */
}
#else
#ifdef Pack_32
do {
}
}
#else
do {
*xc++ = y & 0xffff;
}
*xc++ = y & 0xffff;
}
#endif
#endif
while(!*--xc)
wa--;
return c;
}
double
#ifdef KR_headers
(a, e) Bigint *a; int *e;
#else
(Bigint *a, int *e)
#endif
{
int k;
double d;
#ifdef VAX
#else
#endif
xa0 = a->x;
y = *--xa;
#ifdef DEBUG
if (!y) Bug("zero y in b2d");
#endif
k = hi0bits(y);
*e = 32 - k;
#ifdef Pack_32
if (k < Ebits) {
goto ret_d;
}
if (k -= Ebits) {
}
else {
}
#else
if (k < Ebits + 16) {
goto ret_d;
}
k -= Ebits + 16;
d1 = w << k + 16 | y << k;
#endif
#ifdef VAX
#endif
return dval(d);
}
Bigint *
#ifdef KR_headers
#else
(double d, int *e, int *bits)
#endif
{
Bigint *b;
#ifndef Sudden_Underflow
int i;
#endif
int de, k;
ULong *x, y, z;
#ifdef VAX
#else
#endif
#ifdef Pack_32
b = Balloc(1);
#else
b = Balloc(2);
#endif
if (b == NULL)
return NULL;
x = b->x;
#ifdef Sudden_Underflow
#ifndef IBM
z |= Exp_msk11;
#endif
#else
z |= Exp_msk1;
#endif
#ifdef Pack_32
if ( (y = d1) !=0) {
if ( (k = lo0bits(&y)) !=0) {
x[0] = y | z << (32 - k);
z >>= k;
}
else
x[0] = y;
#ifndef Sudden_Underflow
i =
#endif
}
else {
#ifdef DEBUG
if (!z)
Bug("Zero passed to d2b");
#endif
k = lo0bits(&z);
x[0] = z;
#ifndef Sudden_Underflow
i =
#endif
b->wds = 1;
k += 32;
}
#else
if ( (y = d1) !=0) {
if ( (k = lo0bits(&y)) !=0)
if (k >= 16) {
x[0] = y | z << 32 - k & 0xffff;
x[1] = z >> k - 16 & 0xffff;
x[2] = z >> k;
i = 2;
}
else {
x[0] = y & 0xffff;
x[1] = y >> 16 | z << 16 - k & 0xffff;
x[2] = z >> k & 0xffff;
x[3] = z >> k+16;
i = 3;
}
else {
x[0] = y & 0xffff;
x[1] = y >> 16;
x[2] = z & 0xffff;
x[3] = z >> 16;
i = 3;
}
}
else {
#ifdef DEBUG
if (!z)
Bug("Zero passed to d2b");
#endif
k = lo0bits(&z);
if (k >= 16) {
x[0] = z;
i = 0;
}
else {
x[0] = z & 0xffff;
x[1] = z >> 16;
i = 1;
}
k += 32;
}
while(!x[i])
--i;
b->wds = i + 1;
#endif
#ifndef Sudden_Underflow
if (de) {
#endif
#ifdef IBM
#else
*bits = P - k;
#endif
#ifndef Sudden_Underflow
}
else {
#ifdef Pack_32
#else
#endif
}
#endif
return b;
}
CONST double
#ifdef IEEE_Arith
};
#else
#ifdef IBM
#else
#endif
#endif
CONST double
tens[] = {
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
1e20, 1e21, 1e22
#ifdef VAX
, 1e23, 1e24
#endif
};
char *
#ifdef KR_headers
strcp_D2A(a, b) char *a; char *b;
#else
#endif
{
while((*a = *b++))
a++;
return a;
}
#ifdef NO_STRING_H
Char *
#ifdef KR_headers
#else
#endif
{
while(a < ae)
*a++ = *b++;
return a0;
}
#endif /* NO_STRING_H */