10 # Our exports |
10 # Our exports |
11 ############## |
11 ############## |
12 |
12 |
13 export map_first_slice!, |
13 export map_first_slice!, |
14 reduce_first_slice, |
14 reduce_first_slice, |
15 norm₁, |
15 ⬿ |
16 norm₂, |
|
17 γnorm₂, |
|
18 norm₂w, |
|
19 norm₂², |
|
20 norm₂w², |
|
21 norm₂₁, |
|
22 γnorm₂₁, |
|
23 dot, |
|
24 mean, |
|
25 proj_norm₂₁ball!, |
|
26 proj_nonneg!, |
|
27 curry, |
|
28 ⬿, |
|
29 @threadsif, |
|
30 @background, |
|
31 @backgroundif |
|
32 |
|
33 |
|
34 ########## |
|
35 # Threads |
|
36 ########## |
|
37 |
|
38 macro threadsif(threads, loop) |
|
39 return esc(:(if $threads |
|
40 Threads.@threads $loop |
|
41 else |
|
42 $loop |
|
43 end)) |
|
44 end |
|
45 |
|
46 macro background(bgtask, fgtask) |
|
47 return :(t = Threads.@spawn $(esc(bgtask)); |
|
48 $(esc(fgtask)); |
|
49 wait(t)) |
|
50 end |
|
51 |
|
52 macro backgroundif(threads, bgtask, fgtask) |
|
53 return :(if $(esc(threads)) |
|
54 @background $(esc(bgtask)) $(esc(fgtask)) |
|
55 else |
|
56 $(esc(bgtask)) |
|
57 $(esc(fgtask)) |
|
58 end) |
|
59 end |
|
60 |
|
61 ######################## |
|
62 # Functional programming |
|
63 ######################### |
|
64 |
|
65 curry = (f::Function,y...)->(z...)->f(y...,z...) |
|
66 |
16 |
67 ############################### |
17 ############################### |
68 # For working with NamedTuples |
18 # For working with NamedTuples |
69 ############################### |
19 ############################### |
70 |
20 |
92 @inbounds accum=f(accum, @view(y[:, i])) |
42 @inbounds accum=f(accum, @view(y[:, i])) |
93 end |
43 end |
94 return accum |
44 return accum |
95 end |
45 end |
96 |
46 |
97 ########################### |
|
98 # Norms and inner products |
|
99 ########################### |
|
100 |
|
101 @inline function dot(x, y) |
|
102 @assert(length(x)==length(y)) |
|
103 |
|
104 accum=0 |
|
105 for i=1:length(y) |
|
106 @inbounds accum += x[i]*y[i] |
|
107 end |
|
108 return accum |
|
109 end |
|
110 |
|
111 @inline function norm₂w²(y, w) |
|
112 #Insane memory allocs |
|
113 #return @inbounds sum(i -> y[i]*y[i]*w[i], 1:length(y)) |
|
114 accum=0 |
|
115 for i=1:length(y) |
|
116 @inbounds accum=accum+y[i]*y[i]*w[i] |
|
117 end |
|
118 return accum |
|
119 end |
|
120 |
|
121 @inline function norm₂w(y, w) |
|
122 return √(norm₂w²(y, w)) |
|
123 end |
|
124 |
|
125 @inline function norm₂²(y) |
|
126 #Insane memory allocs |
|
127 #return @inbounds sum(i -> y[i]*y[i], 1:length(y)) |
|
128 accum=0 |
|
129 for i=1:length(y) |
|
130 @inbounds accum=accum+y[i]*y[i] |
|
131 end |
|
132 return accum |
|
133 end |
|
134 |
|
135 @inline function norm₂(y) |
|
136 return √(norm₂²(y)) |
|
137 end |
|
138 |
|
139 @inline function norm₁(y) |
|
140 accum=0 |
|
141 for i=1:length(y) |
|
142 @inbounds accum=accum+abs(y[i]) |
|
143 end |
|
144 return accum |
|
145 end |
|
146 |
|
147 @inline function γnorm₂(y, γ) |
|
148 hubersq = xsq -> begin |
|
149 x=√xsq |
|
150 return if x > γ |
|
151 x-γ/2 |
|
152 elseif x<-γ |
|
153 -x-γ/2 |
|
154 else |
|
155 xsq/(2γ) |
|
156 end |
|
157 end |
|
158 |
|
159 if γ==0 |
|
160 return norm₂(y) |
|
161 else |
|
162 return hubersq(norm₂²(y)) |
|
163 end |
|
164 end |
|
165 |
|
166 function norm₂₁(y) |
|
167 return reduce_first_slice((s, x) -> s+norm₂(x), y) |
|
168 end |
|
169 |
|
170 function γnorm₂₁(y,γ) |
|
171 return reduce_first_slice((s, x) -> s+γnorm₂(x, γ), y) |
|
172 end |
|
173 |
|
174 function mean(v) |
|
175 return sum(v)/prod(size(v)) |
|
176 end |
|
177 |
|
178 @inline function proj_norm₂₁ball!(y, α) |
|
179 α²=α*α |
|
180 |
|
181 if ndims(y)==3 && size(y, 1)==2 |
|
182 @inbounds for i=1:size(y, 2) |
|
183 @simd for j=1:size(y, 3) |
|
184 n² = y[1,i,j]*y[1,i,j]+y[2,i,j]*y[2,i,j] |
|
185 if n²>α² |
|
186 v = α/√n² |
|
187 y[1, i, j] *= v |
|
188 y[2, i, j] *= v |
|
189 end |
|
190 end |
|
191 end |
|
192 else |
|
193 y′=reshape(y, (size(y, 1), prod(size(y)[2:end]))) |
|
194 |
|
195 @inbounds @simd for i=1:size(y′, 2)# in CartesianIndices(size(y)[2:end]) |
|
196 n² = norm₂²(@view(y′[:, i])) |
|
197 if n²>α² |
|
198 @views y′[:, i] .*= (α/√n²) |
|
199 end |
|
200 end |
|
201 end |
|
202 end |
|
203 |
|
204 @inline function proj_nonneg!(y) |
|
205 @inbounds @simd for i=1:length(y) |
|
206 if y[i] < 0 |
|
207 y[i] = 0 |
|
208 end |
|
209 end |
|
210 return y |
|
211 end |
|
212 |
|
213 end # Module |
47 end # Module |
214 |
48 |