Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
typedef	unsigned long	ulong;
2
typedef	unsigned int	uint;
3
typedef	unsigned short	ushort;
4
typedef	unsigned char	uchar;
5
typedef	signed char	schar;
6
 
7
#define	SIGN(n)	(1UL<<(n-1))
8
 
9
typedef	struct	Vlong	Vlong;
10
struct	Vlong
11
{
12
	ulong	hi;
13
	ulong	lo;
14
};
15
 
16
void	abort(void);
17
void	_divu64(Vlong, Vlong, Vlong*, Vlong*);
18
 
19
void
20
_d2v(Vlong *y, double d)
21
{
22
	union { double d; Vlong; } x;
23
	ulong xhi, xlo, ylo, yhi;
24
	int sh;
25
 
26
	x.d = d;
27
 
28
	xhi = (x.hi & 0xfffff) | 0x100000;
29
	xlo = x.lo;
30
	sh = 1075 - ((x.hi >> 20) & 0x7ff);
31
 
32
	ylo = 0;
33
	yhi = 0;
34
	if(sh >= 0) {
35
		/* v = (hi||lo) >> sh */
36
		if(sh < 32) {
37
			if(sh == 0) {
38
				ylo = xlo;
39
				yhi = xhi;
40
			} else {
41
				ylo = (xlo >> sh) | (xhi << (32-sh));
42
				yhi = xhi >> sh;
43
			}
44
		} else {
45
			if(sh == 32) {
46
				ylo = xhi;
47
			} else
48
			if(sh < 64) {
49
				ylo = xhi >> (sh-32);
50
			}
51
		}
52
	} else {
53
		/* v = (hi||lo) << -sh */
54
		sh = -sh;
55
		if(sh <= 10) {
56
			ylo = xlo << sh;
57
			yhi = (xhi << sh) | (xlo >> (32-sh));
58
		} else {
59
			/* overflow */
60
			yhi = d;	/* causes something awful */
61
		}
62
	}
63
	if(x.hi & SIGN(32)) {
64
		if(ylo != 0) {
65
			ylo = -ylo;
66
			yhi = ~yhi;
67
		} else
68
			yhi = -yhi;
69
	}
70
 
71
	y->hi = yhi;
72
	y->lo = ylo;
73
}
74
 
75
void
76
_f2v(Vlong *y, float f)
77
{
78
 
79
	_d2v(y, f);
80
}
81
 
82
double
83
_v2d(Vlong x)
84
{
85
	if(x.hi & SIGN(32)) {
86
		if(x.lo) {
87
			x.lo = -x.lo;
88
			x.hi = ~x.hi;
89
		} else
90
			x.hi = -x.hi;
91
		return -((long)x.hi*4294967296. + x.lo);
92
	}
93
	return (long)x.hi*4294967296. + x.lo;
94
}
95
 
96
float
97
_v2f(Vlong x)
98
{
99
	return _v2d(x);
100
}
101
 
102
void
103
_divvu(Vlong *q, Vlong n, Vlong d)
104
{
105
 
106
	if(n.hi == 0 && d.hi == 0) {
107
		q->hi = 0;
108
		q->lo = n.lo / d.lo;
109
		return;
110
	}
111
	_divu64(n, d, q, 0);
112
}
113
 
114
void
115
_modvu(Vlong *r, Vlong n, Vlong d)
116
{
117
 
118
	if(n.hi == 0 && d.hi == 0) {
119
		r->hi = 0;
120
		r->lo = n.lo % d.lo;
121
		return;
122
	}
123
	_divu64(n, d, 0, r);
124
}
125
 
126
static void
127
vneg(Vlong *v)
128
{
129
 
130
	if(v->lo == 0) {
131
		v->hi = -v->hi;
132
		return;
133
	}
134
	v->lo = -v->lo;
135
	v->hi = ~v->hi;
136
}
137
 
138
void
139
_divv(Vlong *q, Vlong n, Vlong d)
140
{
141
	long nneg, dneg;
142
 
143
	if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {
144
		q->lo = (long)n.lo / (long)d.lo;
145
		q->hi = ((long)q->lo) >> 31;
146
		return;
147
	}
148
	nneg = n.hi >> 31;
149
	if(nneg)
150
		vneg(&n);
151
	dneg = d.hi >> 31;
152
	if(dneg)
153
		vneg(&d);
154
	_divu64(n, d, q, 0);
155
	if(nneg != dneg)
156
		vneg(q);
157
}
158
 
159
void
160
_modv(Vlong *r, Vlong n, Vlong d)
161
{
162
	long nneg, dneg;
163
 
164
	if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {
165
		r->lo = (long)n.lo % (long)d.lo;
166
		r->hi = ((long)r->lo) >> 31;
167
		return;
168
	}
169
	nneg = n.hi >> 31;
170
	if(nneg)
171
		vneg(&n);
172
	dneg = d.hi >> 31;
173
	if(dneg)
174
		vneg(&d);
175
	_divu64(n, d, 0, r);
176
	if(nneg)
177
		vneg(r);
178
}
179
 
180
void
181
_vasop(Vlong *ret, void *lv, void fn(Vlong*, Vlong, Vlong), int type, Vlong rv)
182
{
183
	Vlong t, u;
184
 
185
	u = *ret;
186
	switch(type) {
187
	default:
188
		abort();
189
		break;
190
 
191
	case 1:	/* schar */
192
		t.lo = *(schar*)lv;
193
		t.hi = t.lo >> 31;
194
		fn(&u, t, rv);
195
		*(schar*)lv = u.lo;
196
		break;
197
 
198
	case 2:	/* uchar */
199
		t.lo = *(uchar*)lv;
200
		t.hi = 0;
201
		fn(&u, t, rv);
202
		*(uchar*)lv = u.lo;
203
		break;
204
 
205
	case 3:	/* short */
206
		t.lo = *(short*)lv;
207
		t.hi = t.lo >> 31;
208
		fn(&u, t, rv);
209
		*(short*)lv = u.lo;
210
		break;
211
 
212
	case 4:	/* ushort */
213
		t.lo = *(ushort*)lv;
214
		t.hi = 0;
215
		fn(&u, t, rv);
216
		*(ushort*)lv = u.lo;
217
		break;
218
 
219
	case 9:	/* int */
220
		t.lo = *(int*)lv;
221
		t.hi = t.lo >> 31;
222
		fn(&u, t, rv);
223
		*(int*)lv = u.lo;
224
		break;
225
 
226
	case 10:	/* uint */
227
		t.lo = *(uint*)lv;
228
		t.hi = 0;
229
		fn(&u, t, rv);
230
		*(uint*)lv = u.lo;
231
		break;
232
 
233
	case 5:	/* long */
234
		t.lo = *(long*)lv;
235
		t.hi = t.lo >> 31;
236
		fn(&u, t, rv);
237
		*(long*)lv = u.lo;
238
		break;
239
 
240
	case 6:	/* ulong */
241
		t.lo = *(ulong*)lv;
242
		t.hi = 0;
243
		fn(&u, t, rv);
244
		*(ulong*)lv = u.lo;
245
		break;
246
 
247
	case 7:	/* vlong */
248
	case 8:	/* uvlong */
249
		fn(&u, *(Vlong*)lv, rv);
250
		*(Vlong*)lv = u;
251
		break;
252
	}
253
	*ret = u;
254
}