View difference between Paste ID: LQZPS08e and xu5U1kib
SHOW: | | - or go back to the newest paste.
1
/**
2
 * Experimentations autour de nombre flottants en faisant varier le nombre de
3-
	
3+
 * bits de la mantisse.
4-
	
4+
 * 
5
 * @author Samuel DEVULDER Avril 2016
6
 */
7
public class FP extends Number implements Comparable<FP> {
8
	// http://www.quinapalus.com/efunc.html
9-
	static final int BITS = 7;
9+
10
	private static final long serialVersionUID = 1L;
11-
	static long ONE_MSK = 1l<<BITS;
11+
12-
	
12+
13
14
	static final int BITS = 15;
15
16
	static long ONE_MSK = 1l << BITS;
17
18-
	static FP LN10 = new FP(1, 1, (long) (Math.log(10) * ONE_MSK/2 + .5));
18+
19-
	static FP E = new FP(1, 1, (long) (Math.exp(1) * ONE_MSK/2 + .5));
19+
20-
	static FP PI = new FP(1, 1, (long) (Math.PI * ONE_MSK/2 + .5));
20+
21
	static FP SQRT2 = new FP(1, 0, (long) (Math.sqrt(2) * ONE_MSK + .5));
22-
	static FP MAX = new FP(1, 127, ONE_MSK*2 - 1);
22+
23
	static FP LN10 = new FP(1, 1, (long) (Math.log(10) * ONE_MSK / 2 + .5));
24
	static FP E = new FP(1, 1, (long) (Math.exp(1) * ONE_MSK / 2 + .5));
25
	static FP PI = new FP(1, 1, (long) (Math.PI * ONE_MSK / 2 + .5));
26
	static FP TEN = new FP(1, 3, 10 << (BITS - 3));
27
	static FP MAX = new FP(1, 127, ONE_MSK * 2 - 1);
28
29
	public static void main(String[] args) {
30
		System.out.println("LN2=" + LN2);
31
		System.out.println("ONE=" + ONE);
32
		System.out.println("SQRT2=" + SQRT2);
33
		System.out.println("TWO=" + TWO);
34
		System.out.println("LN10=" + LN10);
35
		System.out.println("PI=" + PI);
36
		System.out.println("TEN=" + TEN);
37
		System.out.println("MAX=" + MAX);
38
		System.out.println("ONE+SQRT2=" + ONE.add(SQRT2));
39
		System.out.println("ONE-SQRT2=" + ONE.sub(SQRT2));
40
		System.out.println("SQRT2-SQRT2=" + SQRT2.sub(SQRT2));
41
		System.out.println("SQRT2*SQRT2=" + SQRT2.mul(SQRT2));
42
		System.out.println("SQRT2/SQRT2=" + SQRT2.div(SQRT2));
43
		System.out.println("ONE/MAX=" + ONE.div(MAX));
44
		System.out.println("parse1=" + new FP("-314.1592653589E-2"));
45
		System.out.println("parse2=" + new FP("3.141592653589"));
46
47-
		
47+
48
		System.out.println("ln(10)=" + TEN.ln());
49
50
		System.out.println("log10(2)=" + TWO.log10());
51
		System.out.println("log10(10)=" + TEN.log10());
52
53
		System.out.println("sqrt(2)=" + TWO.sqrt());
54
		System.out.println("sqrt(10)=" + TEN.sqrt());
55
56
		System.out.println("exp(-2)=" + TWO.neg().exp());
57
		System.out.println("exp(-1)=" + ONE.neg().exp());
58
		System.out.println("exp(0)=" + ZERO.exp());
59
		System.out.println("exp(1)=" + ONE.exp());
60
		System.out.println("exp(2)=" + TWO.exp());
61
		System.out.println("exp(ln2)=" + LN2.exp());
62
		System.out.println("exp(ln10)=" + LN10.exp());
63-
	
63+
64
65
	FP(int sign, int exp, long mantissa) {
66
		build(sign, exp, mantissa);
67-
	
67+
68
69
	protected int sign() {
70
		return sign;
71-
	
71+
72
73
	protected int exponent() {
74
		return exp;
75
	}
76
77
	protected long mantissa() {
78
		return mantissa;
79
	}
80
81
	public FP(double d) {
82
		int sgn = d < 0 ? -1 : d > 0 ? 1 : 0;
83
		int exp = Math.getExponent(d);
84
		int man = (int) Math.scalb(sgn < 0 ? -d : d, BITS - exp);
85
		build(man == 0 ? 0 : sgn, exp, man);
86
	}
87
88
	protected FP build(int sign, int exp, long mantissa) {
89
		this.sign = (byte) sign;
90
		this.exp = (byte) exp;
91
		this.mantissa = mantissa & (ONE_MSK * 2 - 1);
92
		if (sign != 0 && (mantissa & ONE_MSK) == 0)
93
			throw new RuntimeException("Bad mantissa "
94
					+ Long.toHexString(this.mantissa));
95
		return this;
96
	}
97
98
	public FP(String s_) {
99
		int i = 0;
100
		char[] s = s_.toCharArray();
101
102
		// read sign
103
		int sgn = 1;
104
		while (i < s.length && (s[i] == '-' || s[i] == '+')) {
105
			if (s[i++] == '-')
106
				sgn = -sgn;
107
		}
108
109
		// read int part
110
		FP v = ZERO;
111
		while (i < s.length && s[i] >= '0' && s[i] <= '9') {
112
			v = v.mul(TEN).add(s[i++] - '0');
113
		}
114
115
		// read decimal
116
		if (i < s.length && s[i] == '.') {
117
			FP div = ONE;
118
			++i;
119
			while (i < s.length && s[i] >= '0' && s[i] <= '9') {
120
				div = div.div(TEN);
121
				v = v.add(div.mul(s[i++] - '0'));
122-
				e = e.pow(10).mul(pow_tab[s[i++]-'0']);
122+
123
		}
124
125
		// read exponent
126
		if (i < s.length && (s[i] == 'e' || s[i] == 'E')) {
127
			++i;
128
129
			int sgn2 = 1;
130
			while (i < s.length && (s[i] == '-' || s[i] == '+')) {
131
				if (s[i++] == '-')
132
					sgn2 = -sgn2;
133-
	static FP[] pow_tab = {ONE, TEN, TEN.square(), TEN.pow(3), TEN.pow(4), TEN.pow(5), TEN.pow(6), TEN.pow(7), TEN.pow(8), TEN.pow(9)};
133+
134
135
			FP e = ONE;
136
			while (i < s.length && s[i] >= '0' && s[i] <= '9') {
137
				e = e.pow(10).mul(pow_tab[s[i++] - '0']);
138-
		this.mantissa = mantissa & (ONE_MSK*2 - 1);
138+
139-
		if(sign!=0 && (this.mantissa & ONE_MSK)==0) throw new RuntimeException("Bad mantissa " + Long.toHexString(this.mantissa));
139+
140
			v = sgn2 < 0 ? v.div(e) : v.mul(e);
141
		}
142
143
		if (sgn < 0)
144
			v = v.neg();
145
146
		build(v.sign(), v.exponent(), v.mantissa());
147
	}
148
149
	static FP[] pow_tab = { TEN.pow(0), TEN.pow(1), TEN.pow(2), TEN.pow(3),
150
			TEN.pow(4), TEN.pow(5), TEN.pow(6), TEN.pow(7), TEN.pow(8),
151
			TEN.pow(9) };
152
153
	@Override
154
	public boolean equals(Object obj) {
155
		return obj instanceof FP && compareTo((FP) obj) == 0;
156
	}
157
158
	@Override
159
	public int hashCode() {
160
		if (sign == 0)
161
			return 0;
162
		return (int) ((sign * 31 + mantissa) * 31 + exp);
163
	}
164
165
	@Override
166
	public double doubleValue() {
167
		if (sign() == 0)
168
			return 0;
169
		double t = mantissa() * Math.pow(2, exponent() - BITS);
170
		return sign() < 0 ? -t : t;
171
	}
172
173
	@Override
174
	public float floatValue() {
175
		return (float) doubleValue();
176
	}
177
178
	@Override
179
	public int intValue() {
180
		return (int) longValue();
181
	}
182
183
	@Override
184
	public long longValue() {
185
		int sgn = sign();
186
		if (sgn == 0)
187
			return 0;
188
		long val = mantissa() >>> (BITS - exponent());
189
		return sgn < 0 ? -val : val;
190
	}
191
192
	public FP floor() {
193
		int exp = exponent();
194
		if (exp < 0)
195
			return ZERO;
196
		if (exp > BITS)
197
			return this;
198
		long m = (2l << BITS) - ((1l << BITS) >>> exp);
199
		return new FP(sign(), exp, mantissa() & m);
200
	}
201
202
	static FP PRECISION;
203
204
	static {
205
		FP x = ONE, y = new FP(1, -BITS, 1 << BITS);
206
		while (x.compareTo(y) > 0) {
207
			PRECISION = x;
208
			x = x.div(TEN);
209
		}
210
	}
211
212
	public String toString() {
213
		// return Double.toString(doubleValue());
214
215-
		m = x.log10().add(PRECISION).intValue();
215+
216
		if (sign() == 0)
217
			return "0";
218
		StringBuilder sb = new StringBuilder();
219
220
		boolean neg = sign() < 0;
221
		FP x = this.abs();
222
		// if(x.mantissa!=0xFFFF) ++x.mantissa;
223
		int m = 0, m1 = 0;
224
		// while(TEN.pow(m+1).compareTo(x)<=0) ++m;
225
		m = x.log10().intValue();
226
		boolean useExp = (m >= 5 || (neg && m >= 3) || m <= -5);
227
		if (neg)
228
			sb.append('-');
229
		// set up for scientific notation
230
		if (useExp) {
231
			if (m < 0)
232
				--m;
233
			x = x.mul(TEN.pow(-m));
234
			m1 = m;
235
			m = 0;
236
		}
237
		if (m < 1.0) {
238
			m = 0;
239
		}
240
		// convert the number
241
		while (x.compareTo(PRECISION) > 0 || m >= 0) {
242
			FP weight = TEN.pow(m);
243
			if (weight.tst() > 0) {
244
				int digit = x.div(weight).intValue();
245
				x = x.sub(weight.mul(digit));
246
				sb.append((char) ('0' + digit));
247
			}
248
			if (m == 0 && x.tst() > 0)
249
				sb.append('.');
250
			m--;
251
		}
252
		if (useExp) {
253
			// convert the exponent
254
			sb.append('e');
255
			if (m1 > 0) {
256
				sb.append('+');
257
			} else {
258
				sb.append('-');
259
				m1 = -m1;
260
			}
261
			if (m1 > 10) {
262
				sb.append((char) ('0' + m1 / 10));
263
				m1 = m1 % 10;
264
			}
265
			sb.append((char) ('0' + m1));
266
		}
267
		return sb.toString();
268-
	public FP copySign(FP other) {
268+
269-
		return new FP(other.sign(), exponent(), mantissa());
269+
270
	public FP neg() {
271
		return new FP(-sign(), exponent(), mantissa());
272
	}
273
274
	public FP abs() {
275
		return new FP(sign() == 0 ? 0 : 1, exponent(), mantissa());
276
	}
277
278
	public FP mulSign(FP other) {
279
		return new FP((other.sign() & sign()) == 0 ? 0
280
				: ((other.sign() ^ sign()) | 1), exponent(), mantissa());
281
	}
282
283
	public int tst() {
284
		return sign();
285
	}
286
287
	public int compareTo(FP other) {
288
		int d = this.sign() - other.sign();
289
		if (d != 0) {
290
			return d;
291
		}
292
		if (this.sign() == 0)
293
			return 0;
294
		d = this.exponent() - other.exponent();
295
		if (d != 0)
296
			return d;
297
		d = (int) (this.mantissa() - other.mantissa());
298
		return d;
299
	}
300-
		return new FP(mant==0?0:sign, exp, mant);
300+
301
	public FP mul(FP other) {
302
		if ((this.sign() & other.sign()) == 0)
303
			return ZERO;
304
		int sign = (this.sign() ^ other.sign()) | 1;
305
		int exp = this.exponent() + other.exponent();
306
		long mant = (this.mantissa() * other.mantissa()) >>> BITS;
307
		if ((mant & (2l << BITS)) != 0) {
308
			mant >>>= 1;
309
			++exp;
310
		}
311
		return new FP(mant == 0 ? 0 : sign, exp, mant);
312
	}
313
314
	public FP mul(double v) {
315
		return mul(new FP(v));
316
	}
317
318
	public FP square() {
319
		return mul(this);
320
	}
321
322
	public FP pow(int n) {
323
		boolean neg = n < 0;
324
		if (neg)
325
			n = -n;
326
		FP x = this, y = ONE;
327
		while (n != 0) {
328-
			return MAX.copySign(other);
328+
329
				y = y.mul(x);
330
			}
331
			x = x.square();
332
			n >>>= 1;
333
		}
334
		return neg ? y.inv() : y;
335
	}
336
337
	public FP div(FP other) {
338
		if (other.sign() == 0)
339
			return MAX.mulSign(this).mulSign(other);
340
		if (this.sign() == 0)
341
			return ZERO;
342
		int sign = (this.sign() ^ other.sign()) | 1;
343
		int exp = this.exponent() - other.exponent();
344
		long mant = (this.mantissa() << (1 + BITS)) / other.mantissa();
345
		if ((mant & (2l << BITS)) != 0) {
346
			mant >>>= 1;
347
		} else {
348
			--exp;
349
		}
350
		return new FP(sign, exp, mant);
351
	}
352
353
	public FP inv() {
354
		return ONE.div(this);
355
	}
356
357
	public FP sub(FP other) {
358
		return add(other.neg());
359
	}
360
361
	public FP add(FP other) {
362
		if (sign() == 0)
363
			return other;
364
		if (other.sign() == 0)
365
			return this;
366
367
		FP small = this;
368
		FP big = other;
369
		if (small.exponent() == big.exponent()) {
370
			if (small.mantissa() > big.mantissa()) {
371
				small = other;
372
				big = this;
373
			}
374
		} else if (small.exponent() > big.exponent()) {
375
			small = other;
376
			big = this;
377
		}
378
		int exp = big.exponent();
379
		long mant = big.mantissa();
380
		long delta = small.mantissa() >>> (big.exponent() - small.exponent());
381
		if (big.sign() == small.sign()) {
382
			mant += delta;
383
			if ((mant & (2l << BITS)) != 0) {
384
				mant >>>= 1;
385
				++exp;
386
			}
387
		} else {
388
			mant -= delta;
389
			if (mant == 0)
390
				return ZERO;
391
			while ((mant & (1l << BITS)) == 0) {
392-
	static protected FP[] ln = { new FP(8.690628917915396e-06), new FP(0.9992996219306662), new FP(-0.4907434587925273), new FP(0.2867076984634543), new FP(-0.1332213692732176),
392+
393
				--exp;
394
			}
395
		}
396
		return new FP(big.sign(), exp, mant);
397
	}
398
399
	protected FP add(double v) {
400
		return add(new FP(v));
401
	}
402
403
	static protected FP[] ln = { new FP(8.690628917915396e-06),
404
			new FP(0.9992996219306662), new FP(-0.4907434587925273),
405
			new FP(0.2867076984634543), new FP(-0.1332213692732176),
406
			new FP(0.03110469698575859) };
407
408
	public FP ln() {
409
		if (sign() <= 0)
410
			return MAX.neg();
411
		FP x = new FP(1, 0, mantissa()).sub(ONE), y = ZERO;
412
		for (int i = ln.length; --i >= 0;)
413
			y = y.mul(x).add(ln[i]);
414
		int exp = this.exponent() < 0 ? -this.exponent() : this.exponent();
415
		while (exp > 0) {
416
			y = y.add(LN2);
417
			--exp;
418
		}
419
		if (this.exponent() < 0)
420
			y = y.neg();
421
		return y;
422
	}
423
424
	public FP log10() {
425
		return ln().div(LN10);
426
	}
427
428
	public FP sqrt() {
429
		if (sign() <= 0)
430
			return ZERO;
431-
	    if (op > res)
431+
432-
	    {
432+
433-
	        res++;
433+
434-
	    }
434+
435
		while (one != 0) {
436
			if (op >= res + one) {
437
				op -= res + one;
438
				res += one << 1;
439
			}
440
			res >>>= 1;
441-
	
441+
442
		}
443-
		//exp(2^x * y) = exp(y)^(2^x) = exp(2^0) * exp(2^-1)
443+
444-
		
444+
		if (op > res) {
445-
		if(sign()==0) return ONE;
445+
			res++;
446-
		
446+
447
448-
		FP x = ONE, y = E;
448+
449-
		long m = mantissa(), msk=ONE_MSK;
449+
450-
		while(m!=0) {
450+
451-
			if((m & msk)!=0) {x = x.mul(y); m^=msk;} 
451+
452-
			y = y.sqrt(); msk>>=1;
452+
453-
			if(ONE.equals(y)) break;
453+
454
	public FP exp() {
455-
		
455+
		// exp(2^x * y) = exp(y)^(2^x) = exp(2^0) * exp(2^-1)
456
457
		if (sign() == 0)
458-
		while(exp>0) {x = x.square(); --exp; if(MAX.compareTo(x)==0) break;}
458+
			return ONE;
459-
		while(exp<0) {x = x.sqrt(); ++exp; if(ONE.compareTo(x)==0) break;}
459+
460-
		
460+
461-
		return sign()<0?x.inv():x;
461+
		FP x = ONE;
462
		if (false) {
463
			FP y = E;
464
			long m = mantissa(), msk = ONE_MSK;
465
			while (m != 0 && !ONE.equals(y)) {
466
				if ((m & msk) != 0) {
467
					x = x.mul(y);
468
					m ^= msk;
469
				}
470
				y = y.sqrt();
471
				msk >>>= 1;
472
			}
473
		} else {
474
			// optim
475
			long z = mantissa(), y = ONE_MSK, t, k;
476
			int exp = 0;
477
			for (k = 1; (t = (long) (Math.log((k + 1.0) / k) * ONE_MSK + 0.5)) != 0; k <<= 1) {
478
				t = z - t;
479
				if (t >= 0) {
480
					z = t;
481
					y += y / k;
482
					if ((y & (ONE_MSK * 2)) != 0) {
483
						y >>>= 1;
484
						++exp;
485
					}
486
				}
487
			}
488
			x = new FP(1, exp, y);
489
		}
490
491
		// exp(2^exponent)
492
		int exp = exponent();
493
		while (exp > 0 && !MAX.equals(x)) {
494
			x = x.square();
495
			--exp;
496
		}
497
		while (exp < 0 && !ONE.equals(x)) {
498
			x = x.sqrt();
499
			++exp;
500
		}
501
502
		return sign() < 0 ? x.inv() : x;
503
	}
504
}