stick 1.3.2 → 1.3.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +3 -4
- data/README +1 -1
- data/lib/stick/constants/cgs.rb +112 -110
- data/lib/stick/constants/mks.rb +6 -4
- data/lib/stick/constants/number.rb +3 -2
- data/lib/stick/constants/typeless_cgs.rb +105 -106
- data/lib/stick/constants/typeless_mks.rb +106 -107
- data/lib/stick/currency.rb +2 -0
- data/lib/stick/mapcar.rb +36 -23
- data/lib/stick/matrix.rb +10 -395
- data/lib/stick/matrix/core.rb +1408 -0
- data/lib/stick/matrix/exception.rb +23 -0
- data/lib/stick/matrix/givens.rb +59 -0
- data/lib/stick/matrix/hessenberg.rb +63 -0
- data/lib/stick/matrix/householder.rb +106 -0
- data/lib/stick/matrix/jacobi.rb +106 -0
- data/lib/stick/matrix/lu.rb +60 -0
- data/lib/stick/quaternion.rb +10 -6
- data/lib/stick/units.rb +2 -0
- data/lib/stick/units/base.rb +75 -72
- data/lib/stick/units/currency.rb +8 -8
- data/lib/stick/units/loaders.rb +3 -2
- data/lib/stick/units/units.rb +2 -0
- data/lib/stick/vector.rb +20 -0
- data/meta/MANIFEST +23 -3
- data/meta/stick.roll +1 -1
- data/task/tests/solo +293 -0
- data/test/spec_matrix.rb +3 -0
- data/test/test_constants.rb +4 -0
- data/test/test_currency.rb +2 -2
- data/test/test_matrix.rb +7 -1
- data/test/test_units.rb +2 -2
- metadata +15 -2
@@ -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
|
-
|
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
|
-
|
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
|
data/lib/stick/currency.rb
CHANGED
data/lib/stick/mapcar.rb
CHANGED
@@ -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
|
-
#
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
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
|
-
|
49
|
+
|
50
|
+
#end
|
51
|
+
|
41
52
|
|
42
53
|
class Array
|
43
|
-
|
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
|
|
data/lib/stick/matrix.rb
CHANGED
@@ -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
|