stick 1.3.2 → 1.3.3

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.
@@ -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