Calculus via Lambdas in Java 8

Consider the following functional interface:

package com.michaelcotterell.math;

import static java.lang.Math.abs;

import java.util.function.Function;

/**
 * A function that maps Real values to Real values. Here, the term "Real" is 
 * equivalent to <code>double</code>. This functional interface allows users to
 * easily take derivatives and find zeros of the function using established
 * techniques. 
 * 
 *  <p>
 *  This interface is intended to be used with lambda expressions in order to
 *  provide easy access to it's default methods.
 * 
 * @author Michael E. Cotterell <mepcotterell@gmail.com>
 */
@FunctionalInterface
public interface RealFunction extends Function<Double, Double> {
    
    /** The value used for determining if two <code>double</code> values are essentially equal. */
    public static final double EPSILON = 1E-11;
    
    /** The half-width uses for two-sided differentiation. */
    public static final double H = EPSILON;
    
    /**
     * Estimate the derivative of the function at <code>x</code> using a 
     * two-sided method (central difference).
     * 
     * @param x  the point at which to estimate the derivative
     * @return   derivative of the function evaluated at <code>x</code> (estimate)
     */
    default double derivative(double x) {
        return derivative().apply(x);
    } // derivative

    /**
     * Returns the first derivative of the function.
     * 
     * @return first derivative
     */
    default RealFunction derivative() {
        return x -> (apply(x + H) - apply(x - H)) / ((x + H) - (x - H));
    } // derivative
    
    /**
     * Find the root (zero ) of this {@link com.michaelcotterell.math.RealFunction} 
     * using Newton's method, given a <code>guess</code> of where the root is. 
     * This implementation of Newton's method finds an approximation to the 
     * root of the function using enough consecutive terms of the function's 
     * Taylor series such that the value of the function at the estimated root
     * is essentially zero using {@link com.michaelcotterell.math.Constants#EPSILON}. 
     * 
     * @param guess  a guess of where the root is
     * @return       the root of the function, using Newton's method
     */
    default double zero(double guess) {
        double x = guess;
        while (abs(apply(x)) > EPSILON) x = x - apply(x) / derivative(x);
        return x;
    } // newtonZero
    
    /**
     * Find the root (zero ) of this {@link com.michaelcotterell.math.RealFunction} 
     * using Newton's method. This implementation of Newton's method finds an 
     * approximation to the root of the function using enough consecutive terms
     * of the function's Taylor series such that the value of the function at 
     * the estimated root is essentially zero using 
     * {@link com.michaelcotterell.math.Constants#EPSILON}.
     * 
     * <p>
     * This particular method sets the initial guess of where the root is to 10.
     * 
     * @return the root of the function, using Newton's method
     */
    default double zero() {
        return zero(10);
    } // newtonZero
    
} // RealFunction

With this functional interface, we can take derivatives of functions expressed as lambda expressions:

RealFunction f  = x -> x * x;
RealFunction df = f.derivative();
System.out.println(df.apply(4.0)); // ~ 8.0
System.out.println(df.apply(4.5)); // ~ 9.0

Here is a neat implementation of finding the positive square root of a number using Newton's method (as implemented by the default method zero in the interface):

/**
 * Return the positive square root of <code>n</code> using Newton's method.
 * 
 * @param n  a value
 * @return   the positive square root of <code>n</code>
 */
public static double sqrt(double n) {
    RealFunction f = x -> x * x - n; // the square root function
    double guess = 0.3 * n;          // arbitrary starting place; seemed good
    return f.zero(guess);
} // sqrt