Skip to content

Instantly share code, notes, and snippets.

@jzakiya
Last active January 25, 2017 15:15
Show Gist options
  • Save jzakiya/f5a78c88f91a6604367f6ac0e0b0bc92 to your computer and use it in GitHub Desktop.
Save jzakiya/f5a78c88f91a6604367f6ac0e0b0bc92 to your computer and use it in GitHub Desktop.
Test data suite for "roots" rubygem written in ruby
module Roots
require 'complex'
include Math
def root(n,k=0) # return kth (1..n) value of root n or default for k=0
raise "Root n not an integer > 0" unless n.kind_of?(Integer) && n > 0
raise "Index k not an integer >= 0" unless k.kind_of?(Integer) && k >= 0
return self if n == 1 || self == 0
mag = abs**(1.0/n) ; theta = phase/n ; delta = 2*PI/n # arg <-> phase
#mag = abs**n**-1 ; theta = arg/n ; delta = 2*PI/n
return rootn(mag,theta,delta,k>1 ? k-1:0) if kind_of?(Complex)
return rootn(mag,theta,delta,k-1) if k>0 # kth root of n for any real
return mag.round(Roots.digits_to_show) if self > 0 # pos real default
return -mag.round(Roots.digits_to_show) if n&1 == 1 # neg real default, n odd
return rootn(mag,theta) # neg real default, n even, 1st ccw root
end
def roots(n,opt=0) # return array of root n values, [] if no value
raise "Root n not an integer > 0" unless n.kind_of?(Integer) && n > 0
raise "Invalid option" unless opt == 0 || opt =~ /^(c|e|i|o|r|C|E|I|O|R)/
return [self] if n == 1 || self == 0
mag = abs**(1.0/n) ; theta = phase/n ; delta = 2*PI/n # arg <-> phase
#mag = abs**n**-1 ; theta = arg/n ; delta = 2*PI/n
roots = []
case opt
when /^(o|O)/ # odd roots 1,3,5...
0.step(n-1,2) {|k| roots << rootn(mag,theta,delta,k)}
when /^(e|E)/ # even roots 2,4,6...
1.step(n-1,2) {|k| roots << rootn(mag,theta,delta,k)}
when /^(r|R)/ # real roots Complex(x,0) = (x+i0)
n.times {|k| x=rootn(mag,theta,delta,k); roots << x if x.imag == 0}
when /^(i|I)/ # imaginry roots Complex(0,y) = (0+iy)
n.times {|k| x=rootn(mag,theta,delta,k); roots << x if x.real == 0}
when /^(c|C)/ # complex roots Complex(x,y) = (x+iy)
n.times {|k| x=rootn(mag,theta,delta,k); roots << x if x.arg*2 % PI != 0}
else # all n roots
n.times {|k| roots << rootn(mag,theta,delta,k)}
end
return roots
end
private # not accessible as methods in mixin class
# Alias sin|cos to fix C lib errors to get 0.0 values for X|Y axis angles.
def sine(x); cos(x).abs == 1 ? 0 : sin(x) end
def cosine(x); sin(x).abs == 1 ? 0 : cos(x) end
def self.digits_to_show(n = @digits_to_show || 8)
@digits_to_show = n < 1 ? 1 : n
end
def rootn(mag,theta,delta=0,k=0) # root k of n of real|complex
angle_n = theta + k*delta
x = mag*Complex(cosine(angle_n),sine(angle_n))
Complex(x.real.round(Roots.digits_to_show), x.imag.round(Roots.digits_to_show))
end
end
# Mixin 'root' and 'roots' as methods for all number classes.
class Numeric; include Roots end
puts "------------ Start Tests ------------"
Roots.digits_to_show 8
puts "Digits To Show = #{Roots.digits_to_show}"
puts 13.root 1
puts 2**(-2.0)
puts -2**(-3.0)
puts (-2)**(-3.0)
puts -2**(4)
puts (-2)**(4)
puts 100.root 2
puts 77.root 5
puts 77.root 5,1
puts 77.root 5,2
puts 77.root 5,3
puts 77.root 5,4
puts 77.root 5,5
puts 100.root 2
puts 100.root 2,1
puts 100.root 2,2
p 16.roots 4
p 64.roots 6
puts -8.root 3
p -8.roots 3
puts "------------ 1 ------------"
p (64.0).roots 6
p 64.to_f.roots 6
puts 1838384743734228.root 23
puts 1838384743734228.root 23, 10
p 32313.roots 10, "c"
p 32313.roots 10, "o"
p 32313.roots 10, "e"
p 32313.roots 10, "imag"
p 32313.roots 10, "real"
p 32313.roots 4, "i"
p (b = 4213.roots(8))
p b.map{|i| i.to_s}
puts b[1].class
puts b[3]
puts b[3].to_s
p Complex(1,1).roots(4).map(&:to_s)
puts Complex(3,-9).root(5,3)
puts Complex(3,-9).root(5,3).class
puts Complex(3,19).root 7,4
puts (3 + 19i).root 7,4 # not valid in crystal
puts (3 - 19.i).root 3,2
puts "------------ 2 ------------"
[2,3.0,-59,911010101113,Complex(-3,48),-97.25].each{|n| p n.root(7)}
p Complex(1,1).roots 4
p Complex(1,1).roots(4).map(&:to_s)
p Complex(1,1).roots(4)[1]
p Complex(1,1).roots 4
#puts 82.root 0
puts 82.root 1, 0
p 82.roots 2, "e"
puts "------------ 3 ------------"
puts 9.root(2)
put -32.root 5,3
puts (-32).root(5,3)
puts 73.root 6
puts 73.root 6,0
puts 73.root 6,1
puts 73.root 6,2
puts 73.root 6,3
puts 73.root 6,4
puts 73.root 6,5
puts 73.root 6,6
puts (-100.43).root 6,6
puts Complex(3,19).root 7,4
puts 625.roots(10,"r")[1]
p 625.roots(10,"c").size
puts "------------ 4 ------------"
p 934813.roots(3)
p 503321.roots 8, "R"
p -89.roots(4,"real")
p (2.2).roots 3,"Im"
p 64.roots 6,"Cmp"
p Complex(23,7.5).roots 3, "odd"
p Complex(3.21,9).roots 5, "evn"
a = Complex(2,0) #503321.roots(8, "R")[1]
puts a*a*a*a*a*a*a*a
puts Complex(2,9).abs
puts "------------ 5 ------------"
puts 10.root(5,3).abs.round 8
puts Roots.digits_to_show
puts 10.root 4
puts Roots.digits_to_show 9
puts 10.root 4
puts Roots.digits_to_show 10
puts 10.root 4
puts Roots.digits_to_show 11
puts 10.root 4
puts Roots.digits_to_show 12
puts 10.root 4
puts -10.root(4)
puts "------------ 6 ------------"
puts (10 ** 0.25).round 5
puts Complex(1.3233439490191, 534).real
puts Complex(1.3233439490191, 534).real.round 1
puts Complex(1.3233439490191, 534).real.round 2
puts Complex(1.3233439490191, 534).real.round 3
puts Complex(1.3233439490191, 534).real.round 4
puts Complex(1.3233439490191, 534).real.round 5
puts Complex(1.3233439490191, 534).real.round 6
puts Complex(1.3233439490191, 534).real.round 7
puts Complex(1.3233439490191, 534).real.round 8
puts Complex(1.3233439490191, 534).real.round 9
puts Complex(1.3233439490191, 534).real.round 10
puts Complex(1.3233439490191, 534).real.round 11
puts Complex(1.3233439490191, 534).real.round 12
puts Complex(1.3233439490191, 534).real.round 13
puts Complex(1.3233439490191, 534).real.round 14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment