stick 1.3.2 → 1.3.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -14,115 +14,114 @@
14
14
  # - Daniel Carrera
15
15
  # - Brian Gough
16
16
 
17
- #
17
+ module Stick #:nodoc:
18
18
  module Constants
19
+ module Typeless
19
20
 
20
- module Typeless
21
-
22
- # Unitless constants in the MKS system (meters, kg, sec)
23
-
24
- module MKS
25
- SPEED_OF_LIGHT = 2.99792458e8 # m / s
26
- GRAVITATIONAL_CONSTANT = 6.673e-11 # m^3 / kg s^2
27
- PLANCKS_CONSTANT_H = 6.62606876e-34 # kg m^2 / s
28
- PLANCKS_CONSTANT_HBAR = 1.05457159642e-34 # kg m^2 / s
29
- VACUUM_PERMEABILITY = 1.25663706144e-6 # kg m / A^2 s^2
30
- ASTRONOMICAL_UNIT = 1.49597870691e11 # m
31
- LIGHT_YEAR = 9.46053620707e15 # m
32
- PARSEC = 3.08567758135e16 # m
33
- GRAV_ACCEL = 9.80665e0 # m / s^2
34
- ELECTRON_VOLT = 1.602176462e-19 # kg m^2 / s^2
35
- MASS_ELECTRON = 9.10938188e-31 # kg
36
- MASS_MUON = 1.88353109e-28 # kg
37
- MASS_PROTON = 1.67262158e-27 # kg
38
- MASS_NEUTRON = 1.67492716e-27 # kg
39
- RYDBERG = 2.17987190389e-18 # kg m^2 / s^2
40
- BOLTZMANN = 1.3806503e-23 # kg m^2 / K s^2
41
- BOHR_MAGNETON = 9.27400899e-24 # A m^2
42
- NUCLEAR_MAGNETON = 5.05078317e-27 # A m^2
43
- ELECTRON_MAGNETIC_MOMENT = 9.28476362e-24 # A m^2
44
- PROTON_MAGNETIC_MOMENT = 1.410606633e-26 # A m^2
45
- MOLAR_GAS = 8.314472e0 # kg m^2 / K mol s^2
46
- STANDARD_GAS_VOLUME = 2.2710981e-2 # m^3 / mol
47
- MINUTE = 6e1 # s
48
- HOUR = 3.6e3 # s
49
- DAY = 8.64e4 # s
50
- WEEK = 6.048e5 # s
51
- INCH = 2.54e-2 # m
52
- FOOT = 3.048e-1 # m
53
- YARD = 9.144e-1 # m
54
- MILE = 1.609344e3 # m
55
- NAUTICAL_MILE = 1.852e3 # m
56
- FATHOM = 1.8288e0 # m
57
- MIL = 2.54e-5 # m
58
- POINT = 3.52777777778e-4 # m
59
- TEXPOINT = 3.51459803515e-4 # m
60
- MICRON = 1e-6 # m
61
- ANGSTROM = 1e-10 # m
62
- HECTARE = 1e4 # m^2
63
- ACRE = 4.04685642241e3 # m^2
64
- BARN = 1e-28 # m^2
65
- LITER = 1e-3 # m^3
66
- US_GALLON = 3.78541178402e-3 # m^3
67
- QUART = 9.46352946004e-4 # m^3
68
- PINT = 4.73176473002e-4 # m^3
69
- CUP = 2.36588236501e-4 # m^3
70
- FLUID_OUNCE = 2.95735295626e-5 # m^3
71
- TABLESPOON = 1.47867647813e-5 # m^3
72
- TEASPOON = 4.92892159375e-6 # m^3
73
- CANADIAN_GALLON = 4.54609e-3 # m^3
74
- UK_GALLON = 4.546092e-3 # m^3
75
- MILES_PER_HOUR = 4.4704e-1 # m / s
76
- KILOMETERS_PER_HOUR = 2.77777777778e-1 # m / s
77
- KNOT = 5.14444444444e-1 # m / s
78
- POUND_MASS = 4.5359237e-1 # kg
79
- OUNCE_MASS = 2.8349523125e-2 # kg
80
- TON = 9.0718474e2 # kg
81
- METRIC_TON = 1e3 # kg
82
- UK_TON = 1.0160469088e3 # kg
83
- TROY_OUNCE = 3.1103475e-2 # kg
84
- CARAT = 2e-4 # kg
85
- UNIFIED_ATOMIC_MASS = 1.66053873e-27 # kg
86
- ATOMIC_MASS = 1.66053873e-27 # kg
87
- GRAM_FORCE = 9.80665e-3 # kg m / s^2
88
- POUND_FORCE = 4.44822161526e0 # kg m / s^2
89
- KILOPOUND_FORCE = 4.44822161526e3 # kg m / s^2
90
- POUNDAL = 1.38255e-1 # kg m / s^2
91
- CALORIE = 4.1868e0 # kg m^2 / s^2
92
- BTU = 1.05505585262e3 # kg m^2 / s^2
93
- THERM = 1.05506e8 # kg m^2 / s^2
94
- HORSEPOWER = 7.457e2 # kg m^2 / s^3
95
- BAR = 1e5 # kg / m s^2
96
- STD_ATMOSPHERE = 1.01325e5 # kg / m s^2
97
- TORR = 1.33322368421e2 # kg / m s^2
98
- METER_OF_MERCURY = 1.33322368421e5 # kg / m s^2
99
- INCH_OF_MERCURY = 3.38638815789e3 # kg / m s^2
100
- INCH_OF_WATER = 2.490889e2 # kg / m s^2
101
- PSI = 6.89475729317e3 # kg / m s^2
102
- POISE = 1e-1 # kg m^-1 s^-1
103
- STOKES = 1e-4 # m^2 / s
104
- FARADAY = 9.6485341472e4 # A s / mol
105
- ELECTRON_CHARGE = 1.602176462e-19 # A s
106
- GAUSS = 1e-4 # kg / A s^2
107
- STILB = 1e4 # cd / m^2
108
- LUMEN = 1e0 # cd sr
109
- LUX = 1e0 # cd sr / m^2
110
- PHOT = 1e4 # cd sr / m^2
111
- FOOTCANDLE = 1.076e1 # cd sr / m^2
112
- LAMBERT = 1e4 # cd sr / m^2
113
- FOOTLAMBERT = 1.07639104e1 # cd sr / m^2
114
- CURIE = 3.7e10 # 1 / s
115
- ROENTGEN = 2.58e-4 # A s / kg
116
- RAD = 1e-2 # m^2 / s^2
117
- SOLAR_MASS = 1.98892e30 # kg
118
- BOHR_RADIUS = 5.291772083e-11 # m
119
- VACUUM_PERMITTIVITY = 8.854187817e-12 # A^2 s^4 / kg m^3
120
- NEWTON = 1e0 # kg m / s^2
121
- DYNE = 1e-5 # kg m / s^2
122
- JOULE = 1e0 # kg m^2 / s^2
123
- ERG = 1e-7 # kg m^2 / s^2
124
- end
21
+ # Unitless constants in the MKS system (meters, kg, sec)
125
22
 
126
- end
23
+ module MKS
24
+ SPEED_OF_LIGHT = 2.99792458e8 # m / s
25
+ GRAVITATIONAL_CONSTANT = 6.673e-11 # m^3 / kg s^2
26
+ PLANCKS_CONSTANT_H = 6.62606876e-34 # kg m^2 / s
27
+ PLANCKS_CONSTANT_HBAR = 1.05457159642e-34 # kg m^2 / s
28
+ VACUUM_PERMEABILITY = 1.25663706144e-6 # kg m / A^2 s^2
29
+ ASTRONOMICAL_UNIT = 1.49597870691e11 # m
30
+ LIGHT_YEAR = 9.46053620707e15 # m
31
+ PARSEC = 3.08567758135e16 # m
32
+ GRAV_ACCEL = 9.80665e0 # m / s^2
33
+ ELECTRON_VOLT = 1.602176462e-19 # kg m^2 / s^2
34
+ MASS_ELECTRON = 9.10938188e-31 # kg
35
+ MASS_MUON = 1.88353109e-28 # kg
36
+ MASS_PROTON = 1.67262158e-27 # kg
37
+ MASS_NEUTRON = 1.67492716e-27 # kg
38
+ RYDBERG = 2.17987190389e-18 # kg m^2 / s^2
39
+ BOLTZMANN = 1.3806503e-23 # kg m^2 / K s^2
40
+ BOHR_MAGNETON = 9.27400899e-24 # A m^2
41
+ NUCLEAR_MAGNETON = 5.05078317e-27 # A m^2
42
+ ELECTRON_MAGNETIC_MOMENT = 9.28476362e-24 # A m^2
43
+ PROTON_MAGNETIC_MOMENT = 1.410606633e-26 # A m^2
44
+ MOLAR_GAS = 8.314472e0 # kg m^2 / K mol s^2
45
+ STANDARD_GAS_VOLUME = 2.2710981e-2 # m^3 / mol
46
+ MINUTE = 6e1 # s
47
+ HOUR = 3.6e3 # s
48
+ DAY = 8.64e4 # s
49
+ WEEK = 6.048e5 # s
50
+ INCH = 2.54e-2 # m
51
+ FOOT = 3.048e-1 # m
52
+ YARD = 9.144e-1 # m
53
+ MILE = 1.609344e3 # m
54
+ NAUTICAL_MILE = 1.852e3 # m
55
+ FATHOM = 1.8288e0 # m
56
+ MIL = 2.54e-5 # m
57
+ POINT = 3.52777777778e-4 # m
58
+ TEXPOINT = 3.51459803515e-4 # m
59
+ MICRON = 1e-6 # m
60
+ ANGSTROM = 1e-10 # m
61
+ HECTARE = 1e4 # m^2
62
+ ACRE = 4.04685642241e3 # m^2
63
+ BARN = 1e-28 # m^2
64
+ LITER = 1e-3 # m^3
65
+ US_GALLON = 3.78541178402e-3 # m^3
66
+ QUART = 9.46352946004e-4 # m^3
67
+ PINT = 4.73176473002e-4 # m^3
68
+ CUP = 2.36588236501e-4 # m^3
69
+ FLUID_OUNCE = 2.95735295626e-5 # m^3
70
+ TABLESPOON = 1.47867647813e-5 # m^3
71
+ TEASPOON = 4.92892159375e-6 # m^3
72
+ CANADIAN_GALLON = 4.54609e-3 # m^3
73
+ UK_GALLON = 4.546092e-3 # m^3
74
+ MILES_PER_HOUR = 4.4704e-1 # m / s
75
+ KILOMETERS_PER_HOUR = 2.77777777778e-1 # m / s
76
+ KNOT = 5.14444444444e-1 # m / s
77
+ POUND_MASS = 4.5359237e-1 # kg
78
+ OUNCE_MASS = 2.8349523125e-2 # kg
79
+ TON = 9.0718474e2 # kg
80
+ METRIC_TON = 1e3 # kg
81
+ UK_TON = 1.0160469088e3 # kg
82
+ TROY_OUNCE = 3.1103475e-2 # kg
83
+ CARAT = 2e-4 # kg
84
+ UNIFIED_ATOMIC_MASS = 1.66053873e-27 # kg
85
+ ATOMIC_MASS = 1.66053873e-27 # kg
86
+ GRAM_FORCE = 9.80665e-3 # kg m / s^2
87
+ POUND_FORCE = 4.44822161526e0 # kg m / s^2
88
+ KILOPOUND_FORCE = 4.44822161526e3 # kg m / s^2
89
+ POUNDAL = 1.38255e-1 # kg m / s^2
90
+ CALORIE = 4.1868e0 # kg m^2 / s^2
91
+ BTU = 1.05505585262e3 # kg m^2 / s^2
92
+ THERM = 1.05506e8 # kg m^2 / s^2
93
+ HORSEPOWER = 7.457e2 # kg m^2 / s^3
94
+ BAR = 1e5 # kg / m s^2
95
+ STD_ATMOSPHERE = 1.01325e5 # kg / m s^2
96
+ TORR = 1.33322368421e2 # kg / m s^2
97
+ METER_OF_MERCURY = 1.33322368421e5 # kg / m s^2
98
+ INCH_OF_MERCURY = 3.38638815789e3 # kg / m s^2
99
+ INCH_OF_WATER = 2.490889e2 # kg / m s^2
100
+ PSI = 6.89475729317e3 # kg / m s^2
101
+ POISE = 1e-1 # kg m^-1 s^-1
102
+ STOKES = 1e-4 # m^2 / s
103
+ FARADAY = 9.6485341472e4 # A s / mol
104
+ ELECTRON_CHARGE = 1.602176462e-19 # A s
105
+ GAUSS = 1e-4 # kg / A s^2
106
+ STILB = 1e4 # cd / m^2
107
+ LUMEN = 1e0 # cd sr
108
+ LUX = 1e0 # cd sr / m^2
109
+ PHOT = 1e4 # cd sr / m^2
110
+ FOOTCANDLE = 1.076e1 # cd sr / m^2
111
+ LAMBERT = 1e4 # cd sr / m^2
112
+ FOOTLAMBERT = 1.07639104e1 # cd sr / m^2
113
+ CURIE = 3.7e10 # 1 / s
114
+ ROENTGEN = 2.58e-4 # A s / kg
115
+ RAD = 1e-2 # m^2 / s^2
116
+ SOLAR_MASS = 1.98892e30 # kg
117
+ BOHR_RADIUS = 5.291772083e-11 # m
118
+ VACUUM_PERMITTIVITY = 8.854187817e-12 # A^2 s^4 / kg m^3
119
+ NEWTON = 1e0 # kg m / s^2
120
+ DYNE = 1e-5 # kg m / s^2
121
+ JOULE = 1e0 # kg m^2 / s^2
122
+ ERG = 1e-7 # kg m^2 / s^2
123
+ end
127
124
 
128
125
  end
126
+ end
127
+ end
@@ -1,5 +1,6 @@
1
1
  require 'stick/units/currency'
2
2
 
3
+ module Stick
3
4
  module Units
4
5
 
5
6
  # Load conversion units.
@@ -8,3 +9,4 @@ module Units
8
9
  end
9
10
 
10
11
  end
12
+ end
@@ -9,38 +9,50 @@
9
9
  # NOTES:
10
10
  #
11
11
  # Google Summer of Code 2007 project for Ruby Central Inc.
12
+ #
13
+ # TODO:
14
+ # - #mapcar should ne be defined in toplevel. But Matrix
15
+ # is using it at class-level. WTF?
12
16
 
13
17
  require 'generator'
14
- #
15
- # Non-recursive mapcar (works on all Enumerables)
16
- #
17
- def mapcar(*enums)
18
- generators = enums.collect { |e| Generator.new(e) }
19
- result = []
20
- while true
21
- begin
22
- params = generators.collect { |g| g.current; g.next }
23
- rescue EOFError
24
- return result
18
+
19
+ #module Enumerable
20
+
21
+ # Non-recursive mapcar (works on all Enumerables)
22
+
23
+ def mapcar(*enums)
24
+ generators = enums.collect { |e| Generator.new(e) }
25
+ result = []
26
+ while true
27
+ begin
28
+ params = generators.collect { |g| g.current; g.next }
29
+ rescue EOFError
30
+ return result
31
+ end
32
+ result << yield(*params)
25
33
  end
26
- result << yield(*params)
27
34
  end
28
- end
29
35
 
30
- def map(*enums)
31
- generators = []; enums.each { |e| generators << Generator.new(e) }
32
- while true
33
- begin
34
- params = []; generators.each { |g| g.current; params << g.next }
35
- rescue EOFError
36
- return
36
+ #
37
+
38
+ def map(*enums)
39
+ generators = []; enums.each { |e| generators << Generator.new(e) }
40
+ while true
41
+ begin
42
+ params = []; generators.each { |g| g.current; params << g.next }
43
+ rescue EOFError
44
+ return
45
+ end
46
+ yield(*params)
37
47
  end
38
- yield(*params)
39
48
  end
40
- end
49
+
50
+ #end
51
+
41
52
 
42
53
  class Array
43
- def Array.map(n, *arrays)
54
+
55
+ def self.map(n, *arrays)
44
56
  len = arrays.length
45
57
  if n == 0
46
58
  n = arrays[0].length
@@ -57,5 +69,6 @@ class Array
57
69
  yield(*params)
58
70
  end
59
71
  end
72
+
60
73
  end
61
74
 
@@ -1,22 +1,18 @@
1
- # = TITLE:
2
- #
3
- # Matrix Extensions
4
- #
5
- # AUTHOR:
6
- #
7
- # Cosmin Bonchis
8
- #
9
- # NOTES:
10
- #
11
- # Google Summer of Code 2007 project for Ruby Central Inc.
12
-
13
1
  require 'rational'
14
- require 'matrix'
15
2
 
16
3
  require 'stick/mapcar'
4
+ require 'stick/matrix/core'
5
+ require 'stick/matrix/givens'
6
+ require 'stick/matrix/hessenberg'
7
+ require 'stick/matrix/householder'
8
+ require 'stick/matrix/jacobi'
9
+ require 'stick/matrix/lu'
10
+
17
11
 
12
+ module Stick
18
13
 
19
14
  class Vector
15
+
20
16
  include Enumerable
21
17
 
22
18
  module Norm
@@ -599,168 +595,6 @@ class Matrix
599
595
  end
600
596
  end
601
597
 
602
- module LU
603
- #
604
- # Return the Gauss vector, MC, Golub, 3.2.1 Gauss Transformation, p94
605
- #
606
- def LU.gauss_vector(mat, k)
607
- t = mat.column2matrix(k)
608
- tk = t[k, 0]
609
- (0..k).each{|i| t[i, 0] = 0}
610
- return t if tk == 0
611
- (k+1...mat.row_size).each{|i| t[i, 0] = t[i, 0].to_f / tk}
612
- t
613
- end
614
-
615
- #
616
- # Return the Gauss transformation matrix: M_k = I - tau * e_k^T
617
- #
618
- def LU.gauss(mat, k)
619
- i = Matrix.I(mat.column_size)
620
- tau = gauss_vector(mat, k)
621
- e = i.row2matrix(k)
622
- i - tau * e
623
- end
624
-
625
- #
626
- # LU factorization: A = LU
627
- # where L is lower triangular and U is upper triangular
628
- #
629
- def LU.factorization(mat)
630
- u = mat.clone
631
- n = u.column_size
632
- i = Matrix.I(n)
633
- l = i.clone
634
- (n-1).times {|k|
635
- mk = gauss(u, k)
636
- u = mk * u # M_{n-1} * ... * M_1 * A = U
637
- l += i - mk # L = M_1^{-1} * ... * M_{n-1}^{-1} = I + sum_{k=1}^{n-1} tau * e
638
- }
639
- return l, u
640
- end
641
- end
642
-
643
- #
644
- # Return the upper triangular matrix of LU factorization
645
- # M_{n-1} * ... * M_1 * A = U
646
- #
647
- def U
648
- LU.factorization(self)[1]
649
- end
650
-
651
- #
652
- # Return the lower triangular matrix of LU factorization
653
- # L = M_1^{-1} * ... * M_{n-1}^{-1} = I + sum_{k=1}^{n-1} tau * e
654
- #
655
- def L
656
- LU.factorization(self)[0]
657
- end
658
-
659
- module Householder
660
- #
661
- # a QR factorization that uses Householder transformation
662
- # Q^T * A = R
663
- # MC, Golub & van Loan, pg 224, 5.2.1 Householder QR
664
- #
665
- def Householder.QR(mat)
666
- h = []
667
- a = mat.clone
668
- m = a.row_size
669
- n = a.column_size
670
- n.times{|j|
671
- v, beta = a[j..m - 1, j].house
672
-
673
- h[j] = Matrix.diag(Matrix.I(j), Matrix.I(m-j)- beta * (v * v.t))
674
-
675
- a[j..m-1, j..n-1] = (Matrix.I(m-j) - beta * (v * v.t)) * a[j..m-1, j..n-1]
676
- a[(j+1)..m-1,j] = v[2..(m-j)] if j < m - 1 }
677
- h
678
- end
679
-
680
- #
681
- # From the essential part of Householder vector
682
- # it returns the coresponding upper(U_j)/lower(V_j) matrix
683
- #
684
- def Householder.bidiagUV(essential, dim, beta)
685
- v = Vector.concat(Vector[1], essential)
686
- dimv = v.size
687
- Matrix.diag(Matrix.I(dim - dimv), Matrix.I(dimv) - beta * (v * v.t) )
688
- end
689
-
690
- #
691
- # Householder Bidiagonalization algorithm. MC, Golub, pg 252, Algorithm 5.4.2
692
- # Returns the matrices U_B and V_B such that: U_B^T * A * V_B = B,
693
- # where B is upper bidiagonal.
694
- #
695
- def Householder.bidiag(mat)
696
- a = mat.clone
697
- m = a.row_size
698
- n = a.column_size
699
- ub = Matrix.I(m)
700
- vb = Matrix.I(n)
701
- n.times{|j|
702
- v, beta = a[j..m-1,j].house
703
- a[j..m-1, j..n-1] = (Matrix.I(m-j) - beta * (v * v.t)) * a[j..m-1, j..n-1]
704
- a[j+1..m-1, j] = v[1..(m-j-1)]
705
- ub *= bidiagUV(a[j+1..m-1,j], m, beta) #Ub = U_1 * U_2 * ... * U_n
706
- if j < n - 2
707
- v, beta = (a[j, j+1..n-1]).house
708
- a[j..m-1, j+1..n-1] = a[j..m-1, j+1..n-1] * (Matrix.I(n-j-1) - beta * (v * v.t))
709
- a[j, j+2..n-1] = v[1..n-j-2]
710
- vb *= bidiagUV(a[j, j+2..n-1], n, beta) #Vb = V_1 * U_2 * ... * V_n-2
711
- end }
712
- return ub, vb
713
- end
714
-
715
- #
716
- #Householder Reduction to Hessenberg Form
717
- #
718
- def Householder.toHessenberg(mat)
719
- h = mat.clone
720
- n = h.row_size
721
- u0 = Matrix.I(n)
722
- for k in (0...n - 2)
723
- v, beta = h[k+1..n-1, k].house #the householder matrice part
724
- houseV = Matrix.I(n-k-1) - beta * (v * v.t)
725
- u0 *= Matrix.diag(Matrix.I(k+1), houseV)
726
- h[k+1..n-1, k..n-1] = houseV * h[k+1..n-1, k..n-1]
727
- h[0..n-1, k+1..n-1] = h[0..n-1, k+1..n-1] * houseV
728
- end
729
- return h, u0
730
- end
731
-
732
-
733
- end #end of Householder module
734
-
735
- #
736
- # Returns the upper bidiagonal matrix obtained with Householder Bidiagonalization algorithm
737
- #
738
- def bidiagonal
739
- ub, vb = Householder.bidiag(self)
740
- ub.t * self * vb
741
- end
742
-
743
- #
744
- # Returns the orthogonal matrix Q of Householder QR factorization
745
- # where Q = H_1 * H_2 * H_3 * ... * H_n,
746
- #
747
- def houseQ
748
- h = Householder.QR(self)
749
- q = h[0]
750
- (1...h.size).each{|i| q *= h[i]}
751
- q
752
- end
753
-
754
- #
755
- # Returns the matrix R of Householder QR factorization
756
- # R = H_n * H_n-1 * ... * H_1 * A is an upper triangular matrix
757
- #
758
- def houseR
759
- h = Householder.QR(self)
760
- r = self.clone
761
- h.size.times{|i| r = h[i] * r}
762
- r
763
- end
764
598
 
765
599
  #
766
600
  # Modified Gram Schmidt QR factorization (MC, Golub, p. 232)
@@ -798,225 +632,6 @@ class Matrix
798
632
  gram_schmidt[1]
799
633
  end
800
634
 
801
-
802
- module Givens
803
- #
804
- # Returns the values "c and s" of a Given rotation
805
- # MC, Golub, pg 216, Alghorithm 5.1.3
806
- #
807
- def Givens.givens(a, b)
808
- if b == 0
809
- c = 0; s = 0
810
- else
811
- if b.abs > a.abs
812
- tau = Float(-a)/b; s = 1/Math.sqrt(1+tau**2); c = s * tau
813
- else
814
- tau = Float(-b)/a; c = 1/Math.sqrt(1+tau**2); s = c * tau
815
- end
816
- end
817
- return c, s
818
- end
819
-
820
- #
821
- # a QR factorization using Givens rotation
822
- # Computes the upper triangular matrix R and the orthogonal matrix Q
823
- # where Q^t A = R (MC, Golub, p227 algorithm 5.2.2)
824
- #
825
- def Givens.QR(mat)
826
- r = mat.clone
827
- m = r.row_size
828
- n = r.column_size
829
- q = Matrix.I(m)
830
- n.times{|j|
831
- m-1.downto(j+1){|i|
832
- c, s = givens(r[i - 1, j], r[i, j])
833
- qt = Matrix.I(m); qt[i-1..i, i-1..i] = Matrix[[c, s],[-s, c]]
834
- q *= qt
835
- r[i-1..i, j..n-1] = Matrix[[c, -s],[s, c]] * r[i-1..i, j..n-1]}}
836
- return r, q
837
- end
838
-
839
- end
840
-
841
- #
842
- # Returns the upper triunghiular matrix R of a Givens QR factorization
843
- #
844
- def givensR
845
- Givens.QR(self)[0]
846
- end
847
-
848
- #
849
- # Returns the orthogonal matrix Q of Givens QR factorization.
850
- # Q = G_1 * ... * G_t where G_j is the j'th Givens rotation
851
- # and 't' is the total number of rotations
852
- #
853
- def givensQ
854
- Givens.QR(self)[1]
855
- end
856
-
857
- module Hessenberg
858
- #
859
- # the matrix must be an upper R^(n x n) Hessenberg matrix
860
- #
861
- def Hessenberg.QR(mat)
862
- r = mat.clone
863
- n = r.row_size
864
- q = Matrix.I(n)
865
- for j in (0...n-1)
866
- c, s = Givens.givens(r[j,j], r[j+1, j])
867
- cs = Matrix[[c, s], [-s, c]]
868
- q *= Matrix.diag(Matrix.I(j), cs, Matrix.I(n - j - 2))
869
- r[j..j+1, j..n-1] = cs.t * r[j..j+1, j..n-1]
870
- end
871
- return q, r
872
- end
873
- end
874
-
875
- #
876
- # Returns the orthogonal matrix Q of Hessenberg QR factorization
877
- # Q = G_1 *...* G_(n-1) where G_j is the Givens rotation G_j = G(j, j+1, omega_j)
878
- #
879
- def hessenbergQ
880
- Hessenberg.QR(self)[0]
881
- end
882
-
883
- #
884
- # Returns the upper triunghiular matrix R of a Hessenberg QR factorization
885
- #
886
- def hessenbergR
887
- Hessenberg.QR(self)[1]
888
- end
889
-
890
- #
891
- # Return an upper Hessenberg matrix obtained with Householder reduction to Hessenberg Form algorithm
892
- #
893
- def hessenberg_form_H
894
- Householder.toHessenberg(self)[0]
895
- end
896
-
897
- #
898
- # The real Schur decomposition.
899
- # The eigenvalues are aproximated in diagonal elements of the real Schur decomposition matrix
900
- #
901
- def realSchur(eps = 1.0e-10, steps = 100)
902
- h = self.hessenberg_form_H
903
- h1 = Matrix[]
904
- i = 0
905
- loop do
906
- h1 = h.hessenbergR * h.hessenbergQ
907
- break if Matrix.diag_in_delta?(h1, h, eps) or steps <= 0
908
- h = h1.clone
909
- steps -= 1
910
- i += 1
911
- end
912
- h1
913
- end
914
-
915
-
916
- module Jacobi
917
- #
918
- # Returns the nurm of the off-diagonal element
919
- #
920
- def Jacobi.off(a)
921
- n = a.row_size
922
- sum = 0
923
- n.times{|i| n.times{|j| sum += a[i, j]**2 if j != i}}
924
- Math.sqrt(sum)
925
- end
926
-
927
- #
928
- # Returns the index pair (p, q) with 1<= p < q <= n and A[p, q] is the maximum in absolute value
929
- #
930
- def Jacobi.max(a)
931
- n = a.row_size
932
- max = 0
933
- p = 0
934
- q = 0
935
- n.times{|i|
936
- ((i+1)...n).each{|j|
937
- val = a[i, j].abs
938
- if val > max
939
- max = val
940
- p = i
941
- q = j
942
- end }}
943
- return p, q
944
- end
945
-
946
- #
947
- # Compute the cosine-sine pair (c, s) for the element A[p, q]
948
- #
949
- def Jacobi.sym_schur2(a, p, q)
950
- if a[p, q] != 0
951
- tau = Float(a[q, q] - a[p, p])/(2 * a[p, q])
952
- if tau >= 0
953
- t = 1./(tau + Math.sqrt(1 + tau ** 2))
954
- else
955
- t = -1./(-tau + Math.sqrt(1 + tau ** 2))
956
- end
957
- c = 1./Math.sqrt(1 + t ** 2)
958
- s = t * c
959
- else
960
- c = 1
961
- s = 0
962
- end
963
- return c, s
964
- end
965
-
966
- #
967
- # Returns the Jacobi rotation matrix
968
- #
969
- def Jacobi.J(p, q, c, s, n)
970
- j = Matrix.I(n)
971
- j[p,p] = c; j[p, q] = s
972
- j[q,p] = -s; j[q, q] = c
973
- j
974
- end
975
- end
976
-
977
- #
978
- # Classical Jacobi 8.4.3 Golub & van Loan
979
- #
980
- def cJacobi(tol = 1.0e-10)
981
- a = self.clone
982
- n = row_size
983
- v = Matrix.I(n)
984
- eps = tol * a.normF
985
- while Jacobi.off(a) > eps
986
- p, q = Jacobi.max(a)
987
- c, s = Jacobi.sym_schur2(a, p, q)
988
- #print "\np:#{p} q:#{q} c:#{c} s:#{s}\n"
989
- j = Jacobi.J(p, q, c, s, n)
990
- a = j.t * a * j
991
- v = v * j
992
- end
993
- return a, v
994
- end
995
-
996
- #
997
- # Returns the aproximation matrix computed with Classical Jacobi algorithm.
998
- # The aproximate eigenvalues values are in the diagonal of the matrix A.
999
- #
1000
- def cJacobiA(tol = 1.0e-10)
1001
- cJacobi(tol)[0]
1002
- end
1003
-
1004
- #
1005
- # Returns a Vector with the eigenvalues aproximated values.
1006
- # The eigenvalues are computed with the Classic Jacobi Algorithm.
1007
- #
1008
- def eigenvaluesJacobi
1009
- a = cJacobiA
1010
- Vector[*(0...row_size).collect{|i| a[i, i]}]
1011
- end
1012
-
1013
- #
1014
- # Returns the orthogonal matrix obtained with the Jacobi eigenvalue algorithm.
1015
- # The columns of V are the eigenvector.
1016
- #
1017
- def cJacobiV(tol = 1.0e-10)
1018
- cJacobi(tol)[1]
1019
- end
1020
635
  end
1021
636
 
1022
-
637
+ end