Point Cloud Library (PCL)  1.15.1
cutil_math.h
1 /*
2  * Copyright 1993-2010 NVIDIA Corporation. All rights reserved.
3  *
4  * Please refer to the NVIDIA end user license agreement (EULA) associated
5  * with this source code for terms and conditions that govern your use of
6  * this software. Any use, reproduction, disclosure, or distribution of
7  * this software and related documentation outside the terms of the EULA
8  * is strictly prohibited.
9  *
10  */
11 
12 /*
13  This file implements common mathematical operations on vector types
14  (float3, float4 etc.) since these are not provided as standard by CUDA.
15 
16  The syntax is modelled on the Cg standard library.
17 
18  This is part of the CUTIL library and is not supported by NVIDIA.
19 
20  Thanks to Linh Hah for additions and fixes.
21 */
22 
23 #pragma once
24 
25 #include "cuda_runtime.h"
26 
27 using uint = unsigned int;
28 using ushort = unsigned short;
29 
30 #ifndef __CUDACC__
31 #include <math.h>
32 
33 ////////////////////////////////////////////////////////////////////////////////
34 // host implementations of CUDA functions
35 ////////////////////////////////////////////////////////////////////////////////
36 
37 inline float fminf(float a, float b)
38 {
39  return a < b ? a : b;
40 }
41 
42 inline float fmaxf(float a, float b)
43 {
44  return a > b ? a : b;
45 }
46 
47 inline int max(int a, int b)
48 {
49  return a > b ? a : b;
50 }
51 
52 inline int min(int a, int b)
53 {
54  return a < b ? a : b;
55 }
56 
57 inline float rsqrtf(float x)
58 {
59  return 1.0f / sqrtf(x);
60 }
61 #endif
62 
63 ////////////////////////////////////////////////////////////////////////////////
64 // constructors
65 ////////////////////////////////////////////////////////////////////////////////
66 
67 inline __host__ __device__ float2 make_float2(float s)
68 {
69  return make_float2(s, s);
70 }
71 inline __host__ __device__ float2 make_float2(float3 a)
72 {
73  return make_float2(a.x, a.y);
74 }
75 inline __host__ __device__ float2 make_float2(int2 a)
76 {
77  return make_float2(float(a.x), float(a.y));
78 }
79 inline __host__ __device__ float2 make_float2(uint2 a)
80 {
81  return make_float2(float(a.x), float(a.y));
82 }
83 
84 inline __host__ __device__ int2 make_int2(int s)
85 {
86  return make_int2(s, s);
87 }
88 inline __host__ __device__ int2 make_int2(int3 a)
89 {
90  return make_int2(a.x, a.y);
91 }
92 inline __host__ __device__ int2 make_int2(uint2 a)
93 {
94  return make_int2(int(a.x), int(a.y));
95 }
96 inline __host__ __device__ int2 make_int2(float2 a)
97 {
98  return make_int2(int(a.x), int(a.y));
99 }
100 
101 inline __host__ __device__ uint2 make_uint2(uint s)
102 {
103  return make_uint2(s, s);
104 }
105 inline __host__ __device__ uint2 make_uint2(uint3 a)
106 {
107  return make_uint2(a.x, a.y);
108 }
109 inline __host__ __device__ uint2 make_uint2(int2 a)
110 {
111  return make_uint2(uint(a.x), uint(a.y));
112 }
113 
114 inline __host__ __device__ float3 make_float3(float s)
115 {
116  return make_float3(s, s, s);
117 }
118 inline __host__ __device__ float3 make_float3(float2 a)
119 {
120  return make_float3(a.x, a.y, 0.0f);
121 }
122 inline __host__ __device__ float3 make_float3(float2 a, float s)
123 {
124  return make_float3(a.x, a.y, s);
125 }
126 inline __host__ __device__ float3 make_float3(float4 a)
127 {
128  return make_float3(a.x, a.y, a.z);
129 }
130 inline __host__ __device__ float3 make_float3(int3 a)
131 {
132  return make_float3(float(a.x), float(a.y), float(a.z));
133 }
134 inline __host__ __device__ float3 make_float3(uint3 a)
135 {
136  return make_float3(float(a.x), float(a.y), float(a.z));
137 }
138 
139 inline __host__ __device__ int3 make_int3(int s)
140 {
141  return make_int3(s, s, s);
142 }
143 inline __host__ __device__ int3 make_int3(int2 a)
144 {
145  return make_int3(a.x, a.y, 0);
146 }
147 inline __host__ __device__ int3 make_int3(int2 a, int s)
148 {
149  return make_int3(a.x, a.y, s);
150 }
151 inline __host__ __device__ int3 make_int3(uint3 a)
152 {
153  return make_int3(int(a.x), int(a.y), int(a.z));
154 }
155 inline __host__ __device__ int3 make_int3(float3 a)
156 {
157  return make_int3(int(a.x), int(a.y), int(a.z));
158 }
159 
160 inline __host__ __device__ uint3 make_uint3(uint s)
161 {
162  return make_uint3(s, s, s);
163 }
164 inline __host__ __device__ uint3 make_uint3(uint2 a)
165 {
166  return make_uint3(a.x, a.y, 0);
167 }
168 inline __host__ __device__ uint3 make_uint3(uint2 a, uint s)
169 {
170  return make_uint3(a.x, a.y, s);
171 }
172 inline __host__ __device__ uint3 make_uint3(uint4 a)
173 {
174  return make_uint3(a.x, a.y, a.z);
175 }
176 inline __host__ __device__ uint3 make_uint3(int3 a)
177 {
178  return make_uint3(uint(a.x), uint(a.y), uint(a.z));
179 }
180 
181 inline __host__ __device__ float4 make_float4(float s)
182 {
183  return make_float4(s, s, s, s);
184 }
185 inline __host__ __device__ float4 make_float4(float3 a)
186 {
187  return make_float4(a.x, a.y, a.z, 0.0f);
188 }
189 inline __host__ __device__ float4 make_float4(float3 a, float w)
190 {
191  return make_float4(a.x, a.y, a.z, w);
192 }
193 inline __host__ __device__ float4 make_float4(int4 a)
194 {
195  return make_float4(float(a.x), float(a.y), float(a.z), float(a.w));
196 }
197 inline __host__ __device__ float4 make_float4(uint4 a)
198 {
199  return make_float4(float(a.x), float(a.y), float(a.z), float(a.w));
200 }
201 
202 inline __host__ __device__ int4 make_int4(int s)
203 {
204  return make_int4(s, s, s, s);
205 }
206 inline __host__ __device__ int4 make_int4(int3 a)
207 {
208  return make_int4(a.x, a.y, a.z, 0);
209 }
210 inline __host__ __device__ int4 make_int4(int3 a, int w)
211 {
212  return make_int4(a.x, a.y, a.z, w);
213 }
214 inline __host__ __device__ int4 make_int4(uint4 a)
215 {
216  return make_int4(int(a.x), int(a.y), int(a.z), int(a.w));
217 }
218 inline __host__ __device__ int4 make_int4(float4 a)
219 {
220  return make_int4(int(a.x), int(a.y), int(a.z), int(a.w));
221 }
222 
223 
224 inline __host__ __device__ uint4 make_uint4(uint s)
225 {
226  return make_uint4(s, s, s, s);
227 }
228 inline __host__ __device__ uint4 make_uint4(uint3 a)
229 {
230  return make_uint4(a.x, a.y, a.z, 0);
231 }
232 inline __host__ __device__ uint4 make_uint4(uint3 a, uint w)
233 {
234  return make_uint4(a.x, a.y, a.z, w);
235 }
236 inline __host__ __device__ uint4 make_uint4(int4 a)
237 {
238  return make_uint4(uint(a.x), uint(a.y), uint(a.z), uint(a.w));
239 }
240 
241 ////////////////////////////////////////////////////////////////////////////////
242 // negate
243 ////////////////////////////////////////////////////////////////////////////////
244 
245 inline __host__ __device__ float2 operator-(float2 &a)
246 {
247  return make_float2(-a.x, -a.y);
248 }
249 inline __host__ __device__ int2 operator-(int2 &a)
250 {
251  return make_int2(-a.x, -a.y);
252 }
253 inline __host__ __device__ float3 operator-(float3 &a)
254 {
255  return make_float3(-a.x, -a.y, -a.z);
256 }
257 inline __host__ __device__ int3 operator-(int3 &a)
258 {
259  return make_int3(-a.x, -a.y, -a.z);
260 }
261 inline __host__ __device__ float4 operator-(float4 &a)
262 {
263  return make_float4(-a.x, -a.y, -a.z, -a.w);
264 }
265 inline __host__ __device__ int4 operator-(int4 &a)
266 {
267  return make_int4(-a.x, -a.y, -a.z, -a.w);
268 }
269 
270 ////////////////////////////////////////////////////////////////////////////////
271 // addition
272 ////////////////////////////////////////////////////////////////////////////////
273 
274 inline __host__ __device__ float2 operator+(float2 a, float2 b)
275 {
276  return make_float2(a.x + b.x, a.y + b.y);
277 }
278 inline __host__ __device__ void operator+=(float2 &a, float2 b)
279 {
280  a.x += b.x; a.y += b.y;
281 }
282 inline __host__ __device__ float2 operator+(float2 a, float b)
283 {
284  return make_float2(a.x + b, a.y + b);
285 }
286 inline __host__ __device__ float2 operator+(float b, float2 a)
287 {
288  return make_float2(a.x + b, a.y + b);
289 }
290 inline __host__ __device__ void operator+=(float2 &a, float b)
291 {
292  a.x += b; a.y += b;
293 }
294 
295 inline __host__ __device__ int2 operator+(int2 a, int2 b)
296 {
297  return make_int2(a.x + b.x, a.y + b.y);
298 }
299 inline __host__ __device__ void operator+=(int2 &a, int2 b)
300 {
301  a.x += b.x; a.y += b.y;
302 }
303 inline __host__ __device__ int2 operator+(int2 a, int b)
304 {
305  return make_int2(a.x + b, a.y + b);
306 }
307 inline __host__ __device__ int2 operator+(int b, int2 a)
308 {
309  return make_int2(a.x + b, a.y + b);
310 }
311 inline __host__ __device__ void operator+=(int2 &a, int b)
312 {
313  a.x += b; a.y += b;
314 }
315 
316 inline __host__ __device__ uint2 operator+(uint2 a, uint2 b)
317 {
318  return make_uint2(a.x + b.x, a.y + b.y);
319 }
320 inline __host__ __device__ void operator+=(uint2 &a, uint2 b)
321 {
322  a.x += b.x; a.y += b.y;
323 }
324 inline __host__ __device__ uint2 operator+(uint2 a, uint b)
325 {
326  return make_uint2(a.x + b, a.y + b);
327 }
328 inline __host__ __device__ uint2 operator+(uint b, uint2 a)
329 {
330  return make_uint2(a.x + b, a.y + b);
331 }
332 inline __host__ __device__ void operator+=(uint2 &a, uint b)
333 {
334  a.x += b; a.y += b;
335 }
336 
337 
338 inline __host__ __device__ float3 operator+(float3 a, float3 b)
339 {
340  return make_float3(a.x + b.x, a.y + b.y, a.z + b.z);
341 }
342 inline __host__ __device__ void operator+=(float3 &a, float3 b)
343 {
344  a.x += b.x; a.y += b.y; a.z += b.z;
345 }
346 inline __host__ __device__ float3 operator+(float3 a, float b)
347 {
348  return make_float3(a.x + b, a.y + b, a.z + b);
349 }
350 inline __host__ __device__ void operator+=(float3 &a, float b)
351 {
352  a.x += b; a.y += b; a.z += b;
353 }
354 
355 inline __host__ __device__ int3 operator+(int3 a, int3 b)
356 {
357  return make_int3(a.x + b.x, a.y + b.y, a.z + b.z);
358 }
359 inline __host__ __device__ void operator+=(int3 &a, int3 b)
360 {
361  a.x += b.x; a.y += b.y; a.z += b.z;
362 }
363 inline __host__ __device__ int3 operator+(int3 a, int b)
364 {
365  return make_int3(a.x + b, a.y + b, a.z + b);
366 }
367 inline __host__ __device__ void operator+=(int3 &a, int b)
368 {
369  a.x += b; a.y += b; a.z += b;
370 }
371 
372 inline __host__ __device__ uint3 operator+(uint3 a, uint3 b)
373 {
374  return make_uint3(a.x + b.x, a.y + b.y, a.z + b.z);
375 }
376 inline __host__ __device__ void operator+=(uint3 &a, uint3 b)
377 {
378  a.x += b.x; a.y += b.y; a.z += b.z;
379 }
380 inline __host__ __device__ uint3 operator+(uint3 a, uint b)
381 {
382  return make_uint3(a.x + b, a.y + b, a.z + b);
383 }
384 inline __host__ __device__ void operator+=(uint3 &a, uint b)
385 {
386  a.x += b; a.y += b; a.z += b;
387 }
388 
389 inline __host__ __device__ int3 operator+(int b, int3 a)
390 {
391  return make_int3(a.x + b, a.y + b, a.z + b);
392 }
393 inline __host__ __device__ uint3 operator+(uint b, uint3 a)
394 {
395  return make_uint3(a.x + b, a.y + b, a.z + b);
396 }
397 inline __host__ __device__ float3 operator+(float b, float3 a)
398 {
399  return make_float3(a.x + b, a.y + b, a.z + b);
400 }
401 
402 inline __host__ __device__ float4 operator+(float4 a, float4 b)
403 {
404  return make_float4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
405 }
406 inline __host__ __device__ void operator+=(float4 &a, float4 b)
407 {
408  a.x += b.x; a.y += b.y; a.z += b.z; a.w += b.w;
409 }
410 inline __host__ __device__ float4 operator+(float4 a, float b)
411 {
412  return make_float4(a.x + b, a.y + b, a.z + b, a.w + b);
413 }
414 inline __host__ __device__ float4 operator+(float b, float4 a)
415 {
416  return make_float4(a.x + b, a.y + b, a.z + b, a.w + b);
417 }
418 inline __host__ __device__ void operator+=(float4 &a, float b)
419 {
420  a.x += b; a.y += b; a.z += b; a.w += b;
421 }
422 
423 inline __host__ __device__ int4 operator+(int4 a, int4 b)
424 {
425  return make_int4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
426 }
427 inline __host__ __device__ void operator+=(int4 &a, int4 b)
428 {
429  a.x += b.x; a.y += b.y; a.z += b.z; a.w += b.w;
430 }
431 inline __host__ __device__ int4 operator+(int4 a, int b)
432 {
433  return make_int4(a.x + b, a.y + b, a.z + b, a.w + b);
434 }
435 inline __host__ __device__ int4 operator+(int b, int4 a)
436 {
437  return make_int4(a.x + b, a.y + b, a.z + b, a.w + b);
438 }
439 inline __host__ __device__ void operator+=(int4 &a, int b)
440 {
441  a.x += b; a.y += b; a.z += b; a.w += b;
442 }
443 
444 inline __host__ __device__ uint4 operator+(uint4 a, uint4 b)
445 {
446  return make_uint4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
447 }
448 inline __host__ __device__ void operator+=(uint4 &a, uint4 b)
449 {
450  a.x += b.x; a.y += b.y; a.z += b.z; a.w += b.w;
451 }
452 inline __host__ __device__ uint4 operator+(uint4 a, uint b)
453 {
454  return make_uint4(a.x + b, a.y + b, a.z + b, a.w + b);
455 }
456 inline __host__ __device__ uint4 operator+(uint b, uint4 a)
457 {
458  return make_uint4(a.x + b, a.y + b, a.z + b, a.w + b);
459 }
460 inline __host__ __device__ void operator+=(uint4 &a, uint b)
461 {
462  a.x += b; a.y += b; a.z += b; a.w += b;
463 }
464 
465 ////////////////////////////////////////////////////////////////////////////////
466 // subtract
467 ////////////////////////////////////////////////////////////////////////////////
468 
469 inline __host__ __device__ float2 operator-(float2 a, float2 b)
470 {
471  return make_float2(a.x - b.x, a.y - b.y);
472 }
473 inline __host__ __device__ void operator-=(float2 &a, float2 b)
474 {
475  a.x -= b.x; a.y -= b.y;
476 }
477 inline __host__ __device__ float2 operator-(float2 a, float b)
478 {
479  return make_float2(a.x - b, a.y - b);
480 }
481 inline __host__ __device__ float2 operator-(float b, float2 a)
482 {
483  return make_float2(b - a.x, b - a.y);
484 }
485 inline __host__ __device__ void operator-=(float2 &a, float b)
486 {
487  a.x -= b; a.y -= b;
488 }
489 
490 inline __host__ __device__ int2 operator-(int2 a, int2 b)
491 {
492  return make_int2(a.x - b.x, a.y - b.y);
493 }
494 inline __host__ __device__ void operator-=(int2 &a, int2 b)
495 {
496  a.x -= b.x; a.y -= b.y;
497 }
498 inline __host__ __device__ int2 operator-(int2 a, int b)
499 {
500  return make_int2(a.x - b, a.y - b);
501 }
502 inline __host__ __device__ int2 operator-(int b, int2 a)
503 {
504  return make_int2(b - a.x, b - a.y);
505 }
506 inline __host__ __device__ void operator-=(int2 &a, int b)
507 {
508  a.x -= b; a.y -= b;
509 }
510 
511 inline __host__ __device__ uint2 operator-(uint2 a, uint2 b)
512 {
513  return make_uint2(a.x - b.x, a.y - b.y);
514 }
515 inline __host__ __device__ void operator-=(uint2 &a, uint2 b)
516 {
517  a.x -= b.x; a.y -= b.y;
518 }
519 inline __host__ __device__ uint2 operator-(uint2 a, uint b)
520 {
521  return make_uint2(a.x - b, a.y - b);
522 }
523 inline __host__ __device__ uint2 operator-(uint b, uint2 a)
524 {
525  return make_uint2(b - a.x, b - a.y);
526 }
527 inline __host__ __device__ void operator-=(uint2 &a, uint b)
528 {
529  a.x -= b; a.y -= b;
530 }
531 
532 inline __host__ __device__ float3 operator-(float3 a, float3 b)
533 {
534  return make_float3(a.x - b.x, a.y - b.y, a.z - b.z);
535 }
536 inline __host__ __device__ void operator-=(float3 &a, float3 b)
537 {
538  a.x -= b.x; a.y -= b.y; a.z -= b.z;
539 }
540 inline __host__ __device__ float3 operator-(float3 a, float b)
541 {
542  return make_float3(a.x - b, a.y - b, a.z - b);
543 }
544 inline __host__ __device__ float3 operator-(float b, float3 a)
545 {
546  return make_float3(b - a.x, b - a.y, b - a.z);
547 }
548 inline __host__ __device__ void operator-=(float3 &a, float b)
549 {
550  a.x -= b; a.y -= b; a.z -= b;
551 }
552 
553 inline __host__ __device__ int3 operator-(int3 a, int3 b)
554 {
555  return make_int3(a.x - b.x, a.y - b.y, a.z - b.z);
556 }
557 inline __host__ __device__ void operator-=(int3 &a, int3 b)
558 {
559  a.x -= b.x; a.y -= b.y; a.z -= b.z;
560 }
561 inline __host__ __device__ int3 operator-(int3 a, int b)
562 {
563  return make_int3(a.x - b, a.y - b, a.z - b);
564 }
565 inline __host__ __device__ int3 operator-(int b, int3 a)
566 {
567  return make_int3(b - a.x, b - a.y, b - a.z);
568 }
569 inline __host__ __device__ void operator-=(int3 &a, int b)
570 {
571  a.x -= b; a.y -= b; a.z -= b;
572 }
573 
574 inline __host__ __device__ uint3 operator-(uint3 a, uint3 b)
575 {
576  return make_uint3(a.x - b.x, a.y - b.y, a.z - b.z);
577 }
578 inline __host__ __device__ void operator-=(uint3 &a, uint3 b)
579 {
580  a.x -= b.x; a.y -= b.y; a.z -= b.z;
581 }
582 inline __host__ __device__ uint3 operator-(uint3 a, uint b)
583 {
584  return make_uint3(a.x - b, a.y - b, a.z - b);
585 }
586 inline __host__ __device__ uint3 operator-(uint b, uint3 a)
587 {
588  return make_uint3(b - a.x, b - a.y, b - a.z);
589 }
590 inline __host__ __device__ void operator-=(uint3 &a, uint b)
591 {
592  a.x -= b; a.y -= b; a.z -= b;
593 }
594 
595 inline __host__ __device__ float4 operator-(float4 a, float4 b)
596 {
597  return make_float4(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
598 }
599 inline __host__ __device__ void operator-=(float4 &a, float4 b)
600 {
601  a.x -= b.x; a.y -= b.y; a.z -= b.z; a.w -= b.w;
602 }
603 inline __host__ __device__ float4 operator-(float4 a, float b)
604 {
605  return make_float4(a.x - b, a.y - b, a.z - b, a.w - b);
606 }
607 inline __host__ __device__ void operator-=(float4 &a, float b)
608 {
609  a.x -= b; a.y -= b; a.z -= b; a.w -= b;
610 }
611 
612 inline __host__ __device__ int4 operator-(int4 a, int4 b)
613 {
614  return make_int4(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
615 }
616 inline __host__ __device__ void operator-=(int4 &a, int4 b)
617 {
618  a.x -= b.x; a.y -= b.y; a.z -= b.z; a.w -= b.w;
619 }
620 inline __host__ __device__ int4 operator-(int4 a, int b)
621 {
622  return make_int4(a.x - b, a.y - b, a.z - b, a.w - b);
623 }
624 inline __host__ __device__ int4 operator-(int b, int4 a)
625 {
626  return make_int4(b - a.x, b - a.y, b - a.z, b - a.w);
627 }
628 inline __host__ __device__ void operator-=(int4 &a, int b)
629 {
630  a.x -= b; a.y -= b; a.z -= b; a.w -= b;
631 }
632 
633 inline __host__ __device__ uint4 operator-(uint4 a, uint4 b)
634 {
635  return make_uint4(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
636 }
637 inline __host__ __device__ void operator-=(uint4 &a, uint4 b)
638 {
639  a.x -= b.x; a.y -= b.y; a.z -= b.z; a.w -= b.w;
640 }
641 inline __host__ __device__ uint4 operator-(uint4 a, uint b)
642 {
643  return make_uint4(a.x - b, a.y - b, a.z - b, a.w - b);
644 }
645 inline __host__ __device__ uint4 operator-(uint b, uint4 a)
646 {
647  return make_uint4(b - a.x, b - a.y, b - a.z, b - a.w);
648 }
649 inline __host__ __device__ void operator-=(uint4 &a, uint b)
650 {
651  a.x -= b; a.y -= b; a.z -= b; a.w -= b;
652 }
653 
654 ////////////////////////////////////////////////////////////////////////////////
655 // multiply
656 ////////////////////////////////////////////////////////////////////////////////
657 
658 inline __host__ __device__ float2 operator*(float2 a, float2 b)
659 {
660  return make_float2(a.x * b.x, a.y * b.y);
661 }
662 inline __host__ __device__ void operator*=(float2 &a, float2 b)
663 {
664  a.x *= b.x; a.y *= b.y;
665 }
666 inline __host__ __device__ float2 operator*(float2 a, float b)
667 {
668  return make_float2(a.x * b, a.y * b);
669 }
670 inline __host__ __device__ float2 operator*(float b, float2 a)
671 {
672  return make_float2(b * a.x, b * a.y);
673 }
674 inline __host__ __device__ void operator*=(float2 &a, float b)
675 {
676  a.x *= b; a.y *= b;
677 }
678 
679 inline __host__ __device__ int2 operator*(int2 a, int2 b)
680 {
681  return make_int2(a.x * b.x, a.y * b.y);
682 }
683 inline __host__ __device__ void operator*=(int2 &a, int2 b)
684 {
685  a.x *= b.x; a.y *= b.y;
686 }
687 inline __host__ __device__ int2 operator*(int2 a, int b)
688 {
689  return make_int2(a.x * b, a.y * b);
690 }
691 inline __host__ __device__ int2 operator*(int b, int2 a)
692 {
693  return make_int2(b * a.x, b * a.y);
694 }
695 inline __host__ __device__ void operator*=(int2 &a, int b)
696 {
697  a.x *= b; a.y *= b;
698 }
699 
700 inline __host__ __device__ uint2 operator*(uint2 a, uint2 b)
701 {
702  return make_uint2(a.x * b.x, a.y * b.y);
703 }
704 inline __host__ __device__ void operator*=(uint2 &a, uint2 b)
705 {
706  a.x *= b.x; a.y *= b.y;
707 }
708 inline __host__ __device__ uint2 operator*(uint2 a, uint b)
709 {
710  return make_uint2(a.x * b, a.y * b);
711 }
712 inline __host__ __device__ uint2 operator*(uint b, uint2 a)
713 {
714  return make_uint2(b * a.x, b * a.y);
715 }
716 inline __host__ __device__ void operator*=(uint2 &a, uint b)
717 {
718  a.x *= b; a.y *= b;
719 }
720 
721 inline __host__ __device__ float3 operator*(float3 a, float3 b)
722 {
723  return make_float3(a.x * b.x, a.y * b.y, a.z * b.z);
724 }
725 inline __host__ __device__ void operator*=(float3 &a, float3 b)
726 {
727  a.x *= b.x; a.y *= b.y; a.z *= b.z;
728 }
729 inline __host__ __device__ float3 operator*(float3 a, float b)
730 {
731  return make_float3(a.x * b, a.y * b, a.z * b);
732 }
733 inline __host__ __device__ float3 operator*(float b, float3 a)
734 {
735  return make_float3(b * a.x, b * a.y, b * a.z);
736 }
737 inline __host__ __device__ void operator*=(float3 &a, float b)
738 {
739  a.x *= b; a.y *= b; a.z *= b;
740 }
741 
742 inline __host__ __device__ int3 operator*(int3 a, int3 b)
743 {
744  return make_int3(a.x * b.x, a.y * b.y, a.z * b.z);
745 }
746 inline __host__ __device__ void operator*=(int3 &a, int3 b)
747 {
748  a.x *= b.x; a.y *= b.y; a.z *= b.z;
749 }
750 inline __host__ __device__ int3 operator*(int3 a, int b)
751 {
752  return make_int3(a.x * b, a.y * b, a.z * b);
753 }
754 inline __host__ __device__ int3 operator*(int b, int3 a)
755 {
756  return make_int3(b * a.x, b * a.y, b * a.z);
757 }
758 inline __host__ __device__ void operator*=(int3 &a, int b)
759 {
760  a.x *= b; a.y *= b; a.z *= b;
761 }
762 
763 inline __host__ __device__ uint3 operator*(uint3 a, uint3 b)
764 {
765  return make_uint3(a.x * b.x, a.y * b.y, a.z * b.z);
766 }
767 inline __host__ __device__ void operator*=(uint3 &a, uint3 b)
768 {
769  a.x *= b.x; a.y *= b.y; a.z *= b.z;
770 }
771 inline __host__ __device__ uint3 operator*(uint3 a, uint b)
772 {
773  return make_uint3(a.x * b, a.y * b, a.z * b);
774 }
775 inline __host__ __device__ uint3 operator*(uint b, uint3 a)
776 {
777  return make_uint3(b * a.x, b * a.y, b * a.z);
778 }
779 inline __host__ __device__ void operator*=(uint3 &a, uint b)
780 {
781  a.x *= b; a.y *= b; a.z *= b;
782 }
783 
784 inline __host__ __device__ float4 operator*(float4 a, float4 b)
785 {
786  return make_float4(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w);
787 }
788 inline __host__ __device__ void operator*=(float4 &a, float4 b)
789 {
790  a.x *= b.x; a.y *= b.y; a.z *= b.z; a.w *= b.w;
791 }
792 inline __host__ __device__ float4 operator*(float4 a, float b)
793 {
794  return make_float4(a.x * b, a.y * b, a.z * b, a.w * b);
795 }
796 inline __host__ __device__ float4 operator*(float b, float4 a)
797 {
798  return make_float4(b * a.x, b * a.y, b * a.z, b * a.w);
799 }
800 inline __host__ __device__ void operator*=(float4 &a, float b)
801 {
802  a.x *= b; a.y *= b; a.z *= b; a.w *= b;
803 }
804 
805 inline __host__ __device__ int4 operator*(int4 a, int4 b)
806 {
807  return make_int4(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w);
808 }
809 inline __host__ __device__ void operator*=(int4 &a, int4 b)
810 {
811  a.x *= b.x; a.y *= b.y; a.z *= b.z; a.w *= b.w;
812 }
813 inline __host__ __device__ int4 operator*(int4 a, int b)
814 {
815  return make_int4(a.x * b, a.y * b, a.z * b, a.w * b);
816 }
817 inline __host__ __device__ int4 operator*(int b, int4 a)
818 {
819  return make_int4(b * a.x, b * a.y, b * a.z, b * a.w);
820 }
821 inline __host__ __device__ void operator*=(int4 &a, int b)
822 {
823  a.x *= b; a.y *= b; a.z *= b; a.w *= b;
824 }
825 
826 inline __host__ __device__ uint4 operator*(uint4 a, uint4 b)
827 {
828  return make_uint4(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w);
829 }
830 inline __host__ __device__ void operator*=(uint4 &a, uint4 b)
831 {
832  a.x *= b.x; a.y *= b.y; a.z *= b.z; a.w *= b.w;
833 }
834 inline __host__ __device__ uint4 operator*(uint4 a, uint b)
835 {
836  return make_uint4(a.x * b, a.y * b, a.z * b, a.w * b);
837 }
838 inline __host__ __device__ uint4 operator*(uint b, uint4 a)
839 {
840  return make_uint4(b * a.x, b * a.y, b * a.z, b * a.w);
841 }
842 inline __host__ __device__ void operator*=(uint4 &a, uint b)
843 {
844  a.x *= b; a.y *= b; a.z *= b; a.w *= b;
845 }
846 
847 ////////////////////////////////////////////////////////////////////////////////
848 // divide
849 ////////////////////////////////////////////////////////////////////////////////
850 
851 inline __host__ __device__ float2 operator/(float2 a, float2 b)
852 {
853  return make_float2(a.x / b.x, a.y / b.y);
854 }
855 inline __host__ __device__ void operator/=(float2 &a, float2 b)
856 {
857  a.x /= b.x; a.y /= b.y;
858 }
859 inline __host__ __device__ float2 operator/(float2 a, float b)
860 {
861  return make_float2(a.x / b, a.y / b);
862 }
863 inline __host__ __device__ void operator/=(float2 &a, float b)
864 {
865  a.x /= b; a.y /= b;
866 }
867 inline __host__ __device__ float2 operator/(float b, float2 a)
868 {
869  return make_float2(b / a.x, b / a.y);
870 }
871 
872 inline __host__ __device__ float3 operator/(float3 a, float3 b)
873 {
874  return make_float3(a.x / b.x, a.y / b.y, a.z / b.z);
875 }
876 inline __host__ __device__ void operator/=(float3 &a, float3 b)
877 {
878  a.x /= b.x; a.y /= b.y; a.z /= b.z;
879 }
880 inline __host__ __device__ float3 operator/(float3 a, float b)
881 {
882  return make_float3(a.x / b, a.y / b, a.z / b);
883 }
884 inline __host__ __device__ void operator/=(float3 &a, float b)
885 {
886  a.x /= b; a.y /= b; a.z /= b;
887 }
888 inline __host__ __device__ float3 operator/(float b, float3 a)
889 {
890  return make_float3(b / a.x, b / a.y, b / a.z);
891 }
892 
893 inline __host__ __device__ float4 operator/(float4 a, float4 b)
894 {
895  return make_float4(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w);
896 }
897 inline __host__ __device__ void operator/=(float4 &a, float4 b)
898 {
899  a.x /= b.x; a.y /= b.y; a.z /= b.z; a.w /= b.w;
900 }
901 inline __host__ __device__ float4 operator/(float4 a, float b)
902 {
903  return make_float4(a.x / b, a.y / b, a.z / b, a.w / b);
904 }
905 inline __host__ __device__ void operator/=(float4 &a, float b)
906 {
907  a.x /= b; a.y /= b; a.z /= b; a.w /= b;
908 }
909 inline __host__ __device__ float4 operator/(float b, float4 a){
910  return make_float4(b / a.x, b / a.y, b / a.z, b / a.w);
911 }
912 
913 ////////////////////////////////////////////////////////////////////////////////
914 // min
915 ////////////////////////////////////////////////////////////////////////////////
916 
917 inline __host__ __device__ float2 fminf(float2 a, float2 b)
918 {
919  return make_float2(fminf(a.x,b.x), fminf(a.y,b.y));
920 }
921 inline __host__ __device__ float3 fminf(float3 a, float3 b)
922 {
923  return make_float3(fminf(a.x,b.x), fminf(a.y,b.y), fminf(a.z,b.z));
924 }
925 inline __host__ __device__ float4 fminf(float4 a, float4 b)
926 {
927  return make_float4(fminf(a.x,b.x), fminf(a.y,b.y), fminf(a.z,b.z), fminf(a.w,b.w));
928 }
929 
930 inline __host__ __device__ int2 min(int2 a, int2 b)
931 {
932  return make_int2(min(a.x,b.x), min(a.y,b.y));
933 }
934 inline __host__ __device__ int3 min(int3 a, int3 b)
935 {
936  return make_int3(min(a.x,b.x), min(a.y,b.y), min(a.z,b.z));
937 }
938 inline __host__ __device__ int4 min(int4 a, int4 b)
939 {
940  return make_int4(min(a.x,b.x), min(a.y,b.y), min(a.z,b.z), min(a.w,b.w));
941 }
942 
943 inline __host__ __device__ uint2 min(uint2 a, uint2 b)
944 {
945  return make_uint2(min(a.x,b.x), min(a.y,b.y));
946 }
947 inline __host__ __device__ uint3 min(uint3 a, uint3 b)
948 {
949  return make_uint3(min(a.x,b.x), min(a.y,b.y), min(a.z,b.z));
950 }
951 inline __host__ __device__ uint4 min(uint4 a, uint4 b)
952 {
953  return make_uint4(min(a.x,b.x), min(a.y,b.y), min(a.z,b.z), min(a.w,b.w));
954 }
955 
956 ////////////////////////////////////////////////////////////////////////////////
957 // max
958 ////////////////////////////////////////////////////////////////////////////////
959 
960 inline __host__ __device__ float2 fmaxf(float2 a, float2 b)
961 {
962  return make_float2(fmaxf(a.x,b.x), fmaxf(a.y,b.y));
963 }
964 inline __host__ __device__ float3 fmaxf(float3 a, float3 b)
965 {
966  return make_float3(fmaxf(a.x,b.x), fmaxf(a.y,b.y), fmaxf(a.z,b.z));
967 }
968 inline __host__ __device__ float4 fmaxf(float4 a, float4 b)
969 {
970  return make_float4(fmaxf(a.x,b.x), fmaxf(a.y,b.y), fmaxf(a.z,b.z), fmaxf(a.w,b.w));
971 }
972 
973 inline __host__ __device__ int2 max(int2 a, int2 b)
974 {
975  return make_int2(max(a.x,b.x), max(a.y,b.y));
976 }
977 inline __host__ __device__ int3 max(int3 a, int3 b)
978 {
979  return make_int3(max(a.x,b.x), max(a.y,b.y), max(a.z,b.z));
980 }
981 inline __host__ __device__ int4 max(int4 a, int4 b)
982 {
983  return make_int4(max(a.x,b.x), max(a.y,b.y), max(a.z,b.z), max(a.w,b.w));
984 }
985 
986 inline __host__ __device__ uint2 max(uint2 a, uint2 b)
987 {
988  return make_uint2(max(a.x,b.x), max(a.y,b.y));
989 }
990 inline __host__ __device__ uint3 max(uint3 a, uint3 b)
991 {
992  return make_uint3(max(a.x,b.x), max(a.y,b.y), max(a.z,b.z));
993 }
994 inline __host__ __device__ uint4 max(uint4 a, uint4 b)
995 {
996  return make_uint4(max(a.x,b.x), max(a.y,b.y), max(a.z,b.z), max(a.w,b.w));
997 }
998 
999 ////////////////////////////////////////////////////////////////////////////////
1000 // lerp
1001 // - linear interpolation between a and b, based on value t in [0, 1] range
1002 ////////////////////////////////////////////////////////////////////////////////
1003 
1004 #if !defined(__cplusplus) || (__cplusplus < 202002L)
1005 // C++20 and higher provides std::lerp
1006 inline __device__ __host__ float lerp(float a, float b, float t)
1007 {
1008  return a + t*(b-a);
1009 }
1010 #endif
1011 inline __device__ __host__ float2 lerp(float2 a, float2 b, float t)
1012 {
1013  return a + t*(b-a);
1014 }
1015 inline __device__ __host__ float3 lerp(float3 a, float3 b, float t)
1016 {
1017  return a + t*(b-a);
1018 }
1019 inline __device__ __host__ float4 lerp(float4 a, float4 b, float t)
1020 {
1021  return a + t*(b-a);
1022 }
1023 
1024 ////////////////////////////////////////////////////////////////////////////////
1025 // clamp
1026 // - clamp the value v to be in the range [a, b]
1027 ////////////////////////////////////////////////////////////////////////////////
1028 
1029 inline __device__ __host__ float clamp(float f, float a, float b)
1030 {
1031  return fmaxf(a, fminf(f, b));
1032 }
1033 inline __device__ __host__ int clamp(int f, int a, int b)
1034 {
1035  return max(a, min(f, b));
1036 }
1037 inline __device__ __host__ uint clamp(uint f, uint a, uint b)
1038 {
1039  return max(a, min(f, b));
1040 }
1041 
1042 inline __device__ __host__ float2 clamp(float2 v, float a, float b)
1043 {
1044  return make_float2(clamp(v.x, a, b), clamp(v.y, a, b));
1045 }
1046 inline __device__ __host__ float2 clamp(float2 v, float2 a, float2 b)
1047 {
1048  return make_float2(clamp(v.x, a.x, b.x), clamp(v.y, a.y, b.y));
1049 }
1050 inline __device__ __host__ float3 clamp(float3 v, float a, float b)
1051 {
1052  return make_float3(clamp(v.x, a, b), clamp(v.y, a, b), clamp(v.z, a, b));
1053 }
1054 inline __device__ __host__ float3 clamp(float3 v, float3 a, float3 b)
1055 {
1056  return make_float3(clamp(v.x, a.x, b.x), clamp(v.y, a.y, b.y), clamp(v.z, a.z, b.z));
1057 }
1058 inline __device__ __host__ float4 clamp(float4 v, float a, float b)
1059 {
1060  return make_float4(clamp(v.x, a, b), clamp(v.y, a, b), clamp(v.z, a, b), clamp(v.w, a, b));
1061 }
1062 inline __device__ __host__ float4 clamp(float4 v, float4 a, float4 b)
1063 {
1064  return make_float4(clamp(v.x, a.x, b.x), clamp(v.y, a.y, b.y), clamp(v.z, a.z, b.z), clamp(v.w, a.w, b.w));
1065 }
1066 
1067 inline __device__ __host__ int2 clamp(int2 v, int a, int b)
1068 {
1069  return make_int2(clamp(v.x, a, b), clamp(v.y, a, b));
1070 }
1071 inline __device__ __host__ int2 clamp(int2 v, int2 a, int2 b)
1072 {
1073  return make_int2(clamp(v.x, a.x, b.x), clamp(v.y, a.y, b.y));
1074 }
1075 inline __device__ __host__ int3 clamp(int3 v, int a, int b)
1076 {
1077  return make_int3(clamp(v.x, a, b), clamp(v.y, a, b), clamp(v.z, a, b));
1078 }
1079 inline __device__ __host__ int3 clamp(int3 v, int3 a, int3 b)
1080 {
1081  return make_int3(clamp(v.x, a.x, b.x), clamp(v.y, a.y, b.y), clamp(v.z, a.z, b.z));
1082 }
1083 inline __device__ __host__ int4 clamp(int4 v, int a, int b)
1084 {
1085  return make_int4(clamp(v.x, a, b), clamp(v.y, a, b), clamp(v.z, a, b), clamp(v.w, a, b));
1086 }
1087 inline __device__ __host__ int4 clamp(int4 v, int4 a, int4 b)
1088 {
1089  return make_int4(clamp(v.x, a.x, b.x), clamp(v.y, a.y, b.y), clamp(v.z, a.z, b.z), clamp(v.w, a.w, b.w));
1090 }
1091 
1092 inline __device__ __host__ uint2 clamp(uint2 v, uint a, uint b)
1093 {
1094  return make_uint2(clamp(v.x, a, b), clamp(v.y, a, b));
1095 }
1096 inline __device__ __host__ uint2 clamp(uint2 v, uint2 a, uint2 b)
1097 {
1098  return make_uint2(clamp(v.x, a.x, b.x), clamp(v.y, a.y, b.y));
1099 }
1100 inline __device__ __host__ uint3 clamp(uint3 v, uint a, uint b)
1101 {
1102  return make_uint3(clamp(v.x, a, b), clamp(v.y, a, b), clamp(v.z, a, b));
1103 }
1104 inline __device__ __host__ uint3 clamp(uint3 v, uint3 a, uint3 b)
1105 {
1106  return make_uint3(clamp(v.x, a.x, b.x), clamp(v.y, a.y, b.y), clamp(v.z, a.z, b.z));
1107 }
1108 inline __device__ __host__ uint4 clamp(uint4 v, uint a, uint b)
1109 {
1110  return make_uint4(clamp(v.x, a, b), clamp(v.y, a, b), clamp(v.z, a, b), clamp(v.w, a, b));
1111 }
1112 inline __device__ __host__ uint4 clamp(uint4 v, uint4 a, uint4 b)
1113 {
1114  return make_uint4(clamp(v.x, a.x, b.x), clamp(v.y, a.y, b.y), clamp(v.z, a.z, b.z), clamp(v.w, a.w, b.w));
1115 }
1116 
1117 ////////////////////////////////////////////////////////////////////////////////
1118 // dot product
1119 ////////////////////////////////////////////////////////////////////////////////
1120 
1121 inline __host__ __device__ float dot(float2 a, float2 b)
1122 {
1123  return a.x * b.x + a.y * b.y;
1124 }
1125 inline __host__ __device__ float dot(float3 a, float3 b)
1126 {
1127  return a.x * b.x + a.y * b.y + a.z * b.z;
1128 }
1129 inline __host__ __device__ float dot(float4 a, float4 b)
1130 {
1131  return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
1132 }
1133 
1134 inline __host__ __device__ int dot(int2 a, int2 b)
1135 {
1136  return a.x * b.x + a.y * b.y;
1137 }
1138 inline __host__ __device__ int dot(int3 a, int3 b)
1139 {
1140  return a.x * b.x + a.y * b.y + a.z * b.z;
1141 }
1142 inline __host__ __device__ int dot(int4 a, int4 b)
1143 {
1144  return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
1145 }
1146 
1147 inline __host__ __device__ uint dot(uint2 a, uint2 b)
1148 {
1149  return a.x * b.x + a.y * b.y;
1150 }
1151 inline __host__ __device__ uint dot(uint3 a, uint3 b)
1152 {
1153  return a.x * b.x + a.y * b.y + a.z * b.z;
1154 }
1155 inline __host__ __device__ uint dot(uint4 a, uint4 b)
1156 {
1157  return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
1158 }
1159 
1160 ////////////////////////////////////////////////////////////////////////////////
1161 // length
1162 ////////////////////////////////////////////////////////////////////////////////
1163 
1164 inline __host__ __device__ float length(float2 v)
1165 {
1166  return sqrtf(dot(v, v));
1167 }
1168 inline __host__ __device__ float length(float3 v)
1169 {
1170  return sqrtf(dot(v, v));
1171 }
1172 inline __host__ __device__ float length(float4 v)
1173 {
1174  return sqrtf(dot(v, v));
1175 }
1176 
1177 ////////////////////////////////////////////////////////////////////////////////
1178 // normalize
1179 ////////////////////////////////////////////////////////////////////////////////
1180 
1181 inline __host__ __device__ float2 normalize(float2 v)
1182 {
1183  float invLen = rsqrtf(dot(v, v));
1184  return v * invLen;
1185 }
1186 inline __host__ __device__ float3 normalize(float3 v)
1187 {
1188  float invLen = rsqrtf(dot(v, v));
1189  return v * invLen;
1190 }
1191 inline __host__ __device__ float4 normalize(float4 v)
1192 {
1193  float invLen = rsqrtf(dot(v, v));
1194  return v * invLen;
1195 }
1196 
1197 ////////////////////////////////////////////////////////////////////////////////
1198 // floor
1199 ////////////////////////////////////////////////////////////////////////////////
1200 
1201 inline __host__ __device__ float2 floorf(float2 v)
1202 {
1203  return make_float2(floorf(v.x), floorf(v.y));
1204 }
1205 inline __host__ __device__ float3 floorf(float3 v)
1206 {
1207  return make_float3(floorf(v.x), floorf(v.y), floorf(v.z));
1208 }
1209 inline __host__ __device__ float4 floorf(float4 v)
1210 {
1211  return make_float4(floorf(v.x), floorf(v.y), floorf(v.z), floorf(v.w));
1212 }
1213 
1214 ////////////////////////////////////////////////////////////////////////////////
1215 // frac - returns the fractional portion of a scalar or each vector component
1216 ////////////////////////////////////////////////////////////////////////////////
1217 
1218 inline __host__ __device__ float fracf(float v)
1219 {
1220  return v - floorf(v);
1221 }
1222 inline __host__ __device__ float2 fracf(float2 v)
1223 {
1224  return make_float2(fracf(v.x), fracf(v.y));
1225 }
1226 inline __host__ __device__ float3 fracf(float3 v)
1227 {
1228  return make_float3(fracf(v.x), fracf(v.y), fracf(v.z));
1229 }
1230 inline __host__ __device__ float4 fracf(float4 v)
1231 {
1232  return make_float4(fracf(v.x), fracf(v.y), fracf(v.z), fracf(v.w));
1233 }
1234 
1235 ////////////////////////////////////////////////////////////////////////////////
1236 // fmod
1237 ////////////////////////////////////////////////////////////////////////////////
1238 
1239 inline __host__ __device__ float2 fmodf(float2 a, float2 b)
1240 {
1241  return make_float2(fmodf(a.x, b.x), fmodf(a.y, b.y));
1242 }
1243 inline __host__ __device__ float3 fmodf(float3 a, float3 b)
1244 {
1245  return make_float3(fmodf(a.x, b.x), fmodf(a.y, b.y), fmodf(a.z, b.z));
1246 }
1247 inline __host__ __device__ float4 fmodf(float4 a, float4 b)
1248 {
1249  return make_float4(fmodf(a.x, b.x), fmodf(a.y, b.y), fmodf(a.z, b.z), fmodf(a.w, b.w));
1250 }
1251 
1252 ////////////////////////////////////////////////////////////////////////////////
1253 // absolute value
1254 ////////////////////////////////////////////////////////////////////////////////
1255 
1256 inline __host__ __device__ float2 fabs(float2 v)
1257 {
1258  return make_float2(fabs(v.x), fabs(v.y));
1259 }
1260 inline __host__ __device__ float3 fabs(float3 v)
1261 {
1262  return make_float3(fabs(v.x), fabs(v.y), fabs(v.z));
1263 }
1264 inline __host__ __device__ float4 fabs(float4 v)
1265 {
1266  return make_float4(fabs(v.x), fabs(v.y), fabs(v.z), fabs(v.w));
1267 }
1268 
1269 inline __host__ __device__ int2 abs(int2 v)
1270 {
1271  return make_int2(abs(v.x), abs(v.y));
1272 }
1273 inline __host__ __device__ int3 abs(int3 v)
1274 {
1275  return make_int3(abs(v.x), abs(v.y), abs(v.z));
1276 }
1277 inline __host__ __device__ int4 abs(int4 v)
1278 {
1279  return make_int4(abs(v.x), abs(v.y), abs(v.z), abs(v.w));
1280 }
1281 
1282 ////////////////////////////////////////////////////////////////////////////////
1283 // reflect
1284 // - returns reflection of incident ray I around surface normal N
1285 // - N should be normalized, reflected vector's length is equal to length of I
1286 ////////////////////////////////////////////////////////////////////////////////
1287 
1288 inline __host__ __device__ float3 reflect(float3 i, float3 n)
1289 {
1290  return i - 2.0f * n * dot(n,i);
1291 }
1292 
1293 ////////////////////////////////////////////////////////////////////////////////
1294 // cross product
1295 ////////////////////////////////////////////////////////////////////////////////
1296 
1297 inline __host__ __device__ float3 cross(float3 a, float3 b)
1298 {
1299  return 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);
1300 }
1301 
1302 ////////////////////////////////////////////////////////////////////////////////
1303 // smoothstep
1304 // - returns 0 if x < a
1305 // - returns 1 if x > b
1306 // - otherwise returns smooth interpolation between 0 and 1 based on x
1307 ////////////////////////////////////////////////////////////////////////////////
1308 
1309 inline __device__ __host__ float smoothstep(float a, float b, float x)
1310 {
1311  float y = clamp((x - a) / (b - a), 0.0f, 1.0f);
1312  return (y*y*(3.0f - (2.0f*y)));
1313 }
1314 inline __device__ __host__ float2 smoothstep(float2 a, float2 b, float2 x)
1315 {
1316  float2 y = clamp((x - a) / (b - a), 0.0f, 1.0f);
1317  return (y*y*(make_float2(3.0f) - (make_float2(2.0f)*y)));
1318 }
1319 inline __device__ __host__ float3 smoothstep(float3 a, float3 b, float3 x)
1320 {
1321  float3 y = clamp((x - a) / (b - a), 0.0f, 1.0f);
1322  return (y*y*(make_float3(3.0f) - (make_float3(2.0f)*y)));
1323 }
1324 inline __device__ __host__ float4 smoothstep(float4 a, float4 b, float4 x)
1325 {
1326  float4 y = clamp((x - a) / (b - a), 0.0f, 1.0f);
1327  return (y*y*(make_float4(3.0f) - (make_float4(2.0f)*y)));
1328 }