diff --git a/usage/src/main/java/com/ning/billing/usage/timeline/samples/HalfFloat.java b/usage/src/main/java/com/ning/billing/usage/timeline/samples/HalfFloat.java
new file mode 100644
index 0000000..90f9e77
--- /dev/null
+++ b/usage/src/main/java/com/ning/billing/usage/timeline/samples/HalfFloat.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2010-2012 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.usage.timeline.samples;
+
+public class HalfFloat {
+
+ private final short halfFloat;
+
+ public HalfFloat(final float input) {
+ halfFloat = (short)fromFloat(input);
+ }
+
+ public float getFloat() {
+ return toFloat((int)halfFloat);
+ }
+
+ // These two static methods were pinched from http://stackoverflow.com/questions/6162651/half-precision-floating-point-in-java/6162687#6162687
+ // The last comment on that page is the author saying "I hereby commit these to the public domain"
+
+ // Ignores the higher 16 bits
+ public static float toFloat(final int hbits) {
+ int mant = hbits & 0x03ff; // 10 bits mantissa
+ int exp = hbits & 0x7c00; // 5 bits exponent
+ if (exp == 0x7c00) { // NaN/Inf
+ exp = 0x3fc00; // -> NaN/Inf
+ }
+ else if (exp != 0) { // normalized value
+ exp += 0x1c000; // exp - 15 + 127
+ if(mant == 0 && exp > 0x1c400) { // smooth transition
+ return Float.intBitsToFloat((hbits & 0x8000) << 16 | exp << 13 | 0x3ff);
+ }
+ }
+ else if (mant != 0) { // && exp==0 -> subnormal
+ exp = 0x1c400; // make it normal
+ do {
+ mant <<= 1; // mantissa * 2
+ exp -= 0x400; // decrease exp by 1
+ } while ((mant & 0x400) == 0); // while not normal
+ mant &= 0x3ff; // discard subnormal bit
+ } // else +/-0 -> +/-0
+ return Float.intBitsToFloat( // combine all parts
+ (hbits & 0x8000) << 16 // sign << (31 - 15)
+ | (exp | mant) << 13); // value << (23 - 10)
+ }
+
+ // returns all higher 16 bits as 0 for all results
+ public static int fromFloat(final float fval) {
+ final int fbits = Float.floatToIntBits(fval);
+ final int sign = fbits >>> 16 & 0x8000; // sign only
+ int val = (fbits & 0x7fffffff) + 0x1000; // rounded value
+
+ if (val >= 0x47800000) { // might be or become NaN/Inf
+ if ((fbits & 0x7fffffff) >= 0x47800000) { // is or must become NaN/Inf
+
+ if (val < 0x7f800000) { // was value but too large
+ return sign | 0x7c00; // make it +/-Inf
+ }
+ return sign | 0x7c00 | // remains +/-Inf or NaN
+ (fbits & 0x007fffff) >>> 13; // keep NaN (and Inf) bits
+ }
+ return sign | 0x7bff; // unrounded not quite Inf
+ }
+ if(val >= 0x38800000) // remains normalized value
+ return sign | val - 0x38000000 >>> 13; // exp - 127 + 15
+ if(val < 0x33000000) // too small for subnormal
+ return sign; // becomes +/-0
+ val = (fbits & 0x7fffffff) >>> 23; // tmp exp for subnormal calc
+ return sign | ((fbits & 0x7fffff | 0x800000) // add subnormal bit
+ + (0x800000 >>> val - 102) >>> 126 - val); // round depending on cut off; div by 2^(1-(exp-127+15)) and >> 13 | exp=0
+ }
+
+ private static String describe(final int halfFloat) {
+ final int sign = (halfFloat >> 15) & 1;
+ final int exponent = (halfFloat >> 10) & 0x1f;
+ final double fraction = (double)(0x400 + (halfFloat & 0x3ff)) / (1.0 * 0x400);
+ final double product = fraction * Math.pow(2.0, exponent - 15) * (sign == 0 ? 1.0 : -1.0);
+ return String.format("HalfFloat %f, representation %x, sign %d, exponent 0x%x == 2**%d, fraction %f, product %f",
+ toFloat(halfFloat),
+ halfFloat,
+ sign,
+ exponent,
+ exponent - 15,
+ fraction,
+ product);
+ }
+
+ public static void main(String[] args) {
+ System.out.printf("%f double-converted = %f\n", 200.0, toFloat(fromFloat((float)200.0)));
+ System.out.printf("%s\n", describe(fromFloat(200.0f)));
+ }
+}