library CommonMath {
    using SafeMath for uint256;

    /**
     * Calculates and returns the maximum value for a uint256
     *
     * @return  The maximum value for uint256
     */
    function maxUInt256()
        internal
        pure
        returns (uint256)
    {
        return 2 ** 256 - 1;
    }

    /**
    * @dev Performs the power on a specified value, reverts on overflow.
    */
    function safePower(
        uint256 a,
        uint256 pow
    )
        internal
        pure
        returns (uint256)
    {
        require(a > 0);

        uint256 result = 1;
        for (uint256 i = 0; i < pow; i++){
            uint256 previousResult = result;

            // Using safemath multiplication prevents overflows
            result = previousResult.mul(a);
        }

        return result;
    }

    /**
     * Checks for rounding errors and returns value of potential partial amounts of a principal
     *
     * @param  _principal       Number fractional amount is derived from
     * @param  _numerator       Numerator of fraction
     * @param  _denominator     Denominator of fraction
     * @return uint256          Fractional amount of principal calculated
     */
    function getPartialAmount(
        uint256 _principal,
        uint256 _numerator,
        uint256 _denominator
    )
        internal
        pure
        returns (uint256)
    {
        // Get remainder of partial amount (if 0 not a partial amount)
        uint256 remainder = mulmod(_principal, _numerator, _denominator);

        // Return if not a partial amount
        if (remainder == 0) {
            return _principal.mul(_numerator).div(_denominator);
        }

        // Calculate error percentage
        uint256 errPercentageTimes1000000 = remainder.mul(1000000).div(_numerator.mul(_principal));

        // Require error percentage is less than 0.1%.
        require(
            errPercentageTimes1000000 < 1000,
            "CommonMath.getPartialAmount: Rounding error exceeds bounds"
        );

        return _principal.mul(_numerator).div(_denominator);
    }

}
function getPartialAmount(
    uint256 _principal,
    uint256 _numerator,
    uint256 _denominator
)
    internal
    pure
    returns (uint256)
{
    // Get remainder of partial amount (if 0 not a partial amount)
    uint256 remainder = mulmod(_principal, _numerator, _denominator);

    // Return if not a partial amount
    if (remainder == 0) {
        return _principal.mul(_numerator).div(_denominator);
    }

    // Calculate error percentage
    uint256 errPercentageTimes1000000 = remainder.mul(1000000).div(_numerator.mul(_principal));

    // Require error percentage is less than 0.1%.
    require(
        errPercentageTimes1000000 < 1000,
        "CommonMath.getPartialAmount: Rounding error exceeds bounds"
    );

    return _principal.mul(_numerator).div(_denominator);
}

/**
 * Checks for rounding errors and returns value of potential partial amounts of a principal
 *
 * @param  _principal       Number fractional amount is derived from
 * @param  _numerator       Numerator of fraction
 * @param  _denominator     Denominator of fraction
 * @return uint256          Fractional amount of principal calculated
 */