Ansel
0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
svd.h
Go to the documentation of this file.
1
/*
2
This file is part of darktable,
3
Copyright (C) 2016 johannes hanika.
4
Copyright (C) 2016 Roman Lebedev.
5
Copyright (C) 2016 Tobias Ellinghaus.
6
Copyright (C) 2019 Heiko Bauke.
7
Copyright (C) 2020 Pascal Obry.
8
Copyright (C) 2021 Laurențiu Nicola.
9
Copyright (C) 2022 Martin Bařinka.
10
11
darktable is free software: you can redistribute it and/or modify
12
it under the terms of the GNU General Public License as published by
13
the Free Software Foundation, either version 3 of the License, or
14
(at your option) any later version.
15
16
darktable is distributed in the hope that it will be useful,
17
but WITHOUT ANY WARRANTY; without even the implied warranty of
18
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
GNU General Public License for more details.
20
21
You should have received a copy of the GNU General Public License
22
along with darktable. If not, see <http://www.gnu.org/licenses/>.
23
*/
24
34
#pragma once
35
36
#include <
math.h
>
37
#include <stdio.h>
38
#include <stdlib.h>
39
40
41
static
inline
double
SIGN
(
double
a,
double
b)
42
{
43
return
copysign(a, b);
44
}
45
46
47
static
inline
double
PYTHAG
(
double
a,
double
b)
48
{
49
const
double
at = fabs(a), bt = fabs(b);
50
if
(at > bt)
51
{
52
const
double
ct = bt / at;
53
return
at * sqrt(1.0 + ct * ct);
54
}
55
if
(bt > 0.0)
56
{
57
const
double
ct = at / bt;
58
return
bt * sqrt(1.0 + ct * ct);
59
}
60
return
0.0;
61
}
62
63
80
static
inline
int
dsvd
(
81
double
*a,
// input matrix a[j*str + i] is j-th row and i-th column. will be overwritten by u
82
int
m
,
// number of rows of a and u
83
int
n
,
// number of cols of a and u
84
int
str,
// row stride of a and u
85
double
*w,
// output singular values w[n]
86
double
*
v
)
// output v matrix v[n*n]
87
{
88
if
(
m
<
n
)
89
{
90
fprintf(stderr,
"[svd] #rows must be >= #cols \n"
);
91
return
0;
92
}
93
94
double
c,
f
, h, s,
x
, y, z;
95
double
anorm = 0.0,
g
= 0.0, scale = 0.0;
96
double
*rv1 = malloc(
n
*
sizeof
(
double
));
97
int
l = 0;
98
99
/* Householder reduction to bidiagonal form */
100
for
(
int
i
= 0;
i
<
n
;
i
++)
101
{
102
/* left-hand reduction */
103
l =
i
+ 1;
104
rv1[
i
] = scale *
g
;
105
g
= s = scale = 0.0;
106
if
(
i
<
m
)
107
{
108
for
(
int
k
=
i
;
k
<
m
;
k
++)
109
scale += fabs(a[
k
*str+
i
]);
110
if
(scale != 0.0)
111
{
112
for
(
int
k
=
i
;
k
<
m
;
k
++)
113
{
114
a[
k
*str+
i
] = a[
k
*str+
i
]/scale;
115
s += a[
k
*str+
i
] * a[
k
*str+
i
];
116
}
117
f
= a[
i
*str+
i
];
118
g
= -
SIGN
(sqrt(s),
f
);
119
h =
f
*
g
- s;
120
a[
i
*str+
i
] =
f
-
g
;
121
if
(
i
!=
n
- 1)
122
{
123
for
(
int
j = l; j <
n
; j++)
124
{
125
s = 0.0;
126
for
(
int
k
=
i
;
k
<
m
;
k
++)
127
s += a[
k
*str+
i
] * a[
k
*str+j];
128
f
= s / h;
129
for
(
int
k
=
i
;
k
<
m
;
k
++)
130
a[
k
*str+j] +=
f
* a[
k
*str+
i
];
131
}
132
}
133
for
(
int
k
=
i
;
k
<
m
;
k
++)
134
a[
k
*str+
i
] = a[
k
*str+
i
]*scale;
135
}
136
}
137
w[
i
] = scale *
g
;
138
139
/* right-hand reduction */
140
g
= s = scale = 0.0;
141
if
(
i
<
m
&&
i
!=
n
- 1)
142
{
143
for
(
int
k
= l;
k
<
n
;
k
++)
144
scale += fabs(a[
i
*str+
k
]);
145
if
(scale != 0.0)
146
{
147
for
(
int
k
= l;
k
<
n
;
k
++)
148
{
149
a[
i
*str+
k
] = a[
i
*str+
k
]/scale;
150
s += a[
i
*str+
k
] * a[
i
*str+
k
];
151
}
152
f
= a[
i
*str+l];
153
g
= -
SIGN
(sqrt(s),
f
);
154
h =
f
*
g
- s;
155
a[
i
*str+l] =
f
-
g
;
156
for
(
int
k
= l;
k
<
n
;
k
++)
157
rv1[
k
] = a[
i
*str+
k
] / h;
158
if
(
i
!=
m
- 1)
159
{
160
for
(
int
j = l; j <
m
; j++)
161
{
162
s = 0.0;
163
for
(
int
k
= l;
k
<
n
;
k
++)
164
s += a[j*str+
k
] * a[
i
*str+
k
];
165
for
(
int
k
= l;
k
<
n
;
k
++)
166
a[j*str+
k
] += s * rv1[
k
];
167
}
168
}
169
for
(
int
k
= l;
k
<
n
;
k
++)
170
a[
i
*str+
k
] = a[
i
*str+
k
]*scale;
171
}
172
}
173
anorm =
MAX
(anorm, (fabs(w[
i
]) + fabs(rv1[
i
])));
174
}
175
176
/* accumulate the right-hand transformation */
177
for
(
int
i
=
n
- 1;
i
>= 0;
i
--)
178
{
179
if
(
i
<
n
- 1)
180
{
181
if
(
g
!= 0.0)
182
{
183
for
(
int
j = l; j <
n
; j++)
184
v
[j*
n
+
i
] = a[
i
*str+j] / a[
i
*str+l] /
g
;
185
/* double division to avoid underflow */
186
for
(
int
j = l; j <
n
; j++)
187
{
188
s = 0.0;
189
for
(
int
k
= l;
k
<
n
;
k
++)
190
s += a[
i
*str+
k
] *
v
[
k
*
n
+j];
191
for
(
int
k
= l;
k
<
n
;
k
++)
192
v
[
k
*
n
+j] += s *
v
[
k
*
n
+
i
];
193
}
194
}
195
for
(
int
j = l; j <
n
; j++)
196
v
[
i
*
n
+j] =
v
[j*
n
+
i
] = 0.0;
197
}
198
v
[
i
*
n
+
i
] = 1.0;
199
g
= rv1[
i
];
200
l =
i
;
201
}
202
203
/* accumulate the left-hand transformation */
204
for
(
int
i
=
n
- 1;
i
>= 0;
i
--)
205
{
206
l =
i
+ 1;
207
g
= w[
i
];
208
if
(
i
<
n
- 1)
209
for
(
int
j = l; j <
n
; j++)
210
a[
i
*str+j] = 0.0;
211
if
(
g
!= 0.0)
212
{
213
g
= 1.0 /
g
;
214
if
(
i
!=
n
- 1)
215
{
216
for
(
int
j = l; j <
n
; j++)
217
{
218
s = 0.0;
219
for
(
int
k
= l;
k
<
m
;
k
++)
220
s += a[
k
*str+
i
] * a[
k
*str+j];
221
f
= (s / a[
i
*str+
i
]) *
g
;
222
for
(
int
k
=
i
;
k
<
m
;
k
++)
223
a[
k
*str+j] +=
f
* a[
k
*str+
i
];
224
}
225
}
226
for
(
int
j =
i
; j <
m
; j++)
227
a[j*str+
i
] = a[j*str+
i
]*
g
;
228
}
229
else
230
{
231
for
(
int
j =
i
; j <
m
; j++)
232
a[j*str+
i
] = 0.0;
233
}
234
++a[
i
*str+
i
];
235
}
236
237
/* diagonalize the bidiagonal form */
238
for
(
int
k
=
n
- 1;
k
>= 0;
k
--)
239
{
/* loop over singular values */
240
const
int
max_its = 30;
241
for
(
int
its = 0; its <= max_its; its++)
242
{
/* loop over allowed iterations */
243
_Bool
flag
= 1;
244
int
nm = 0;
245
for
(l =
k
; l >= 0; l--)
246
{
/* test for splitting */
247
nm =
MAX
(0, l - 1);
248
if
(fabs(rv1[l]) + anorm == anorm)
249
{
250
flag
= 0;
251
break
;
252
}
253
if
(l == 0 || fabs(w[nm]) + anorm == anorm)
254
break
;
255
}
256
if
(
flag
)
257
{
258
s = 1.0;
259
for
(
int
i
= l;
i
<=
k
;
i
++)
260
{
261
f
= s * rv1[
i
];
262
if
(fabs(
f
) + anorm != anorm)
263
{
264
g
= w[
i
];
265
h =
PYTHAG
(
f
,
g
);
266
w[
i
] = h;
267
h = 1.0 / h;
268
c =
g
* h;
269
s = (-
f
* h);
270
for
(
int
j = 0; j <
m
; j++)
271
{
272
y = a[j*str+nm];
273
z = a[j*str+
i
];
274
a[j*str+nm] = y * c + z * s;
275
a[j*str+
i
] = z * c - y * s;
276
}
277
}
278
}
279
}
280
z = w[
k
];
281
if
(l ==
k
)
282
{
/* convergence */
283
if
(z < 0.0)
284
{
/* make singular value nonnegative */
285
w[
k
] = -z;
286
for
(
int
j = 0; j <
n
; j++)
287
v
[j*
n
+
k
] = -
v
[j*
n
+
k
];
288
}
289
break
;
290
}
291
if
(its >= max_its) {
292
fprintf(stderr,
"[svd] no convergence after %d iterations\n"
, its);
293
dt_free
(rv1);
294
return
0;
295
}
296
297
/* shift from bottom 2 x 2 minor */
298
x
= w[l];
299
nm =
k
- 1;
300
y = w[nm];
301
g
= rv1[nm];
302
h = rv1[
k
];
303
f
= ((y - z) * (y + z) + (
g
- h) * (
g
+ h)) / (2.0 * h * y);
304
g
=
PYTHAG
(
f
, 1.0);
305
f
= ((
x
- z) * (
x
+ z) + h * ((y / (
f
+
SIGN
(
g
,
f
))) - h)) /
x
;
306
307
/* next QR transformation */
308
c = s = 1.0;
309
for
(
int
j = l; j <= nm; j++)
310
{
311
const
int
i
= j + 1;
312
g
= rv1[
i
];
313
y = w[
i
];
314
h = s *
g
;
315
g
= c *
g
;
316
z =
PYTHAG
(
f
, h);
317
rv1[j] = z;
318
c =
f
/ z;
319
s = h / z;
320
f
=
x
* c +
g
* s;
321
g
=
g
* c -
x
* s;
322
h = y * s;
323
y = y * c;
324
for
(
int
jj = 0; jj <
n
; jj++)
325
{
326
x
=
v
[jj*
n
+j];
327
z =
v
[jj*
n
+
i
];
328
v
[jj*
n
+j] =
x
* c + z * s;
329
v
[jj*
n
+
i
] = z * c -
x
* s;
330
}
331
z =
PYTHAG
(
f
, h);
332
w[j] = z;
333
if
(z != 0.0)
334
{
335
z = 1.0 / z;
336
c =
f
* z;
337
s = h * z;
338
}
339
f
= (c *
g
) + (s * y);
340
x
= (c * y) - (s *
g
);
341
for
(
int
jj = 0; jj <
m
; jj++)
342
{
343
y = a[jj*str+j];
344
z = a[jj*str+
i
];
345
a[jj*str+j] = y * c + z * s;
346
a[jj*str+
i
] = z * c - y * s;
347
}
348
}
349
rv1[l] = 0.0;
350
rv1[
k
] =
f
;
351
w[
k
] =
x
;
352
}
353
}
354
dt_free
(rv1);
355
return
1;
356
}
357
358
// clang-format off
359
// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
360
// vim: shiftwidth=2 expandtab tabstop=2 cindent
361
// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
362
// clang-format on
m
#define m
Definition
basecurve.c:278
i
const float i
Definition
colorspaces_inline_conversions.h:440
g
const float g
Definition
colorspaces_inline_conversions.h:674
f
const dt_aligned_pixel_t f
Definition
colorspaces_inline_conversions.h:102
n
const float n
Definition
colorspaces_inline_conversions.h:678
dt_free
#define dt_free(ptr)
Definition
darktable.h:456
flag
const char flag
Definition
image.h:252
x
static const float x
Definition
iop_profile.h:235
v
const float v
Definition
iop_profile.h:221
k
float *const restrict const size_t k
Definition
luminance_mask.h:78
math.h
PYTHAG
static double PYTHAG(double a, double b)
Definition
svd.h:47
SIGN
static double SIGN(double a, double b)
Definition
svd.h:41
dsvd
static int dsvd(double *a, int m, int n, int str, double *w, double *v)
Compute the singular value decomposition of a dense matrix.
Definition
svd.h:80
MAX
#define MAX(a, b)
Definition
thinplate.c:29
src
common
svd
svd.h
Generated by
1.9.8