require 'benchmark'

require 'rational'

$result = nil

def test_it
=begin
  result = [
=end

#=begin
  Rational(1, 2) + Rational(3, 4)
  Rational(1, 2) + 10
  Rational(1, 3) + 10.6
#=end

  Rational(1, 2) - Rational(3, 4)
  Rational(1, 2) - 10
  Rational(1, 3) - 10.6
#=begin
  Rational(1, 2) * Rational(3, 4)
  Rational(1, 2) * 10
  Rational(1, 3) * 10.6

  Rational(1, 2) / Rational(3, 4)
  Rational(1, 2) / 10
  Rational(1, 3) / 10.6

  Rational(1, 2) ** Rational(3, 4)
  Rational(1, 2) ** 10
  Rational(1, 2) ** -10
  Rational(1, 2) ** 0
  Rational(1, 3) ** 10.6

  Rational(1, 2) == Rational(3, 4)
  Rational(1, 2) == 10
  Rational(1, 3) == 10.6

  Rational(1, 2) <=> Rational(3, 4)
  Rational(1, 2) <=> 10
  Rational(1, 3) <=> 10.6

  - Rational(1, 2)
  - Rational(-1, 3)
  - Rational(1, 4)

  Rational(1, 2).abs
  Rational(-1, 3).abs
  Rational(1, 4).abs

#=end
#=begin
  Rational(3, 4).to_s
  Rational(5, 6).inspect
#=end

=begin
  ]

  if $result
    unless result == $result
      pp result
      pp $result
      raise "Assertion failed"
    end
  else
    $result = result
  end
=end
end


n = 100000
Benchmark.bm(40) do | bm |

  1.times do
    ObjectSpace.garbage_collect
    bm.report("test_it") do 
      n.times do
        test_it
      end
    end
  end

######################################################################

  require 'ks_rational'

  ObjectSpace.garbage_collect
  bm.report("test_it ks_rational") do 
    n.times do
      test_it
    end
  end

end

if false

######################################################################

  def - (a)
    case a
    when Rational
      num = @numerator * a.denominator
      num_a = a.numerator * @denominator
      Rational(num - num_a, @denominator * a.denominator)
    when Integer
      self - Rational.new!(a, 1)
    when Float
      Float(self) - a
    else
      x, y = a.coerce(self)
      x - y
    end
  end

  ObjectSpace.garbage_collect
  bm.report("test_it case stmt") do 
    n.times do
      test_it
    end
  end

######################################################################

=begin

class ::Rational
  def to_s
    if @denominator == 1
      @numerator.to_s
    else
      "#{@numerator}/#{@denominator}"
    end
  end

  def inspect
    "Rational(#{@numerator.inspect}, #{@denominator.inspect})"
  end
end

  ObjectSpace.garbage_collect
  bm.report("test_it string-interp") do 
    n.times do
      test_it
    end
  end

=end

######################################################################

class ::Rational
  def - (a)
    case a
    when Rational, Integer
    when Float
      return Float(self) - a
    else
      x, y = a.coerce(self)
      return x - y
    end

    num = @numerator * a.denominator
    num_a = a.numerator * @denominator
    Rational(num - num_a, @denominator*a.denominator)
  end
end

  bm.report("test_it: use #denom, #numer") do 
    n.times do
      test_it
    end
  end

######################################################################


class ::Rational
  def - (a)
    case a
    when Rational
      a_numerator =  a.numerator
      a_denominator = a.denominator
    when Integer
      a_numerator = a
      a_denominator = 1
    when Float
      return Float(self) - a
    else
      x, y = a.coerce(self)
      return x - y
    end

    num = @numerator * a_denominator
    num_a = a_numerator * @denominator
    Rational(num - num_a, @denominator * a_denominator)
  end
end

  ObjectSpace.garbage_collect
  bm.report("test_it: use temp vars") do 
    n.times do
      test_it
    end
  end

end

  
