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