roots 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. data/lib/roots.rb +166 -0
  2. metadata +48 -0
data/lib/roots.rb ADDED
@@ -0,0 +1,166 @@
1
+ =begin
2
+ Author: Jabari Zakiya, Original: 2009-12-25
3
+ Revision-2: 2009-12-31
4
+ Revision-3: 2010-6-2
5
+ Revision-4: 2010-12-15
6
+
7
+ Module 'Roots' provides two methods 'root' and 'roots'
8
+ which will find all the nth roots of real and complex
9
+ numerical values.
10
+
11
+ ---------------
12
+ Install process:
13
+ Place module file 'roots.rb' into 'lib' directory of ruby
14
+ version. Then from irb session, or a source code file, do:
15
+
16
+ require 'roots'
17
+ #For extended math features also do: require 'mathn'
18
+ #Mixin 'Roots' into class Numeric
19
+ Rev-4 Add line 'class Numeric; include Roots end'
20
+ to end of file to automatically add root/s methods in
21
+ all class Numeric types.
22
+ ---------------
23
+
24
+ Use syntax: val.root(n,{k})
25
+ root(n,k=0) n is root 1/n exponent, integer > 0
26
+ k is nth ccw root 1..n , integer >=0
27
+ If k not given default root returned, which are:
28
+ for +val => real root |val**(1.0/n)|
29
+ for -val => real root -|val**(1.0/n)| when n is odd
30
+ for -val => first ccw complex root when n is even
31
+
32
+ 9.root(2); -32.root(5,3), -100.43.root 6,6
33
+
34
+ Use syntax: val.roots(n,{opt})
35
+ roots(n,opt=0) n is root 1/n exponent, integer > 0
36
+ opt, optional string input, are:
37
+ 0 : default (no input), return array of n ccw roots
38
+ 'c'|'C': complex, return array of complex roots
39
+ 'e'|'E': even, return array even numbered roots
40
+ 'o'|'O': odd , return array odd numbered roots
41
+ 'i'|'I': imag, return array of imaginary roots
42
+ 'r'|'R': real, return array of real roots
43
+ An empty array is returned for an opt with no members.
44
+
45
+ 9348134943.roots(9); -89.roots(4,'real'); 2.2.roots 3,'Im'
46
+
47
+ Can ask: How many real roots of x: x.roots(n,'real').size
48
+ What's the 3rd 5th root of (4+9i): Complex(4,9).root(5,3)
49
+
50
+ ---------------
51
+ Mathematical foundations
52
+
53
+ 1) i = (-1)^(1/2)
54
+ 2) i^1 = i
55
+ 3) i^2 = -1
56
+ 4) i^3 = -i
57
+ 5) i^4 = 1
58
+ 6) Then it repeats, e.g.: i^5 = i*(i^4) = i
59
+ 7) e^(i*x) = cos(x) + i*sin(x)
60
+ 8) when x = PI/2 then e^(PI*i/2) = i
61
+
62
+ For roots (-a)^(1/n) of negative real values:
63
+
64
+ x = |a^(1/n)|*(-1)^(1/n)
65
+ from 2) above
66
+ x = |a^(1/n)|*(i^2)^(1/n)
67
+ x = |a^(1/n)|*(i)^(2/n)
68
+ apply 8) from above
69
+ x = |a^{1/n)|*e^(PI*i/2)^(2/n)
70
+ x = |a^(1/n)|*e^(PI*i/n)
71
+ 9) x = |a^(1/n)|*(cos(PI/n) + i*sin(PI/n))
72
+
73
+ For roots (a)^(1/n) of positive real values:
74
+
75
+ x = (a)^(1/n)
76
+ x = (a*1)^(1/n)
77
+ x = |a^(1/n)|*(1)^(1/n)
78
+ from 5) above
79
+ x = |a^(1/n)|*(i^4))^(1/n)
80
+ x = |a^(1/n)|*(i)^(4/n)
81
+ apply 8) from above
82
+ x = |a^{1/n)|*e^(PI*i/2)^(4/n)
83
+ x = |a^(1/n)|*e^(2*PI*i/n)
84
+ 10) x = |a^(1/n)|*(cos(2*PI/n) + i*sin(2*PI/n))
85
+
86
+ There are n distinct roots (values):
87
+ ---------------
88
+
89
+ Ruby currently gives incorrect values for x|y axis angles
90
+ cos PI/2 => 6.12303176911189e-17
91
+ sin PI => 1.22460635382238e-16
92
+ cos 3*PI/2 => -1.83690953073357e-16
93
+ sin 2*PI => -2.44921970764475e-16
94
+
95
+ These all should be 0.0, which causes incorrect root values there.
96
+ I 'fix' these errors by clipping absolute values less than a value
97
+ I call TRIG-EPSILON so they produces the correct results.
98
+
99
+ Extract this code into separate file and 'require' into your apps
100
+ to get correct|exact results for x|y axis angles and still get same
101
+ accuracy for extremely small delta angles to the x|y axis.
102
+ cosine(89.9999999999*PI/180) => 1.74534333112399e-11
103
+ cosine(90.0*PI/180) => 0.0
104
+ cosine(90.0000000001*PI/180) => -1.74543140899798e-12
105
+ =end
106
+
107
+ # file roots.rb
108
+
109
+ module Roots
110
+ require 'complex'
111
+ include Math
112
+
113
+ def root(n,k=0) # return nth root k=1..n;, or default for k=0
114
+ raise "Root n not an integer > 0" unless n.kind_of?(Integer) && n>0
115
+ raise "Index k not an integer >= 0" unless k.kind_of?(Integer) && k>=0
116
+ return self if n == 1 || self == 0
117
+ mag = abs**n**-1
118
+ return rootn(mag,arg/n,k>0 ? k-1:0,n) if kind_of?(Complex)
119
+ return rootn(mag,PI/n,k-1) if k>0 # nth root any real
120
+ return mag if self > 0 # pos real default
121
+ return -mag if n&1 == 1 # neg real default, n odd
122
+ return rootn(mag,PI/n) # neg real default, n even
123
+ end
124
+
125
+ def roots(n,opt=0) # returns array of roots, [] option not valid
126
+ raise "Root n not an integer > 0" unless n.kind_of?(Integer) && n>0
127
+ raise "Invalid option" unless opt == 0 || opt =~ /^(c|e|i|o|r|C|E|I|O|R)/
128
+ return [self] if n == 1 || self == 0
129
+ mag = abs**n**-1
130
+ theta = kind_of?(Complex) ? arg/n : PI/n
131
+ roots = []
132
+ case opt
133
+ when /^(o|O)/ # odd roots 1,3,5...
134
+ 0.step(n-1,2) {|k| roots << rootn(mag,theta,k,n)}
135
+ when /^(e|E)/ # even roots 2,4,6...
136
+ 1.step(n-1,2) {|k| roots << rootn(mag,theta,k,n)}
137
+ when /^(r|R)/ # real roots Complex(x,0) = (x+i0)
138
+ n.times {|k|
139
+ x=rootn(mag,theta,k,n); roots << x if x.imag == 0}
140
+ when /^(i|I)/ # imaginry roots Complex(0,y) = (0+iy)
141
+ n.times {|k|
142
+ x=rootn(mag,theta,k,n); roots << x if x.real == 0}
143
+ when /^(c|C)/ # complex roots Complex(x,y) = (x+iy)
144
+ n.times {|k|
145
+ x=rootn(mag,theta,k,n); roots << x unless
146
+ x.imag == 0 || x.real == 0}
147
+ else # all n roots
148
+ n.times {|k| roots << rootn(mag,theta,k,n)}
149
+ end
150
+ return roots
151
+ end
152
+
153
+ private # don't show as methods in mixin class
154
+ TRIG_EPSILON = 2.5e-16
155
+ def sine(x); y=sin(x); y.abs < TRIG_EPSILON ? 0.0:y end
156
+ def cosine(x); y=cos(x); y.abs < TRIG_EPSILON ? 0.0:y end
157
+ def tangent(x); sine(x)/cosine(x) end # more accurate tan
158
+
159
+ def rootn(mag,theta,k=0,n=1) # nth root of a real|complex
160
+ angle_n = kind_of?(Complex) ? theta+(2*k*PI)/n :
161
+ self > 0 ? 2*(k+1)*theta : (2*k+1)*theta
162
+ mag*Complex(cosine(angle_n),sine(angle_n))
163
+ end
164
+ end
165
+
166
+ class Numeric; include Roots end
metadata ADDED
@@ -0,0 +1,48 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: roots
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jabari Zakiya
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-27 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: ! 'For val (real/complex) and root n: val.root(n,[1-n]) and val.roots(n,
15
+ [opt]) '
16
+ email:
17
+ - jzakiya@gmail.com
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - lib/roots.rb
23
+ homepage: http://www.scribd.com/doc/60067570/Roots-in-Ruby
24
+ licenses: []
25
+ post_install_message:
26
+ rdoc_options: []
27
+ require_paths:
28
+ - lib
29
+ required_ruby_version: !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ required_rubygems_version: !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ requirements: []
42
+ rubyforge_project:
43
+ rubygems_version: 1.8.24
44
+ signing_key:
45
+ specification_version: 3
46
+ summary: two methods 'root' and 'roots' to compute all n roots of real/complex numbers
47
+ test_files: []
48
+ has_rdoc: