Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
matrices.h
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2010-2011 Henrik Andersson.
4 Copyright (C) 2010 johannes hanika.
5 Copyright (C) 2010 Pascal de Bruijn.
6 Copyright (C) 2012 Richard Wonka.
7 Copyright (C) 2013-2014 Jérémy Rosen.
8 Copyright (C) 2016 Tobias Ellinghaus.
9 Copyright (C) 2020 Pascal Obry.
10 Copyright (C) 2021 Ralf Brown.
11 Copyright (C) 2022 Martin Bařinka.
12 Copyright (C) 2025 Aurélien PIERRE.
13
14 darktable is free software: you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 darktable is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with darktable. If not, see <http://www.gnu.org/licenses/>.
26*/
27
28#ifndef DT_MATH_MATRICES_H
29#define DT_MATH_MATRICES_H
30
31#include "math/math.h"
32
33// a 3x3 matrix, padded to permit SSE instructions to be used for multiplication and addition
35
37static inline int mat3SSEinv(dt_colormatrix_t dst, const dt_colormatrix_t src)
38{
39#define A(y, x) src[(y - 1)][(x - 1)]
40#define B(y, x) dst[(y - 1)][(x - 1)]
41
42 const float det = A(1, 1) * (A(3, 3) * A(2, 2) - A(3, 2) * A(2, 3))
43 - A(2, 1) * (A(3, 3) * A(1, 2) - A(3, 2) * A(1, 3))
44 + A(3, 1) * (A(2, 3) * A(1, 2) - A(2, 2) * A(1, 3));
45
46 const float epsilon = 1e-7f;
47 if(fabsf(det) < epsilon) return 1;
48
49 const float invDet = 1.f / det;
50
51 B(1, 1) = invDet * (A(3, 3) * A(2, 2) - A(3, 2) * A(2, 3));
52 B(1, 2) = -invDet * (A(3, 3) * A(1, 2) - A(3, 2) * A(1, 3));
53 B(1, 3) = invDet * (A(2, 3) * A(1, 2) - A(2, 2) * A(1, 3));
54
55 B(2, 1) = -invDet * (A(3, 3) * A(2, 1) - A(3, 1) * A(2, 3));
56 B(2, 2) = invDet * (A(3, 3) * A(1, 1) - A(3, 1) * A(1, 3));
57 B(2, 3) = -invDet * (A(2, 3) * A(1, 1) - A(2, 1) * A(1, 3));
58
59 B(3, 1) = invDet * (A(3, 2) * A(2, 1) - A(3, 1) * A(2, 2));
60 B(3, 2) = -invDet * (A(3, 2) * A(1, 1) - A(3, 1) * A(1, 2));
61 B(3, 3) = invDet * (A(2, 2) * A(1, 1) - A(2, 1) * A(1, 2));
62#undef A
63#undef B
64 return 0;
65}
66
67
68// transpose a padded 3x3 matrix
69static inline void transpose_3xSSE(const dt_colormatrix_t input, dt_colormatrix_t output)
70{
71 output[0][0] = input[0][0];
72 output[0][1] = input[1][0];
73 output[0][2] = input[2][0];
74 output[0][3] = 0.0f;
75
76 output[1][0] = input[0][1];
77 output[1][1] = input[1][1];
78 output[1][2] = input[2][1];
79 output[1][3] = 0.0f;
80
81 output[2][0] = input[0][2];
82 output[2][1] = input[1][2];
83 output[2][2] = input[2][2];
84 output[2][3] = 0.0f;
85
86 for_four_channels(c, aligned(output))
87 output[3][c] = 0.0f;
88}
89
90
91// transpose and pad a 3x3 matrix into the padded format optimized for vectorization
92static inline void transpose_3x3_to_3xSSE(const float input[9], dt_colormatrix_t output)
93{
94 output[0][0] = input[0];
95 output[0][1] = input[3];
96 output[0][2] = input[6];
97 output[0][3] = 0.0f;
98
99 output[1][0] = input[1];
100 output[1][1] = input[4];
101 output[1][2] = input[7];
102 output[1][3] = 0.0f;
103
104 output[2][0] = input[2];
105 output[2][1] = input[5];
106 output[2][2] = input[8];
107 output[2][3] = 0.0f;
108
109 for_four_channels(c, aligned(output))
110 output[3][c] = 0.0f;
111}
112
113// convert a 3x3 matrix into the padded format optimized for vectorization
114static inline void repack_double3x3_to_3xSSE(const double input[9], dt_colormatrix_t output)
115{
116 output[0][0] = input[0];
117 output[0][1] = input[1];
118 output[0][2] = input[2];
119 output[0][3] = 0.0f;
120
121 output[1][0] = input[3];
122 output[1][1] = input[4];
123 output[1][2] = input[5];
124 output[1][3] = 0.0f;
125
126 output[2][0] = input[6];
127 output[2][1] = input[7];
128 output[2][2] = input[8];
129 output[2][3] = 0.0f;
130
131 for(size_t c = 0; c < 4; c++)
132 output[3][c] = 0.0f;
133}
134
135// convert a 3x3 matrix into the padded format optimized for vectorization
136static inline void pack_3xSSE_to_3x3(const dt_colormatrix_t input, float output[9])
137{
138 output[0] = input[0][0];
139 output[1] = input[0][1];
140 output[2] = input[0][2];
141 output[3] = input[1][0];
142 output[4] = input[1][1];
143 output[5] = input[1][2];
144 output[6] = input[2][0];
145 output[7] = input[2][1];
146 output[8] = input[2][2];
147}
148
149// convert a 3x3 matrix into 3 padded float4 rows: [m00 m01 m02 0, ...]
150static inline void pack_3xSSE_to_3x4(const dt_colormatrix_t input, float output[12])
151{
152 output[0] = input[0][0];
153 output[1] = input[0][1];
154 output[2] = input[0][2];
155 output[3] = 0.0f;
156 output[4] = input[1][0];
157 output[5] = input[1][1];
158 output[6] = input[1][2];
159 output[7] = 0.0f;
160 output[8] = input[2][0];
161 output[9] = input[2][1];
162 output[10] = input[2][2];
163 output[11] = 0.0f;
164}
165
166// vectorized multiplication of padded 3x3 matrices
167static inline void dt_colormatrix_mul(dt_colormatrix_t dst, const dt_colormatrix_t m1, const dt_colormatrix_t m2)
168{
169 for(int k = 0; k < 3; ++k)
170 {
171 dt_aligned_pixel_t sum = { 0.0f };
173 {
174 for(int j = 0; j < 3; j++)
175 sum[i] += m1[k][j] * m2[j][i];
176 dst[k][i] = sum[i];
177 }
178 }
179}
180
181// multiply two padded 3x3 matrices
182// dest needs to be different from m1 and m2
183// dest = m1 * m2 in this order
184// TODO: see if that refactors with the previous
186static inline void mat3SSEmul(dt_colormatrix_t dest, const dt_colormatrix_t m1, const dt_colormatrix_t m2)
187{
188 for(int k = 0; k < 3; k++)
189 {
190 for(int i = 0; i < 3; i++)
191 {
192 float x = 0.0f;
193 for(int j = 0; j < 3; j++)
194 x += m1[k][j] * m2[j][i];
195 dest[k][i] = x;
196 }
197 }
198}
199
200__OMP_DECLARE_SIMD__(uniform(M) aligned(M:64) aligned(v_in, v_out:16))
201static inline void dot_product(const dt_aligned_pixel_t v_in, const dt_colormatrix_t M, dt_aligned_pixel_t v_out)
202{
203 // specialized 3x4 dot products of 4x1 RGB-alpha pixels
204 __OMP_SIMD__(aligned(M:64) aligned(v_in, v_out:16))
205 for(size_t i = 0; i < 3; ++i) v_out[i] = scalar_product(v_in, M[i]);
206}
207
208#endif // DT_MATH_MATRICES_H
209
210// clang-format off
211// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
212// vim: shiftwidth=2 expandtab tabstop=2 cindent
213// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
214// clang-format on
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
static const float x
float *const restrict const size_t k
#define B(y, x)
#define A(y, x)
static void transpose_3x3_to_3xSSE(const float input[9], dt_colormatrix_t output)
Definition matrices.h:92
const dt_colormatrix_t dt_aligned_pixel_t v_out
Definition matrices.h:202
float DT_ALIGNED_ARRAY dt_colormatrix_t[4][4]
Definition matrices.h:34
static void mat3SSEmul(dt_colormatrix_t dest, const dt_colormatrix_t m1, const dt_colormatrix_t m2)
Definition matrices.h:186
static void transpose_3xSSE(const dt_colormatrix_t input, dt_colormatrix_t output)
Definition matrices.h:69
static void pack_3xSSE_to_3x4(const dt_colormatrix_t input, float output[12])
Definition matrices.h:150
static void dt_colormatrix_mul(dt_colormatrix_t dst, const dt_colormatrix_t m1, const dt_colormatrix_t m2)
Definition matrices.h:167
static int mat3SSEinv(dt_colormatrix_t dst, const dt_colormatrix_t src)
Definition matrices.h:37
static void repack_double3x3_to_3xSSE(const double input[9], dt_colormatrix_t output)
Definition matrices.h:114
static void pack_3xSSE_to_3x3(const dt_colormatrix_t input, float output[9])
Definition matrices.h:136
const dt_colormatrix_t M
Definition matrices.h:201
#define DT_ALIGNED_ARRAY
Align an object on a cacheline boundary, so AVX2 can load it whole.
Definition mem_alloc.h:80
#define __OMP_SIMD__(...)
Definition openmp.h:99
#define __OMP_DECLARE_SIMD__(...)
Definition openmp.h:100
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
Definition simd.h:53
#define for_each_channel(_var,...)
Definition simd.h:87
#define for_four_channels(_var,...)
Definition simd.h:89