package org.das2.qds.buffer; import java.nio.ByteBuffer; /** * reader to read Vax floats, motivated by RPWS group need to read ISEE data. *
* @author jbf */ public final class VaxFloatDataSet extends BufferDataSet { // from http://www.codeproject.com/Articles/12363/Transform-between-IEEE-IBM-or-VAX-floating-point-n //SEF : S EEEEEEEE FFFFFFF FFFFFFFF FFFFFFFF //bits : 1 2 9 10 32 //bytes : byte2 byte1 byte4 byte3 // JBF: Note the above wasn't used, but instead code from google for "vax float java nio Jenness" public VaxFloatDataSet(int rank, int reclen, int recoffs, int len0, int len1, int len2, int len3, ByteBuffer back) { super(rank, reclen, recoffs, len0, len1, len2, len3, VAX_FLOAT, back); this.makeImmutable(); } /** * convert from 4byte vax float to Java double. See * ftp://202.127.24.195/pub/astrolibs/.../java/gsd/.../GSDVAXBytes.java * google for "vax float java nio Jenness" * @param buf1 * @param offset * @return double value represented. */ private double vaxFloatValue2(ByteBuffer buf, int offset) { ByteBuffer tmp = ByteBuffer.allocate(4); // Take this from gsd2_nativr.c as written by Horst and Remo // Extract the exponent int e = ((buf.get(1+offset) << 1) & 0xfe) | ((buf.get(0+offset) >> 7) & 0x1); /* If the (biased) exponent is greater than 2, then the * VAXF number can be represented in IEEE_S form as a * normalised number. Decrement the exponent by 2. This * allows for a difference of 1 between the exponent bias * values of the two number formats and a further * difference of one in the assumed position of the binary * radix point. */ if (e > 2) { e -= 2; /* Construct the resulting IEEE_S number, using the * appropriate bytes of the VAXF number but * replacing the exponent field with its modified * value. */ tmp.put(0, (byte) ((buf.get(1+offset) & 0x80) | ((e >> 1) & 0x7f))); tmp.put(1, (byte) ((buf.get(0+offset) & 0x7f) | ((e << 7) & 0x80))); tmp.put(2, (byte) (buf.get(3+offset))); tmp.put(3, (byte) (buf.get(2+offset))); } else if (e == 0) { /* If the (biased) VAXF exponent is zero, then the * resulting IEEE_S value is zero (or we have a VAX * reserved operand, but we assume that can't happen). */ for (int i = 0; i < 4; i++) { tmp.put(i, (byte) 0); } } else { /* Otherwise, if the (biased) exponent is 2 or less, * then the IEEE_S equivalent will be a denormalised * number, so the fraction field must be modified. * Extract all the bits of the VAXF fraction field into * a single integer (remember we can't assume what * order the integer's bytes are stored in). Also add * the (normally omitted) leading 1. */ int f = buf.get(2+offset) | (buf.get(3+offset) << 8) | ((buf.get(0+offset) & 0x7f) << 16) | (0x1 << 23); /* Shift the fraction bits to account for the * limited range of the exponent. Then pack the * fraction field into the IEEE_S number. Retain the * VAXF sign bit, but set the exponent field to zero * (indicating a denormalised number). */ f = f >> (3 - e); tmp.put(0, (byte) (buf.get(1+offset) & 0x80)); tmp.put(1, (byte) ((f >> 16) & 0x7f)); tmp.put(2, (byte) ((f >> 8) & 0xff)); tmp.put(3, (byte) (f & 0xff)); } /* We know we are always BIG endian so just convert the byte buffer to a float */ return tmp.getFloat(); } @Override public double value() { return vaxFloatValue2(back, offset()); } @Override public double value(int i0) { return vaxFloatValue2(back, offset(i0)); } @Override public double value(int i0, int i1) { return vaxFloatValue2(back, offset(i0, i1)); } @Override public double value(int i0, int i1, int i2) { return vaxFloatValue2(back, offset(i0, i1, i2)); } @Override public double value(int i0, int i1, int i2, int i3) { return vaxFloatValue2(back, offset(i0, i1, i2, i3)); } // public static void main(String[] args) throws FileNotFoundException, IOException { // // /opt/project/isee/archive/a1977/77295.arc // // 77295 69197230 62470 first three are 4-byte floats. I can read these. // // 3.12926e+07 -5.01478e+07 1.97070e+07 GSEX GSEY GSEZ // // File f = new File("/opt/project/isee/archive/a1977/77295.arc"); // FileChannel fc = new FileInputStream(f).getChannel(); // ByteBuffer buf = fc.map(FileChannel.MapMode.READ_ONLY, 0, 10000); // buf.order(ByteOrder.LITTLE_ENDIAN); // VaxFloat vf = new VaxFloat(1, 880, 12, 10, 1, 1, 1, buf); // System.err.println(vf.value(0)); // Int i = new Int(1, 880, 0, 10, 1, 1, 1, buf); // System.err.println(i.value(0)); // verified. // } @Override public void putValue(double d) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void putValue(int i0, double d) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void putValue(int i0, int i1, double d) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void putValue(int i0, int i1, int i2, double d) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void putValue(int i0, int i1, int i2, int i3, double d) { throw new UnsupportedOperationException("Not supported yet."); } }*vap+bin:sftp://klunk.physics.uiowa.edu/opt/project/isee/archive/a1977/77295.arc?recLength=880&type=vaxfloat&recOffset=20 *