1d11907f1SDavid du Colombier #include "fpi.h"
2d11907f1SDavid du Colombier
3d11907f1SDavid du Colombier /*
4d11907f1SDavid du Colombier * the following routines depend on memory format, not the machine
5d11907f1SDavid du Colombier */
6d11907f1SDavid du Colombier
7*426f2a32SDavid du Colombier enum {
8*426f2a32SDavid du Colombier Sign = 1u << 31,
9*426f2a32SDavid du Colombier };
10*426f2a32SDavid du Colombier
11d11907f1SDavid du Colombier void
fpis2i(Internal * i,void * v)12d11907f1SDavid du Colombier fpis2i(Internal *i, void *v)
13d11907f1SDavid du Colombier {
14d11907f1SDavid du Colombier Single *s = v;
15d11907f1SDavid du Colombier
16*426f2a32SDavid du Colombier i->s = (*s & Sign) ? 1: 0;
17*426f2a32SDavid du Colombier if((*s & ~Sign) == 0){
18d11907f1SDavid du Colombier SetZero(i);
19d11907f1SDavid du Colombier return;
20d11907f1SDavid du Colombier }
21d11907f1SDavid du Colombier i->e = ((*s>>23) & 0x00FF) - SingleExpBias + ExpBias;
22d11907f1SDavid du Colombier i->h = (*s & 0x007FFFFF)<<(1+NGuardBits);
23d11907f1SDavid du Colombier i->l = 0;
24d11907f1SDavid du Colombier if(i->e)
25d11907f1SDavid du Colombier i->h |= HiddenBit;
26d11907f1SDavid du Colombier else
27d11907f1SDavid du Colombier i->e++;
28d11907f1SDavid du Colombier }
29d11907f1SDavid du Colombier
30d11907f1SDavid du Colombier void
fpid2i(Internal * i,void * v)31d11907f1SDavid du Colombier fpid2i(Internal *i, void *v)
32d11907f1SDavid du Colombier {
33d11907f1SDavid du Colombier Double *d = v;
34d11907f1SDavid du Colombier
35*426f2a32SDavid du Colombier i->s = (d->h & Sign) ? 1: 0;
36d11907f1SDavid du Colombier i->e = (d->h>>20) & 0x07FF;
37d11907f1SDavid du Colombier i->h = ((d->h & 0x000FFFFF)<<(4+NGuardBits))|((d->l>>25) & 0x7F);
38d11907f1SDavid du Colombier i->l = (d->l & 0x01FFFFFF)<<NGuardBits;
39d11907f1SDavid du Colombier if(i->e)
40d11907f1SDavid du Colombier i->h |= HiddenBit;
41d11907f1SDavid du Colombier else
42d11907f1SDavid du Colombier i->e++;
43d11907f1SDavid du Colombier }
44d11907f1SDavid du Colombier
45d11907f1SDavid du Colombier void
fpiw2i(Internal * i,void * v)46d11907f1SDavid du Colombier fpiw2i(Internal *i, void *v)
47d11907f1SDavid du Colombier {
48d11907f1SDavid du Colombier Word w, word = *(Word*)v;
49d11907f1SDavid du Colombier short e;
50d11907f1SDavid du Colombier
51d11907f1SDavid du Colombier if(word < 0){
52d11907f1SDavid du Colombier i->s = 1;
53d11907f1SDavid du Colombier word = -word;
54d11907f1SDavid du Colombier }
55d11907f1SDavid du Colombier else
56d11907f1SDavid du Colombier i->s = 0;
57d11907f1SDavid du Colombier if(word == 0){
58d11907f1SDavid du Colombier SetZero(i);
59d11907f1SDavid du Colombier return;
60d11907f1SDavid du Colombier }
61d11907f1SDavid du Colombier if(word > 0){
62d11907f1SDavid du Colombier for (e = 0, w = word; w; w >>= 1, e++)
63d11907f1SDavid du Colombier ;
64d11907f1SDavid du Colombier } else
65d11907f1SDavid du Colombier e = 32;
66d11907f1SDavid du Colombier if(e > FractBits){
67d11907f1SDavid du Colombier i->h = word>>(e - FractBits);
68d11907f1SDavid du Colombier i->l = (word & ((1<<(e - FractBits)) - 1))<<(2*FractBits - e);
69d11907f1SDavid du Colombier }
70d11907f1SDavid du Colombier else {
71d11907f1SDavid du Colombier i->h = word<<(FractBits - e);
72d11907f1SDavid du Colombier i->l = 0;
73d11907f1SDavid du Colombier }
74d11907f1SDavid du Colombier i->e = (e - 1) + ExpBias;
75d11907f1SDavid du Colombier }
76d11907f1SDavid du Colombier
77d11907f1SDavid du Colombier void
fpiv2i(Internal * i,void * v)784e3613abSDavid du Colombier fpiv2i(Internal *i, void *v)
794e3613abSDavid du Colombier {
804e3613abSDavid du Colombier Vlong w, word = *(Vlong*)v;
814e3613abSDavid du Colombier short e;
824e3613abSDavid du Colombier
834e3613abSDavid du Colombier if(word < 0){
844e3613abSDavid du Colombier i->s = 1;
854e3613abSDavid du Colombier word = -word;
864e3613abSDavid du Colombier }
874e3613abSDavid du Colombier else
884e3613abSDavid du Colombier i->s = 0;
894e3613abSDavid du Colombier if(word == 0){
904e3613abSDavid du Colombier SetZero(i);
914e3613abSDavid du Colombier return;
924e3613abSDavid du Colombier }
934e3613abSDavid du Colombier if(word > 0){
944e3613abSDavid du Colombier for (e = 0, w = word; w; w >>= 1, e++)
954e3613abSDavid du Colombier ;
964e3613abSDavid du Colombier } else
97*426f2a32SDavid du Colombier e = 64;
984e3613abSDavid du Colombier if(e > FractBits){
994e3613abSDavid du Colombier i->h = word>>(e - FractBits);
1004e3613abSDavid du Colombier i->l = (word & ((1<<(e - FractBits)) - 1))<<(2*FractBits - e);
1014e3613abSDavid du Colombier }
1024e3613abSDavid du Colombier else {
1034e3613abSDavid du Colombier i->h = word<<(FractBits - e);
1044e3613abSDavid du Colombier i->l = 0;
1054e3613abSDavid du Colombier }
1064e3613abSDavid du Colombier i->e = (e - 1) + ExpBias;
1074e3613abSDavid du Colombier }
1084e3613abSDavid du Colombier
109*426f2a32SDavid du Colombier /*
110*426f2a32SDavid du Colombier * Note that all of these conversions from Internal format
111*426f2a32SDavid du Colombier * potentially alter *i, so it should be a disposable copy
112*426f2a32SDavid du Colombier * of the value to be converted.
113*426f2a32SDavid du Colombier */
114*426f2a32SDavid du Colombier
1154e3613abSDavid du Colombier void
fpii2s(void * v,Internal * i)116d11907f1SDavid du Colombier fpii2s(void *v, Internal *i)
117d11907f1SDavid du Colombier {
118d11907f1SDavid du Colombier short e;
119d11907f1SDavid du Colombier Single *s = (Single*)v;
120d11907f1SDavid du Colombier
121d11907f1SDavid du Colombier fpiround(i);
122d11907f1SDavid du Colombier if(i->h & HiddenBit)
123d11907f1SDavid du Colombier i->h &= ~HiddenBit;
124d11907f1SDavid du Colombier else
125d11907f1SDavid du Colombier i->e--;
126*426f2a32SDavid du Colombier *s = i->s ? Sign: 0;
127d11907f1SDavid du Colombier e = i->e;
128d11907f1SDavid du Colombier if(e < ExpBias){
129d11907f1SDavid du Colombier if(e <= (ExpBias - SingleExpBias))
130d11907f1SDavid du Colombier return;
131d11907f1SDavid du Colombier e = SingleExpBias - (ExpBias - e);
132d11907f1SDavid du Colombier }
133d11907f1SDavid du Colombier else if(e >= (ExpBias + (SingleExpMax-SingleExpBias))){
134d11907f1SDavid du Colombier *s |= SingleExpMax<<23;
135d11907f1SDavid du Colombier return;
136d11907f1SDavid du Colombier }
137d11907f1SDavid du Colombier else
138d11907f1SDavid du Colombier e = SingleExpBias + (e - ExpBias);
139d11907f1SDavid du Colombier *s |= (e<<23)|(i->h>>(1+NGuardBits));
140d11907f1SDavid du Colombier }
141d11907f1SDavid du Colombier
142d11907f1SDavid du Colombier void
fpii2d(void * v,Internal * i)143d11907f1SDavid du Colombier fpii2d(void *v, Internal *i)
144d11907f1SDavid du Colombier {
145d11907f1SDavid du Colombier Double *d = (Double*)v;
146d11907f1SDavid du Colombier
147d11907f1SDavid du Colombier fpiround(i);
148d11907f1SDavid du Colombier if(i->h & HiddenBit)
149d11907f1SDavid du Colombier i->h &= ~HiddenBit;
150d11907f1SDavid du Colombier else
151d11907f1SDavid du Colombier i->e--;
152d11907f1SDavid du Colombier i->l = ((i->h & GuardMask)<<25)|(i->l>>NGuardBits);
153d11907f1SDavid du Colombier i->h >>= NGuardBits;
154*426f2a32SDavid du Colombier d->h = i->s ? Sign: 0;
155d11907f1SDavid du Colombier d->h |= (i->e<<20)|((i->h & 0x00FFFFFF)>>4);
156d11907f1SDavid du Colombier d->l = (i->h<<28)|i->l;
157d11907f1SDavid du Colombier }
158d11907f1SDavid du Colombier
159d11907f1SDavid du Colombier void
fpii2w(Word * word,Internal * i)160d11907f1SDavid du Colombier fpii2w(Word *word, Internal *i)
161d11907f1SDavid du Colombier {
162d11907f1SDavid du Colombier Word w;
163d11907f1SDavid du Colombier short e;
164d11907f1SDavid du Colombier
165d11907f1SDavid du Colombier fpiround(i);
166d11907f1SDavid du Colombier e = (i->e - ExpBias) + 1;
167d11907f1SDavid du Colombier if(e <= 0)
168d11907f1SDavid du Colombier w = 0;
169d11907f1SDavid du Colombier else if(e > 31)
170d11907f1SDavid du Colombier w = 0x7FFFFFFF;
171d11907f1SDavid du Colombier else if(e > FractBits)
172d11907f1SDavid du Colombier w = (i->h<<(e - FractBits))|(i->l>>(2*FractBits - e));
173d11907f1SDavid du Colombier else
174d11907f1SDavid du Colombier w = i->h>>(FractBits-e);
175d11907f1SDavid du Colombier if(i->s)
176d11907f1SDavid du Colombier w = -w;
177d11907f1SDavid du Colombier *word = w;
178d11907f1SDavid du Colombier }
1794e3613abSDavid du Colombier
1804e3613abSDavid du Colombier void
fpii2v(Vlong * word,Internal * i)1814e3613abSDavid du Colombier fpii2v(Vlong *word, Internal *i)
1824e3613abSDavid du Colombier {
1834e3613abSDavid du Colombier Vlong w;
1844e3613abSDavid du Colombier short e;
1854e3613abSDavid du Colombier
1864e3613abSDavid du Colombier fpiround(i);
1874e3613abSDavid du Colombier e = (i->e - ExpBias) + 1;
1884e3613abSDavid du Colombier if(e <= 0)
1894e3613abSDavid du Colombier w = 0;
1904e3613abSDavid du Colombier else if(e > 63)
1914e3613abSDavid du Colombier w = (1ull<<63) - 1; /* maxlong */
1924e3613abSDavid du Colombier else if(e > FractBits)
1934e3613abSDavid du Colombier w = (Vlong)i->h<<(e - FractBits) | i->l>>(2*FractBits - e);
1944e3613abSDavid du Colombier else
1954e3613abSDavid du Colombier w = i->h>>(FractBits-e);
1964e3613abSDavid du Colombier if(i->s)
1974e3613abSDavid du Colombier w = -w;
1984e3613abSDavid du Colombier *word = w;
1994e3613abSDavid du Colombier }
200