Class MathTools

java.lang.Object
com.github.tommyettinger.digital.MathTools

public final class MathTools extends Object
Mathematical operations not provided by java.lang.Math.
Includes code that was originally part of the Uncommon Maths software package as Maths. Also includes code adapted from libGDX as their MathUtils class. There's also cbrt(float) by Marc B. Reynolds, building on the legendary fast inverse square root, and a generalized bias/gain function, barronSpline(float, float, float), popularized by Jon Barron.
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final float
    The float value that is closer than any other to e, the base of the natural logarithms.
    static final float
    A float that is meant to be used as the smallest reasonable tolerance for methods like isEqual(float, float, float).
    static final long[]
    1275 negative, odd long values that are calculated using a generalization of the golden ratio and exponents of those generalizations.
    static final float
    The famous golden ratio, (1.0 + Math.sqrt(5.0)) * 0.5; this is the "most irrational" of irrational numbers, and has various useful properties.
    static final float
    The inverse of the golden ratio, (1.0 - Math.sqrt(5.0)) * -0.5 or GOLDEN_RATIO - 1.0; this also has various useful properties.
  • Method Summary

    Modifier and Type
    Method
    Description
    static double
    barronSpline(double x, double shape, double turning)
    A generalization on bias and gain functions that can represent both; this version is branch-less.
    static float
    barronSpline(float x, float shape, float turning)
    A generalization on bias and gain functions that can represent both; this version is branch-less.
    static float
    cbrt(float x)
    An approximation of the cube-root function for float inputs and outputs.
    static double
    clamp(double value, double min, double max)
    If the specified value is not greater than or equal to the specified minimum and less than or equal to the specified maximum, adjust it so that it is.
    static float
    clamp(float value, float min, float max)
    If the specified value is not greater than or equal to the specified minimum and less than or equal to the specified maximum, adjust it so that it is.
    static int
    clamp(int value, int min, int max)
    If the specified value is not greater than or equal to the specified minimum and less than or equal to the specified maximum, adjust it so that it is.
    static long
    clamp(long value, long min, long max)
    If the specified value is not greater than or equal to the specified minimum and less than or equal to the specified maximum, adjust it so that it is.
    static int
    fastCeil(double t)
    Like Math.ceil(double), but returns an int.
    static int
    fastCeil(float t)
    Like Math.ceil(double), but takes a float and returns an int.
    static int
    fastFloor(double t)
    Like Math.floor(double) , but returns an int.
    static int
    fastFloor(float t)
    Like Math.floor(double), but takes a float and returns an int.
    static long
    greatestCommonDivisor(long a, long b)
    Determines the greatest common divisor of a pair of natural numbers using the Euclidean algorithm.
    static boolean
    isEqual(double a, double b, double tolerance)
    Equivalent to libGDX's isEqual() method in MathUtils; this compares two doubles for equality and allows the given tolerance during comparison.
    static boolean
    isEqual(float a, float b)
    Equivalent to libGDX's isEqual() method in MathUtils; this compares two floats for equality and allows just enough tolerance to ignore a rounding error.
    static boolean
    isEqual(float a, float b, float tolerance)
    Equivalent to libGDX's isEqual() method in MathUtils; this compares two floats for equality and allows the given tolerance during comparison.
    static long
    isqrt(long n)
    Integer square root (using floor), maintaining correct results even for very large long values.
    static float
    lerp(float fromValue, float toValue, float progress)
    Linearly interpolates between fromValue to toValue on progress position.
    static float
    lerpAngle(float fromRadians, float toRadians, float progress)
    Linearly interpolates between two angles in radians.
    static float
    lerpAngleDeg(float fromDegrees, float toDegrees, float progress)
    Linearly interpolates between two angles in degrees.
    static float
    lerpAngleTurns(float fromTurns, float toTurns, float progress)
    Linearly interpolates between two angles in turns.
    static double
    log(double base, double arg)
    Calculate logarithms for arbitrary bases.
    static long
    longFloor(double t)
    Like Math.floor(double), but returns a long.
    static long
    longFloor(float t)
    Like Math.floor(double), but takes a float and returns a long.
    static float
    map(float inRangeStart, float inRangeEnd, float outRangeStart, float outRangeEnd, float value)
    Linearly map a value from one range to another.
    static int
    Given any odd int a, this finds another odd int b such that a * b == 1.
    static long
    Given any odd long a, this finds another odd long b such that a * b == 1L.
    static int
    Returns the next higher power of two relative to n, or n if it is already a power of two.
    static float
    norm(float rangeStart, float rangeEnd, float value)
    Linearly normalizes value from a range.
    static long
    raiseToPower(int value, int power)
    Calculate the first argument raised to the power of the second.
    static double
    remainder(double op, double d)
    Like the modulo operator %, but the result will always match the sign of d instead of op.
    static float
    sway(float value)
    Very similar to TrigTools.sinTurns(float) with half frequency, or Math.sin(double) with Math.PI frequency, but optimized (and shaped) a little differently.
    static float
    swayCubic(float value)
    Very similar to TrigTools.sinTurns(float) with half frequency, or Math.sin(double) with Math.PI frequency, but optimized (and shaped) a little differently.
    static float
    swayTight(float value)
    Takes any float and produces a float in the 0f to 1f range, with a graph of input to output that looks much like a sine wave, curving to have a flat slope when given an integer input and a steep slope when the input is halfway between two integers, smoothly curving at any points between those extremes.
    static double
    truncate(double n)
    Forces precision loss on the given double so very small fluctuations away from an integer will be erased.
    static float
    truncate(float n)
    Forces precision loss on the given float so very small fluctuations away from an integer will be erased.
    static float
    zigzag(float value)
    Takes any float and produces a float in the -1f to 1f range, with similar inputs producing close to a consistent rate of up and down through the range.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • FLOAT_ROUNDING_ERROR

      public static final float FLOAT_ROUNDING_ERROR
      A float that is meant to be used as the smallest reasonable tolerance for methods like isEqual(float, float, float).
      See Also:
    • E

      public static final float E
      The float value that is closer than any other to e, the base of the natural logarithms.
      See Also:
    • GOLDEN_RATIO

      public static final float GOLDEN_RATIO
      The famous golden ratio, (1.0 + Math.sqrt(5.0)) * 0.5; this is the "most irrational" of irrational numbers, and has various useful properties.
      See Also:
    • GOLDEN_RATIO_INVERSE

      public static final float GOLDEN_RATIO_INVERSE
      The inverse of the golden ratio, (1.0 - Math.sqrt(5.0)) * -0.5 or GOLDEN_RATIO - 1.0; this also has various useful properties.
      See Also:
    • GOLDEN_LONGS

      public static final long[] GOLDEN_LONGS
      1275 negative, odd long values that are calculated using a generalization of the golden ratio and exponents of those generalizations. Mostly, these are useful because they are all 64-bit constants that have an irrational-number-like pattern to their bits, which makes them pretty much all useful as increments for large counters (also called Weyl sequences) and also sometimes as multipliers for data that should be somewhat random. The earlier numbers in the array are closer to the bit patterns of irrational numbers. Note that these are not at all uniformly-distributed, and should not be used for tasks where random negative longs must be uniform.
  • Method Details

    • raiseToPower

      public static long raiseToPower(int value, int power)
      Calculate the first argument raised to the power of the second. This method only supports non-negative powers.
      Parameters:
      value - The number to be raised.
      power - The exponent (must be positive).
      Returns:
      value raised to power.
    • log

      public static double log(double base, double arg)
      Calculate logarithms for arbitrary bases.
      Parameters:
      base - The base for the logarithm.
      arg - The value to calculate the logarithm for.
      Returns:
      The log of arg in the specified base.
    • isEqual

      public static boolean isEqual(double a, double b, double tolerance)
      Equivalent to libGDX's isEqual() method in MathUtils; this compares two doubles for equality and allows the given tolerance during comparison. An example is 0.3 - 0.2 == 0.1 vs. isEqual(0.3 - 0.2, 0.1, 0.000001); the first is incorrectly false, while the second is correctly true.
      Parameters:
      a - the first float to compare
      b - the second float to compare
      tolerance - the maximum difference between a and b permitted for this to return true, inclusive
      Returns:
      true if a and b have a difference less than or equal to tolerance, or false otherwise.
    • isEqual

      public static boolean isEqual(float a, float b)
      Equivalent to libGDX's isEqual() method in MathUtils; this compares two floats for equality and allows just enough tolerance to ignore a rounding error. An example is 0.3f - 0.2f == 0.1f vs. isEqual(0.3f - 0.2f, 0.1f); the first is incorrectly false, while the second is correctly true.
      Parameters:
      a - the first float to compare
      b - the second float to compare
      Returns:
      true if a and b are equal or extremely close to equal, or false otherwise.
    • isEqual

      public static boolean isEqual(float a, float b, float tolerance)
      Equivalent to libGDX's isEqual() method in MathUtils; this compares two floats for equality and allows the given tolerance during comparison. An example is 0.3f - 0.2f == 0.1f vs. isEqual(0.3f - 0.2f, 0.1f, 0.000001f); the first is incorrectly false, while the second is correctly true.
      Parameters:
      a - the first float to compare
      b - the second float to compare
      tolerance - the maximum difference between a and b permitted for this to return true, inclusive
      Returns:
      true if a and b have a difference less than or equal to tolerance, or false otherwise.
    • clamp

      public static int clamp(int value, int min, int max)
      If the specified value is not greater than or equal to the specified minimum and less than or equal to the specified maximum, adjust it so that it is.
      Note that it can often be just as easy to directly call the same code this calls, while being slightly friendlier to inlining in large method: Math.min(Math.max(value, min), max).
      Parameters:
      value - The value to check.
      min - The minimum permitted value.
      max - The maximum permitted value.
      Returns:
      value if it is between the specified limits, min if the value is too low, or max if the value is too high.
    • clamp

      public static long clamp(long value, long min, long max)
      If the specified value is not greater than or equal to the specified minimum and less than or equal to the specified maximum, adjust it so that it is.
      Note that it can often be just as easy to directly call the same code this calls, while being slightly friendlier to inlining in large method: Math.min(Math.max(value, min), max).
      Parameters:
      value - The value to check.
      min - The minimum permitted value.
      max - The maximum permitted value.
      Returns:
      value if it is between the specified limits, min if the value is too low, or max if the value is too high.
    • clamp

      public static double clamp(double value, double min, double max)
      If the specified value is not greater than or equal to the specified minimum and less than or equal to the specified maximum, adjust it so that it is.
      Note that it can often be just as easy to directly call the same code this calls, while being slightly friendlier to inlining in large method: Math.min(Math.max(value, min), max).
      Parameters:
      value - The value to check.
      min - The minimum permitted value.
      max - The maximum permitted value.
      Returns:
      value if it is between the specified limits, min if the value is too low, or max if the value is too high.
    • clamp

      public static float clamp(float value, float min, float max)
      If the specified value is not greater than or equal to the specified minimum and less than or equal to the specified maximum, adjust it so that it is.
      Note that it can often be just as easy to directly call the same code this calls, while being slightly friendlier to inlining in large method: Math.min(Math.max(value, min), max).
      Parameters:
      value - The value to check.
      min - The minimum permitted value.
      max - The maximum permitted value.
      Returns:
      value if it is between the specified limits, min if the value is too low, or max if the value is too high.
    • remainder

      public static double remainder(double op, double d)
      Like the modulo operator %, but the result will always match the sign of d instead of op.
      Parameters:
      op - the dividend; negative values are permitted and wrap instead of producing negative results
      d - the divisor; if this is negative then the result will be negative, otherwise it will be positive
      Returns:
      the remainder of the division of op by d, with a sign matching d
    • greatestCommonDivisor

      public static long greatestCommonDivisor(long a, long b)
      Determines the greatest common divisor of a pair of natural numbers using the Euclidean algorithm. This method only works with natural numbers. If negative integers are passed in, the absolute values will be used. The return value is always positive.
      Parameters:
      a - The first value.
      b - The second value.
      Returns:
      The greatest common divisor.
    • modularMultiplicativeInverse

      public static int modularMultiplicativeInverse(int a)
      Given any odd int a, this finds another odd int b such that a * b == 1.
      This is incompatible with GWT, but it should usually only find uses in exploratory code or in tests anyway... It is only incompatible because it tends to rely on multiplication overflow to work. The overload that takes a long and gets the inverse modulo (2 to the 64) is GWT-compatible.
      Parameters:
      a - any odd int; note that even numbers do not have inverses modulo 2 to the 32
      Returns:
      the multiplicative inverse of a modulo 4294967296 (or, 2 to the 32)
    • modularMultiplicativeInverse

      public static long modularMultiplicativeInverse(long a)
      Given any odd long a, this finds another odd long b such that a * b == 1L.
      Parameters:
      a - any odd long; note that even numbers do not have inverses modulo 2 to the 64
      Returns:
      the multiplicative inverse of a modulo 18446744073709551616 (or, 2 to the 64)
    • isqrt

      public static long isqrt(long n)
      Integer square root (using floor), maintaining correct results even for very large long values. This version treats negative inputs as unsigned and returns positive square roots for them (these are usually large).
      This is based on code recently added to Python, but isn't identical. Notably, this doesn't branch except in the for loop, and it handles negative inputs differently.
      Parameters:
      n - a long value that will be treated as if unsigned
      Returns:
      the square root of n, rounded down to the next lower long if the result isn't already a long
    • cbrt

      public static float cbrt(float x)
      An approximation of the cube-root function for float inputs and outputs. This can be about twice as fast as Math.cbrt(double). It correctly returns negative results when given negative inputs.
      Has very low relative error (less than 1E-9) when inputs are uniformly distributed between -512 and 512, and absolute mean error of less than 1E-6 in the same scenario. Uses a bit-twiddling method similar to one presented in Hacker's Delight and also used in early 3D graphics (see Wikipedia for more, but this code approximates cbrt(x) and not 1/sqrt(x)). This specific code was originally by Marc B. Reynolds, posted in his "Stand-alone-junk" repo .
      Parameters:
      x - any finite float to find the cube root of
      Returns:
      the cube root of x, approximated
    • barronSpline

      public static float barronSpline(float x, float shape, float turning)
      A generalization on bias and gain functions that can represent both; this version is branch-less. This is based on this micro-paper by Jon Barron, which generalizes the earlier bias and gain rational functions by Schlick. The second and final page of the paper has useful graphs of what the s (shape) and t (turning point) parameters do; shape should be 0 or greater, while turning must be between 0 and 1, inclusive. This effectively combines two different curving functions so they continue into each other when x equals turning. The shape parameter will cause this to imitate "smoothstep-like" splines when greater than 1 (where the values ease into their starting and ending levels), or to be the inverse when less than 1 (where values start like square root does, taking off very quickly, but also end like square does, landing abruptly at the ending level). You should only give x values between 0 and 1, inclusive.
      Parameters:
      x - progress through the spline, from 0 to 1, inclusive
      shape - must be greater than or equal to 0; values greater than 1 are "normal interpolations"
      turning - a value between 0.0 and 1.0, inclusive, where the shape changes
      Returns:
      a float between 0 and 1, inclusive
    • barronSpline

      public static double barronSpline(double x, double shape, double turning)
      A generalization on bias and gain functions that can represent both; this version is branch-less. This is based on this micro-paper by Jon Barron, which generalizes the earlier bias and gain rational functions by Schlick. The second and final page of the paper has useful graphs of what the s (shape) and t (turning point) parameters do; shape should be 0 or greater, while turning must be between 0 and 1, inclusive. This effectively combines two different curving functions so they continue into each other when x equals turning. The shape parameter will cause this to imitate "smoothstep-like" splines when greater than 1 (where the values ease into their starting and ending levels), or to be the inverse when less than 1 (where values start like square root does, taking off very quickly, but also end like square does, landing abruptly at the ending level). You should only give x values between 0 and 1, inclusive.
      Parameters:
      x - progress through the spline, from 0 to 1, inclusive
      shape - must be greater than or equal to 0; values greater than 1 are "normal interpolations"
      turning - a value between 0.0 and 1.0, inclusive, where the shape changes
      Returns:
      a double between 0 and 1, inclusive
    • longFloor

      public static long longFloor(double t)
      Like Math.floor(double), but returns a long. Doesn't consider "weird doubles" like INFINITY and NaN.
      Parameters:
      t - the double to find the floor for
      Returns:
      the floor of t, as a long
    • longFloor

      public static long longFloor(float t)
      Like Math.floor(double), but takes a float and returns a long. Doesn't consider "weird floats" like INFINITY and NaN.
      Parameters:
      t - the double to find the floor for
      Returns:
      the floor of t, as a long
    • fastFloor

      public static int fastFloor(double t)
      Like Math.floor(double) , but returns an int. Doesn't consider "weird doubles" like INFINITY and NaN.
      Parameters:
      t - the float to find the floor for
      Returns:
      the floor of t, as an int
    • fastFloor

      public static int fastFloor(float t)
      Like Math.floor(double), but takes a float and returns an int. Doesn't consider "weird floats" like INFINITY and NaN. This method will only properly floor floats from -16384 to Float.MAX_VALUE - 16384.
      Taken from libGDX MathUtils.
      Parameters:
      t - the float to find the floor for
      Returns:
      the floor of t, as an int
    • fastCeil

      public static int fastCeil(double t)
      Like Math.ceil(double), but returns an int. Doesn't consider "weird doubles" like INFINITY and NaN.
      Parameters:
      t - the float to find the ceiling for
      Returns:
      the ceiling of t, as an int
    • fastCeil

      public static int fastCeil(float t)
      Like Math.ceil(double), but takes a float and returns an int. Doesn't consider "weird floats" like INFINITY and NaN.
      Parameters:
      t - the float to find the ceiling for
      Returns:
      the ceiling of t, as an int
    • nextPowerOfTwo

      public static int nextPowerOfTwo(int n)
      Returns the next higher power of two relative to n, or n if it is already a power of two. This returns 2 if n is any value less than 2 (including negative numbers, but also 1, which is a power of two).
      Parameters:
      n - the lower bound for the result
      Returns:
      the next higher power of two that is greater than or equal to n
    • truncate

      public static float truncate(float n)
      Forces precision loss on the given float so very small fluctuations away from an integer will be erased. This is meant primarily for cleaning up floats, so they can be presented without needing scientific notation. It leaves about 3 decimal digits after the point intact, and should make any digits after that simply 0.
      Parameters:
      n - any float, but typically a fairly small one (between -8 and 8, as a guideline)
      Returns:
      n with its 13 least significant bits effectively removed
    • truncate

      public static double truncate(double n)
      Forces precision loss on the given double so very small fluctuations away from an integer will be erased. This is meant primarily for cleaning up doubles, so they can be presented without needing scientific notation. It leaves about 3 decimal digits after the point intact, and should make any digits after that simply 0.
      Parameters:
      n - any double, but typically a fairly small one (between -8 and 8, as a guideline)
      Returns:
      n with its 42 least significant bits effectively removed
    • lerp

      public static float lerp(float fromValue, float toValue, float progress)
      Linearly interpolates between fromValue to toValue on progress position.
      Parameters:
      fromValue - starting float value; can be any finite float
      toValue - ending float value; can be any finite float
      progress - how far the interpolation should go, between 0 (equal to fromValue) and 1 (equal to toValue)
    • norm

      public static float norm(float rangeStart, float rangeEnd, float value)
      Linearly normalizes value from a range. Range must not be empty. This is the inverse of lerp(float, float, float).
      Parameters:
      rangeStart - range start normalized to 0
      rangeEnd - range end normalized to 1
      value - value to normalize
      Returns:
      normalized value; values outside the range are not clamped to 0 and 1
    • map

      public static float map(float inRangeStart, float inRangeEnd, float outRangeStart, float outRangeEnd, float value)
      Linearly map a value from one range to another. Input range must not be empty. This is the same as chaining norm(float, float, float) from input range and lerp(float, float, float) to output range.
      Parameters:
      inRangeStart - input range start
      inRangeEnd - input range end
      outRangeStart - output range start
      outRangeEnd - output range end
      value - value to map
      Returns:
      mapped value; values outside the input range are not clamped to output range
    • lerpAngle

      public static float lerpAngle(float fromRadians, float toRadians, float progress)
      Linearly interpolates between two angles in radians. Takes into account that angles wrap at PI2 and always takes the direction with the smallest delta angle.
      Parameters:
      fromRadians - start angle in radians
      toRadians - target angle in radians
      progress - interpolation value in the range [0, 1]
      Returns:
      the interpolated angle in the range [0, PI2)
    • lerpAngleDeg

      public static float lerpAngleDeg(float fromDegrees, float toDegrees, float progress)
      Linearly interpolates between two angles in degrees. Takes into account that angles wrap at 360 degrees and always takes the direction with the smallest delta angle.
      Parameters:
      fromDegrees - start angle in degrees
      toDegrees - target angle in degrees
      progress - interpolation value in the range [0, 1]
      Returns:
      the interpolated angle in the range [0, 360)
    • lerpAngleTurns

      public static float lerpAngleTurns(float fromTurns, float toTurns, float progress)
      Linearly interpolates between two angles in turns. Takes into account that angles wrap at 1.0 and always takes the direction with the smallest delta angle. This version, unlike the versions for radians and degrees, avoids any modulus operation (instead calling fastFloor(float) twice).
      Parameters:
      fromTurns - start angle in turns
      toTurns - target angle in turns
      progress - interpolation value in the range [0, 1]
      Returns:
      the interpolated angle in the range [0, 1)
    • zigzag

      public static float zigzag(float value)
      Takes any float and produces a float in the -1f to 1f range, with similar inputs producing close to a consistent rate of up and down through the range. This is meant for noise, where it may be useful to limit the amount of change between nearby points' noise values and prevent sudden "jumps" in noise value. An input of any even number should produce something very close to -1f, any odd number should produce something very close to 1f, and any number halfway between two incremental integers (like 8.5f or -10.5f) should produce 0f or a very small fraction. This method is closely related to sway(float), which will smoothly curve its output to produce more values that are close to -1 or 1.
      Parameters:
      value - any float
      Returns:
      a float from -1f (inclusive) to 1f (inclusive)
    • sway

      public static float sway(float value)
      Very similar to TrigTools.sinTurns(float) with half frequency, or Math.sin(double) with Math.PI frequency, but optimized (and shaped) a little differently. This looks like a squished sine wave when graphed, and is essentially just interpolating between each pair of odd and even inputs using what FastNoise calls QUINTIC interpolation. This interpolation is slightly flatter at peaks and valleys than a sine wave is.
      An input of any even number should produce something very close to -1f, any odd number should produce something very close to 1f, and any number halfway between two incremental integers (like 8.5f or -10.5f) should produce 0f or a very small fraction. In the (unlikely) event that this is given a float that is too large to represent many or any non-integer values, this will simply return -1f or 1f.
      This version of a sway method uses quintic interpolation; it uses up to the fifth power of value.
      Parameters:
      value - any float other than NaN or infinite values; extremely large values can't work properly
      Returns:
      a float from -1f (inclusive) to 1f (inclusive)
    • swayCubic

      public static float swayCubic(float value)
      Very similar to TrigTools.sinTurns(float) with half frequency, or Math.sin(double) with Math.PI frequency, but optimized (and shaped) a little differently. This looks like a squished sine wave when graphed, and is essentially just interpolating between each pair of odd and even inputs using what is sometimes called HERMITE interpolation. This interpolation is rounder at peaks and valleys than a sine wave is; it is also called smoothstep in GLSL, and is called cubic here because it gets the third power of a value.
      An input of any even number should produce something very close to -1f, any odd number should produce something very close to 1f, and any number halfway between two incremental integers (like 8.5f or -10.5f) should produce 0f or a very small fraction. In the (unlikely) event that this is given a float that is too large to represent many or any non-integer values, this will simply return -1f or 1f.
      Parameters:
      value - any float other than NaN or infinite values; extremely large values can't work properly
      Returns:
      a float from -1f (inclusive) to 1f (inclusive)
    • swayTight

      public static float swayTight(float value)
      Takes any float and produces a float in the 0f to 1f range, with a graph of input to output that looks much like a sine wave, curving to have a flat slope when given an integer input and a steep slope when the input is halfway between two integers, smoothly curving at any points between those extremes. This is meant for noise, where it may be useful to limit the amount of change between nearby points' noise values and prevent both sudden "jumps" in noise value and "cracks" where a line takes a sudden jagged movement at an angle.
      An input of any even number should produce something very close to 0f, any odd number should produce something very close to 1f, and any number halfway between two incremental integers (like 8.5f or -10.5f) should produce 0.5f. In the (unlikely) event that this is given a float that is too large to represent many or any non-integer values, this will simply return 0f or 1f. This version is called "Tight" because its range is tighter than sway(float).
      This version of a sway method uses quintic interpolation; it uses up to the fifth power of value.
      Parameters:
      value - any float other than NaN or infinite values; extremely large values can't work properly
      Returns:
      a float from 0f (inclusive) to 1f (inclusive)