lib/ruby_units/math.rb
# frozen_string_literal: true
module RubyUnits
# Math will convert unit objects to radians and then attempt to use the value for
# trigonometric functions.
module Math
# Take the square root of a unit or number
#
# @param number [Numeric, RubyUnits::Unit]
# @return [Numeric, RubyUnits::Unit]
def sqrt(number)
if number.is_a?(RubyUnits::Unit)
(number**Rational(1, 2)).to_unit
else
super
end
end
# Take the cube root of a unit or number
#
# @param number [Numeric, RubyUnits::Unit]
# @return [Numeric, RubyUnits::Unit]
def cbrt(number)
if number.is_a?(RubyUnits::Unit)
(number**Rational(1, 3)).to_unit
else
super
end
end
# @param angle [Numeric, RubyUnits::Unit]
# @return [Numeric]
def sin(angle)
angle.is_a?(RubyUnits::Unit) ? super(angle.convert_to("radian").scalar) : super
end
# @param number [Numeric, RubyUnits::Unit]
# @return [Numeric, RubyUnits::Unit]
def asin(number)
if number.is_a?(RubyUnits::Unit)
[super, "radian"].to_unit
else
super
end
end
# @param angle [Numeric, RubyUnits::Unit]
# @return [Numeric]
def cos(angle)
angle.is_a?(RubyUnits::Unit) ? super(angle.convert_to("radian").scalar) : super
end
# @param number [Numeric, RubyUnits::Unit]
# @return [Numeric, RubyUnits::Unit]
def acos(number)
if number.is_a?(RubyUnits::Unit)
[super, "radian"].to_unit
else
super
end
end
# @param number [Numeric, RubyUnits::Unit]
# @return [Numeric]
def sinh(number)
number.is_a?(RubyUnits::Unit) ? super(number.convert_to("radian").scalar) : super
end
# @param number [Numeric, RubyUnits::Unit]
# @return [Numeric]
def cosh(number)
number.is_a?(RubyUnits::Unit) ? super(number.convert_to("radian").scalar) : super
end
# @param angle [Numeric, RubyUnits::Unit]
# @return [Numeric]
def tan(angle)
angle.is_a?(RubyUnits::Unit) ? super(angle.convert_to("radian").scalar) : super
end
# @param number [Numeric, RubyUnits::Unit]
# @return [Numeric]
def tanh(number)
number.is_a?(RubyUnits::Unit) ? super(number.convert_to("radian").scalar) : super
end
# @param x [Numeric, RubyUnits::Unit]
# @param y [Numeric, RubyUnits::Unit]
# @return [Numeric]
def hypot(x, y)
if x.is_a?(RubyUnits::Unit) && y.is_a?(RubyUnits::Unit)
((x**2) + (y**2))**Rational(1, 2)
else
super
end
end
# @param number [Numeric, RubyUnits::Unit]
# @return [Numeric] if argument is a number
# @return [RubyUnits::Unit] if argument is a unit
def atan(number)
if number.is_a?(RubyUnits::Unit)
[super, "radian"].to_unit
else
super
end
end
# @param x [Numeric, RubyUnits::Unit]
# @param y [Numeric, RubyUnits::Unit]
# @return [Numeric] if all parameters are numbers
# @return [RubyUnits::Unit] if parameters are units
# @raise [ArgumentError] if parameters are not numbers or compatible units
def atan2(x, y)
raise ArgumentError, "Incompatible RubyUnits::Units" if (x.is_a?(RubyUnits::Unit) && y.is_a?(RubyUnits::Unit)) && !x.compatible?(y)
if (x.is_a?(RubyUnits::Unit) && y.is_a?(RubyUnits::Unit)) && x.compatible?(y)
[super(x.base_scalar, y.base_scalar), "radian"].to_unit
else
super
end
end
# @param number [Numeric, RubyUnits::Unit]
# @return [Numeric]
def log10(number)
if number.is_a?(RubyUnits::Unit)
super(number.to_f)
else
super
end
end
# @param number [Numeric, RubyUnits::Unit]
# @param base [Numeric]
# @return [Numeric]
def log(number, base = ::Math::E)
if number.is_a?(RubyUnits::Unit)
super(number.to_f, base)
else
super
end
end
end
end
# @see https://github.com/lsegal/yard/issues/1353
module Math
singleton_class.prepend(RubyUnits::Math)
end