@@ -5,25 +5,27 @@ mutable struct LSR1Data{T}
5
5
mem :: Int
6
6
scaling :: Bool
7
7
scaling_factor :: T
8
- s :: Matrix{T }
9
- y :: Matrix{T }
8
+ s :: Vector{Vector{T} }
9
+ y :: Vector{Vector{T} }
10
10
ys :: Vector{T}
11
- a :: Matrix{T }
11
+ a :: Vector{Vector{T} }
12
12
as :: Vector{T}
13
13
insert :: Int
14
+ Ax :: Vector{T}
14
15
end
15
16
16
17
function LSR1Data (T :: DataType , n :: Int ; mem :: Int = 5 , scaling :: Bool = true , inverse :: Bool = false )
17
18
inverse && @warn " inverse LSR1 operator not yet implemented"
18
19
LSR1Data {T} (max (mem, 1 ),
19
20
scaling,
20
21
convert (T, 1 ),
21
- zeros (T, n, mem) ,
22
- zeros (T, n, mem) ,
22
+ [ zeros (T, n) for _ = 1 : mem] ,
23
+ [ zeros (T, n) for _ = 1 : mem] ,
23
24
zeros (T, mem),
24
- zeros (T, n, mem) ,
25
+ [ zeros (T, n) for _ = 1 : mem] ,
25
26
zeros (T, mem),
26
- 1 )
27
+ 1 ,
28
+ Vector {T} (undef, n))
27
29
end
28
30
29
31
LSR1Data (n :: Int ; kwargs... ) = LSR1Data (Float64, n; kwargs... )
@@ -60,15 +62,18 @@ function LSR1Operator(T :: DataType, n :: Int; kwargs...)
60
62
function lsr1_multiply (data :: LSR1Data , x :: AbstractArray )
61
63
# Multiply operator with a vector.
62
64
63
- result_type = promote_type (T, eltype (x))
64
- q = convert (Array{result_type}, copy (x))
65
+ q = data . Ax
66
+ q . = x
65
67
66
68
data. scaling && (q ./= data. scaling_factor) # q = B₀ * x
67
69
68
70
for i = 1 : data. mem
69
71
k = mod (data. insert + i - 2 , data. mem) + 1
70
72
if data. ys[k] != 0
71
- @views q .+ = dot (data. a[:, k], x) / data. as[k] * data. a[:, k]
73
+ ax = dot (data. a[k], x) / data. as[k]
74
+ for j ∈ eachindex (q)
75
+ q[j] += ax * data. a[k][j]
76
+ end
72
77
end
73
78
end
74
79
return q
@@ -97,16 +102,20 @@ function push!(op :: LSR1Operator, s :: AbstractVector, y :: AbstractVector)
97
102
Bs = op * s
98
103
ymBs = y - Bs
99
104
ys = dot (y, s)
105
+ sNorm = norm (s)
106
+ yy = dot (y, y)
100
107
101
- well_defined = abs (dot (ymBs, s)) ≥ 1.0e-8 + 1.0e-8 * norm (ymBs)^ 2
108
+ ϵ = eps (eltype (op))
109
+ well_defined = abs (dot (ymBs, s)) ≥ ϵ + ϵ * norm (ymBs) * sNorm
102
110
103
111
sufficient_curvature = true
104
112
scaling_condition = true
105
113
if data. scaling
106
- sufficient_curvature = abs (ys) ≥ 1.0e-8
114
+ yNorm = √ yy
115
+ sufficient_curvature = abs (ys) ≥ ϵ * yNorm * sNorm
107
116
if sufficient_curvature
108
- scaling_factor = ys / dot (y, y)
109
- scaling_condition = norm (y - s / scaling_factor) >= 1.0e-8
117
+ scaling_factor = ys / yy
118
+ scaling_condition = norm (y - s / scaling_factor) >= ϵ * yNorm * sNorm
110
119
end
111
120
end
112
121
@@ -116,12 +125,12 @@ function push!(op :: LSR1Operator, s :: AbstractVector, y :: AbstractVector)
116
125
return op
117
126
end
118
127
119
- data. s[:, data. insert] .= s
120
- data. y[:, data. insert] .= y
128
+ data. s[data. insert] .= s
129
+ data. y[data. insert] .= y
121
130
data. ys[data. insert] = ys
122
131
123
132
# update scaling factor
124
- data. scaling && (data. scaling_factor = ys / dot (y, y) )
133
+ data. scaling && (data. scaling_factor = ys / yy )
125
134
126
135
# update next insertion position
127
136
data. insert = mod (data. insert, data. mem) + 1
@@ -130,14 +139,15 @@ function push!(op :: LSR1Operator, s :: AbstractVector, y :: AbstractVector)
130
139
for i = 1 : data. mem
131
140
k = mod (data. insert + i - 2 , data. mem) + 1
132
141
if data. ys[k] != 0
133
- data. a[:, k] .= data. y[:, k] - data. s[:, k] / data. scaling_factor # = y - B₀ * s
142
+ data. a[k] .= data. y[k] - data. s[k] / data. scaling_factor # = y - B₀ * s
134
143
for j = 1 : i- 1
135
144
l = mod (data. insert + j - 2 , data. mem) + 1
136
145
if data. ys[l] != 0
137
- @views data. a[:, k] .- = dot (data. a[:, l], data. s[:, k]) / data. as[l] * data. a[:, l]
146
+ as = dot (data. a[l], data. s[k]) / data. as[l]
147
+ data. a[k] .- = as * data. a[l]
138
148
end
139
149
end
140
- @views data. as[k] = dot (data. a[:, k], data. s[:, k])
150
+ data. as[k] = dot (data. a[k], data. s[k])
141
151
end
142
152
end
143
153
@@ -147,21 +157,27 @@ end
147
157
148
158
"""
149
159
diag(op)
160
+ diag!(op, d)
150
161
151
162
Extract the diagonal of a L-SR1 operator in forward mode.
152
163
"""
153
164
function diag (op :: LSR1Operator{T} ) where T
165
+ d = Vector {T} (undef, op. nrow)
166
+ diag! (op, d)
167
+ end
168
+
169
+ function diag! (op :: LSR1Operator{T} , d) where T
154
170
op. inverse && throw (" only the diagonal of a forward L-SR1 approximation is available" )
155
171
data = op. data
156
172
157
- d = ones (T, op . nrow )
173
+ fill! (d, 1 )
158
174
data. scaling && (d ./= data. scaling_factor)
159
175
160
176
for i = 1 : data. mem
161
177
k = mod (data. insert + i - 2 , data. mem) + 1
162
178
if data. ys[k] != 0.0
163
179
for j = 1 : op. nrow
164
- d[j] += data. a[j, k ]^ 2 / data. as[k]
180
+ d[j] += data. a[k][j ]^ 2 / data. as[k]
165
181
end
166
182
end
167
183
end
@@ -174,10 +190,12 @@ end
174
190
Reset the given LSR1 data.
175
191
"""
176
192
function reset! (data :: LSR1Data{T} ) where T
177
- fill! (data. s, 0 )
178
- fill! (data. y, 0 )
193
+ for i = 1 : data. mem
194
+ fill! (data. s[i], 0 )
195
+ fill! (data. y[i], 0 )
196
+ fill! (data. a[i], 0 )
197
+ end
179
198
fill! (data. ys, 0 )
180
- fill! (data. a, 0 )
181
199
fill! (data. as, 0 )
182
200
data. scaling_factor = T (1 )
183
201
data. insert = 1
0 commit comments