You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@vxquery.apache.org by pr...@apache.org on 2015/04/13 22:11:49 UTC

[2/4] vxquery git commit: Shivani's patch for VXQUERY-141 and a fix XTest results when running multiple threads.

Shivani's patch for VXQUERY-141 and a fix XTest results when running multiple threads.


Project: http://git-wip-us.apache.org/repos/asf/vxquery/repo
Commit: http://git-wip-us.apache.org/repos/asf/vxquery/commit/19df29bb
Tree: http://git-wip-us.apache.org/repos/asf/vxquery/tree/19df29bb
Diff: http://git-wip-us.apache.org/repos/asf/vxquery/diff/19df29bb

Branch: refs/heads/master
Commit: 19df29bb8f3b27a1532d4a4de8fac776df541b82
Parents: 5475329
Author: Eldon Carman <ec...@ucr.edu>
Authored: Mon Apr 13 11:36:19 2015 -0700
Committer: Eldon Carman <ec...@ucr.edu>
Committed: Mon Apr 13 11:36:19 2015 -0700

----------------------------------------------------------------------
 .../functions/cast/CastToDecimalOperation.java  |   6 +-
 .../functions/cast/CastToDoubleOperation.java   |  12 +-
 .../functions/cast/CastToFloatOperation.java    | 101 ++-----
 .../functions/cast/CastToStringOperation.java   | 273 ++++---------------
 .../java/org/apache/vxquery/xtest/XTest.java    |   3 +
 5 files changed, 89 insertions(+), 306 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/vxquery/blob/19df29bb/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToDecimalOperation.java
----------------------------------------------------------------------
diff --git a/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToDecimalOperation.java b/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToDecimalOperation.java
index 03a1e14..f44a8e0 100644
--- a/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToDecimalOperation.java
+++ b/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToDecimalOperation.java
@@ -66,8 +66,12 @@ public class CastToDecimalOperation extends AbstractCastToOperation {
                 throw new SystemException(ErrorCode.FORG0001);
             }
         }
+        if (Double.isNaN(doublep.getDouble()) || Double.isInfinite(doublep.getDouble())) {
+            throw new SystemException(ErrorCode.FORG0001);
+        }
         abvsInner.reset();
-        castToString.convertDoubleCanonical(doublep, dOutInner);
+        dOutInner.write(ValueTag.XS_STRING_TAG);
+        dOutInner.writeUTF(Double.toString(doublep.getDouble()));
         stringp.set(abvsInner.getByteArray(), abvsInner.getStartOffset() + 1, abvsInner.getLength() - 1);
         convertStringExtra(stringp, dOut, true);
     }

http://git-wip-us.apache.org/repos/asf/vxquery/blob/19df29bb/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToDoubleOperation.java
----------------------------------------------------------------------
diff --git a/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToDoubleOperation.java b/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToDoubleOperation.java
index 13bb1f0..43b06ff 100644
--- a/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToDoubleOperation.java
+++ b/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToDoubleOperation.java
@@ -92,14 +92,16 @@ public class CastToDoubleOperation extends AbstractCastToOperation {
             if (charIterator.next() != ICharacterIterator.EOS_CHAR) {
                 throw new SystemException(ErrorCode.FORG0001);
             } else if (c == Character.valueOf('I') && c2 == Character.valueOf('N') && c3 == Character.valueOf('F')) {
-                valueDouble = Double.POSITIVE_INFINITY;
+                if (negativeValue) {
+                    valueDouble = Double.NEGATIVE_INFINITY;
+                } else {
+                    valueDouble = Double.POSITIVE_INFINITY;
+                }
             } else if (c == Character.valueOf('N') && c2 == Character.valueOf('a') && c3 == Character.valueOf('N')) {
                 valueDouble = Double.NaN;
             } else {
                 throw new SystemException(ErrorCode.FORG0001);
             }
-            dOut.write(ValueTag.XS_DOUBLE_TAG);
-            dOut.writeDouble((negativeValue ? -valueDouble : valueDouble));
         } else {
             // We create an object to keep the conversion algorithm simple and improve precision.
             // While a better solution may be available this will hold us over until then.
@@ -110,9 +112,9 @@ public class CastToDoubleOperation extends AbstractCastToOperation {
             } catch (NumberFormatException e) {
                 throw new SystemException(ErrorCode.FORG0001);
             }
-            dOut.write(ValueTag.XS_DOUBLE_TAG);
-            dOut.writeDouble(valueDouble);
         }
+        dOut.write(ValueTag.XS_DOUBLE_TAG);
+        dOut.writeDouble(valueDouble);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/vxquery/blob/19df29bb/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToFloatOperation.java
----------------------------------------------------------------------
diff --git a/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToFloatOperation.java b/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToFloatOperation.java
index d311c4c..6dbf917 100644
--- a/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToFloatOperation.java
+++ b/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToFloatOperation.java
@@ -40,10 +40,6 @@ public class CastToFloatOperation extends AbstractCastToOperation {
     /*
      * All the positive powers of 10 that can be represented exactly in float.
      */
-    private static final float powersOf10upTo10[] = { 1.0e0f, 1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f, 1.0e6f, 1.0e7f,
-            1.0e8f, 1.0e9f, 1.0e10f };
-    private static final float powersOf10from20to30[] = { 1.0e20f, 1.0e21f, 1.0e22f, 1.0e23f, 1.0e24f, 1.0e25f,
-            1.0e26f, 1.0e27f, 1.0e28f, 1.0e29f, 1.0e30f };
 
     @Override
     public void convertBoolean(BooleanPointable boolp, DataOutput dOut) throws SystemException, IOException {
@@ -83,10 +79,8 @@ public class CastToFloatOperation extends AbstractCastToOperation {
     public void convertString(UTF8StringPointable stringp, DataOutput dOut) throws SystemException, IOException {
         ICharacterIterator charIterator = new UTF8StringCharacterIterator(stringp);
         charIterator.reset();
-        byte decimalPlace = 0;
-        long value = 0;
         float valueFloat;
-        boolean pastDecimal = false, negativeValue = false;
+        boolean negativeValue = false;
         int c = ICharacterIterator.EOS_CHAR;
         int c2 = ICharacterIterator.EOS_CHAR;
         int c3 = ICharacterIterator.EOS_CHAR;
@@ -104,94 +98,31 @@ public class CastToFloatOperation extends AbstractCastToOperation {
             if (charIterator.next() != ICharacterIterator.EOS_CHAR) {
                 throw new SystemException(ErrorCode.FORG0001);
             } else if (c == Character.valueOf('I') && c2 == Character.valueOf('N') && c3 == Character.valueOf('F')) {
-                valueFloat = Float.NEGATIVE_INFINITY;
+                if (negativeValue) {
+                    valueFloat = Float.NEGATIVE_INFINITY;
+                } else {
+                    valueFloat = Float.POSITIVE_INFINITY;
+                }
             } else if (c == Character.valueOf('N') && c2 == Character.valueOf('a') && c3 == Character.valueOf('N')) {
                 valueFloat = Float.NaN;
             } else {
                 throw new SystemException(ErrorCode.FORG0001);
             }
         } else {
-            // Read in the number.
-            do {
-                if (Character.isDigit(c)) {
-                    value = value * 10 - Character.getNumericValue(c);
-                    if (pastDecimal) {
-                        decimalPlace--;
-                    }
-                } else if (c == Character.valueOf('.') && pastDecimal == false) {
-                    pastDecimal = true;
-                } else if (c == Character.valueOf('E') || c == Character.valueOf('e')) {
-                    break;
-                } else {
-                    throw new SystemException(ErrorCode.FORG0001);
-                }
-            } while ((c = charIterator.next()) != ICharacterIterator.EOS_CHAR);
-
-            // Parse the exponent.
-            if (c == Character.valueOf('E') || c == Character.valueOf('e')) {
-                int moveOffset = 0;
-                boolean negativeOffset = false;
-                // Check for the negative sign.
-                c = charIterator.next();
-                if (c == Character.valueOf('-')) {
-                    negativeOffset = true;
-                    c = charIterator.next();
-                }
-                // Process the numeric value.
-                do {
-                    if (Character.isDigit(c)) {
-                        moveOffset = moveOffset * 10 + Character.getNumericValue(c);
-                    } else {
-                        throw new SystemException(ErrorCode.FORG0001);
-                    }
-                } while ((c = charIterator.next()) != ICharacterIterator.EOS_CHAR);
-                decimalPlace += (negativeOffset ? -moveOffset : moveOffset);
-            }
-
-            /*
-             * The following conditions to create the floating point value is using known valid float values.
-             * In addition, each one only needs one or two operations to get the float value, further minimizing
-             * possible errors. (Not perfect, but pretty good.)
-             */
-            valueFloat = (float) value;
-            if (decimalPlace == 0 || valueFloat == 0.0f) {
-                // No modification required to float value.
-            } else if (decimalPlace >= 0) {
-                if (decimalPlace <= 10) {
-                    valueFloat *= powersOf10upTo10[decimalPlace];
-                } else if (decimalPlace <= 20) {
-                    valueFloat *= powersOf10upTo10[10];
-                    valueFloat *= powersOf10upTo10[decimalPlace - 10];
-                } else if (decimalPlace <= 30) {
-                    valueFloat *= powersOf10from20to30[decimalPlace];
-                } else if (decimalPlace <= 38) {
-                    valueFloat *= powersOf10from20to30[10];
-                    valueFloat *= powersOf10upTo10[decimalPlace - 30];
-                }
-            } else {
-                if (decimalPlace >= -10) {
-                    valueFloat /= powersOf10upTo10[-decimalPlace];
-                } else if (decimalPlace >= -20) {
-                    valueFloat /= powersOf10upTo10[10];
-                    valueFloat /= powersOf10upTo10[-decimalPlace - 10];
-                } else if (decimalPlace >= -30) {
-                    valueFloat /= powersOf10from20to30[-decimalPlace];
-                } else if (decimalPlace >= -40) {
-                    valueFloat /= powersOf10from20to30[10];
-                    valueFloat /= powersOf10upTo10[-decimalPlace - 30];
-                } else if (decimalPlace >= -45) {
-                    valueFloat /= powersOf10from20to30[0];
-                    valueFloat /= powersOf10from20to30[-decimalPlace - 20];
-                }
+            // We create an object to keep the conversion algorithm simple and improve precision.
+            // While a better solution may be available this will hold us over until then.
+            StringBuilder sb = new StringBuilder();
+            stringp.toString(sb);
+            try {
+                valueFloat = Float.parseFloat(sb.toString());
+            } catch (NumberFormatException e) {
+                throw new SystemException(ErrorCode.FORG0001);
             }
         }
 
         dOut.write(ValueTag.XS_FLOAT_TAG);
-        if (valueFloat == 0.0f) {
-            dOut.writeFloat((negativeValue ? -0.0f : 0.0f));
-        } else {
-            dOut.writeFloat((negativeValue ? valueFloat : -valueFloat));
-        }
+        dOut.writeFloat(valueFloat);
+
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/vxquery/blob/19df29bb/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToStringOperation.java
----------------------------------------------------------------------
diff --git a/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToStringOperation.java b/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToStringOperation.java
index 3cbcd5b..5f84682 100644
--- a/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToStringOperation.java
+++ b/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToStringOperation.java
@@ -49,16 +49,6 @@ public class CastToStringOperation extends AbstractCastToOperation {
     private DataOutput dOutInner = abvsInner.getDataOutput();
     int returnTag = ValueTag.XS_STRING_TAG;
     private final char[] hex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
-    private static final int DOUBLE_MANTISSA_BITS = 52; // size of the mantissa in bits
-    private static final int DOUBLE_MANTISSA_OFFSET = -1075;
-    private static final int DOUBLE_EXPONENT_MAX = 1023;
-    private static final int DOUBLE_EXPONENT_MIN = -1022;
-    private static final int FLOAT_MANTISSA_BITS = 23; // size of the mantissa in bits
-    private static final int FLOAT_MANTISSA_OFFSET = -150;
-    private static final int FLOAT_EXPONENT_MAX = 127;
-    private static final int FLOAT_EXPONENT_MIN = -126;
-    private static final int b = 2; // base of stored value
-    private static final int B = 10; // base of printed value
 
     @Override
     public void convertAnyURI(UTF8StringPointable stringp, DataOutput dOut) throws SystemException, IOException {
@@ -151,14 +141,15 @@ public class CastToStringOperation extends AbstractCastToOperation {
         abvsInner.reset();
         double value = doublep.getDouble();
 
-        if (!Double.isInfinite(value) && !Double.isNaN(value) && Math.abs(value) >= 0.000001
-                && Math.abs(value) <= 1000000) {
-            CastToDecimalOperation castToDecimal = new CastToDecimalOperation();
-            castToDecimal.convertDouble(doublep, dOutInner);
-            XSDecimalPointable decp = (XSDecimalPointable) XSDecimalPointable.FACTORY.createPointable();
-            decp.set(abvsInner.getByteArray(), abvsInner.getStartOffset() + 1,
-                    XSDecimalPointable.TYPE_TRAITS.getFixedLength());
-            convertDecimal(decp, dOut);
+        if (Double.isInfinite(value)) {
+            if (value == Double.NEGATIVE_INFINITY) {
+                FunctionHelper.writeCharSequence("-", dOutInner);
+            }
+            FunctionHelper.writeCharSequence("INF", dOutInner);
+            sendStringDataOutput(dOut);
+        } else if (Double.isNaN(value)) {
+            FunctionHelper.writeCharSequence("NaN", dOutInner);
+            sendStringDataOutput(dOut);
         } else if (value == -0.0 || value == 0.0) {
             long bits = Double.doubleToLongBits(value);
             boolean negative = ((bits >> 63) == 0) ? false : true;
@@ -168,8 +159,23 @@ public class CastToStringOperation extends AbstractCastToOperation {
             }
             FunctionHelper.writeCharSequence("0", dOutInner);
             sendStringDataOutput(dOut);
+        } else if (Math.abs(value) >= 0.000001 && Math.abs(value) <= 10000000) {
+            //the jdk (toString function) does not output number in desired format when 
+            //a number is between one and ten million, so we take care of this 
+            //case separately here.
+            CastToDecimalOperation castToDecimal = new CastToDecimalOperation();
+            castToDecimal.convertDouble(doublep, dOutInner);
+            XSDecimalPointable decp = (XSDecimalPointable) XSDecimalPointable.FACTORY.createPointable();
+            decp.set(abvsInner.getByteArray(), abvsInner.getStartOffset() + 1,
+                    XSDecimalPointable.TYPE_TRAITS.getFixedLength());
+            if (Math.abs(value) <= 1000000) {
+                convertDecimal(decp, dOut);
+            } else {
+                decimalToScientificNotn(decp, dOut);
+            }
         } else {
-            convertDoubleCanonical(doublep, dOut);
+            dOut.write(returnTag);
+            dOut.writeUTF(Double.toString(value));
         }
     }
 
@@ -177,109 +183,9 @@ public class CastToStringOperation extends AbstractCastToOperation {
         abvsInner.reset();
         double value = doublep.getDouble();
 
-        if (Double.isInfinite(value)) {
-            if (value == Double.NEGATIVE_INFINITY) {
-                FunctionHelper.writeCharSequence("-", dOutInner);
-            }
-            FunctionHelper.writeCharSequence("INF", dOutInner);
-        } else if (Double.isNaN(value)) {
-            FunctionHelper.writeCharSequence("NaN", dOutInner);
-        } else {
-            /*
-             * The double to string algorithm is based on a paper by Robert G Burger and 
-             * R Kent Dybvig titled "Print Floating-Point Numbers Quickly and Accurately".
-             */
-            long bits = Double.doubleToLongBits(value);
-            boolean decimalPlaced = false;
-
-            boolean negative = ((bits >> 63) == 0) ? false : true;
-            int e = (int) ((bits >> 52) & 0x7ffL);
-            long f = (e == 0) ? (bits & 0xfffffffffffffL) << 1 : (bits & 0xfffffffffffffL) | 0x10000000000000L;
-            e = e + DOUBLE_MANTISSA_OFFSET;
-
-            if (negative) {
-                FunctionHelper.writeChar('-', dOutInner);
-            }
-            if (value == 0) {
-                FunctionHelper.writeCharSequence("0.0E0", dOutInner);
-            } else {
-                // Initialize variables
-                double r, s, mPlus, mMinus;
-                if (e >= 0) {
-                    if (f == Math.pow(b, DOUBLE_MANTISSA_BITS - 1)) {
-                        r = f * Math.pow(b, e) * 2;
-                        s = 2;
-                        mPlus = Math.pow(b, e);
-                        mMinus = Math.pow(b, e + 1);
-                    } else {
-                        r = f * Math.pow(b, e + 1) * 2;
-                        s = b * 2;
-                        mPlus = Math.pow(b, e);
-                        mMinus = Math.pow(b, e);
-                    }
-                } else {
-                    if (e == DOUBLE_EXPONENT_MIN || f != Math.pow(b, DOUBLE_MANTISSA_BITS - 1)) {
-                        r = f * Math.pow(b, e) * 2;
-                        s = 2;
-                        mPlus = Math.pow(b, e);
-                        mMinus = Math.pow(b, e + 1);
-                    } else {
-                        r = f * Math.pow(b, e + 1) * 2;
-                        s = b * 2;
-                        mPlus = Math.pow(b, e);
-                        mMinus = Math.pow(b, e);
-                    }
-                }
-
-                double k = Math.ceil(Math.log10((r + mPlus) / s));
-                if (k >= 0) {
-                    s = s * Math.pow(B, k);
-                } else {
-                    r = r * Math.pow(B, -k);
-                    mPlus = mPlus * Math.pow(B, -k);
-                    mMinus = mMinus * Math.pow(B, -k);
-                }
-
-                double d;
-                while (!Double.isInfinite(mPlus) && !Double.isNaN(mPlus) && !Double.isInfinite(mMinus)
-                        && !Double.isNaN(mMinus) && !Double.isInfinite(r) && !Double.isNaN(r)) {
-                    if (s == r) {
-                        // Special case where the value is off by a factor of ten.
-                        d = 1;
-                    } else {
-                        d = Math.floor((r * B) / s);
-                    }
-                    r = r * B % s;
-                    mPlus = mPlus * B;
-                    mMinus = mMinus * B;
-
-                    if (r < mMinus && r + mPlus > s) {
-                        if (r * 2 > s) {
-                            d = d + 1;
-                        }
-                        FunctionHelper.writeChar((char) ('0' + d), dOutInner);
-                        break;
-                    } else if (r + mPlus > s) {
-                        d = d + 1;
-                        FunctionHelper.writeChar((char) ('0' + d), dOutInner);
-                        break;
-                    } else if (r < mMinus) {
-                        FunctionHelper.writeChar((char) ('0' + d), dOutInner);
-                        break;
-                    }
-                    FunctionHelper.writeChar((char) ('0' + d), dOutInner);
-                    if (!decimalPlaced) {
-                        decimalPlaced = true;
-                        FunctionHelper.writeChar('.', dOutInner);
-                    }
-                }
-
-                long decimalPlace = FunctionHelper.getPowerOf10(value, DOUBLE_EXPONENT_MAX, DOUBLE_EXPONENT_MIN) - 1;
-                FunctionHelper.writeChar('E', dOutInner);
-                FunctionHelper.writeNumberWithPadding(decimalPlace, 1, dOutInner);
-            }
-        }
-        sendStringDataOutput(dOut);
+        dOut.write(returnTag);
+        dOut.writeUTF(Double.toString(value));
+        return;
     }
 
     @Override
@@ -435,99 +341,9 @@ public class CastToStringOperation extends AbstractCastToOperation {
         } else if (Float.isNaN(value)) {
             FunctionHelper.writeCharSequence("NaN", dOutInner);
         } else {
-            /*
-             * The double to string algorithm is based on a paper by Robert G Burger and 
-             * R Kent Dybvig titled "Print Floating-Point Numbers Quickly and Accurately".
-             */
-            long bits = Float.floatToIntBits(value);
-            boolean decimalPlaced = false;
-
-            boolean negative = ((bits >> 31) == 0) ? false : true;
-            int e = (int) ((bits >> 23) & 0xff);
-            int f = (int) ((e == 0) ? (bits & 0x7fffff) << 1 : (bits & 0x7fffff) | 0x800000);
-            e = e + FLOAT_MANTISSA_OFFSET;
-
-            if (negative) {
-                FunctionHelper.writeChar('-', dOutInner);
-            }
-            if (value == 0) {
-                FunctionHelper.writeCharSequence("0.0E0", dOutInner);
-            } else {
-                // Initialize variables
-                double r, s, mPlus, mMinus;
-                if (e >= 0) {
-                    if (f == Math.pow(b, FLOAT_MANTISSA_BITS - 1)) {
-                        r = f * Math.pow(b, e) * 2;
-                        s = 2;
-                        mPlus = Math.pow(b, e);
-                        mMinus = Math.pow(b, e + 1);
-                    } else {
-                        r = f * Math.pow(b, e + 1) * 2;
-                        s = b * 2;
-                        mPlus = Math.pow(b, e);
-                        mMinus = Math.pow(b, e);
-                    }
-                } else {
-                    if (e == FLOAT_EXPONENT_MIN || f != Math.pow(b, FLOAT_MANTISSA_BITS - 1)) {
-                        r = f * Math.pow(b, e) * 2;
-                        s = 2;
-                        mPlus = Math.pow(b, e);
-                        mMinus = Math.pow(b, e + 1);
-                    } else {
-                        r = f * Math.pow(b, e + 1) * 2;
-                        s = b * 2;
-                        mPlus = Math.pow(b, e);
-                        mMinus = Math.pow(b, e);
-                    }
-                }
-
-                double k = Math.ceil(Math.log10((r + mPlus) / s));
-                if (k >= 0) {
-                    s = s * Math.pow(B, k);
-                } else {
-                    r = r * Math.pow(B, -k);
-                    mPlus = mPlus * Math.pow(B, -k);
-                    mMinus = mMinus * Math.pow(B, -k);
-                }
-
-                double d;
-                while (!Double.isInfinite(mPlus) && !Double.isNaN(mPlus) && !Double.isInfinite(mMinus)
-                        && !Double.isNaN(mMinus)) {
-                    if (s == r) {
-                        // Special case where the value is off by a factor of ten.
-                        d = 1;
-                    } else {
-                        d = Math.floor((r * B) / s);
-                    }
-                    r = r * B % s;
-                    mPlus = mPlus * B;
-                    mMinus = mMinus * B;
-
-                    if (r < mMinus && r + mPlus > s) {
-                        if (r * 2 > s) {
-                            d = d + 1;
-                        }
-                        FunctionHelper.writeChar((char) ('0' + d), dOutInner);
-                        break;
-                    } else if (r + mPlus > s) {
-                        d = d + 1;
-                        FunctionHelper.writeChar((char) ('0' + d), dOutInner);
-                        break;
-                    } else if (r < mMinus) {
-                        FunctionHelper.writeChar((char) ('0' + d), dOutInner);
-                        break;
-                    }
-                    FunctionHelper.writeChar((char) ('0' + d), dOutInner);
-                    if (!decimalPlaced) {
-                        decimalPlaced = true;
-                        FunctionHelper.writeChar('.', dOutInner);
-                    }
-                }
-
-                long decimalPlace = FunctionHelper.getPowerOf10(value, FLOAT_EXPONENT_MAX, FLOAT_EXPONENT_MIN) - 1;
-                FunctionHelper.writeChar('E', dOutInner);
-                FunctionHelper.writeNumberWithPadding(decimalPlace, 1, dOutInner);
-            }
+            dOut.write(returnTag);
+            dOut.writeUTF(Float.toString(value));
+            return;
         }
         sendStringDataOutput(dOut);
     }
@@ -849,4 +665,31 @@ public class CastToStringOperation extends AbstractCastToOperation {
         dOut.write(abvsInner.getByteArray(), abvsInner.getStartOffset(), abvsInner.getLength());
     }
 
+    public void decimalToScientificNotn(XSDecimalPointable decp, DataOutput dOut) throws SystemException, IOException {
+        byte decimalPlace = decp.getDecimalPlace();
+        long value = decp.getDecimalValue();
+        byte nDigits = decp.getDigitCount();
+        abvsInner.reset();
+
+        if (!FunctionHelper.isNumberPostive(value)) {
+            // Negative result, but the rest of the calculations can be based on a positive value.
+            FunctionHelper.writeChar('-', dOutInner);
+            value *= -1;
+        }
+
+        if (value == 0) {
+            FunctionHelper.writeChar('0', dOutInner);
+        } else {
+            long pow10 = (long) Math.pow(10, nDigits - 1);
+            FunctionHelper.writeNumberWithPadding((value / pow10), 0, dOutInner);
+            FunctionHelper.writeChar('.', dOutInner);
+            long mod = value % pow10;
+            FunctionHelper.writeNumberWithPadding(mod, (nDigits - 1), dOutInner);
+            FunctionHelper.writeChar('E', dOutInner);
+            long power = (nDigits - 1) - decimalPlace;
+            FunctionHelper.writeNumberWithPadding(power, 0, dOutInner);
+        }
+        sendStringDataOutput(dOut);
+    }
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/vxquery/blob/19df29bb/vxquery-xtest/src/main/java/org/apache/vxquery/xtest/XTest.java
----------------------------------------------------------------------
diff --git a/vxquery-xtest/src/main/java/org/apache/vxquery/xtest/XTest.java b/vxquery-xtest/src/main/java/org/apache/vxquery/xtest/XTest.java
index 87f0687..0e2a6e0 100644
--- a/vxquery-xtest/src/main/java/org/apache/vxquery/xtest/XTest.java
+++ b/vxquery-xtest/src/main/java/org/apache/vxquery/xtest/XTest.java
@@ -90,6 +90,9 @@ public class XTest {
             Thread.sleep(opts.keepalive);
         }
         eSvc.shutdown();
+        while (!eSvc.awaitTermination(5L, TimeUnit.SECONDS)) {
+            System.err.println("Failed to close all threads, trying again...");
+        }
         for (ResultReporter r : reporters) {
             r.close();
         }