Implementation of `ulp` and `nextAfter` for platforms where these are missing I need the ulp method in Codename ONE, and since it isn't available there, I tried to come up with my own version. The code is completely written from scratch, based solely on the documentation of the java.lang.Math class.

Please ignore the @Override annotations. This is from a utility class I wrote to be able to use the same code for Java SE and Codename ONE development (this obviously is the Codename ONE version).

private static final double MAX_ULP = com.codename1.util.MathUtil.pow(2.0, 971);

@Override
public double ulp(double d) {
    if (Double.isNaN(d)) {
        // If the argument is NaN, then the result is NaN.
        return Double.NaN;
    } else if (Double.isInfinite(d)) {
        // If the argument is positive or negative infinity, then the
        // result is positive infinity.
        return Double.POSITIVE_INFINITY;
    } else if (d == 0.0) {
        // If the argument is positive or negative zero, then the result is Double.MIN_VALUE.
        return Double.MIN_VALUE;
    } else if (d == Double.MAX_VALUE || d == -Double.MAX_VALUE) {
        //If the argument is ±Double.MAX_VALUE, then the result is equal to 2^971.
        return MAX_ULP;
    } else {
        d = Math.abs(d);
        return nextAfter(d, Double.MAX_VALUE) - d;
    }
}

@Override
public double copySign(double x, double y) {
    return com.codename1.util.MathUtil.copysign(x, y);
}

private boolean isSameSign(double x, double y) {
    return copySign(x, y) == x;
}

@Override
public double nextAfter(double start, double direction) {
    if (Double.isNaN(start) || Double.isNaN(direction)) {
        // If either argument is a NaN, then NaN is returned.
        return Double.NaN;
    } else if (start == direction) {
        // If both arguments compare as equal the second argument is returned.
        return direction;
    } else if ((start == Double.MIN_VALUE || start == -Double.MIN_VALUE)
            &amp;&amp; (!isSameSign(start, direction) || Math.abs(direction) &lt; Math.abs(start))) {
        // If start is ±Double.MIN_VALUE and direction has a value such that
        // the result should have a smaller magnitude, then a zero with
        // the same sign as start is returned.
        return copySign(0.0, start);
    } else if (Double.isInfinite(start) &amp;&amp; !Double.isInfinite(direction)) {
        // If start is infinite and direction has a value such that the
        // result should have a smaller magnitude, Double.MAX_VALUE with
        // the same sign as start is returned.
        return copySign(Double.MAX_VALUE, start);
    } else if ((start == Double.MAX_VALUE || start == -Double.MAX_VALUE)
            &amp;&amp; (Double.isInfinite(direction) &amp;&amp; isSameSign(start, direction))) {
        // If start is equal to ± Double.MAX_VALUE and direction has a
        // value such that the result should have a larger magnitude, an
        // infinity with same sign as start is returned.
        return start &gt; 0.0 ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY;
    } else if (start==0.0) {
        return copySign(Double.MIN_VALUE, direction);
    } else {
        long d = ((direction &gt; start) == (start&gt;=0)) ? 1L : -1L;
        long x = Double.doubleToLongBits(start) + d;
        return Double.longBitsToDouble(x);
    }

}


PS: I wrote this code from scratch (for licence reasons), so if anybody has a use for this, feel free to use and modify it in your own projects.

EDIT: The code I originally posted still had an error I found after checking all corner cases against the JDK version. I had to introduce another check for start==0.0 in nextAfter to get all unit tests pass. Also, the condition for setting d was flawed.
The code looks neat enough, well formatted, etc. That's great. There is one common issue you have in your code, and that is the else-if for early-return blocks.

The code:

if (conditionA) {
    ... do something
    return something;
} else if (conditionB) {
    ... do something
    return something;
} else if .....


has redundant if blocks. The logic is right, but, it would be better as:

if (conditionA) {
    ... do something
    return something;
}
if (conditionB) {
    ... do something
    return something;
}
if .....


You have that pattern in a lot of places.

A second general concern I have is that you do not specify 'final' for your parameters in places where it can make sense. The 'final' concept is debatable for performance, but I have found that it makes a difference in both the disciple, and occasionally the performance. For example, the function:


private boolean isSameSign(double x, double y) {
    return copySign(x, y) == x;
}



would be better as:

private boolean isSameSign(final double x, final double y) {
    return copySign(x, y) == x;
}


ulp()

It would be convenient in your ULP to do the d = Math.abs(d) earlier in the function as it simplifies some logic. Consider the following:

public double ulp(final double input) {
    final double d = Math.abs(input);
    if (Double.isNaN(d)) {
        // If the argument is NaN, then the result is NaN.
        return Double.NaN;
    }
    if (Double.isInfinite(d)) {
        // If the argument is positive or negative infinity, then the
        // result is positive infinity.
        return Double.POSITIVE_INFINITY;
    }
    if (d == 0.0) {
        // If the argument is positive or negative zero, then the result is Double.MIN_VALUE.
        return Double.MIN_VALUE;
    }
    if (d == Double.MAX_VALUE) {
        //If the argument is ±Double.MAX_VALUE, then the result is equal to 2^971.
        return MAX_ULP;
    }
    return nextAfter(d, Double.MAX_VALUE) - d;
}


I assume that your research on \$2^{971}\$ is accurate for Double.MAX_VALUE.

copySign()

Edit: This method confused me, and lead me to introduce a bug in my code (now fixed).

It is my opinion that the arguments are the wrong way around. I would expect copySign(x, y) to copy the sign from x to y, but your code implements it the other way around. Instead of arguments x and y, they should have better names, and the method should be named differently as well:

public double copySignToFrom(final double target, final double sign) {...}


My preference would be to just reverse the arguments, but that method is overridden, and the implementation is not actually shown here (Note: Show all your code next time...).

nextAfter()

Again, like ulp(), this function would benefit from removing the 'else if' construct. The early return makes it unnecessary.

The logic in here looks good. I have tried to see if there's a better way of doing things, and, I think there may be... by recording the signs of the start &amp; direction, you can do all the math in absolute terms, and re-conevrt the signs later.... It's a toss up as to whether the performance will be better to do the conversion each time, and then have simpler conditions on the logic.

So, the only real criticism I have here is the else if, but, for interest, consider the following:

Edit: revised my code example because of copySign usage bug...

public class DoublePlay {

    private static final long MASK = Long.MIN_VALUE;

//    @Override
    public double copySign(double target, double source) {
        if ((Double.doubleToLongBits(target) &amp; MASK) == (Double.doubleToLongBits(source) &amp; MASK)) {
            return target;
        }
        return Double.longBitsToDouble(Double.doubleToLongBits(target) ^ MASK);
    }

    private boolean isSameSign(double x, double y) {
        return copySign(x, y) == x;
    }

    public double nextAfter(final double start, final double direction) {
        if (Double.isNaN(start) || Double.isNaN(direction)) {
            // If either argument is a NaN, then NaN is returned.
            return Double.NaN;
        }
        if (start == direction) {
            // If both arguments compare as equal the second argument is returned.
            return direction;
        }

        final double absstart = Math.abs(start);
        final double absdir = Math.abs(direction);
        final boolean tozero = !isSameSign(start, direction) || absdir &lt; absstart;

        if (tozero) {
            // we are reducing the magnitude, going toward zero.
            if (absstart == Double.MIN_VALUE) {
                return copySign(0.0, start);
            }
            if (Double.isInfinite(absstart)) {
                return copySign(Double.MAX_VALUE, start);
            }
            return copySign(Double.longBitsToDouble(Double.doubleToLongBits(absstart) - 1L), start);
        }

        // we are increasing the magnitude, toward +-Infinity
        if (absstart == Double.MAX_VALUE) {
            return copySign(Double.POSITIVE_INFINITY, start);
        }
        return copySign(Double.longBitsToDouble(Double.doubleToLongBits(absstart) +1L), start);

    }

    private static final void testValue(DoublePlay dp, final double base, final double direction) {
        double result = dp.nextAfter(base, direction);
        System.out.printf("From: %016x %s%nStep: %016x %s%nTo  : %016x %s%n%n", 
                Double.doubleToLongBits(base), String.valueOf(base),
                Double.doubleToLongBits(direction), String.valueOf(direction),
                Double.doubleToLongBits(result), String.valueOf(result)
                );
    }

    public static void main(String[] args) {
        DoublePlay dp = new DoublePlay();
        testValue(dp, Double.MIN_VALUE, Double.POSITIVE_INFINITY);
        testValue(dp, Double.MIN_VALUE, Double.NEGATIVE_INFINITY);
        testValue(dp, -Double.MIN_VALUE, Double.POSITIVE_INFINITY);
        testValue(dp, -Double.MIN_VALUE, Double.NEGATIVE_INFINITY);
    }

}


The above code makes the decision 'early' about whether the magnitude of the nextAfter() is increasing (to infinity), or decreasing (to zero). It simplifies the rest of the conditions.

Added an Ideone with the code as well