Cycles: principled absorption color now has more effect at lower values.
[blender.git] / intern / cycles / util / util_math_float3.h
1 /*
2  * Copyright 2011-2017 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef __UTIL_MATH_FLOAT3_H__
18 #define __UTIL_MATH_FLOAT3_H__
19
20 #ifndef __UTIL_MATH_H__
21 #  error "Do not include this file directly, include util_types.h instead."
22 #endif
23
24 CCL_NAMESPACE_BEGIN
25
26 /*******************************************************************************
27  * Declaration.
28  */
29
30 #ifndef __KERNEL_OPENCL__
31 ccl_device_inline float3 operator-(const float3& a);
32 ccl_device_inline float3 operator*(const float3& a, const float3& b);
33 ccl_device_inline float3 operator*(const float3& a, const float f);
34 ccl_device_inline float3 operator*(const float f, const float3& a);
35 ccl_device_inline float3 operator/(const float f, const float3& a);
36 ccl_device_inline float3 operator/(const float3& a, const float f);
37 ccl_device_inline float3 operator/(const float3& a, const float3& b);
38 ccl_device_inline float3 operator+(const float3& a, const float3& b);
39 ccl_device_inline float3 operator-(const float3& a, const float3& b);
40 ccl_device_inline float3 operator+=(float3& a, const float3& b);
41 ccl_device_inline float3 operator-=(float3& a, const float3& b);
42 ccl_device_inline float3 operator*=(float3& a, const float3& b);
43 ccl_device_inline float3 operator*=(float3& a, float f);
44 ccl_device_inline float3 operator/=(float3& a, const float3& b);
45 ccl_device_inline float3 operator/=(float3& a, float f);
46
47 ccl_device_inline bool operator==(const float3& a, const float3& b);
48 ccl_device_inline bool operator!=(const float3& a, const float3& b);
49
50 ccl_device_inline float dot(const float3& a, const float3& b);
51 ccl_device_inline float dot_xy(const float3& a, const float3& b);
52 ccl_device_inline float3 cross(const float3& a, const float3& b);
53 ccl_device_inline float3 normalize(const float3& a);
54 ccl_device_inline float3 min(const float3& a, const float3& b);
55 ccl_device_inline float3 max(const float3& a, const float3& b);
56 ccl_device_inline float3 clamp(const float3& a, const float3& mn, const float3& mx);
57 ccl_device_inline float3 fabs(const float3& a);
58 ccl_device_inline float3 mix(const float3& a, const float3& b, float t);
59 ccl_device_inline float3 rcp(const float3& a);
60 ccl_device_inline float3 sqrt(const float3& a);
61 #endif  /* !__KERNEL_OPENCL__ */
62
63 ccl_device_inline float min3(float3 a);
64 ccl_device_inline float max3(float3 a);
65 ccl_device_inline float len(const float3 a);
66 ccl_device_inline float len_squared(const float3 a);
67
68 ccl_device_inline float3 saturate3(float3 a);
69 ccl_device_inline float3 safe_normalize(const float3 a);
70 ccl_device_inline float3 normalize_len(const float3 a, float *t);;
71 ccl_device_inline float3 safe_normalize_len(const float3 a, float *t);
72 ccl_device_inline float3 interp(float3 a, float3 b, float t);
73
74 ccl_device_inline bool is_zero(const float3 a);
75 ccl_device_inline float reduce_add(const float3 a);
76 ccl_device_inline float average(const float3 a);
77 ccl_device_inline bool isequal_float3(const float3 a, const float3 b);
78
79 /*******************************************************************************
80  * Definition.
81  */
82
83 #ifndef __KERNEL_OPENCL__
84 ccl_device_inline float3 operator-(const float3& a)
85 {
86 #ifdef __KERNEL_SSE__
87         return float3(_mm_xor_ps(a.m128, _mm_castsi128_ps(_mm_set1_epi32(0x80000000))));
88 #else
89         return make_float3(-a.x, -a.y, -a.z);
90 #endif
91 }
92
93 ccl_device_inline float3 operator*(const float3& a, const float3& b)
94 {
95 #ifdef __KERNEL_SSE__
96         return float3(_mm_mul_ps(a.m128,b.m128));
97 #else
98         return make_float3(a.x*b.x, a.y*b.y, a.z*b.z);
99 #endif
100 }
101
102 ccl_device_inline float3 operator*(const float3& a, const float f)
103 {
104 #ifdef __KERNEL_SSE__
105         return float3(_mm_mul_ps(a.m128,_mm_set1_ps(f)));
106 #else
107         return make_float3(a.x*f, a.y*f, a.z*f);
108 #endif
109 }
110
111 ccl_device_inline float3 operator*(const float f, const float3& a)
112 {
113 #if defined(__KERNEL_SSE__)
114         return float3(_mm_mul_ps(_mm_set1_ps(f), a.m128));
115 #else
116         return make_float3(a.x*f, a.y*f, a.z*f);
117 #endif
118 }
119
120 ccl_device_inline float3 operator/(const float f, const float3& a)
121 {
122 #if defined(__KERNEL_SSE__)
123         return float3(_mm_div_ps(_mm_set1_ps(f), a.m128));
124 #else
125         return make_float3(f / a.x, f / a.y, f / a.z);
126 #endif
127 }
128
129 ccl_device_inline float3 operator/(const float3& a, const float f)
130 {
131         float invf = 1.0f/f;
132         return a * invf;
133 }
134
135 ccl_device_inline float3 operator/(const float3& a, const float3& b)
136 {
137 #if defined(__KERNEL_SSE__)
138         return float3(_mm_div_ps(a.m128, b.m128));
139 #else
140         return make_float3(a.x / b.x, a.y / b.y, a.z / b.z);
141 #endif
142 }
143
144 ccl_device_inline float3 operator+(const float3& a, const float3& b)
145 {
146 #ifdef __KERNEL_SSE__
147         return float3(_mm_add_ps(a.m128, b.m128));
148 #else
149         return make_float3(a.x + b.x, a.y + b.y, a.z + b.z);
150 #endif
151 }
152
153 ccl_device_inline float3 operator-(const float3& a, const float3& b)
154 {
155 #ifdef __KERNEL_SSE__
156         return float3(_mm_sub_ps(a.m128, b.m128));
157 #else
158         return make_float3(a.x - b.x, a.y - b.y, a.z - b.z);
159 #endif
160 }
161
162 ccl_device_inline float3 operator+=(float3& a, const float3& b)
163 {
164         return a = a + b;
165 }
166
167 ccl_device_inline float3 operator-=(float3& a, const float3& b)
168 {
169         return a = a - b;
170 }
171
172 ccl_device_inline float3 operator*=(float3& a, const float3& b)
173 {
174         return a = a * b;
175 }
176
177 ccl_device_inline float3 operator*=(float3& a, float f)
178 {
179         return a = a * f;
180 }
181
182 ccl_device_inline float3 operator/=(float3& a, const float3& b)
183 {
184         return a = a / b;
185 }
186
187 ccl_device_inline float3 operator/=(float3& a, float f)
188 {
189         float invf = 1.0f/f;
190         return a = a * invf;
191 }
192
193 ccl_device_inline bool operator==(const float3& a, const float3& b)
194 {
195 #ifdef __KERNEL_SSE__
196         return (_mm_movemask_ps(_mm_cmpeq_ps(a.m128, b.m128)) & 7) == 7;
197 #else
198         return (a.x == b.x && a.y == b.y && a.z == b.z);
199 #endif
200 }
201
202 ccl_device_inline bool operator!=(const float3& a, const float3& b)
203 {
204         return !(a == b);
205 }
206
207 ccl_device_inline float dot(const float3& a, const float3& b)
208 {
209 #if defined(__KERNEL_SSE41__) && defined(__KERNEL_SSE__)
210         return _mm_cvtss_f32(_mm_dp_ps(a, b, 0x7F));
211 #else
212         return a.x*b.x + a.y*b.y + a.z*b.z;
213 #endif
214 }
215
216 ccl_device_inline float dot_xy(const float3& a, const float3& b)
217 {
218 #if defined(__KERNEL_SSE41__) && defined(__KERNEL_SSE__)
219         return _mm_cvtss_f32(_mm_hadd_ps(_mm_mul_ps(a,b),b));
220 #else
221         return a.x*b.x + a.y*b.y;
222 #endif
223 }
224
225 ccl_device_inline float3 cross(const float3& a, const float3& b)
226 {
227         float3 r = make_float3(a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x);
228         return r;
229 }
230
231 ccl_device_inline float3 normalize(const float3& a)
232 {
233 #if defined(__KERNEL_SSE41__) && defined(__KERNEL_SSE__)
234         __m128 norm = _mm_sqrt_ps(_mm_dp_ps(a.m128, a.m128, 0x7F));
235         return float3(_mm_div_ps(a.m128, norm));
236 #else
237         return a/len(a);
238 #endif
239 }
240
241 ccl_device_inline float3 min(const float3& a, const float3& b)
242 {
243 #ifdef __KERNEL_SSE__
244         return float3(_mm_min_ps(a.m128, b.m128));
245 #else
246         return make_float3(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z));
247 #endif
248 }
249
250 ccl_device_inline float3 max(const float3& a, const float3& b)
251 {
252 #ifdef __KERNEL_SSE__
253         return float3(_mm_max_ps(a.m128, b.m128));
254 #else
255         return make_float3(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z));
256 #endif
257 }
258
259 ccl_device_inline float3 clamp(const float3& a, const float3& mn, const float3& mx)
260 {
261         return min(max(a, mn), mx);
262 }
263
264 ccl_device_inline float3 fabs(const float3& a)
265 {
266 #ifdef __KERNEL_SSE__
267         __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff));
268         return float3(_mm_and_ps(a.m128, mask));
269 #else
270         return make_float3(fabsf(a.x), fabsf(a.y), fabsf(a.z));
271 #endif
272 }
273
274 ccl_device_inline float3 sqrt(const float3& a)
275 {
276 #ifdef __KERNEL_SSE__
277         return float3(_mm_sqrt_ps(a));
278 #else
279         return make_float3(sqrtf(a.x), sqrtf(a.y), sqrtf(a.z));
280 #endif
281 }
282
283 ccl_device_inline float3 mix(const float3& a, const float3& b, float t)
284 {
285         return a + t*(b - a);
286 }
287
288 ccl_device_inline float3 rcp(const float3& a)
289 {
290 #ifdef __KERNEL_SSE__
291         /* Don't use _mm_rcp_ps due to poor precision. */
292         return float3(_mm_div_ps(_mm_set_ps1(1.0f), a.m128));
293 #else
294         return make_float3(1.0f/a.x, 1.0f/a.y, 1.0f/a.z);
295 #endif
296 }
297 #endif  /* !__KERNEL_OPENCL__ */
298
299 ccl_device_inline float min3(float3 a)
300 {
301         return min(min(a.x, a.y), a.z);
302 }
303
304 ccl_device_inline float max3(float3 a)
305 {
306         return max(max(a.x, a.y), a.z);
307 }
308
309 ccl_device_inline float len(const float3 a)
310 {
311 #if defined(__KERNEL_SSE41__) && defined(__KERNEL_SSE__)
312         return _mm_cvtss_f32(_mm_sqrt_ss(_mm_dp_ps(a.m128, a.m128, 0x7F)));
313 #else
314         return sqrtf(dot(a, a));
315 #endif
316 }
317
318 ccl_device_inline float len_squared(const float3 a)
319 {
320         return dot(a, a);
321 }
322
323 ccl_device_inline float3 saturate3(float3 a)
324 {
325         return make_float3(saturate(a.x), saturate(a.y), saturate(a.z));
326 }
327
328 ccl_device_inline float3 normalize_len(const float3 a, float *t)
329 {
330         *t = len(a);
331         float x = 1.0f / *t;
332         return a*x;
333 }
334
335 ccl_device_inline float3 safe_normalize(const float3 a)
336 {
337         float t = len(a);
338         return (t != 0.0f)? a * (1.0f/t) : a;
339 }
340
341 ccl_device_inline float3 safe_normalize_len(const float3 a, float *t)
342 {
343         *t = len(a);
344         return (*t != 0.0f)? a/(*t): a;
345 }
346
347 ccl_device_inline float3 interp(float3 a, float3 b, float t)
348 {
349         return a + t*(b - a);
350 }
351
352 ccl_device_inline bool is_zero(const float3 a)
353 {
354 #ifdef __KERNEL_SSE__
355         return a == make_float3(0.0f);
356 #else
357         return (a.x == 0.0f && a.y == 0.0f && a.z == 0.0f);
358 #endif
359 }
360
361 ccl_device_inline float reduce_add(const float3 a)
362 {
363         return (a.x + a.y + a.z);
364 }
365
366 ccl_device_inline float average(const float3 a)
367 {
368         return reduce_add(a)*(1.0f/3.0f);
369 }
370
371 ccl_device_inline bool isequal_float3(const float3 a, const float3 b)
372 {
373 #ifdef __KERNEL_OPENCL__
374         return all(a == b);
375 #else
376         return a == b;
377 #endif
378 }
379
380 ccl_device_inline bool isfinite3_safe(float3 v)
381 {
382         return isfinite_safe(v.x) && isfinite_safe(v.y) && isfinite_safe(v.z);
383 }
384
385 ccl_device_inline float3 ensure_finite3(float3 v)
386 {
387         if(!isfinite_safe(v.x)) v.x = 0.0f;
388         if(!isfinite_safe(v.y)) v.y = 0.0f;
389         if(!isfinite_safe(v.z)) v.z = 0.0f;
390         return v;
391 }
392
393 CCL_NAMESPACE_END
394
395 #endif /* __UTIL_MATH_FLOAT3_H__ */