xref: /netbsd-src/lib/libc/gdtoa/strtoIg.c (revision 9feb722ead58d8a751d6d81d917a158e180ce5c0)
1 /* $NetBSD: strtoIg.c,v 1.5 2021/05/06 16:15:33 christos Exp $ */
2 
3 /****************************************************************
4 
5 The author of this software is David M. Gay.
6 
7 Copyright (C) 1998 by Lucent Technologies
8 All Rights Reserved
9 
10 Permission to use, copy, modify, and distribute this software and
11 its documentation for any purpose and without fee is hereby
12 granted, provided that the above copyright notice appear in all
13 copies and that both that the copyright notice and this
14 permission notice and warranty disclaimer appear in supporting
15 documentation, and that the name of Lucent or any of its entities
16 not be used in advertising or publicity pertaining to
17 distribution of the software without specific, written prior
18 permission.
19 
20 LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
21 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
22 IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
23 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
24 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
25 IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
26 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
27 THIS 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  int
37 #ifdef KR_headers
strtoIg(s00,se,fpi,exp,B,rvp)38 strtoIg(s00, se, fpi, exp, B, rvp) CONST char *s00; char **se; CONST FPI *fpi; Long *exp; Bigint **B; int *rvp;
39 #else
40 strtoIg(CONST char *s00, char **se, CONST FPI *fpi, Long *exp, Bigint **B, int *rvp)
41 #endif
42 {
43 	Bigint *b, *b1;
44 	int i, nb, nw, nw1, rv, rv1, swap;
45 	unsigned int nb1, nb11;
46 	Long e1;
47 
48 	b = *B;
49 	rv = strtodg(s00, se, fpi, exp, b->x);
50 	if (rv == STRTOG_NoMemory)
51 		return rv;
52 	if (!(rv & STRTOG_Inexact)) {
53 		B[1] = 0;
54 		return *rvp = rv;
55 		}
56 	e1 = exp[0];
57 	rv1 = rv ^ STRTOG_Inexact;
58 	b1 = Balloc(b->k);
59 	if (b1 == NULL)
60 		return STRTOG_NoMemory;
61 	Bcopy(b1, b);
62 	nb = fpi->nbits;
63 	nb1 = nb & 31;
64 	nb11 = (nb1 - 1) & 31;
65 	nw = b->wds;
66 	nw1 = nw - 1;
67 	if (rv & STRTOG_Inexlo) {
68 		swap = 0;
69 		b1 = increment(b1);
70 		if ((rv & STRTOG_Retmask) == STRTOG_Zero) {
71 			if (fpi->sudden_underflow) {
72 				b1->x[0] = 0;
73 				b1->x[nw1] = 1L << nb11;
74 				rv1 += STRTOG_Normal - STRTOG_Zero;
75 				rv1 &= ~STRTOG_Underflow;
76 				goto swapcheck;
77 				}
78 			rv1 &= STRTOG_Inexlo | STRTOG_Underflow | STRTOG_Zero;
79 			rv1 |= STRTOG_Inexhi | STRTOG_Denormal;
80 			goto swapcheck;
81 			}
82 		if (b1->wds > nw
83 		 || (nb1 && b1->x[nw1] & 1L << nb1)) {
84 			if (++e1 > fpi->emax)
85 				rv1 = STRTOG_Infinite | STRTOG_Inexhi;
86 			rshift(b1, 1);
87 			}
88 		else if ((rv & STRTOG_Retmask) == STRTOG_Denormal) {
89 			if (b1->x[nw1] & 1L << nb11) {
90 				rv1 += STRTOG_Normal - STRTOG_Denormal;
91 				rv1 &= ~STRTOG_Underflow;
92 				}
93 			}
94 		}
95 	else {
96 		swap = STRTOG_Neg;
97 		if ((rv & STRTOG_Retmask) == STRTOG_Infinite) {
98 			b1 = set_ones(b1, nb);
99 			e1 = fpi->emax;
100 			rv1 = STRTOG_Normal | STRTOG_Inexlo;
101 			goto swapcheck;
102 			}
103 		decrement(b1);
104 		if ((rv & STRTOG_Retmask) == STRTOG_Denormal) {
105 			for(i = nw1; !b1->x[i]; --i)
106 				if (!i) {
107 					rv1 = STRTOG_Zero | STRTOG_Inexlo;
108 					break;
109 					}
110 			goto swapcheck;
111 			}
112 		if (!(b1->x[nw1] & 1L << nb11)) {
113 			if (e1 == fpi->emin) {
114 				if (fpi->sudden_underflow)
115 					rv1 += STRTOG_Zero - STRTOG_Normal;
116 				else
117 					rv1 += STRTOG_Denormal - STRTOG_Normal;
118 				rv1 |= STRTOG_Underflow;
119 				}
120 			else {
121 				b1 = lshift(b1, 1);
122 				if (b1 == NULL)
123 					return STRTOG_NoMemory;
124 				b1->x[0] |= 1;
125 				--e1;
126 				}
127 			}
128 		}
129  swapcheck:
130 	if (swap ^ (rv & STRTOG_Neg)) {
131 		rvp[0] = rv1;
132 		rvp[1] = rv;
133 		B[0] = b1;
134 		B[1] = b;
135 		exp[1] = exp[0];
136 		exp[0] = e1;
137 		}
138 	else {
139 		rvp[0] = rv;
140 		rvp[1] = rv1;
141 		B[1] = b1;
142 		exp[1] = e1;
143 		}
144 	return rv;
145 	}
146