module PerfectShape::Math

Perfect Shape Math utility methods

Mostly ported from java.lang.Math: docs.oracle.com/javase/8/docs/api/java/lang/Math.html

Also includes standard Ruby ::Math utility methods

Public Class Methods

const_missing(constant) click to toggle source
# File lib/perfect_shape/math.rb, line 108
def const_missing(constant)
  ::Math::const_get(constant)
end
degrees_to_radians(degrees) click to toggle source

converts angle from degrees to radians (normalizing to BigDecimal)

# File lib/perfect_shape/math.rb, line 36
def degrees_to_radians(degrees)
  (Math::PI/BigDecimal('180'))*BigDecimal(degrees.to_s)
end
ieee754_remainder(x, y) click to toggle source

Computes the remainder operation on two arguments as prescribed by the IEEE 754 standard.

Algorithm is exactly: x – (round(x/y)*y)

The ‘round` part rounds to the nearest even number when it is a halfway between n & y (integer + 0.5 number)

The remainder value is mathematically equal to x - y × n, where n is the mathematical integer closest to the exact mathematical value of the quotient x/y, and if two mathematical integers are equally close to x/y, then n is the integer that is even. If the remainder is zero, its sign is the same as the sign of the first argument. Special cases:

If either argument is NaN, or the first argument is infinite, or the second argument is positive zero or negative zero, then the result is NaN.

If the first argument is finite and the second argument is infinite, then the result is the same as the first argument.

@param x the dividend. @param y the divisor. @return the remainder when x is divided by y.

# File lib/perfect_shape/math.rb, line 78
def ieee754_remainder(x, y)
  x = BigDecimal(x.to_s)
  y = BigDecimal(y.to_s)
  return BigDecimal::NAN if x.nan? || y.nan? || x.infinite? || y.zero?
  return x if x.finite? && y.infinite?
  division = x / y
  rounded_division_low = BigDecimal(division.floor)
  rounded_division_high = BigDecimal(division.ceil)
  rounded_division_half = rounded_division_low + 0.5
  rounded_division = if division == rounded_division_half
    rounded_division_low.to_i.even? ? rounded_division_low : rounded_division_high
  else
    BigDecimal(division.round)
  end
  (x - (rounded_division * y))
end
Also aliased as: ieee_remainder
ieee_remainder(x, y)
Alias for: ieee754_remainder
method_missing(method_name, *args, &block) click to toggle source
Calls superclass method
# File lib/perfect_shape/math.rb, line 100
def method_missing(method_name, *args, &block)
  if ::Math.respond_to?(method_name, true)
    ::Math.send(method_name, *args, &block)
  else
    super
  end
end
normalize_degrees(angle) click to toggle source

Normalizes the specified angle into the range -180 to 180.

# File lib/perfect_shape/math.rb, line 41
def normalize_degrees(angle)
  angle = BigDecimal(angle.to_s)
  if angle > 180.0
    if angle <= (180.0 + 360.0)
      angle = angle - BigDecimal('360.0')
    else
      angle = Math.ieee_remainder(angle, 360.0)
      # IEEEremainder can return -180 here for some input values...
      angle = BigDecimal('180.0') if angle == -180.0
    end
  elsif angle <= -180.0
    if angle > (-180.0 - 360.0)
      angle = angle + BigDecimal('360.0')
    else
      angle = Math.ieee_remainder(angle, 360.0)
      # IEEEremainder can return -180 here for some input values...
      angle = BigDecimal('180.0') if angle == -180.0
    end
  end
  angle
end
radians_to_degrees(radians) click to toggle source

converts angle from radians to degrees (normalizing to BigDecimal)

# File lib/perfect_shape/math.rb, line 31
def radians_to_degrees(radians)
  (BigDecimal('180')/Math::PI)*BigDecimal(radians.to_s)
end
respond_to?(method_name, include_private = false) click to toggle source
Calls superclass method
# File lib/perfect_shape/math.rb, line 96
def respond_to?(method_name, include_private = false)
  super || ::Math.respond_to?(method_name, include_private)
end