contract Exponential {

    using SafeMath for uint256;

    uint256 constant public EXP_SCALE = 1e18;
    uint256 constant HALF_EXP_SCALE = EXP_SCALE / 2;
    uint256 constant MANTISSA_ONE = EXP_SCALE;

    struct Exp {
        uint256 mantissa;
    }

    /**
     * @dev Creates an exponential from numerator and denominator values.
     */
    function getExp(uint256 numerator, uint256 denominator) pure internal returns (Exp memory) {
        uint256 scaledNumerator = numerator.mul(EXP_SCALE);

        uint256 rational = scaledNumerator.div(denominator);

        return Exp({mantissa: rational});
    }

    /**
     * @dev Multiply an Exp by a scalar, returning a new Exp.
     */
    function mulScalar(Exp memory a, uint256 scalar) pure internal returns (Exp memory) {
        uint256 scaledMantissa = a.mantissa.mul(scalar);

        return Exp({mantissa: scaledMantissa});
    }

    /**
     * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.
     */
    function mulScalarTruncateAdd(Exp memory a, uint256 scalar, uint256 addend) pure internal returns (uint256) {
        Exp memory product = mulScalar(a, scalar);

        return truncate(product).add(addend);
    }

    /**
     * @dev Multiplies two exponentials, returning a new exponential.
     */
    function mulExp(Exp memory a, Exp memory b) pure internal returns (Exp memory) {

        uint256 doubleScaledProduct = a.mantissa.mul(b.mantissa);

        // We add half the scale before dividing so that we get rounding instead of truncation.
        //  See "Listing 6" and text above it at https://accu.org/index.php/journals/1717
        // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.
        uint256 doubleScaledProductWithHalfScale = HALF_EXP_SCALE.add(doubleScaledProduct);

        uint256 product = doubleScaledProductWithHalfScale.div(EXP_SCALE);

        return Exp({mantissa: product});
    }


    /**
     * @dev Truncates the given exp to a whole number value.
     *      For example, truncate(Exp{mantissa: 15 * expScale}) = 15
     */
    function truncate(Exp memory exp) pure internal returns (uint256) {
        return exp.mantissa.div(EXP_SCALE);
    }

}
function mulScalar(Exp memory a, uint256 scalar) pure internal returns (Exp memory) {
    uint256 scaledMantissa = a.mantissa.mul(scalar);

    return Exp({mantissa: scaledMantissa});
}

/**
 * @dev Multiply an Exp by a scalar, returning a new Exp.
 */