1/* $NetBSD: misc.c,v 1.10 2011/11/18 08:20:13 martin Exp $ */
2
3/****************************************************************
4
5The author of this software is David M. Gay.
6
7Copyright (C) 1998, 1999 by Lucent Technologies
8All Rights Reserved
9
10Permission to use, copy, modify, and distribute this software and
11its documentation for any purpose and without fee is hereby
12granted, provided that the above copyright notice appear in all
13copies and that both that the copyright notice and this
14permission notice and warranty disclaimer appear in supporting
15documentation, and that the name of Lucent or any of its entities
16not be used in advertising or publicity pertaining to
17distribution of the software without specific, written prior
18permission.
19
20LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
21INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
22IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
23SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
24WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
25IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
26ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
27THIS SOFTWARE.
28
29****************************************************************/
30
31/* Please send bug reports to David M. Gay (dmg at acm dot org,
32 * with " at " changed at "@" and " dot " changed to ".").	*/
33
34#include "gdtoaimp.h"
35
36 static Bigint *freelist[Kmax+1];
37#ifndef Omit_Private_Memory
38#ifndef PRIVATE_MEM
39#define PRIVATE_MEM 2304
40#endif
41#define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
42static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
43#endif
44
45 Bigint *
46Balloc
47#ifdef KR_headers
48	(k) int k;
49#else
50	(int k)
51#endif
52{
53	int x;
54	Bigint *rv;
55#ifndef Omit_Private_Memory
56	size_t len;
57#endif
58
59	ACQUIRE_DTOA_LOCK(0);
60	/* The k > Kmax case does not need ACQUIRE_DTOA_LOCK(0), */
61	/* but this case seems very unlikely. */
62	if ((size_t)k <= Kmax && (rv = freelist[k]) !=0) {
63		freelist[k] = rv->next;
64		}
65	else {
66		x = 1 << k;
67#ifdef Omit_Private_Memory
68		rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
69#else
70		len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
71			/sizeof(double);
72		if ((size_t)k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) {
73			rv = (Bigint*)(void *)pmem_next;
74			pmem_next += len;
75			}
76		else
77			rv = (Bigint*)MALLOC(len*sizeof(double));
78#endif
79		if (rv == NULL) {
80			FREE_DTOA_LOCK(0);
81			return NULL;
82		}
83		rv->k = k;
84		rv->maxwds = x;
85		}
86	FREE_DTOA_LOCK(0);
87	rv->sign = rv->wds = 0;
88	return rv;
89	}
90
91 void
92Bfree
93#ifdef KR_headers
94	(v) Bigint *v;
95#else
96	(Bigint *v)
97#endif
98{
99	if (v) {
100		if ((size_t)v->k > Kmax)
101#ifdef FREE
102			FREE((void*)v);
103#else
104			free((void*)v);
105#endif
106		else {
107			ACQUIRE_DTOA_LOCK(0);
108			v->next = freelist[v->k];
109			freelist[v->k] = v;
110			FREE_DTOA_LOCK(0);
111			}
112		}
113	}
114
115 int
116lo0bits
117#ifdef KR_headers
118	(y) ULong *y;
119#else
120	(ULong *y)
121#endif
122{
123	int k;
124	ULong x = *y;
125
126	if (x & 7) {
127		if (x & 1)
128			return 0;
129		if (x & 2) {
130			*y = x >> 1;
131			return 1;
132			}
133		*y = x >> 2;
134		return 2;
135		}
136	k = 0;
137	if (!(x & 0xffff)) {
138		k = 16;
139		x >>= 16;
140		}
141	if (!(x & 0xff)) {
142		k += 8;
143		x >>= 8;
144		}
145	if (!(x & 0xf)) {
146		k += 4;
147		x >>= 4;
148		}
149	if (!(x & 0x3)) {
150		k += 2;
151		x >>= 2;
152		}
153	if (!(x & 1)) {
154		k++;
155		x >>= 1;
156		if (!x)
157			return 32;
158		}
159	*y = x;
160	return k;
161	}
162
163 Bigint *
164multadd
165#ifdef KR_headers
166	(b, m, a) Bigint *b; int m, a;
167#else
168	(Bigint *b, int m, int a)	/* multiply by m and add a */
169#endif
170{
171	int i, wds;
172#ifdef ULLong
173	ULong *x;
174	ULLong carry, y;
175#else
176	ULong carry, *x, y;
177#ifdef Pack_32
178	ULong xi, z;
179#endif
180#endif
181	Bigint *b1;
182
183	wds = b->wds;
184	x = b->x;
185	i = 0;
186	carry = a;
187	do {
188#ifdef ULLong
189		y = *x * (ULLong)m + carry;
190		carry = y >> 32;
191		/* LINTED conversion */
192		*x++ = y & 0xffffffffUL;
193#else
194#ifdef Pack_32
195		xi = *x;
196		y = (xi & 0xffff) * m + carry;
197		z = (xi >> 16) * m + (y >> 16);
198		carry = z >> 16;
199		*x++ = (z << 16) + (y & 0xffff);
200#else
201		y = *x * m + carry;
202		carry = y >> 16;
203		*x++ = y & 0xffff;
204#endif
205#endif
206		}
207		while(++i < wds);
208	if (carry) {
209		if (wds >= b->maxwds) {
210			b1 = Balloc(b->k+1);
211			if (b1 == NULL) {
212				Bfree(b);
213				return NULL;
214				}
215			Bcopy(b1, b);
216			Bfree(b);
217			b = b1;
218			}
219		/* LINTED conversion */
220		b->x[wds++] = carry;
221		b->wds = wds;
222		}
223	return b;
224	}
225
226 int
227hi0bits_D2A
228#ifdef KR_headers
229	(x) ULong x;
230#else
231	(ULong x)
232#endif
233{
234	int k = 0;
235
236	if (!(x & 0xffff0000)) {
237		k = 16;
238		x <<= 16;
239		}
240	if (!(x & 0xff000000)) {
241		k += 8;
242		x <<= 8;
243		}
244	if (!(x & 0xf0000000)) {
245		k += 4;
246		x <<= 4;
247		}
248	if (!(x & 0xc0000000)) {
249		k += 2;
250		x <<= 2;
251		}
252	if (!(x & 0x80000000)) {
253		k++;
254		if (!(x & 0x40000000))
255			return 32;
256		}
257	return k;
258	}
259
260 Bigint *
261i2b
262#ifdef KR_headers
263	(i) int i;
264#else
265	(int i)
266#endif
267{
268	Bigint *b;
269
270	b = Balloc(1);
271	if (b == NULL)
272		return NULL;
273	b->x[0] = i;
274	b->wds = 1;
275	return b;
276	}
277
278 Bigint *
279mult
280#ifdef KR_headers
281	(a, b) Bigint *a, *b;
282#else
283	(Bigint *a, Bigint *b)
284#endif
285{
286	Bigint *c;
287	int k, wa, wb, wc;
288	ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
289	ULong y;
290#ifdef ULLong
291	ULLong carry, z;
292#else
293	ULong carry, z;
294#ifdef Pack_32
295	ULong z2;
296#endif
297#endif
298
299	if (a->wds < b->wds) {
300		c = a;
301		a = b;
302		b = c;
303		}
304	k = a->k;
305	wa = a->wds;
306	wb = b->wds;
307	wc = wa + wb;
308	if (wc > a->maxwds)
309		k++;
310	c = Balloc(k);
311	if (c == NULL)
312		return NULL;
313	for(x = c->x, xa = x + wc; x < xa; x++)
314		*x = 0;
315	xa = a->x;
316	xae = xa + wa;
317	xb = b->x;
318	xbe = xb + wb;
319	xc0 = c->x;
320#ifdef ULLong
321	for(; xb < xbe; xc0++) {
322		if ( (y = *xb++) !=0) {
323			x = xa;
324			xc = xc0;
325			carry = 0;
326			do {
327				z = *x++ * (ULLong)y + *xc + carry;
328				carry = z >> 32;
329				/* LINTED conversion */
330				*xc++ = z & 0xffffffffUL;
331				}
332				while(x < xae);
333			/* LINTED conversion */
334			*xc = carry;
335			}
336		}
337#else
338#ifdef Pack_32
339	for(; xb < xbe; xb++, xc0++) {
340		if ( (y = *xb & 0xffff) !=0) {
341			x = xa;
342			xc = xc0;
343			carry = 0;
344			do {
345				z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
346				carry = z >> 16;
347				z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
348				carry = z2 >> 16;
349				Storeinc(xc, z2, z);
350				}
351				while(x < xae);
352			*xc = carry;
353			}
354		if ( (y = *xb >> 16) !=0) {
355			x = xa;
356			xc = xc0;
357			carry = 0;
358			z2 = *xc;
359			do {
360				z = (*x & 0xffff) * y + (*xc >> 16) + carry;
361				carry = z >> 16;
362				Storeinc(xc, z, z2);
363				z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
364				carry = z2 >> 16;
365				}
366				while(x < xae);
367			*xc = z2;
368			}
369		}
370#else
371	for(; xb < xbe; xc0++) {
372		if ( (y = *xb++) !=0) {
373			x = xa;
374			xc = xc0;
375			carry = 0;
376			do {
377				z = *x++ * y + *xc + carry;
378				carry = z >> 16;
379				*xc++ = z & 0xffff;
380				}
381				while(x < xae);
382			*xc = carry;
383			}
384		}
385#endif
386#endif
387	for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
388	c->wds = wc;
389	return c;
390	}
391
392 static Bigint *p5s;
393
394 Bigint *
395pow5mult
396#ifdef KR_headers
397	(b, k) Bigint *b; int k;
398#else
399	(Bigint *b, int k)
400#endif
401{
402	Bigint *b1, *p5, *p51;
403	int i;
404	static CONST int p05[3] = { 5, 25, 125 };
405
406	if ( (i = k & 3) !=0) {
407		b = multadd(b, p05[i-1], 0);
408		if (b == NULL)
409			return NULL;
410		}
411
412	if (!(k = (unsigned int)k >> 2))
413		return b;
414	if ((p5 = p5s) == 0) {
415		/* first time */
416#ifdef MULTIPLE_THREADS
417		ACQUIRE_DTOA_LOCK(1);
418		if (!(p5 = p5s)) {
419			p5 = p5s = i2b(625);
420			if (p5 == NULL) {
421				FREE_DTOA_LOCK(1);
422				return NULL;
423			}
424			p5->next = 0;
425			}
426		FREE_DTOA_LOCK(1);
427#else
428		p5 = p5s = i2b(625);
429		if (p5 == NULL)
430			return NULL;
431		p5->next = 0;
432#endif
433		}
434	for(;;) {
435		if (k & 1) {
436			b1 = mult(b, p5);
437			if (b1 == NULL)
438				return NULL;
439			Bfree(b);
440			b = b1;
441			}
442		if (!(k = (unsigned int)k >> 1))
443			break;
444		if ((p51 = p5->next) == 0) {
445#ifdef MULTIPLE_THREADS
446			ACQUIRE_DTOA_LOCK(1);
447			if (!(p51 = p5->next)) {
448				p51 = p5->next = mult(p5,p5);
449				if (p51 == NULL) {
450					FREE_DTOA_LOCK(1);
451					return NULL;
452				}
453				p51->next = 0;
454				}
455			FREE_DTOA_LOCK(1);
456#else
457			p51 = p5->next = mult(p5,p5);
458			if (p51 == NULL)
459				return NULL;
460			p51->next = 0;
461#endif
462			}
463		p5 = p51;
464		}
465	return b;
466	}
467
468 Bigint *
469lshift
470#ifdef KR_headers
471	(b, k) Bigint *b; int k;
472#else
473	(Bigint *b, int k)
474#endif
475{
476	int i, k1, n, n1;
477	Bigint *b1;
478	ULong *x, *x1, *xe, z;
479
480	n = (unsigned int)k >> kshift;
481	k1 = b->k;
482	n1 = n + b->wds + 1;
483	for(i = b->maxwds; n1 > i; i <<= 1)
484		k1++;
485	b1 = Balloc(k1);
486	if (b1 == NULL)
487		return NULL;
488	x1 = b1->x;
489	for(i = 0; i < n; i++)
490		*x1++ = 0;
491	x = b->x;
492	xe = x + b->wds;
493	if (k &= kmask) {
494#ifdef Pack_32
495		k1 = 32 - k;
496		z = 0;
497		do {
498			*x1++ = *x << k | z;
499			z = *x++ >> k1;
500			}
501			while(x < xe);
502		if ((*x1 = z) !=0)
503			++n1;
504#else
505		k1 = 16 - k;
506		z = 0;
507		do {
508			*x1++ = *x << k  & 0xffff | z;
509			z = *x++ >> k1;
510			}
511			while(x < xe);
512		if (*x1 = z)
513			++n1;
514#endif
515		}
516	else do
517		*x1++ = *x++;
518		while(x < xe);
519	b1->wds = n1 - 1;
520	Bfree(b);
521	return b1;
522	}
523
524 int
525cmp
526#ifdef KR_headers
527	(a, b) Bigint *a, *b;
528#else
529	(Bigint *a, Bigint *b)
530#endif
531{
532	ULong *xa, *xa0, *xb, *xb0;
533	int i, j;
534
535	i = a->wds;
536	j = b->wds;
537#ifdef DEBUG
538	if (i > 1 && !a->x[i-1])
539		Bug("cmp called with a->x[a->wds-1] == 0");
540	if (j > 1 && !b->x[j-1])
541		Bug("cmp called with b->x[b->wds-1] == 0");
542#endif
543	if (i -= j)
544		return i;
545	xa0 = a->x;
546	xa = xa0 + j;
547	xb0 = b->x;
548	xb = xb0 + j;
549	for(;;) {
550		if (*--xa != *--xb)
551			return *xa < *xb ? -1 : 1;
552		if (xa <= xa0)
553			break;
554		}
555	return 0;
556	}
557
558 Bigint *
559diff
560#ifdef KR_headers
561	(a, b) Bigint *a, *b;
562#else
563	(Bigint *a, Bigint *b)
564#endif
565{
566	Bigint *c;
567	int i, wa, wb;
568	ULong *xa, *xae, *xb, *xbe, *xc;
569#ifdef ULLong
570	ULLong borrow, y;
571#else
572	ULong borrow, y;
573#ifdef Pack_32
574	ULong z;
575#endif
576#endif
577
578	i = cmp(a,b);
579	if (!i) {
580		c = Balloc(0);
581		if (c == NULL)
582			return NULL;
583		c->wds = 1;
584		c->x[0] = 0;
585		return c;
586		}
587	if (i < 0) {
588		c = a;
589		a = b;
590		b = c;
591		i = 1;
592		}
593	else
594		i = 0;
595	c = Balloc(a->k);
596	if (c == NULL)
597		return NULL;
598	c->sign = i;
599	wa = a->wds;
600	xa = a->x;
601	xae = xa + wa;
602	wb = b->wds;
603	xb = b->x;
604	xbe = xb + wb;
605	xc = c->x;
606	borrow = 0;
607#ifdef ULLong
608	do {
609		y = (ULLong)*xa++ - *xb++ - borrow;
610		borrow = y >> 32 & 1UL;
611		/* LINTED conversion */
612		*xc++ = y & 0xffffffffUL;
613		}
614		while(xb < xbe);
615	while(xa < xae) {
616		y = *xa++ - borrow;
617		borrow = y >> 32 & 1UL;
618		/* LINTED conversion */
619		*xc++ = y & 0xffffffffUL;
620		}
621#else
622#ifdef Pack_32
623	do {
624		y = (*xa & 0xffff) - (*xb & 0xffff) - borrow;
625		borrow = (y & 0x10000) >> 16;
626		z = (*xa++ >> 16) - (*xb++ >> 16) - borrow;
627		borrow = (z & 0x10000) >> 16;
628		Storeinc(xc, z, y);
629		}
630		while(xb < xbe);
631	while(xa < xae) {
632		y = (*xa & 0xffff) - borrow;
633		borrow = (y & 0x10000) >> 16;
634		z = (*xa++ >> 16) - borrow;
635		borrow = (z & 0x10000) >> 16;
636		Storeinc(xc, z, y);
637		}
638#else
639	do {
640		y = *xa++ - *xb++ - borrow;
641		borrow = (y & 0x10000) >> 16;
642		*xc++ = y & 0xffff;
643		}
644		while(xb < xbe);
645	while(xa < xae) {
646		y = *xa++ - borrow;
647		borrow = (y & 0x10000) >> 16;
648		*xc++ = y & 0xffff;
649		}
650#endif
651#endif
652	while(!*--xc)
653		wa--;
654	c->wds = wa;
655	return c;
656	}
657
658 double
659b2d
660#ifdef KR_headers
661	(a, e) Bigint *a; int *e;
662#else
663	(Bigint *a, int *e)
664#endif
665{
666	ULong *xa, *xa0, w, y, z;
667	int k;
668	U d;
669#ifdef VAX
670	ULong d0, d1;
671#else
672#define d0 word0(&d)
673#define d1 word1(&d)
674#endif
675
676	xa0 = a->x;
677	xa = xa0 + a->wds;
678	y = *--xa;
679#ifdef DEBUG
680	if (!y) Bug("zero y in b2d");
681#endif
682	k = hi0bits(y);
683	*e = 32 - k;
684#ifdef Pack_32
685	if (k < Ebits) {
686		d0 = Exp_1 | y >> (Ebits - k);
687		w = xa > xa0 ? *--xa : 0;
688		d1 = y << ((32-Ebits) + k) | w >> (Ebits - k);
689		goto ret_d;
690		}
691	z = xa > xa0 ? *--xa : 0;
692	if (k -= Ebits) {
693		d0 = Exp_1 | y << k | z >> (32 - k);
694		y = xa > xa0 ? *--xa : 0;
695		d1 = z << k | y >> (32 - k);
696		}
697	else {
698		d0 = Exp_1 | y;
699		d1 = z;
700		}
701#else
702	if (k < Ebits + 16) {
703		z = xa > xa0 ? *--xa : 0;
704		d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
705		w = xa > xa0 ? *--xa : 0;
706		y = xa > xa0 ? *--xa : 0;
707		d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
708		goto ret_d;
709		}
710	z = xa > xa0 ? *--xa : 0;
711	w = xa > xa0 ? *--xa : 0;
712	k -= Ebits + 16;
713	d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
714	y = xa > xa0 ? *--xa : 0;
715	d1 = w << k + 16 | y << k;
716#endif
717 ret_d:
718#ifdef VAX
719	word0(&d) = d0 >> 16 | d0 << 16;
720	word1(&d) = d1 >> 16 | d1 << 16;
721#endif
722	return dval(&d);
723	}
724#undef d0
725#undef d1
726
727 Bigint *
728d2b
729#ifdef KR_headers
730	(dd, e, bits) double dd; int *e, *bits;
731#else
732	(double dd, int *e, int *bits)
733#endif
734{
735	Bigint *b;
736	U d;
737#ifndef Sudden_Underflow
738	int i;
739#endif
740	int de, k;
741	ULong *x, y, z;
742#ifdef VAX
743	ULong d0, d1;
744#else
745#define d0 word0(&d)
746#define d1 word1(&d)
747#endif
748	d.d = dd;
749#ifdef VAX
750	d0 = word0(&d) >> 16 | word0(&d) << 16;
751	d1 = word1(&d) >> 16 | word1(&d) << 16;
752#endif
753
754#ifdef Pack_32
755	b = Balloc(1);
756#else
757	b = Balloc(2);
758#endif
759	if (b == NULL)
760		return NULL;
761	x = b->x;
762
763	z = d0 & Frac_mask;
764	d0 &= 0x7fffffff;	/* clear sign bit, which we ignore */
765#ifdef Sudden_Underflow
766	de = (int)(d0 >> Exp_shift);
767#ifndef IBM
768	z |= Exp_msk11;
769#endif
770#else
771	if ( (de = (int)(d0 >> Exp_shift)) !=0)
772		z |= Exp_msk1;
773#endif
774#ifdef Pack_32
775	if ( (y = d1) !=0) {
776		if ( (k = lo0bits(&y)) !=0) {
777			x[0] = y | z << (32 - k);
778			z >>= k;
779			}
780		else
781			x[0] = y;
782#ifndef Sudden_Underflow
783		i =
784#endif
785		     b->wds = (x[1] = z) !=0 ? 2 : 1;
786		}
787	else {
788		k = lo0bits(&z);
789		x[0] = z;
790#ifndef Sudden_Underflow
791		i =
792#endif
793		    b->wds = 1;
794		k += 32;
795		}
796#else
797	if ( (y = d1) !=0) {
798		if ( (k = lo0bits(&y)) !=0)
799			if (k >= 16) {
800				x[0] = y | z << 32 - k & 0xffff;
801				x[1] = z >> k - 16 & 0xffff;
802				x[2] = z >> k;
803				i = 2;
804				}
805			else {
806				x[0] = y & 0xffff;
807				x[1] = y >> 16 | z << 16 - k & 0xffff;
808				x[2] = z >> k & 0xffff;
809				x[3] = z >> k+16;
810				i = 3;
811				}
812		else {
813			x[0] = y & 0xffff;
814			x[1] = y >> 16;
815			x[2] = z & 0xffff;
816			x[3] = z >> 16;
817			i = 3;
818			}
819		}
820	else {
821#ifdef DEBUG
822		if (!z)
823			Bug("Zero passed to d2b");
824#endif
825		k = lo0bits(&z);
826		if (k >= 16) {
827			x[0] = z;
828			i = 0;
829			}
830		else {
831			x[0] = z & 0xffff;
832			x[1] = z >> 16;
833			i = 1;
834			}
835		k += 32;
836		}
837	while(!x[i])
838		--i;
839	b->wds = i + 1;
840#endif
841#ifndef Sudden_Underflow
842	if (de) {
843#endif
844#ifdef IBM
845		*e = (de - Bias - (P-1) << 2) + k;
846		*bits = 4*P + 8 - k - hi0bits(word0(&d) & Frac_mask);
847#else
848		*e = de - Bias - (P-1) + k;
849		*bits = P - k;
850#endif
851#ifndef Sudden_Underflow
852		}
853	else {
854		*e = de - Bias - (P-1) + 1 + k;
855#ifdef Pack_32
856		*bits = 32*i - hi0bits(x[i-1]);
857#else
858		*bits = (i+2)*16 - hi0bits(x[i]);
859#endif
860		}
861#endif
862	return b;
863	}
864#undef d0
865#undef d1
866
867 CONST double
868#ifdef IEEE_Arith
869bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
870CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256
871		};
872#else
873#ifdef IBM
874bigtens[] = { 1e16, 1e32, 1e64 };
875CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 };
876#else
877bigtens[] = { 1e16, 1e32 };
878CONST double tinytens[] = { 1e-16, 1e-32 };
879#endif
880#endif
881
882 CONST double
883tens[] = {
884		1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
885		1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
886		1e20, 1e21, 1e22
887#ifdef VAX
888		, 1e23, 1e24
889#endif
890		};
891
892 char *
893#ifdef KR_headers
894strcp_D2A(a, b) char *a; char *b;
895#else
896strcp_D2A(char *a, CONST char *b)
897#endif
898{
899	while((*a = *b++))
900		a++;
901	return a;
902	}
903
904#ifdef NO_STRING_H
905
906 Char *
907#ifdef KR_headers
908memcpy_D2A(a, b, len) Char *a; Char *b; size_t len;
909#else
910memcpy_D2A(void *a1, void *b1, size_t len)
911#endif
912{
913	char *a = (char*)a1, *ae = a + len;
914	char *b = (char*)b1, *a0 = a;
915	while(a < ae)
916		*a++ = *b++;
917	return a0;
918	}
919
920#endif /* NO_STRING_H */
921