JAL-1807 Bob's JalviewJS prototype first commit
[jalviewjs.git] / src / javajs / util / BC.java
1 package javajs.util;\r
2 \r
3 public class BC {\r
4 \r
5   public BC() {\r
6     // unnecessary to instantialize unless subclassed\r
7   }\r
8   \r
9   public static float bytesToFloat(byte[] bytes, int j, boolean isBigEndian) throws Exception {\r
10     return intToFloat(bytesToInt(bytes, j, isBigEndian));\r
11   }\r
12 \r
13   public static int bytesToInt(byte[] bytes, int j, boolean isBigEndian) {\r
14     int n = (isBigEndian ? (bytes[j + 3] & 0xff) | (bytes[j + 2] & 0xff) << 8\r
15         | (bytes[j + 1] & 0xff) << 16 | (bytes[j] & 0xff) << 24\r
16         : (bytes[j++] & 0xff) | (bytes[j++] & 0xff) << 8\r
17             | (bytes[j++] & 0xff) << 16 | (bytes[j++] & 0xff) << 24);\r
18     /**\r
19      * @j2sNative\r
20      * \r
21      * return (n > 0x7FFFFFFF ? n - 0x100000000 : n);\r
22      *   \r
23      */\r
24     {\r
25       return n;\r
26     }\r
27   }\r
28 \r
29   public static float intToFloat(int x) throws Exception {\r
30     /**\r
31      * see http://en.wikipedia.org/wiki/Binary32\r
32      * \r
33      * [sign]      [8 bits power] [23 bits fraction]\r
34      * 0x80000000  0x7F800000      0x7FFFFF\r
35      * \r
36      * (untested)\r
37      * \r
38      * @j2sNative\r
39      * \r
40      *       if (x == 0) return 0;\r
41      *       var o = javajs.util.BC;\r
42      *       if (o.fracIEEE == null)\r
43      *         o.setFracIEEE();\r
44      *       var m = ((x & 0x7F800000) >> 23);\r
45      *       return ((x & 0x80000000) == 0 ? 1 : -1) * o.shiftIEEE((x & 0x7FFFFF) | 0x800000, m - 149);\r
46      *  \r
47      */\r
48     {\r
49     return Float.intBitsToFloat(x);\r
50     }\r
51   }\r
52 \r
53   /**\r
54    * see http://en.wikipedia.org/wiki/Binary64\r
55    *  \r
56    * not concerning ourselves with very small or very large numbers and getting\r
57    * this exactly right. Just need a float here.\r
58    * \r
59    * @param bytes\r
60    * @param j\r
61    * @param isBigEndian\r
62    * @return float\r
63    */\r
64   public static float bytesToDoubleToFloat(byte[] bytes, int j, boolean isBigEndian) {\r
65     {\r
66       // IEEE754: sign (1 bit), exponent (11 bits), fraction (52 bits).\r
67       // seeeeeee eeeeffff ffffffff ffffffff ffffffff xxxxxxxx xxxxxxxx xxxxxxxx\r
68       //     b1      b2       b3       b4       b5    ---------float ignores----\r
69 \r
70         if (fracIEEE == null)\r
71            setFracIEEE();\r
72         \r
73       /**\r
74        * @j2sNative\r
75        *       var o = javajs.util.BC;\r
76        *       var b1, b2, b3, b4, b5;\r
77        *       \r
78        *       if (isBigEndian) {\r
79        *       b1 = bytes[j] & 0xFF;\r
80        *       b2 = bytes[j + 1] & 0xFF;\r
81        *       b3 = bytes[j + 2] & 0xFF;\r
82        *       b4 = bytes[j + 3] & 0xFF;\r
83        *       b5 = bytes[j + 4] & 0xFF;\r
84        *       } else {\r
85        *       b1 = bytes[j + 7] & 0xFF;\r
86        *       b2 = bytes[j + 6] & 0xFF;\r
87        *       b3 = bytes[j + 5] & 0xFF;\r
88        *       b4 = bytes[j + 4] & 0xFF;\r
89        *       b5 = bytes[j + 3] & 0xFF;\r
90        *       }\r
91        *       var s = ((b1 & 0x80) == 0 ? 1 : -1);\r
92        *       var e = (((b1 & 0x7F) << 4) | (b2 >> 4)) - 1026;\r
93        *       b2 = (b2 & 0xF) | 0x10;\r
94        *       return s * (o.shiftIEEE(b2, e) + o.shiftIEEE(b3, e - 8) + o.shiftIEEE(b4, e - 16)\r
95        *         + o.shiftIEEE(b5, e - 24));\r
96        */\r
97       {\r
98         double d;\r
99         \r
100         if (isBigEndian)\r
101           d = Double.longBitsToDouble((((long) bytes[j]) & 0xff) << 56\r
102              | (((long) bytes[j + 1]) & 0xff) << 48\r
103              | (((long) bytes[j + 2]) & 0xff) << 40\r
104              | (((long) bytes[j + 3]) & 0xff) << 32\r
105              | (((long) bytes[j + 4]) & 0xff) << 24\r
106              | (((long) bytes[j + 5]) & 0xff) << 16\r
107              | (((long) bytes[j + 6]) & 0xff) << 8 \r
108              | (((long) bytes[7]) & 0xff));\r
109         else\r
110           d = Double.longBitsToDouble((((long) bytes[j + 7]) & 0xff) << 56\r
111              | (((long) bytes[j + 6]) & 0xff) << 48\r
112              | (((long) bytes[j + 5]) & 0xff) << 40\r
113              | (((long) bytes[j + 4]) & 0xff) << 32\r
114              | (((long) bytes[j + 3]) & 0xff) << 24\r
115              | (((long) bytes[j + 2]) & 0xff) << 16\r
116              | (((long) bytes[j + 1]) & 0xff) << 8 \r
117              | (((long) bytes[j]) & 0xff));\r
118         return (float) d;\r
119       }\r
120 \r
121     }\r
122   }\r
123 \r
124   private static float[] fracIEEE;\r
125 \r
126   private static void setFracIEEE() {\r
127     fracIEEE = new float[270];\r
128     for (int i = 0; i < 270; i++)\r
129       fracIEEE[i] = (float) Math.pow(2, i - 141);\r
130     //    System.out.println(fracIEEE[0] + "  " + Parser.FLOAT_MIN_SAFE);\r
131     //    System.out.println(fracIEEE[269] + "  " + Float.MAX_VALUE);\r
132   }\r
133 \r
134   /**\r
135    * only concerned about reasonable float values here -- private but not designated; called by JavaScript\r
136    * \r
137    * @param f\r
138    * @param i\r
139    * @return f * 2^i\r
140    */\r
141   static double shiftIEEE(double f, int i) {\r
142     if (f == 0 || i < -140)\r
143       return 0;\r
144     if (i > 128)\r
145       return Float.MAX_VALUE;\r
146     return f * fracIEEE[i + 140];\r
147   }\r
148 \r
149 //  static {\r
150 //    setFracIEEE();\r
151 //    for (int i = -50; i < 50; i++) {\r
152 //      float f = i * (float) (Math.random() * Math.pow(2, Math.random() * 100 - 50));\r
153 //      int x = Float.floatToIntBits(f);\r
154 //      int m = ((x & 0x7F800000) >> 23);\r
155 //      float f1 = (float) (f == 0 ? 0 : ((x & 0x80000000) == 0 ? 1 : -1) * shiftIEEE((x & 0x7FFFFF) | 0x800000, m - 149));\r
156 //      System.out.println(f + "  " + f1);\r
157 //    }\r
158 //    System.out.println("binarydo");\r
159 //  }\r
160 \r
161 \r
162 \r
163 }\r