Blender V4.3
BLI_math_vector_unroll.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
11/*
12 * Macros that implement an arithmetic operator or a math function
13 * on vector types. Only for internal BLI vector math library use!
14 *
15 * Just doing per-element loop is enough for correct result, however
16 * in debug / non-optimized builds (or even release builds with
17 * assertions enabled), these result in very sub-optimal generated code.
18 * So instead of the loop, also explicitly implement the operator for
19 * common vector sizes (4, 3, 2).
20 */
21
22/* Binary operator `op` on vectors `a` and `b`. */
23#define BLI_UNROLL_MATH_VEC_OP_VEC_VEC(op, a, b) \
24 if constexpr (Size == 4) { \
25 return VecBase<T, Size>(a.x op b.x, a.y op b.y, a.z op b.z, a.w op b.w); \
26 } \
27 else if constexpr (Size == 3) { \
28 return VecBase<T, Size>(a.x op b.x, a.y op b.y, a.z op b.z); \
29 } \
30 else if constexpr (Size == 2) { \
31 return VecBase<T, Size>(a.x op b.x, a.y op b.y); \
32 } \
33 else { \
34 VecBase<T, Size> result; \
35 for (int i = 0; i < Size; i++) { \
36 result[i] = a[i] op b[i]; \
37 } \
38 return result; \
39 }
40
41/* Binary function `op` on vectors `a` and `b`. */
42#define BLI_UNROLL_MATH_VEC_FUNC_VEC_VEC(op, a, b) \
43 if constexpr (Size == 4) { \
44 return VecBase<T, Size>(op(a.x, b.x), op(a.y, b.y), op(a.z, b.z), op(a.w, b.w)); \
45 } \
46 else if constexpr (Size == 3) { \
47 return VecBase<T, Size>(op(a.x, b.x), op(a.y, b.y), op(a.z, b.z)); \
48 } \
49 else if constexpr (Size == 2) { \
50 return VecBase<T, Size>(op(a.x, b.x), op(a.y, b.y)); \
51 } \
52 else { \
53 VecBase<T, Size> result; \
54 for (int i = 0; i < Size; i++) { \
55 result[i] = op(a[i], b[i]); \
56 } \
57 return result; \
58 }
59
60/* Unary operator or function `op` on vector `a`. */
61#define BLI_UNROLL_MATH_VEC_OP_VEC(op, a) \
62 if constexpr (Size == 4) { \
63 return VecBase<T, Size>(op(a.x), op(a.y), op(a.z), op(a.w)); \
64 } \
65 else if constexpr (Size == 3) { \
66 return VecBase<T, Size>(op(a.x), op(a.y), op(a.z)); \
67 } \
68 else if constexpr (Size == 2) { \
69 return VecBase<T, Size>(op(a.x), op(a.y)); \
70 } \
71 else { \
72 VecBase<T, Size> result; \
73 for (int i = 0; i < Size; i++) { \
74 result[i] = op(a[i]); \
75 } \
76 return result; \
77 }
78
79/* Binary operator `op` on scalar `a` and vector `b`. */
80#define BLI_UNROLL_MATH_VEC_OP_SCALAR_VEC(op, a, b) \
81 if constexpr (Size == 4) { \
82 return VecBase<T, Size>(a op b.x, a op b.y, a op b.z, a op b.w); \
83 } \
84 else if constexpr (Size == 3) { \
85 return VecBase<T, Size>(a op b.x, a op b.y, a op b.z); \
86 } \
87 else if constexpr (Size == 2) { \
88 return VecBase<T, Size>(a op b.x, a op b.y); \
89 } \
90 else { \
91 VecBase<T, Size> result; \
92 for (int i = 0; i < Size; i++) { \
93 result[i] = a op b[i]; \
94 } \
95 return result; \
96 }
97
98/* Binary operator `op` on vector `a` and scalar `b`. */
99#define BLI_UNROLL_MATH_VEC_OP_VEC_SCALAR(op, a, b) \
100 if constexpr (Size == 4) { \
101 return VecBase<T, Size>(a.x op b, a.y op b, a.z op b, a.w op b); \
102 } \
103 else if constexpr (Size == 3) { \
104 return VecBase<T, Size>(a.x op b, a.y op b, a.z op b); \
105 } \
106 else if constexpr (Size == 2) { \
107 return VecBase<T, Size>(a.x op b, a.y op b); \
108 } \
109 else { \
110 VecBase<T, Size> result; \
111 for (int i = 0; i < Size; i++) { \
112 result[i] = a[i] op b; \
113 } \
114 return result; \
115 }
116
117/* Assignment-like operator `op` with vector argument `b`. */
118#define BLI_UNROLL_MATH_VEC_OP_ASSIGN_VEC(op, b) \
119 if constexpr (Size == 4) { \
120 this->x op b.x; \
121 this->y op b.y; \
122 this->z op b.z; \
123 this->w op b.w; \
124 } \
125 else if constexpr (Size == 3) { \
126 this->x op b.x; \
127 this->y op b.y; \
128 this->z op b.z; \
129 } \
130 else if constexpr (Size == 2) { \
131 this->x op b.x; \
132 this->y op b.y; \
133 } \
134 else { \
135 for (int i = 0; i < Size; i++) { \
136 (*this)[i] op b[i]; \
137 } \
138 } \
139 return *this
140
141/* Assignment-like operator `op` with scalar argument `b`. */
142#define BLI_UNROLL_MATH_VEC_OP_ASSIGN_SCALAR(op, b) \
143 if constexpr (Size == 4) { \
144 this->x op b; \
145 this->y op b; \
146 this->z op b; \
147 this->w op b; \
148 } \
149 else if constexpr (Size == 3) { \
150 this->x op b; \
151 this->y op b; \
152 this->z op b; \
153 } \
154 else if constexpr (Size == 2) { \
155 this->x op b; \
156 this->y op b; \
157 } \
158 else { \
159 for (int i = 0; i < Size; i++) { \
160 (*this)[i] op b; \
161 } \
162 } \
163 return *this
164
165/* Initialization from a pointer or indexed argument `a`. */
166#define BLI_UNROLL_MATH_VEC_OP_INIT_INDEX(a) \
167 if constexpr (Size == 4) { \
168 this->x = a[0]; \
169 this->y = a[1]; \
170 this->z = a[2]; \
171 this->w = a[3]; \
172 } \
173 else if constexpr (Size == 3) { \
174 this->x = a[0]; \
175 this->y = a[1]; \
176 this->z = a[2]; \
177 } \
178 else if constexpr (Size == 2) { \
179 this->x = a[0]; \
180 this->y = a[1]; \
181 } \
182 else { \
183 for (int i = 0; i < Size; i++) { \
184 (*this)[i] = a[i]; \
185 } \
186 }
187
188/* Initialization from another vector `a`. */
189#define BLI_UNROLL_MATH_VEC_OP_INIT_VECTOR(a) \
190 if constexpr (Size == 4) { \
191 this->x = T(a.x); \
192 this->y = T(a.y); \
193 this->z = T(a.z); \
194 this->w = T(a.w); \
195 } \
196 else if constexpr (Size == 3) { \
197 this->x = T(a.x); \
198 this->y = T(a.y); \
199 this->z = T(a.z); \
200 } \
201 else if constexpr (Size == 2) { \
202 this->x = T(a.x); \
203 this->y = T(a.y); \
204 } \
205 else { \
206 for (int i = 0; i < Size; i++) { \
207 (*this)[i] = T(a[i]); \
208 } \
209 }