Merging r46096 through r46110 from trunk into soc-2011-tomato
[blender-staging.git] / intern / cycles / util / util_math.h
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18
19 #ifndef __UTIL_MATH_H__
20 #define __UTIL_MATH_H__
21
22 /* Math
23  *
24  * Basic math functions on scalar and vector types. This header is used by
25  * both the kernel code when compiled as C++, and other C++ non-kernel code. */
26
27 #ifndef __KERNEL_OPENCL__
28
29 #define _USE_MATH_DEFINES
30
31 #include <float.h>
32 #include <math.h>
33 #include <stdio.h>
34
35 #endif
36
37 #include "util_types.h"
38
39 CCL_NAMESPACE_BEGIN
40
41 /* Float Pi variations */
42
43 #ifndef M_PI_F
44 #define M_PI_F          ((float)3.14159265358979323846264338327950288)
45 #endif
46 #ifndef M_PI_2_F
47 #define M_PI_2_F        ((float)1.57079632679489661923132169163975144)
48 #endif
49 #ifndef M_PI_4_F
50 #define M_PI_4_F        ((float)0.785398163397448309615660845819875721)
51 #endif
52 #ifndef M_1_PI_F
53 #define M_1_PI_F        ((float)0.318309886183790671537767526745028724)
54 #endif
55 #ifndef M_2_PI_F
56 #define M_2_PI_F        ((float)0.636619772367581343075535053490057448)
57 #endif
58
59 /* Scalar */
60
61 #ifdef _WIN32
62
63 #ifndef __KERNEL_GPU__
64
65 #if(!defined(FREE_WINDOWS))
66 #define copysignf(x, y) ((float)_copysign(x, y))
67 #define hypotf(x, y) _hypotf(x, y)
68 #define isnan(x) _isnan(x)
69 #define isfinite(x) _finite(x)
70 #endif
71
72 #endif
73
74 #ifndef __KERNEL_OPENCL__
75
76 __device_inline float fmaxf(float a, float b)
77 {
78         return (a > b)? a: b;
79 }
80
81 __device_inline float fminf(float a, float b)
82 {
83         return (a < b)? a: b;
84 }
85
86 #endif
87
88 #endif
89
90 #ifndef __KERNEL_GPU__
91
92 __device_inline int max(int a, int b)
93 {
94         return (a > b)? a: b;
95 }
96
97 __device_inline int min(int a, int b)
98 {
99         return (a < b)? a: b;
100 }
101
102 __device_inline float max(float a, float b)
103 {
104         return (a > b)? a: b;
105 }
106
107 __device_inline float min(float a, float b)
108 {
109         return (a < b)? a: b;
110 }
111
112 __device_inline double max(double a, double b)
113 {
114         return (a > b)? a: b;
115 }
116
117 __device_inline double min(double a, double b)
118 {
119         return (a < b)? a: b;
120 }
121
122 #endif
123
124 __device_inline float min4(float a, float b, float c, float d)
125 {
126         return min(min(a, b), min(c, d));
127 }
128
129 __device_inline float max4(float a, float b, float c, float d)
130 {
131         return max(max(a, b), max(c, d));
132 }
133
134 #ifndef __KERNEL_OPENCL__
135
136 __device_inline int clamp(int a, int mn, int mx)
137 {
138         return min(max(a, mn), mx);
139 }
140
141 __device_inline float clamp(float a, float mn, float mx)
142 {
143         return min(max(a, mn), mx);
144 }
145
146 #endif
147
148 __device_inline float signf(float f)
149 {
150         return (f < 0.0f)? -1.0f: 1.0f;
151 }
152
153 __device_inline float nonzerof(float f, float eps)
154 {
155         if(fabsf(f) < eps)
156                 return signf(f)*eps;
157         else
158                 return f;
159 }
160
161 /* Float2 Vector */
162
163 #ifndef __KERNEL_OPENCL__
164
165 __device_inline bool is_zero(const float2 a)
166 {
167         return (a.x == 0.0f && a.y == 0.0f);
168 }
169
170 #endif
171
172 #ifndef __KERNEL_OPENCL__
173
174 __device_inline float average(const float2 a)
175 {
176         return (a.x + a.y)*(1.0f/2.0f);
177 }
178
179 #endif
180
181 #ifndef __KERNEL_OPENCL__
182
183 __device_inline float2 operator-(const float2 a)
184 {
185         return make_float2(-a.x, -a.y);
186 }
187
188 __device_inline float2 operator*(const float2 a, const float2 b)
189 {
190         return make_float2(a.x*b.x, a.y*b.y);
191 }
192
193 __device_inline float2 operator*(const float2 a, float f)
194 {
195         return make_float2(a.x*f, a.y*f);
196 }
197
198 __device_inline float2 operator*(float f, const float2 a)
199 {
200         return make_float2(a.x*f, a.y*f);
201 }
202
203 __device_inline float2 operator/(float f, const float2 a)
204 {
205         return make_float2(f/a.x, f/a.y);
206 }
207
208 __device_inline float2 operator/(const float2 a, float f)
209 {
210         float invf = 1.0f/f;
211         return make_float2(a.x*invf, a.y*invf);
212 }
213
214 __device_inline float2 operator/(const float2 a, const float2 b)
215 {
216         return make_float2(a.x/b.x, a.y/b.y);
217 }
218
219 __device_inline float2 operator+(const float2 a, const float2 b)
220 {
221         return make_float2(a.x+b.x, a.y+b.y);
222 }
223
224 __device_inline float2 operator-(const float2 a, const float2 b)
225 {
226         return make_float2(a.x-b.x, a.y-b.y);
227 }
228
229 __device_inline float2 operator+=(float2& a, const float2 b)
230 {
231         return a = a + b;
232 }
233
234 __device_inline float2 operator*=(float2& a, const float2 b)
235 {
236         return a = a * b;
237 }
238
239 __device_inline float2 operator*=(float2& a, float f)
240 {
241         return a = a * f;
242 }
243
244 __device_inline float2 operator/=(float2& a, const float2 b)
245 {
246         return a = a / b;
247 }
248
249 __device_inline float2 operator/=(float2& a, float f)
250 {
251         float invf = 1.0f/f;
252         return a = a * invf;
253 }
254
255
256 __device_inline float dot(const float2 a, const float2 b)
257 {
258         return a.x*b.x + a.y*b.y;
259 }
260
261 __device_inline float cross(const float2 a, const float2 b)
262 {
263         return (a.x*b.y - a.y*b.x);
264 }
265
266 #endif
267
268 #ifndef __KERNEL_OPENCL__
269
270 __device_inline float len(const float2 a)
271 {
272         return sqrtf(dot(a, a));
273 }
274
275 __device_inline float2 normalize(const float2 a)
276 {
277         return a/len(a);
278 }
279
280 __device_inline float2 normalize_len(const float2 a, float *t)
281 {
282         *t = len(a);
283         return a/(*t);
284 }
285
286 __device_inline bool operator==(const float2 a, const float2 b)
287 {
288         return (a.x == b.x && a.y == b.y);
289 }
290
291 __device_inline bool operator!=(const float2 a, const float2 b)
292 {
293         return !(a == b);
294 }
295
296 __device_inline float2 min(float2 a, float2 b)
297 {
298         return make_float2(min(a.x, b.x), min(a.y, b.y));
299 }
300
301 __device_inline float2 max(float2 a, float2 b)
302 {
303         return make_float2(max(a.x, b.x), max(a.y, b.y));
304 }
305
306 __device_inline float2 clamp(float2 a, float2 mn, float2 mx)
307 {
308         return min(max(a, mn), mx);
309 }
310
311 __device_inline float2 fabs(float2 a)
312 {
313         return make_float2(fabsf(a.x), fabsf(a.y));
314 }
315
316 __device_inline float2 as_float2(const float4 a)
317 {
318         return make_float2(a.x, a.y);
319 }
320
321 #endif
322
323 #ifndef __KERNEL_GPU__
324
325 __device_inline void print_float2(const char *label, const float2& a)
326 {
327         printf("%s: %.8f %.8f\n", label, a.x, a.y);
328 }
329
330 #endif
331
332 #ifndef __KERNEL_OPENCL__
333
334 __device_inline float2 interp(float2 a, float2 b, float t)
335 {
336         return a + t*(b - a);
337 }
338
339 #endif
340
341 /* Float3 Vector */
342
343 #ifndef __KERNEL_OPENCL__
344
345 __device_inline float3 operator-(const float3 a)
346 {
347         return make_float3(-a.x, -a.y, -a.z);
348 }
349
350 __device_inline float3 operator*(const float3 a, const float3 b)
351 {
352         return make_float3(a.x*b.x, a.y*b.y, a.z*b.z);
353 }
354
355 __device_inline float3 operator*(const float3 a, float f)
356 {
357         return make_float3(a.x*f, a.y*f, a.z*f);
358 }
359
360 __device_inline float3 operator*(float f, const float3 a)
361 {
362         return make_float3(a.x*f, a.y*f, a.z*f);
363 }
364
365 __device_inline float3 operator/(float f, const float3 a)
366 {
367         return make_float3(f/a.x, f/a.y, f/a.z);
368 }
369
370 __device_inline float3 operator/(const float3 a, float f)
371 {
372         float invf = 1.0f/f;
373         return make_float3(a.x*invf, a.y*invf, a.z*invf);
374 }
375
376 __device_inline float3 operator/(const float3 a, const float3 b)
377 {
378         return make_float3(a.x/b.x, a.y/b.y, a.z/b.z);
379 }
380
381 __device_inline float3 operator+(const float3 a, const float3 b)
382 {
383         return make_float3(a.x+b.x, a.y+b.y, a.z+b.z);
384 }
385
386 __device_inline float3 operator-(const float3 a, const float3 b)
387 {
388         return make_float3(a.x-b.x, a.y-b.y, a.z-b.z);
389 }
390
391 __device_inline float3 operator+=(float3& a, const float3 b)
392 {
393         return a = a + b;
394 }
395
396 __device_inline float3 operator*=(float3& a, const float3 b)
397 {
398         return a = a * b;
399 }
400
401 __device_inline float3 operator*=(float3& a, float f)
402 {
403         return a = a * f;
404 }
405
406 __device_inline float3 operator/=(float3& a, const float3 b)
407 {
408         return a = a / b;
409 }
410
411 __device_inline float3 operator/=(float3& a, float f)
412 {
413         float invf = 1.0f/f;
414         return a = a * invf;
415 }
416
417 __device_inline float dot(const float3 a, const float3 b)
418 {
419         return a.x*b.x + a.y*b.y + a.z*b.z;
420 }
421
422 __device_inline float3 cross(const float3 a, const float3 b)
423 {
424         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);
425         return r;
426 }
427
428 #endif
429
430 __device_inline float len(const float3 a)
431 {
432         return sqrtf(dot(a, a));
433 }
434
435 #ifndef __KERNEL_OPENCL__
436
437 __device_inline float3 normalize(const float3 a)
438 {
439         return a/len(a);
440 }
441
442 #endif
443
444 __device_inline float3 normalize_len(const float3 a, float *t)
445 {
446         *t = len(a);
447         return a/(*t);
448 }
449
450 #ifndef __KERNEL_OPENCL__
451
452 __device_inline bool operator==(const float3 a, const float3 b)
453 {
454 #ifdef __KERNEL_SSE__
455         return (_mm_movemask_ps(_mm_cmpeq_ps(a.m128, b.m128)) & 7) == 7;
456 #else
457         return (a.x == b.x && a.y == b.y && a.z == b.z);
458 #endif
459 }
460
461 __device_inline bool operator!=(const float3 a, const float3 b)
462 {
463         return !(a == b);
464 }
465
466 __device_inline float3 min(float3 a, float3 b)
467 {
468 #ifdef __KERNEL_SSE__
469         return _mm_min_ps(a.m128, b.m128);
470 #else
471         return make_float3(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z));
472 #endif
473 }
474
475 __device_inline float3 max(float3 a, float3 b)
476 {
477 #ifdef __KERNEL_SSE__
478         return _mm_max_ps(a.m128, b.m128);
479 #else
480         return make_float3(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z));
481 #endif
482 }
483
484 __device_inline float3 clamp(float3 a, float3 mn, float3 mx)
485 {
486         return min(max(a, mn), mx);
487 }
488
489 __device_inline float3 fabs(float3 a)
490 {
491 #ifdef __KERNEL_SSE__
492         __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff));
493         return _mm_and_ps(a.m128, mask);
494 #else
495         return make_float3(fabsf(a.x), fabsf(a.y), fabsf(a.z));
496 #endif
497 }
498
499 #endif
500
501 __device_inline float3 float4_to_float3(const float4 a)
502 {
503         return make_float3(a.x, a.y, a.z);
504 }
505
506 __device_inline float4 float3_to_float4(const float3 a)
507 {
508         return make_float4(a.x, a.y, a.z, 1.0f);
509 }
510
511 #ifndef __KERNEL_GPU__
512
513 __device_inline void print_float3(const char *label, const float3& a)
514 {
515         printf("%s: %.8f %.8f %.8f\n", label, a.x, a.y, a.z);
516 }
517
518 __device_inline float3 rcp(const float3& a)
519 {
520 #ifdef __KERNEL_SSE__
521         float4 r = _mm_rcp_ps(a.m128);
522         return _mm_sub_ps(_mm_add_ps(r, r), _mm_mul_ps(_mm_mul_ps(r, r), a));
523 #else
524         return make_float3(1.0f/a.x, 1.0f/a.y, 1.0f/a.z);
525 #endif
526 }
527
528 #endif
529
530 __device_inline float3 interp(float3 a, float3 b, float t)
531 {
532         return a + t*(b - a);
533 }
534
535 __device_inline bool is_zero(const float3 a)
536 {
537 #ifdef __KERNEL_SSE__
538         return a == make_float3(0.0f);
539 #else
540         return (a.x == 0.0f && a.y == 0.0f && a.z == 0.0f);
541 #endif
542 }
543
544 __device_inline float reduce_add(const float3 a)
545 {
546 #ifdef __KERNEL_SSE__
547         return (a.x + a.y + a.z);
548 #else
549         return (a.x + a.y + a.z);
550 #endif
551 }
552
553 __device_inline float average(const float3 a)
554 {
555         return reduce_add(a)*(1.0f/3.0f);
556 }
557
558 /* Float4 Vector */
559
560 #ifdef __KERNEL_SSE__
561
562 template<size_t index_0, size_t index_1, size_t index_2, size_t index_3> __forceinline const float4 shuffle(const float4& b)
563 {
564         return _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(b), _MM_SHUFFLE(index_3, index_2, index_1, index_0)));
565 }
566
567 template<> __forceinline const float4 shuffle<0, 0, 2, 2>(const float4& b)
568 {
569         return _mm_moveldup_ps(b);
570 }
571
572 template<> __forceinline const float4 shuffle<1, 1, 3, 3>(const float4& b)
573 {
574         return _mm_movehdup_ps(b);
575 }
576
577 template<> __forceinline const float4 shuffle<0, 1, 0, 1>(const float4& b)
578 {
579         return _mm_castpd_ps(_mm_movedup_pd(_mm_castps_pd(b)));
580 }
581
582 #endif
583
584 #ifndef __KERNEL_OPENCL__
585
586 __device_inline float4 operator-(const float4& a)
587 {
588 #ifdef __KERNEL_SSE__
589         __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x80000000));
590         return _mm_xor_ps(a.m128, mask);
591 #else
592         return make_float4(-a.x, -a.y, -a.z, -a.w);
593 #endif
594 }
595
596 __device_inline float4 operator*(const float4& a, const float4& b)
597 {
598 #ifdef __KERNEL_SSE__
599         return _mm_mul_ps(a.m128, b.m128);
600 #else
601         return make_float4(a.x*b.x, a.y*b.y, a.z*b.z, a.w*b.w);
602 #endif
603 }
604
605 __device_inline float4 operator*(const float4& a, float f)
606 {
607 #ifdef __KERNEL_SSE__
608         return a * make_float4(f);
609 #else
610         return make_float4(a.x*f, a.y*f, a.z*f, a.w*f);
611 #endif
612 }
613
614 __device_inline float4 operator*(float f, const float4& a)
615 {
616         return a * f;
617 }
618
619 __device_inline float4 rcp(const float4& a)
620 {
621 #ifdef __KERNEL_SSE__
622         float4 r = _mm_rcp_ps(a.m128);
623         return _mm_sub_ps(_mm_add_ps(r, r), _mm_mul_ps(_mm_mul_ps(r, r), a));
624 #else
625         return make_float4(1.0f/a.x, 1.0f/a.y, 1.0f/a.z, 1.0f/a.w);
626 #endif
627 }
628
629 __device_inline float4 operator/(const float4& a, float f)
630 {
631         return a * (1.0f/f);
632 }
633
634 __device_inline float4 operator/(const float4& a, const float4& b)
635 {
636 #ifdef __KERNEL_SSE__
637         return a * rcp(b);
638 #else
639         return make_float4(a.x/b.x, a.y/b.y, a.z/b.z, a.w/b.w);
640 #endif
641
642 }
643
644 __device_inline float4 operator+(const float4& a, const float4& b)
645 {
646 #ifdef __KERNEL_SSE__
647         return _mm_add_ps(a.m128, b.m128);
648 #else
649         return make_float4(a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w);
650 #endif
651 }
652
653 __device_inline float4 operator-(const float4& a, const float4& b)
654 {
655 #ifdef __KERNEL_SSE__
656         return _mm_sub_ps(a.m128, b.m128);
657 #else
658         return make_float4(a.x-b.x, a.y-b.y, a.z-b.z, a.w-b.w);
659 #endif
660 }
661
662 __device_inline float4 operator+=(float4& a, const float4& b)
663 {
664         return a = a + b;
665 }
666
667 __device_inline float4 operator*=(float4& a, const float4& b)
668 {
669         return a = a * b;
670 }
671
672 __device_inline float4 operator/=(float4& a, float f)
673 {
674         return a = a / f;
675 }
676
677 __device_inline int4 operator<(const float4& a, const float4& b)
678 {
679 #ifdef __KERNEL_SSE__
680         return _mm_cvtps_epi32(_mm_cmplt_ps(a.m128, b.m128)); /* todo: avoid cvt */
681 #else
682         return make_int4(a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w);
683 #endif
684 }
685
686 __device_inline int4 operator>=(float4 a, float4 b)
687 {
688 #ifdef __KERNEL_SSE__
689         return _mm_cvtps_epi32(_mm_cmpge_ps(a.m128, b.m128)); /* todo: avoid cvt */
690 #else
691         return make_int4(a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w);
692 #endif
693 }
694
695 __device_inline int4 operator<=(const float4& a, const float4& b)
696 {
697 #ifdef __KERNEL_SSE__
698         return _mm_cvtps_epi32(_mm_cmple_ps(a.m128, b.m128)); /* todo: avoid cvt */
699 #else
700         return make_int4(a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w);
701 #endif
702 }
703
704 __device_inline bool operator==(const float4 a, const float4 b)
705 {
706 #ifdef __KERNEL_SSE__
707         return (_mm_movemask_ps(_mm_cmpeq_ps(a.m128, b.m128)) & 15) == 15;
708 #else
709         return (a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w);
710 #endif
711 }
712
713 __device_inline float4 cross(const float4& a, const float4& b)
714 {
715 #ifdef __KERNEL_SSE__
716         return (shuffle<1,2,0,0>(a)*shuffle<2,0,1,0>(b)) - (shuffle<2,0,1,0>(a)*shuffle<1,2,0,0>(b));
717 #else
718         return make_float4(a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x, 0.0f);
719 #endif
720 }
721
722 __device_inline float4 min(float4 a, float4 b)
723 {
724 #ifdef __KERNEL_SSE__
725         return _mm_min_ps(a.m128, b.m128);
726 #else
727         return make_float4(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z), min(a.w, b.w));
728 #endif
729 }
730
731 __device_inline float4 max(float4 a, float4 b)
732 {
733 #ifdef __KERNEL_SSE__
734         return _mm_max_ps(a.m128, b.m128);
735 #else
736         return make_float4(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z), max(a.w, b.w));
737 #endif
738 }
739
740 #endif
741
742 #ifndef __KERNEL_GPU__
743
744 __device_inline float4 select(const int4& mask, const float4& a, const float4& b)
745 {
746 #ifdef __KERNEL_SSE__
747         /* blendv is sse4, and apparently broken on vs2008 */
748         return _mm_or_ps(_mm_and_ps(_mm_cvtepi32_ps(mask), a), _mm_andnot_ps(_mm_cvtepi32_ps(mask), b)); /* todo: avoid cvt */
749 #else
750         return make_float4((mask.x)? a.x: b.x, (mask.y)? a.y: b.y, (mask.z)? a.z: b.z, (mask.w)? a.w: b.w);
751 #endif
752 }
753
754 __device_inline float4 reduce_min(const float4& a)
755 {
756 #ifdef __KERNEL_SSE__
757         float4 h = min(shuffle<1,0,3,2>(a), a);
758         return min(shuffle<2,3,0,1>(h), h);
759 #else
760         return make_float4(min(min(a.x, a.y), min(a.z, a.w)));
761 #endif
762 }
763
764 __device_inline float4 reduce_max(const float4& a)
765 {
766 #ifdef __KERNEL_SSE__
767         float4 h = max(shuffle<1,0,3,2>(a), a);
768         return max(shuffle<2,3,0,1>(h), h);
769 #else
770         return make_float4(max(max(a.x, a.y), max(a.z, a.w)));
771 #endif
772 }
773
774 #if 0
775 __device_inline float4 reduce_add(const float4& a)
776 {
777 #ifdef __KERNEL_SSE__
778         float4 h = shuffle<1,0,3,2>(a) + a;
779         return shuffle<2,3,0,1>(h) + h;
780 #else
781         return make_float4((a.x + a.y) + (a.z + a.w));
782 #endif
783 }
784 #endif
785
786 __device_inline void print_float4(const char *label, const float4& a)
787 {
788         printf("%s: %.8f %.8f %.8f %.8f\n", label, a.x, a.y, a.z, a.w);
789 }
790
791 #endif
792
793 #ifndef __KERNEL_OPENCL__
794
795 __device_inline bool is_zero(const float4& a)
796 {
797 #ifdef __KERNEL_SSE__
798         return a == make_float4(0.0f);
799 #else
800         return (a.x == 0.0f && a.y == 0.0f && a.z == 0.0f && a.w == 0.0f);
801 #endif
802 }
803
804 __device_inline float reduce_add(const float4& a)
805 {
806 #ifdef __KERNEL_SSE__
807         float4 h = shuffle<1,0,3,2>(a) + a;
808         return _mm_cvtss_f32(shuffle<2,3,0,1>(h) + h); /* todo: efficiency? */
809 #else
810         return ((a.x + a.y) + (a.z + a.w));
811 #endif
812 }
813
814 __device_inline float average(const float4& a)
815 {
816         return reduce_add(a) * 0.25f;
817 }
818
819 __device_inline float dot(const float4& a, const float4& b)
820 {
821         return reduce_add(a * b);
822 }
823
824 #endif
825
826 /* Int3 */
827
828 #ifndef __KERNEL_OPENCL__
829
830 __device_inline int3 min(int3 a, int3 b)
831 {
832 #ifdef __KERNEL_SSE__
833         return _mm_min_epi32(a.m128, b.m128);
834 #else
835         return make_int3(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z));
836 #endif
837 }
838
839 __device_inline int3 max(int3 a, int3 b)
840 {
841 #ifdef __KERNEL_SSE__
842         return _mm_max_epi32(a.m128, b.m128);
843 #else
844         return make_int3(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z));
845 #endif
846 }
847
848 __device_inline int3 clamp(const int3& a, int mn, int mx)
849 {
850 #ifdef __KERNEL_SSE__
851         return min(max(a, make_int3(mn)), make_int3(mx));
852 #else
853         return make_int3(clamp(a.x, mn, mx), clamp(a.y, mn, mx), clamp(a.z, mn, mx));
854 #endif
855 }
856
857 __device_inline int3 clamp(const int3& a, int3& mn, int mx)
858 {
859 #ifdef __KERNEL_SSE__
860         return min(max(a, mn), make_int3(mx));
861 #else
862         return make_int3(clamp(a.x, mn.x, mx), clamp(a.y, mn.y, mx), clamp(a.z, mn.z, mx));
863 #endif
864 }
865
866 #endif
867
868 #ifndef __KERNEL_GPU__
869
870 __device_inline void print_int3(const char *label, const int3& a)
871 {
872         printf("%s: %d %d %d\n", label, a.x, a.y, a.z);
873 }
874
875 #endif
876
877 /* Int4 */
878
879 #ifndef __KERNEL_GPU__
880
881 __device_inline int4 operator+(const int4& a, const int4& b)
882 {
883 #ifdef __KERNEL_SSE__
884         return _mm_add_epi32(a.m128, b.m128);
885 #else
886         return make_int4(a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w);
887 #endif
888 }
889
890 __device_inline int4 operator+=(int4& a, const int4& b)
891 {
892         return a = a + b;
893 }
894
895 __device_inline int4 operator>>(const int4& a, int i)
896 {
897 #ifdef __KERNEL_SSE__
898         return _mm_srai_epi32(a.m128, i);
899 #else
900         return make_int4(a.x >> i, a.y >> i, a.z >> i, a.w >> i);
901 #endif
902 }
903
904 __device_inline int4 min(int4 a, int4 b)
905 {
906 #ifdef __KERNEL_SSE__
907         return _mm_min_epi32(a.m128, b.m128);
908 #else
909         return make_int4(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z), min(a.w, b.w));
910 #endif
911 }
912
913 __device_inline int4 max(int4 a, int4 b)
914 {
915 #ifdef __KERNEL_SSE__
916         return _mm_max_epi32(a.m128, b.m128);
917 #else
918         return make_int4(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z), max(a.w, b.w));
919 #endif
920 }
921
922 __device_inline int4 clamp(const int4& a, const int4& mn, const int4& mx)
923 {
924         return min(max(a, mn), mx);
925 }
926
927 __device_inline int4 select(const int4& mask, const int4& a, const int4& b)
928 {
929 #ifdef __KERNEL_SSE__
930         __m128 m = _mm_cvtepi32_ps(mask);
931         return _mm_castps_si128(_mm_or_ps(_mm_and_ps(m, _mm_castsi128_ps(a)), _mm_andnot_ps(m, _mm_castsi128_ps(b)))); /* todo: avoid cvt */
932 #else
933         return make_int4((mask.x)? a.x: b.x, (mask.y)? a.y: b.y, (mask.z)? a.z: b.z, (mask.w)? a.w: b.w);
934 #endif
935 }
936
937 __device_inline void print_int4(const char *label, const int4& a)
938 {
939         printf("%s: %d %d %d %d\n", label, a.x, a.y, a.z, a.w);
940 }
941
942 #endif
943
944 /* Int/Float conversion */
945
946 #ifndef __KERNEL_OPENCL__
947
948 __device_inline unsigned int as_uint(float f)
949 {
950         union { unsigned int i; float f; } u;
951         u.f = f;
952         return u.i;
953 }
954
955 __device_inline int __float_as_int(float f)
956 {
957         union { int i; float f; } u;
958         u.f = f;
959         return u.i;
960 }
961
962 __device_inline float __int_as_float(int i)
963 {
964         union { int i; float f; } u;
965         u.i = i;
966         return u.f;
967 }
968
969 __device_inline uint __float_as_uint(float f)
970 {
971         union { uint i; float f; } u;
972         u.f = f;
973         return u.i;
974 }
975
976 __device_inline float __uint_as_float(uint i)
977 {
978         union { uint i; float f; } u;
979         u.i = i;
980         return u.f;
981 }
982
983 /* Interpolation */
984
985 template<class A, class B> A lerp(const A& a, const A& b, const B& t)
986 {
987         return (A)(a * ((B)1 - t) + b * t);
988 }
989
990 /* Triangle */
991
992 __device_inline float triangle_area(const float3 v1, const float3 v2, const float3 v3)
993 {
994         return len(cross(v3 - v2, v1 - v2))*0.5f;
995 }
996
997 #endif
998
999 /* Orthonormal vectors */
1000
1001 __device_inline void make_orthonormals(const float3 N, float3 *a, float3 *b)
1002 {
1003         if(N.x != N.y || N.x != N.z)
1004                 *a = make_float3(N.z-N.y, N.x-N.z, N.y-N.x);  //(1,1,1)x N
1005         else
1006                 *a = make_float3(N.z-N.y, N.x+N.z, -N.y-N.x);  //(-1,1,1)x N
1007
1008         *a = normalize(*a);
1009         *b = cross(N, *a);
1010 }
1011
1012 /* Color division */
1013
1014 __device_inline float3 safe_divide_color(float3 a, float3 b)
1015 {
1016         float x, y, z;
1017
1018         x = (b.x != 0.0f)? a.x/b.x: 0.0f;
1019         y = (b.y != 0.0f)? a.y/b.y: 0.0f;
1020         z = (b.z != 0.0f)? a.z/b.z: 0.0f;
1021
1022         return make_float3(x, y, z);
1023 }
1024
1025 CCL_NAMESPACE_END
1026
1027 #endif /* __UTIL_MATH_H__ */
1028