1 package nom.tam.util;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 @Deprecated
58 public final class ByteFormatter {
59
60
61 public static final String NOT_A_NUMBER = "NaN";
62
63
64 public static final String INFINITY = "Infinity";
65
66
67 public static final String NEGATIVE_INFINITY = "-Infinity";
68
69
70
71
72 private static final double DEFAULT_SIMPLE_MAX = 1.e6;
73
74
75
76
77 private static final double DEFAULT_SIMPLE_MIN = 1.e-3;
78
79
80
81
82
83 private static final byte[] DIGITS = {(byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5',
84 (byte) '6', (byte) '7', (byte) '8', (byte) '9'};
85
86 private static final long DOUBLE_EXPONENT_BIT_MASK = 0x7FF0000000000000L;
87
88 private static final int DOUBLE_EXPONENT_EXCESS = 52;
89
90
91
92
93 private static final long DOUBLE_EXPONENT_NORMALIZE_BIT = 0x0010000000000000L;
94
95
96
97
98 private static final int DOUBLE_MIN_EXPONENT = -1023;
99
100 private static final int DOUBLE_SHIFT_BASE = 17;
101
102 private static final int DOUBLE_SHIFT_LIMIT = 200;
103
104 private static final long DOUBLE_VALUE_BIT_MASK = 0x000FFFFFFFFFFFFFL;
105
106 private static final int FLOAT_EXPONENT_BIT_MASK = 0x7F800000;
107
108 private static final int FLOAT_EXPONENT_EXCESS = 23;
109
110
111
112
113 private static final int FLOAT_EXPONENT_NORMALIZE_BIT = 0x00800000;
114
115
116
117
118 private static final int FLOAT_MIN_EXPONENT = -127;
119
120 private static final int FLOAT_SHIFT_BASE = 8;
121
122 private static final int FLOAT_SHIFT_LIMIT = 30;
123
124 private static final int FLOAT_VALUE_BIT_MASK = 0x007FFFFF;
125
126 private static final double I_LOG_10 = 1. / Math.log(ByteFormatter.NUMBER_BASE);
127
128 private static final long LONG_TO_INT_MODULO = 1000000000L;
129
130 private static final int MAX_LONG_LENGTH = 19;
131
132
133
134
135
136 private static final int MAXIMUM_SINGLE_DIGIT_INTEGER = 9;
137
138
139
140
141
142 private static final int MAXIMUM_TWO_DIGIT_INTEGER = 99;
143
144 private static final int TEMP_BUFFER_SIZE = 32;
145
146
147
148
149 private static final int NUMBER_BASE = 10;
150
151
152
153
154
155 private static final double[] NUMBER_BASE_POWERS;
156
157
158
159
160 private static final byte TRUNCATION_FILL = (byte) '*';
161
162
163
164
165 private static final int ZERO_POW;
166
167 static {
168 int min = (int) Math.floor((int) (Math.log(Double.MIN_VALUE) * ByteFormatter.I_LOG_10));
169 int max = (int) Math.floor((int) (Math.log(Double.MAX_VALUE) * ByteFormatter.I_LOG_10));
170 max++;
171 NUMBER_BASE_POWERS = new double[max - min + 1];
172 for (int i = 0; i < ByteFormatter.NUMBER_BASE_POWERS.length; i++) {
173 ByteFormatter.NUMBER_BASE_POWERS[i] = Math.pow(ByteFormatter.NUMBER_BASE, i + min);
174 }
175 ZERO_POW = -min;
176 }
177
178
179
180
181 private final byte[] tbuf1 = new byte[ByteFormatter.TEMP_BUFFER_SIZE];
182
183 private final byte[] tbuf2 = new byte[ByteFormatter.TEMP_BUFFER_SIZE];
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198 private int combineReal(double val, byte[] buf, int off, int len, byte[] mant, int lmant, int shift) {
199
200
201
202 double pos = Math.abs(val);
203 boolean simple = false;
204 int minSize;
205 int maxSize;
206
207 if (pos >= ByteFormatter.DEFAULT_SIMPLE_MIN && pos <= ByteFormatter.DEFAULT_SIMPLE_MAX) {
208 simple = true;
209 }
210
211 int exp = lmant - shift - 1;
212 int lexp = 0;
213
214 if (!simple) {
215 lexp = format(exp, tbuf2, 0, ByteFormatter.TEMP_BUFFER_SIZE);
216
217 minSize = lexp + 2;
218 maxSize = lexp + lmant + 2;
219 } else if (exp >= 0) {
220 minSize = exp + 1;
221
222
223
224 int i;
225 for (i = 0; i < lmant && i <= exp; i++) {
226 if (mant[i] != (byte) '9') {
227 break;
228 }
229 }
230 if (i > exp && i < lmant && mant[i] >= (byte) '5') {
231 minSize++;
232 }
233
234 maxSize = lmant + 1;
235 if (maxSize <= minSize) {
236 maxSize = minSize + 1;
237 }
238 } else {
239 minSize = 2;
240 maxSize = 1 + Math.abs(exp) + lmant;
241 }
242 if (val < 0) {
243 minSize++;
244 }
245
246
247 if (minSize > len || minSize > buf.length - off) {
248 truncationFiller(buf, off, len);
249 return off + len;
250 }
251
252
253 if (val < 0) {
254 buf[off] = (byte) '-';
255 off++;
256 len--;
257 }
258
259 if (simple) {
260 return Math.abs(mantissa(mant, lmant, exp, simple, buf, off, len));
261 }
262 off = mantissa(mant, lmant, 0, simple, buf, off, len - lexp - 1);
263 if (off < 0) {
264 off = -off;
265 len -= off;
266
267 if (exp == MAXIMUM_SINGLE_DIGIT_INTEGER || exp == MAXIMUM_TWO_DIGIT_INTEGER) {
268
269 if (off + len == minSize) {
270 truncationFiller(buf, off, len);
271 return off + len;
272 }
273
274 off--;
275 }
276 exp++;
277 lexp = format(exp, tbuf2, 0, ByteFormatter.TEMP_BUFFER_SIZE);
278 }
279 buf[off] = (byte) 'E';
280 off++;
281 System.arraycopy(tbuf2, 0, buf, off, lexp);
282 return off + lexp;
283 }
284
285
286
287
288
289
290
291
292
293 public int format(boolean val, byte[] array) {
294 return format(val, array, 0, array.length);
295 }
296
297
298
299
300
301
302
303
304
305
306
307 public int format(boolean val, byte[] array, int off, int len) {
308 if (len > 0) {
309 if (val) {
310 array[off] = (byte) 'T';
311 } else {
312 array[off] = (byte) 'F';
313 }
314 off++;
315 }
316 return off;
317 }
318
319
320
321
322
323
324
325
326
327 public int format(double val, byte[] array) {
328 return format(val, array, 0, array.length);
329 }
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353 public int format(double val, byte[] buf, int off, int len) {
354
355 double pos = Math.abs(val);
356
357
358 if (pos == 0.) {
359 return format("0.0", buf, off, len);
360 }
361 if (Double.isNaN(val)) {
362 return format(NOT_A_NUMBER, buf, off, len);
363 }
364 if (Double.isInfinite(val)) {
365 if (val > 0) {
366 return format(INFINITY, buf, off, len);
367 }
368 return format(NEGATIVE_INFINITY, buf, off, len);
369 }
370
371 int power = (int) (Math.log(pos) * ByteFormatter.I_LOG_10);
372 int shift = DOUBLE_SHIFT_BASE - power;
373 double scale;
374 double scale2 = 1;
375
376
377 if (shift < DOUBLE_SHIFT_LIMIT) {
378 scale = ByteFormatter.NUMBER_BASE_POWERS[shift + ByteFormatter.ZERO_POW];
379 } else {
380
381
382
383 scale2 = ByteFormatter.NUMBER_BASE_POWERS[DOUBLE_SHIFT_LIMIT + ByteFormatter.ZERO_POW];
384 scale = ByteFormatter.NUMBER_BASE_POWERS[shift - DOUBLE_SHIFT_LIMIT + ByteFormatter.ZERO_POW];
385 }
386
387 pos = pos * scale * scale2;
388
389
390
391 long bits = Double.doubleToLongBits(pos);
392
393
394 int exp = (int) (((bits & DOUBLE_EXPONENT_BIT_MASK) >> DOUBLE_EXPONENT_EXCESS) + DOUBLE_MIN_EXPONENT);
395
396 long numb = bits & DOUBLE_VALUE_BIT_MASK;
397
398
399
400 if (exp > DOUBLE_MIN_EXPONENT) {
401
402 numb |= DOUBLE_EXPONENT_NORMALIZE_BIT;
403 } else {
404
405 exp++;
406 }
407
408
409
410 numb = numb << exp - DOUBLE_EXPONENT_EXCESS;
411
412
413 int ndig = format(numb, tbuf1, 0, ByteFormatter.TEMP_BUFFER_SIZE);
414
415
416
417 return combineReal(val, buf, off, len, tbuf1, ndig, shift);
418 }
419
420
421
422
423
424
425
426
427
428 public int format(float val, byte[] array) {
429 return format(val, array, 0, array.length);
430 }
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454 public int format(float val, byte[] buf, int off, int len) {
455
456 float pos = Math.abs(val);
457
458
459 if (pos == 0.) {
460 return format("0.0", buf, off, len);
461 }
462 if (Float.isNaN(val)) {
463 return format(NOT_A_NUMBER, buf, off, len);
464 }
465 if (Float.isInfinite(val)) {
466 if (val > 0) {
467 return format("Infinity", buf, off, len);
468 }
469 return format("-Infinity", buf, off, len);
470 }
471
472 int power = (int) Math.floor(Math.log(pos) * ByteFormatter.I_LOG_10);
473 int shift = FLOAT_SHIFT_BASE - power;
474 float scale;
475 float scale2 = 1;
476
477
478 if (shift < FLOAT_SHIFT_LIMIT) {
479 scale = (float) ByteFormatter.NUMBER_BASE_POWERS[shift + ByteFormatter.ZERO_POW];
480 } else {
481
482
483
484 scale2 = (float) ByteFormatter.NUMBER_BASE_POWERS[FLOAT_SHIFT_LIMIT + ByteFormatter.ZERO_POW];
485 scale = (float) ByteFormatter.NUMBER_BASE_POWERS[shift - FLOAT_SHIFT_LIMIT + ByteFormatter.ZERO_POW];
486 }
487
488 pos = pos * scale * scale2;
489
490
491
492 int bits = Float.floatToIntBits(pos);
493
494
495 int exp = ((bits & FLOAT_EXPONENT_BIT_MASK) >> FLOAT_EXPONENT_EXCESS) + FLOAT_MIN_EXPONENT;
496
497 int numb = bits & FLOAT_VALUE_BIT_MASK;
498
499 if (exp > FLOAT_MIN_EXPONENT) {
500
501 numb |= FLOAT_EXPONENT_NORMALIZE_BIT;
502 } else {
503
504 exp++;
505 }
506
507
508
509
510
511 numb = numb << exp - FLOAT_EXPONENT_EXCESS;
512
513
514 int ndig = format(numb, tbuf1, 0, ByteFormatter.TEMP_BUFFER_SIZE);
515
516
517
518 return combineReal(val, buf, off, len, tbuf1, ndig, shift);
519 }
520
521
522
523
524
525
526
527
528
529 public int format(int val, byte[] array) {
530 return format(val, array, 0, array.length);
531 }
532
533
534
535
536
537
538
539
540
541
542
543 public int format(int val, byte[] buf, int off, int len) {
544
545
546 if (val == Integer.MIN_VALUE) {
547 if (len > ByteFormatter.NUMBER_BASE) {
548 return format("-2147483648", buf, off, len);
549 }
550 truncationFiller(buf, off, len);
551 return off + len;
552 }
553
554 int pos = Math.abs(val);
555
556
557
558
559 int ndig = 1;
560 int dmax = ByteFormatter.NUMBER_BASE;
561
562 while (ndig < ByteFormatter.NUMBER_BASE && pos >= dmax) {
563 ndig++;
564 dmax *= ByteFormatter.NUMBER_BASE;
565 }
566
567 if (val < 0) {
568 ndig++;
569 }
570
571
572 if (ndig > len || ndig > buf.length - off) {
573 truncationFiller(buf, off, len);
574 return off + len;
575 }
576
577
578
579
580 off += ndig;
581
582 int xoff = off - 1;
583 do {
584 buf[xoff] = ByteFormatter.DIGITS[pos % ByteFormatter.NUMBER_BASE];
585 xoff--;
586 pos /= ByteFormatter.NUMBER_BASE;
587 } while (pos > 0);
588
589 if (val < 0) {
590 buf[xoff] = (byte) '-';
591 }
592
593 return off;
594 }
595
596
597
598
599
600
601
602
603
604 public int format(long val, byte[] array) {
605 return format(val, array, 0, array.length);
606 }
607
608
609
610
611
612
613
614
615
616
617
618 public int format(long val, byte[] buf, int off, int len) {
619
620 if (val == Long.MIN_VALUE) {
621 if (len > MAX_LONG_LENGTH) {
622 return format("-9223372036854775808", buf, off, len);
623 }
624 truncationFiller(buf, off, len);
625 return off + len;
626 }
627 long pos = Math.abs(val);
628
629
630 int ndig = 1;
631 long dmax = ByteFormatter.NUMBER_BASE;
632
633 while (ndig < MAX_LONG_LENGTH && pos >= dmax) {
634 ndig++;
635 dmax *= ByteFormatter.NUMBER_BASE;
636 }
637 if (val < 0) {
638 ndig++;
639 }
640
641 if (ndig > len || ndig > buf.length - off) {
642 truncationFiller(buf, off, len);
643 return off + len;
644 }
645
646 off += ndig;
647 int xoff = off - 1;
648 buf[xoff] = (byte) '0';
649 boolean last = pos == 0;
650 while (!last) {
651
652 int giga = (int) (pos % LONG_TO_INT_MODULO);
653 pos /= LONG_TO_INT_MODULO;
654 last = pos == 0;
655 for (int i = 0; i < MAXIMUM_SINGLE_DIGIT_INTEGER; i++) {
656
657 buf[xoff] = ByteFormatter.DIGITS[giga % ByteFormatter.NUMBER_BASE];
658 xoff--;
659 giga /= ByteFormatter.NUMBER_BASE;
660 if (last && giga == 0) {
661 break;
662 }
663 }
664 }
665
666 if (val < 0) {
667 buf[xoff] = (byte) '-';
668 }
669
670 return off;
671 }
672
673
674
675
676
677
678
679
680
681 public int format(String val, byte[] array) {
682 return format(val, array, 0, array.length);
683 }
684
685
686
687
688
689
690
691
692
693
694
695
696 public int format(String val, byte[] array, int off, int len) {
697
698 if (val == null) {
699 for (int i = 0; i < len; i++) {
700 array[off + i] = (byte) ' ';
701 }
702 return off + len;
703 }
704
705 int slen = val.length();
706
707 if (slen > len || slen > array.length - off) {
708 val = val.substring(0, len);
709 slen = len;
710 }
711
712 System.arraycopy(AsciiFuncs.getBytes(val), 0, array, off, slen);
713 return off + slen;
714 }
715
716
717
718
719 private int mantissa(byte[] mant, int lmant, int exp, boolean simple, byte[] buf, int off, int len) {
720
721
722 int off0 = off;
723 int pos = 0;
724
725 if (exp < 0) {
726 buf[off] = (byte) '0';
727 len--;
728 off++;
729 if (len > 0) {
730 buf[off] = (byte) '.';
731 off++;
732 len--;
733 }
734
735 int cexp = exp;
736 while (cexp < -1 && len > 0) {
737 buf[off] = (byte) '0';
738 cexp++;
739 off++;
740 len--;
741 }
742
743 } else {
744
745
746 while (exp >= 0 && pos < lmant) {
747 buf[off] = mant[pos];
748 off++;
749 pos++;
750 len--;
751 exp--;
752 }
753
754 for (int i = 0; i <= exp; i++) {
755 buf[off] = (byte) '0';
756 off++;
757 len--;
758 }
759
760
761 if (len > 0) {
762 buf[off] = (byte) '.';
763 len--;
764 off++;
765 }
766 }
767
768
769 while (len > 0 && pos < lmant) {
770 buf[off] = mant[pos];
771 off++;
772 exp--;
773 len--;
774 pos++;
775 }
776
777
778
779 if (pos < lmant && mant[pos] >= (byte) '5') {
780 int i;
781
782
783 for (i = off - 1; i >= off0; i--) {
784
785 if (buf[i] == (byte) '.' || buf[i] == (byte) '-') {
786 continue;
787 }
788 if (buf[i] != (byte) '9') {
789 buf[i]++;
790 break;
791 }
792 buf[i] = (byte) '0';
793 }
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813 if (i < off0) {
814
815 buf[off0] = (byte) '1';
816 boolean foundDecimal = false;
817 for (i = off0 + 1; i < off; i++) {
818 if (buf[i] == (byte) '.') {
819 foundDecimal = true;
820 if (simple) {
821 buf[i] = (byte) '0';
822 i++;
823 if (i < off) {
824 buf[i] = (byte) '.';
825 }
826 }
827 break;
828 }
829 }
830 if (simple && !foundDecimal) {
831 buf[off + 1] = (byte) '0';
832 off++;
833 }
834
835 off = -off;
836 }
837
838 }
839
840 return off;
841 }
842
843
844
845
846
847 private void truncationFiller(byte[] buffer, int offset, int length) {
848 for (int i = offset; i < offset + length; i++) {
849 buffer[i] = ByteFormatter.TRUNCATION_FILL;
850 }
851 }
852
853 }