Skip to content

Instantly share code, notes, and snippets.

@jzakiya
Last active January 25, 2017 15:16
Show Gist options
  • Save jzakiya/3bee0156a5590cb6f16cc91cc7b62d54 to your computer and use it in GitHub Desktop.
Save jzakiya/3bee0156a5590cb6f16cc91cc7b62d54 to your computer and use it in GitHub Desktop.
Test data suite for "roots" rubygem written in crystal
require "complex" # can't require inside module; must use double quotes ""
include Math
module Roots
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.is_a?(Int) && n > 0
raise "Index k not an integer >= 0" unless k.is_a?(Int) && k >= 0
return self if n == 1 || self == 0
v = is_a?(Complex) ? self : self.to_c
mag = v.abs**(1.0/n); theta = v.phase/n; delta = 2*PI/n
#mag = v.abs**(n**-1.0); theta = v.phase/n; delta = 2*PI/n
return rootn(mag,theta,delta,k>1 ? k-1:0) if is_a?(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.is_a?(Int) && 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
v = is_a?(Complex) ? self : self.to_c # convert value to Complex if not one
mag = v.abs**(1.0/n); theta = v.phase/n; delta = 2*PI/n
#mag = v.abs**(n**-1.0); theta = v.phase/n; delta = 2*PI/n
roots = [] of Complex
case opt
when /^(o|O)/ # odd roots 1,3,5...
0.step(to: n-1, by: 2) {|k| roots << rootn(mag,theta,delta,k)}
when /^(e|E)/ # even roots 2,4,6...
1.step(to: n-1,by: 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.phase*2 % PI != 0}
else # all n roots
n.times {|k| roots << rootn(mag,theta,delta,k)}
end
return roots
end
# Alias sin|cos to fix C lib errors to get 0.0 values for X|Y axis angles.
private def sine(x); cos(x).abs == 1 ? 0 : sin(x) end
private 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
private def rootn(mag,theta,delta=0,k=0) # root k of n of real|complex
angle_n = theta + k*delta
#mag*Complex.new(cosine(angle_n),sine(angle_n))
x = mag*Complex.new(cosine(angle_n),sine(angle_n))
Complex.new(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.
struct Value; 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
puts 16.roots 4
puts 64.roots 6
puts -8.root 3
puts -8.roots 3
puts "------------ 1 ------------"
puts (64.0).roots 6
puts 64.to_f.roots 6
puts 1838384743734228.root 23
puts 1838384743734228.root 23, 10
puts 32313.roots 10, "c"
puts 32313.roots 10, "o"
puts 32313.roots 10, "e"
puts 32313.roots 10, "imag"
puts 32313.roots 10, "real"
puts 32313.roots 4, "i"
puts (b = 4213.roots(8))
puts b.map(&.to_s)
puts b[1].class
puts b[3]
puts b[3].to_s
puts Complex.new(1,1).roots(4).map(&.to_s)
puts Complex.new(3,-9).root(5,3)
puts Complex.new(3,-9).root(5,3).class
puts Complex.new(3,19).root 7,4
puts (3 + 19.i).root 7,4
puts (3 - 19.i).root 3,2
puts "------------ 2 ------------"
[2,3.0,-59,911010101113,Complex.new(-3,48),-97.25].each{|n| puts n.root(7)}
puts Complex.new(1,1).roots 4
puts Complex.new(1,1).roots(4).map(&.to_s)
puts Complex.new(1,1).roots(4)[1]
p Complex.new(1,1).roots 4
#puts 82.root 0
puts 82.root 1, 0
puts 82.roots 2, "e"
puts "------------ 3 ------------"
puts 9.root(2)
puts -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.new(3,19).root 7,4
puts 625.roots(10,"r")[1]
puts 625.roots(10,"c").size
puts "------------ 4 ------------"
puts 934813.roots(3)
puts 503321.roots 8, "R"
puts -89.roots(4,"real")
puts (2.2).roots 3,"Im"
puts 64.roots 6,"Cmp"
puts Complex.new(23,7.5).roots 3, "odd"
puts Complex.new(3.21,9).roots 5, "evn"
a = Complex.new(2,0) #503321.roots(8, "R")[1]
puts a*a*a*a*a*a*a*a
puts Complex.new(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.new(1.3233439490191, 534).real
puts Complex.new(1.3233439490191, 534).real.round 1
puts Complex.new(1.3233439490191, 534).real.round 2
puts Complex.new(1.3233439490191, 534).real.round 3
puts Complex.new(1.3233439490191, 534).real.round 4
puts Complex.new(1.3233439490191, 534).real.round 5
puts Complex.new(1.3233439490191, 534).real.round 6
puts Complex.new(1.3233439490191, 534).real.round 7
puts Complex.new(1.3233439490191, 534).real.round 8
puts Complex.new(1.3233439490191, 534).real.round 9
puts Complex.new(1.3233439490191, 534).real.round 10
puts Complex.new(1.3233439490191, 534).real.round 11
puts Complex.new(1.3233439490191, 534).real.round 12
puts Complex.new(1.3233439490191, 534).real.round 13
puts Complex.new(1.3233439490191, 534).real.round 14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment