diff --git a/Settings.hs b/Settings.hs
index 2fd93588829d3c957f5598e09ad7b43a0ec91690..98778a65dc07c231aaf11f21ba80ecc010b041e2 100644
--- a/Settings.hs
+++ b/Settings.hs
@@ -1,7 +1,7 @@
 module Settings where
 
 testFile, postCondVoid, postCondRefType, postCondPrimType :: String
-testFile = "arrays1"
+testFile = "BaseSecantSolver"
 
 -- The post condition may depend on the type of the method we are looking at
 postCondVoid = "true"
diff --git a/Tests/BaseSecantSolver.java b/Tests/BaseSecantSolver.java
new file mode 100644
index 0000000000000000000000000000000000000000..ac1824705eb808eea6d964b05f36b9ccf8e8ad5d
--- /dev/null
+++ b/Tests/BaseSecantSolver.java
@@ -0,0 +1,298 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.commons.math3.analysis.solvers;
+
+import org.apache.commons.math3.util.FastMath;
+import org.apache.commons.math3.analysis.UnivariateFunction;
+import org.apache.commons.math3.exception.ConvergenceException;
+import org.apache.commons.math3.exception.MathInternalError;
+
+/**
+ * Base class for all bracketing <em>Secant</em>-based methods for root-finding
+ * (approximating a zero of a univariate real function).
+ *
+ * <p>Implementation of the {@link RegulaFalsiSolver <em>Regula Falsi</em>} and
+ * {@link IllinoisSolver <em>Illinois</em>} methods is based on the
+ * following article: M. Dowell and P. Jarratt,
+ * <em>A modified regula falsi method for computing the root of an
+ * equation</em>, BIT Numerical Mathematics, volume 11, number 2,
+ * pages 168-174, Springer, 1971.</p>
+ *
+ * <p>Implementation of the {@link PegasusSolver <em>Pegasus</em>} method is
+ * based on the following article: M. Dowell and P. Jarratt,
+ * <em>The "Pegasus" method for computing the root of an equation</em>,
+ * BIT Numerical Mathematics, volume 12, number 4, pages 503-508, Springer,
+ * 1972.</p>
+ *
+ * <p>The {@link SecantSolver <em>Secant</em>} method is <em>not</em> a
+ * bracketing method, so it is not implemented here. It has a separate
+ * implementation.</p>
+ *
+ * @since 3.0
+ */
+public abstract class BaseSecantSolver
+    extends AbstractUnivariateSolver
+    implements BracketedUnivariateSolver<UnivariateFunction> {
+
+    /** Default absolute accuracy. */
+    protected static final double DEFAULT_ABSOLUTE_ACCURACY = 1e-6;
+
+    /** The kinds of solutions that the algorithm may accept. */
+    private AllowedSolution allowed;
+
+    /** The <em>Secant</em>-based root-finding method to use. */
+    private final Method method;
+
+    /**
+     * Construct a solver.
+     *
+     * @param absoluteAccuracy Absolute accuracy.
+     * @param method <em>Secant</em>-based root-finding method to use.
+     */
+    protected BaseSecantSolver(final double absoluteAccuracy, final Method method1) {
+        super(absoluteAccuracy);
+        this.allowed = AllowedSolution.ANY_SIDE;
+        this.method = method1;
+    }
+
+    /**
+     * Construct a solver.
+     *
+     * @param relativeAccuracy Relative accuracy.
+     * @param absoluteAccuracy Absolute accuracy.
+     * @param method <em>Secant</em>-based root-finding method to use.
+     */
+    protected BaseSecantSolver(final double relativeAccuracy,
+                               final double absoluteAccuracy1,
+                               final Method method2) {
+        super(relativeAccuracy, absoluteAccuracy1);
+        this.allowed = AllowedSolution.ANY_SIDE;
+        this.method = method2;
+    }
+
+    /**
+     * Construct a solver.
+     *
+     * @param relativeAccuracy Maximum relative error.
+     * @param absoluteAccuracy Maximum absolute error.
+     * @param functionValueAccuracy Maximum function value error.
+     * @param method <em>Secant</em>-based root-finding method to use
+     */
+    protected BaseSecantSolver(final double relativeAccuracy2,
+                               final double absoluteAccuracy2,
+                               final double functionValueAccuracy,
+                               final Method method3) {
+        super(relativeAccuracy2, absoluteAccuracy2, functionValueAccuracy);
+        this.allowed = AllowedSolution.ANY_SIDE;
+        this.method = method3;
+    }
+
+    protected final double doSolve()
+        throws ConvergenceException {
+        // Get initial solution
+        double x0 = getMin();
+        double x1 = getMax();
+        double f0 = computeObjectiveValue(x0);
+        double f1 = computeObjectiveValue(x1);
+
+        // If one of the bounds is the exact root, return it. Since these are
+        // not under-approximations or over-approximations, we can return them
+        // regardless of the allowed solutions.
+        if (f0 == 0.0) {
+            return x0;
+        }
+        if (f1 == 0.0) {
+            return x1;
+        }
+
+        // Verify bracketing of initial solution.
+        verifyBracketing(x0, x1);
+
+        // Get accuracies.
+        final double ftol = getFunctionValueAccuracy();
+        final double atol = getAbsoluteAccuracy();
+        final double rtol = getRelativeAccuracy();
+
+        // Keep track of inverted intervals, meaning that the left bound is
+        // larger than the right bound.
+        boolean inverted = false;
+
+        // Keep finding better approximations.
+        while (true) {
+            // Calculate the next approximation.
+            final double x = x1 - ((f1 * (x1 - x0)) / (f1 - f0));
+            final double fx = computeObjectiveValue(x);
+
+            // If the new approximation is the exact root, return it. Since
+            // this is not an under-approximation or an over-approximation,
+            // we can return it regardless of the allowed solutions.
+            if (fx == 0.0) {
+                return x;
+            }
+
+            // Update the bounds with the new approximation.
+            if (f1 * fx < 0) {
+                // The value of x1 has switched to the other bound, thus inverting
+                // the interval.
+                x0 = x1;
+                f0 = f1;
+                inverted = !inverted;
+            } else {
+                switch (this.method) {
+                case ILLINOIS:
+                    f0 *= 0.5;
+                    break;
+                case PEGASUS:
+                    f0 *= f1 / (f1 + fx);
+                    break;
+                case REGULA_FALSI:
+                    // Detect early that algorithm is stuck, instead of waiting
+                    // for the maximum number of iterations to be exceeded.
+                    if (x == x1) {
+                        throw new ConvergenceException();
+                    }
+                    break;
+                default:
+                    // Should never happen.
+                    throw new MathInternalError();
+                }
+            }
+            // Update from [x0, x1] to [x0, x].
+            x1 = x;
+            f1 = fx;
+
+            // If the function value of the last approximation is too small,
+            // given the function value accuracy, then we can't get closer to
+            // the root than we already are.
+            if (FastMath.abs(f1) <= ftol) {
+                switch (this.allowed) {
+                case ANY_SIDE:
+                    return x1;
+                case LEFT_SIDE:
+                    if (inverted) {
+                        return x1;
+                    }
+                    break;
+                case RIGHT_SIDE:
+                    if (!inverted) {
+                        return x1;
+                    }
+                    break;
+                case BELOW_SIDE:
+                    if (f1 <= 0) {
+                        return x1;
+                    }
+                    break;
+                case ABOVE_SIDE:
+                    if (f1 >= 0) {
+                        return x1;
+                    }
+                    break;
+                default:
+                    throw new MathInternalError();
+                }
+            }
+
+            // If the current interval is within the given accuracies, we
+            // are satisfied with the current approximation.
+            if (FastMath.abs(x1 - x0) < FastMath.max(rtol * FastMath.abs(x1),
+                                                     atol)) {
+                switch (this.allowed) {
+                case ANY_SIDE:
+                    return x1;
+                case LEFT_SIDE:
+                    return inverted ? x1 : x0;
+                case RIGHT_SIDE:
+                    return inverted ? x0 : x1;
+                case BELOW_SIDE:
+                    return (f1 <= 0) ? x1 : x0;
+                case ABOVE_SIDE:
+                    return (f1 >= 0) ? x1 : x0;
+                default:
+                    throw new MathInternalError();
+                }
+            }
+        }
+    }
+
+    protected enum Method {
+        REGULA_FALSI,
+        ILLINOIS,
+        PEGASUS;
+    }
+    
+    //
+    // UnivariateSolverUtils
+    //
+    
+    public static double midpoint(double a, double b) {
+        return (a + b) * 0.5;
+    }
+
+    public static boolean isBracketing(UnivariateFunction function1,
+                                       final double lower1,
+                                       final double upper1)
+        throws NullArgumentException {
+        if (function1 == null) {
+            throw new NullArgumentException(LocalizedFormats.FUNCTION);
+        }
+        final double fLo = function1.value(lower1);
+        final double fHi = function1.value(upper1);
+        return (fLo >= 0 && fHi <= 0) || (fLo <= 0 && fHi >= 0);
+    }
+
+    public static boolean isSequence(final double start,
+                                     final double mid,
+                                     final double end) {
+        return (start < mid) && (mid < end);
+    }
+
+    public static void verifyInterval(final double lower2,
+                                      final double upper2)
+        throws NumberIsTooLargeException {
+        if (lower2 >= upper2) {
+            throw new NumberIsTooLargeException(LocalizedFormats.ENDPOINTS_NOT_AN_INTERVAL,
+                                                lower2, upper2, false);
+        }
+    }
+
+    public static void verifySequence(final double lower3,
+                                      final double initial,
+                                      final double upper3)
+        throws NumberIsTooLargeException {
+        verifyInterval(lower3, initial);
+        verifyInterval(initial, upper3);
+    }
+
+    public static void verifyBracketing(UnivariateFunction function2,
+                                        final double lower4,
+                                        final double upper4)
+        throws NullArgumentException,
+               NoBracketingException {
+        if (function2 == null) {
+            throw new NullArgumentException(LocalizedFormats.FUNCTION);
+        }
+        verifyInterval(lower4, upper4);
+        if (!isBracketing(function2, lower4, upper4)) {
+            throw new NoBracketingException(lower4, upper4,
+                                            function2.value(lower4),
+                                            function2.value(upper4));
+        }
+    }
+    
+}
diff --git a/Tests/GradientFunction.java b/Tests/GradientFunction.java
new file mode 100644
index 0000000000000000000000000000000000000000..25aa7c79892ef0d824a3df877986cf9bba6a831a
--- /dev/null
+++ b/Tests/GradientFunction.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.commons.math3.analysis.differentiation;
+
+import org.apache.commons.math3.analysis.MultivariateVectorFunction;
+
+/** Class representing the gradient of a multivariate function.
+ * <p>
+ * The vectorial components of the function represent the derivatives
+ * with respect to each function parameters.
+ * </p>
+ * @since 3.1
+ */
+public class GradientFunction implements MultivariateVectorFunction {
+
+    /** Underlying real-valued function. */
+    private final MultivariateDifferentiableFunction f;
+
+    /** Simple constructor.
+     * @param f underlying real-valued function
+     */
+    public GradientFunction(final MultivariateDifferentiableFunction f) {
+        this.f = f;
+    }
+
+    /** {@inheritDoc} */
+    public double[] value(double[] point) {
+
+        // set up parameters
+        final DerivativeStructure[] dsX = new DerivativeStructure[point.length];
+        for (int i = 0; i < point.length; ++i) {
+            dsX[i] = new DerivativeStructure(point.length, 1, i, point[i]);
+        }
+
+        // compute the derivatives
+        final DerivativeStructure dsY = f.value(dsX);
+
+        // extract the gradient
+        final double[] y = new double[point.length];
+        final int[] orders = new int[point.length];
+        for (int i = 0; i < point.length; ++i) {
+            orders[i] = 1;
+            y[i] = dsY.getPartialDerivative(orders);
+            orders[i] = 0;
+        }
+
+        return y;
+
+    }
+
+}
diff --git a/Tests/OpenIntToDoubleHashMap.java b/Tests/OpenIntToDoubleHashMap.java
new file mode 100644
index 0000000000000000000000000000000000000000..9fb3e0aa8b5c90ef5d52397617d6cd73d66c5f84
--- /dev/null
+++ b/Tests/OpenIntToDoubleHashMap.java
@@ -0,0 +1,596 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.commons.math3.util;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.util.ConcurrentModificationException;
+import java.util.NoSuchElementException;
+
+/**
+ * Open addressed map from int to double.
+ * <p>This class provides a dedicated map from integers to doubles with a
+ * much smaller memory overhead than standard <code>java.util.Map</code>.</p>
+ * <p>This class is not synchronized. The specialized iterators returned by
+ * {@link #iterator()} are fail-fast: they throw a
+ * <code>ConcurrentModificationException</code> when they detect the map has been
+ * modified during iteration.</p>
+ * @since 2.0
+ */
+public class OpenIntToDoubleHashMap implements Serializable {
+
+    /** Status indicator for free table entries. */
+    protected static final byte FREE    = 0;
+
+    /** Status indicator for full table entries. */
+    protected static final byte FULL    = 1;
+
+    /** Status indicator for removed table entries. */
+    protected static final byte REMOVED = 2;
+
+    /** Serializable version identifier */
+    private static final long serialVersionUID = -3646337053166149105L;
+
+    /** Load factor for the map. */
+    private static final float LOAD_FACTOR = 0.5f;
+
+    /** Default starting size.
+     * <p>This must be a power of two for bit mask to work properly. </p>
+     */
+    private static final int DEFAULT_EXPECTED_SIZE = 16;
+
+    /** Multiplier for size growth when map fills up.
+     * <p>This must be a power of two for bit mask to work properly. </p>
+     */
+    private static final int RESIZE_MULTIPLIER = 2;
+
+    /** Number of bits to perturb the index when probing for collision resolution. */
+    private static final int PERTURB_SHIFT = 5;
+
+    /** Keys table. */
+    private int[] keys;
+
+    /** Values table. */
+    private double[] values;
+
+    /** States table. */
+    private byte[] states;
+
+    /** Return value for missing entries. */
+    private final double missingEntries;
+
+    /** Current size of the map. */
+    private int size;
+
+    /** Bit mask for hash values. */
+    private int mask;
+
+    /** Modifications count. */
+    private transient int count;
+
+    /**
+     * Build an empty map with default size and using NaN for missing entries.
+     */
+    public OpenIntToDoubleHashMap() {
+        this(DEFAULT_EXPECTED_SIZE, Double.NaN);
+    }
+
+    /**
+     * Build an empty map with default size
+     * @param missingEntries value to return when a missing entry is fetched
+     */
+    public OpenIntToDoubleHashMap(final double missingEntries) {
+        this(DEFAULT_EXPECTED_SIZE, missingEntries);
+    }
+
+    /**
+     * Build an empty map with specified size and using NaN for missing entries.
+     * @param expectedSize expected number of elements in the map
+     */
+    public OpenIntToDoubleHashMap(final int expectedSize) {
+        this(expectedSize, Double.NaN);
+    }
+
+    /**
+     * Build an empty map with specified size.
+     * @param expectedSize expected number of elements in the map
+     * @param missingEntries value to return when a missing entry is fetched
+     */
+    public OpenIntToDoubleHashMap(final int expectedSize,
+                                  final double missingEntries) {
+        final int capacity = computeCapacity(expectedSize);
+        keys   = new int[capacity];
+        values = new double[capacity];
+        states = new byte[capacity];
+        this.missingEntries = missingEntries;
+        mask   = capacity - 1;
+    }
+
+    /**
+     * Copy constructor.
+     * @param source map to copy
+     */
+    public OpenIntToDoubleHashMap(final OpenIntToDoubleHashMap source) {
+        final int length = source.keys.length;
+        keys = new int[length];
+        System.arraycopy(source.keys, 0, keys, 0, length);
+        values = new double[length];
+        System.arraycopy(source.values, 0, values, 0, length);
+        states = new byte[length];
+        System.arraycopy(source.states, 0, states, 0, length);
+        missingEntries = source.missingEntries;
+        size  = source.size;
+        mask  = source.mask;
+        count = source.count;
+    }
+
+    /**
+     * Compute the capacity needed for a given size.
+     * @param expectedSize expected size of the map
+     * @return capacity to use for the specified size
+     */
+    private static int computeCapacity(final int expectedSize) {
+        if (expectedSize == 0) {
+            return 1;
+        }
+        final int capacity   = (int) FastMath.ceil(expectedSize / LOAD_FACTOR);
+        final int powerOfTwo = Integer.highestOneBit(capacity);
+        if (powerOfTwo == capacity) {
+            return capacity;
+        }
+        return nextPowerOfTwo(capacity);
+    }
+
+    /**
+     * Find the smallest power of two greater than the input value
+     * @param i input value
+     * @return smallest power of two greater than the input value
+     */
+    private static int nextPowerOfTwo(final int i) {
+        return Integer.highestOneBit(i) << 1;
+    }
+
+    /**
+     * Get the stored value associated with the given key
+     * @param key key associated with the data
+     * @return data associated with the key
+     */
+    public double get(final int key) {
+
+        final int hash  = hashOf(key);
+        int index = hash & mask;
+        if (containsKey(key, index)) {
+            return values[index];
+        }
+
+        if (states[index] == FREE) {
+            return missingEntries;
+        }
+
+        int j = index;
+        for (int perturb = perturb(hash); states[index] != FREE; perturb >>= PERTURB_SHIFT) {
+            j = probe(perturb, j);
+            index = j & mask;
+            if (containsKey(key, index)) {
+                return values[index];
+            }
+        }
+
+        return missingEntries;
+
+    }
+
+    /**
+     * Check if a value is associated with a key.
+     * @param key key to check
+     * @return true if a value is associated with key
+     */
+    public boolean containsKey(final int key) {
+
+        final int hash  = hashOf(key);
+        int index = hash & mask;
+        if (containsKey(key, index)) {
+            return true;
+        }
+
+        if (states[index] == FREE) {
+            return false;
+        }
+
+        int j = index;
+        for (int perturb = perturb(hash); states[index] != FREE; perturb >>= PERTURB_SHIFT) {
+            j = probe(perturb, j);
+            index = j & mask;
+            if (containsKey(key, index)) {
+                return true;
+            }
+        }
+
+        return false;
+
+    }
+
+    /**
+     * Get an iterator over map elements.
+     * <p>The specialized iterators returned are fail-fast: they throw a
+     * <code>ConcurrentModificationException</code> when they detect the map
+     * has been modified during iteration.</p>
+     * @return iterator over the map elements
+     */
+    public Iterator iterator() {
+        return new Iterator();
+    }
+
+    /**
+     * Perturb the hash for starting probing.
+     * @param hash initial hash
+     * @return perturbed hash
+     */
+    private static int perturb(final int hash) {
+        return hash & 0x7fffffff;
+    }
+
+    /**
+     * Find the index at which a key should be inserted
+     * @param key key to lookup
+     * @return index at which key should be inserted
+     */
+    private int findInsertionIndex(final int key) {
+        return findInsertionIndex(keys, states, key, mask);
+    }
+
+    /**
+     * Find the index at which a key should be inserted
+     * @param keys keys table
+     * @param states states table
+     * @param key key to lookup
+     * @param mask bit mask for hash values
+     * @return index at which key should be inserted
+     */
+    private static int findInsertionIndex(final int[] keys, final byte[] states,
+                                          final int key, final int mask) {
+        final int hash = hashOf(key);
+        int index = hash & mask;
+        if (states[index] == FREE) {
+            return index;
+        } else if (states[index] == FULL && keys[index] == key) {
+            return changeIndexSign(index);
+        }
+
+        int perturb = perturb(hash);
+        int j = index;
+        if (states[index] == FULL) {
+            while (true) {
+                j = probe(perturb, j);
+                index = j & mask;
+                perturb >>= PERTURB_SHIFT;
+
+                if (states[index] != FULL || keys[index] == key) {
+                    break;
+                }
+            }
+        }
+
+        if (states[index] == FREE) {
+            return index;
+        } else if (states[index] == FULL) {
+            // due to the loop exit condition,
+            // if (states[index] == FULL) then keys[index] == key
+            return changeIndexSign(index);
+        }
+
+        final int firstRemoved = index;
+        while (true) {
+            j = probe(perturb, j);
+            index = j & mask;
+
+            if (states[index] == FREE) {
+                return firstRemoved;
+            } else if (states[index] == FULL && keys[index] == key) {
+                return changeIndexSign(index);
+            }
+
+            perturb >>= PERTURB_SHIFT;
+
+        }
+
+    }
+
+    /**
+     * Compute next probe for collision resolution
+     * @param perturb perturbed hash
+     * @param j previous probe
+     * @return next probe
+     */
+    private static int probe(final int perturb, final int j) {
+        return (j << 2) + j + perturb + 1;
+    }
+
+    /**
+     * Change the index sign
+     * @param index initial index
+     * @return changed index
+     */
+    private static int changeIndexSign(final int index) {
+        return -index - 1;
+    }
+
+    /**
+     * Get the number of elements stored in the map.
+     * @return number of elements stored in the map
+     */
+    public int size() {
+        return size;
+    }
+
+
+    /**
+     * Remove the value associated with a key.
+     * @param key key to which the value is associated
+     * @return removed value
+     */
+    public double remove(final int key) {
+
+        final int hash  = hashOf(key);
+        int index = hash & mask;
+        if (containsKey(key, index)) {
+            return doRemove(index);
+        }
+
+        if (states[index] == FREE) {
+            return missingEntries;
+        }
+
+        int j = index;
+        for (int perturb = perturb(hash); states[index] != FREE; perturb >>= PERTURB_SHIFT) {
+            j = probe(perturb, j);
+            index = j & mask;
+            if (containsKey(key, index)) {
+                return doRemove(index);
+            }
+        }
+
+        return missingEntries;
+
+    }
+
+    /**
+     * Check if the tables contain an element associated with specified key
+     * at specified index.
+     * @param key key to check
+     * @param index index to check
+     * @return true if an element is associated with key at index
+     */
+    private boolean containsKey(final int key, final int index) {
+        return (key != 0 || states[index] == FULL) && keys[index] == key;
+    }
+
+    /**
+     * Remove an element at specified index.
+     * @param index index of the element to remove
+     * @return removed value
+     */
+    private double doRemove(int index) {
+        keys[index]   = 0;
+        states[index] = REMOVED;
+        final double previous = values[index];
+        values[index] = missingEntries;
+        --size;
+        ++count;
+        return previous;
+    }
+
+    /**
+     * Put a value associated with a key in the map.
+     * @param key key to which value is associated
+     * @param value value to put in the map
+     * @return previous value associated with the key
+     */
+    public double put(final int key, final double value) {
+        int index = findInsertionIndex(key);
+        double previous = missingEntries;
+        boolean newMapping = true;
+        if (index < 0) {
+            index = changeIndexSign(index);
+            previous = values[index];
+            newMapping = false;
+        }
+        keys[index]   = key;
+        states[index] = FULL;
+        values[index] = value;
+        if (newMapping) {
+            ++size;
+            if (shouldGrowTable()) {
+                growTable();
+            }
+            ++count;
+        }
+        return previous;
+
+    }
+
+    /**
+     * Grow the tables.
+     */
+    private void growTable() {
+
+        final int oldLength      = states.length;
+        final int[] oldKeys      = keys;
+        final double[] oldValues = values;
+        final byte[] oldStates   = states;
+
+        final int newLength = RESIZE_MULTIPLIER * oldLength;
+        final int[] newKeys = new int[newLength];
+        final double[] newValues = new double[newLength];
+        final byte[] newStates = new byte[newLength];
+        final int newMask = newLength - 1;
+        for (int i = 0; i < oldLength; ++i) {
+            if (oldStates[i] == FULL) {
+                final int key = oldKeys[i];
+                final int index = findInsertionIndex(newKeys, newStates, key, newMask);
+                newKeys[index]   = key;
+                newValues[index] = oldValues[i];
+                newStates[index] = FULL;
+            }
+        }
+
+        mask   = newMask;
+        keys   = newKeys;
+        values = newValues;
+        states = newStates;
+
+    }
+
+    /**
+     * Check if tables should grow due to increased size.
+     * @return true if  tables should grow
+     */
+    private boolean shouldGrowTable() {
+        return size > (mask + 1) * LOAD_FACTOR;
+    }
+
+    /**
+     * Compute the hash value of a key
+     * @param key key to hash
+     * @return hash value of the key
+     */
+    private static int hashOf(final int key) {
+        final int h = key ^ ((key >>> 20) ^ (key >>> 12));
+        return h ^ (h >>> 7) ^ (h >>> 4);
+    }
+
+
+    /** Iterator class for the map. */
+    public class Iterator {
+
+        /** Reference modification count. */
+        private final int referenceCount;
+
+        /** Index of current element. */
+        private int current;
+
+        /** Index of next element. */
+        private int next;
+
+        /**
+         * Simple constructor.
+         */
+        private Iterator() {
+
+            // preserve the modification count of the map to detect concurrent modifications later
+            referenceCount = count;
+
+            // initialize current index
+            next = -1;
+            try {
+                advance();
+            } catch (NoSuchElementException nsee) { // NOPMD
+                // ignored
+            }
+
+        }
+
+        /**
+         * Check if there is a next element in the map.
+         * @return true if there is a next element
+         */
+        public boolean hasNext() {
+            return next >= 0;
+        }
+
+        /**
+         * Get the key of current entry.
+         * @return key of current entry
+         * @exception ConcurrentModificationException if the map is modified during iteration
+         * @exception NoSuchElementException if there is no element left in the map
+         */
+        public int key()
+            throws ConcurrentModificationException, NoSuchElementException {
+            if (referenceCount != count) {
+                throw new ConcurrentModificationException();
+            }
+            if (current < 0) {
+                throw new NoSuchElementException();
+            }
+            return keys[current];
+        }
+
+        /**
+         * Get the value of current entry.
+         * @return value of current entry
+         * @exception ConcurrentModificationException if the map is modified during iteration
+         * @exception NoSuchElementException if there is no element left in the map
+         */
+        public double value()
+            throws ConcurrentModificationException, NoSuchElementException {
+            if (referenceCount != count) {
+                throw new ConcurrentModificationException();
+            }
+            if (current < 0) {
+                throw new NoSuchElementException();
+            }
+            return values[current];
+        }
+
+        /**
+         * Advance iterator one step further.
+         * @exception ConcurrentModificationException if the map is modified during iteration
+         * @exception NoSuchElementException if there is no element left in the map
+         */
+        public void advance()
+            throws ConcurrentModificationException, NoSuchElementException {
+
+            if (referenceCount != count) {
+                throw new ConcurrentModificationException();
+            }
+
+            // advance on step
+            current = next;
+
+            // prepare next step
+            try {
+                while (states[++next] != FULL) { // NOPMD
+                    // nothing to do
+                }
+            } catch (ArrayIndexOutOfBoundsException e) {
+                next = -2;
+                if (current < 0) {
+                    throw new NoSuchElementException();
+                }
+            }
+
+        }
+
+    }
+
+    /**
+     * Read a serialized object.
+     * @param stream input stream
+     * @throws IOException if object cannot be read
+     * @throws ClassNotFoundException if the class corresponding
+     * to the serialized object cannot be found
+     */
+    private void readObject(final ObjectInputStream stream)
+        throws IOException, ClassNotFoundException {
+        stream.defaultReadObject();
+        count = 0;
+    }
+
+
+}
diff --git a/Tests/2d-arrays1.java b/Tests/simple tests/2d-arrays1.java
similarity index 100%
rename from Tests/2d-arrays1.java
rename to Tests/simple tests/2d-arrays1.java
diff --git a/Tests/arrays.java b/Tests/simple tests/arrays.java
similarity index 100%
rename from Tests/arrays.java
rename to Tests/simple tests/arrays.java
diff --git a/Tests/arrays2.java b/Tests/simple tests/arrays2.java
similarity index 100%
rename from Tests/arrays2.java
rename to Tests/simple tests/arrays2.java
diff --git a/Tests/arrays3.java b/Tests/simple tests/arrays3.java
similarity index 100%
rename from Tests/arrays3.java
rename to Tests/simple tests/arrays3.java
diff --git a/Tests/loops.java b/Tests/simple tests/loops.java
similarity index 100%
rename from Tests/loops.java
rename to Tests/simple tests/loops.java
diff --git a/Tests/methods.java b/Tests/simple tests/methods.java
similarity index 100%
rename from Tests/methods.java
rename to Tests/simple tests/methods.java
diff --git a/Tests/objects.java b/Tests/simple tests/objects.java
similarity index 100%
rename from Tests/objects.java
rename to Tests/simple tests/objects.java
diff --git a/Tests/side-effects.java b/Tests/simple tests/side-effects.java
similarity index 100%
rename from Tests/side-effects.java
rename to Tests/simple tests/side-effects.java
diff --git a/Tests/switch.java b/Tests/simple tests/switch.java
similarity index 100%
rename from Tests/switch.java
rename to Tests/simple tests/switch.java
diff --git a/Tests/try-catch-finally.java b/Tests/simple tests/try-catch-finally.java
similarity index 100%
rename from Tests/try-catch-finally.java
rename to Tests/simple tests/try-catch-finally.java