1// Copyright 2009-2021 Intel Corporation
2// SPDX-License-Identifier: Apache-2.0
3
4#pragma once
5
6#include "math.isph"
7
8#define __define_ispc_vector2(TYPE,ABB)         \
9  struct Vec2##ABB {                            \
10    TYPE x; TYPE y;                             \
11  };                                            \
12
13#define __define_ispc_vector3(TYPE,ABB)         \
14  struct Vec3##ABB {                            \
15    TYPE x,y,z;                                 \
16  };                                            \
17  struct Vec3##ABB##a {                         \
18    TYPE x,y,z,w;                               \
19  };                                            \
20
21#define __define_ispc_vector4(TYPE,ABB)         \
22  struct Vec4##ABB {                            \
23    TYPE x,y,z,w;                               \
24  };                                            \
25
26__define_ispc_vector2(int,i);
27__define_ispc_vector2(unsigned int,ui);
28__define_ispc_vector2(unsigned int8,uc);
29__define_ispc_vector2(float,f);
30
31__define_ispc_vector3(int,i);
32__define_ispc_vector3(unsigned int,ui);
33__define_ispc_vector3(unsigned int8,uc);
34__define_ispc_vector3(float,f);
35
36__define_ispc_vector4(int,i);
37__define_ispc_vector4(unsigned int,ui);
38__define_ispc_vector4(unsigned int8,uc);
39__define_ispc_vector4(float,f);
40
41#undef __define_ispc_vector2
42#undef __define_ispc_vector3
43#undef __define_ispc_vector4
44
45
46
47
48/*! defines all constructors "make_Vec2[T]" for 2-vector type */
49#define __define_ispc_constructors2(UV,TYPE,ABB,ITYPE,IABB)     \
50  inline UV Vec2##ABB make_Vec2##ABB(const UV ITYPE x,          \
51                                     const UV ITYPE y)          \
52  {                                                             \
53    UV Vec2##ABB ret;                                           \
54    ret.x = x;                                                  \
55    ret.y = y;                                                  \
56    return ret;                                                 \
57  }                                                             \
58  inline UV Vec2##ABB make_Vec2##ABB(const UV ITYPE x)          \
59  {                                                             \
60    UV Vec2##ABB ret;                                           \
61    ret.x = x;                                                  \
62    ret.y = x;                                                  \
63    return ret;                                                 \
64  }                                                             \
65
66/*! defines all constructors "make_Vec3[T]" and "make_Vec3[T]a" for
67  3-vector type */
68#define __define_ispc_constructors3(UV,TYPE,ABB,ITYPE,IABB)             \
69  inline UV Vec3##ABB make_Vec3##ABB(const UV ITYPE x)                  \
70  {                                                                     \
71    UV Vec3##ABB ret;                                                   \
72    ret.x = x;                                                          \
73    ret.y = x;                                                          \
74    ret.z = x;                                                          \
75    return ret;                                                         \
76  }                                                                     \
77  inline UV Vec3##ABB make_Vec3##ABB(const UV Vec3##IABB v)             \
78  {                                                                     \
79    UV Vec3##ABB ret;                                                   \
80    ret.x = v.x;                                                        \
81    ret.y = v.y;                                                        \
82    ret.z = v.z;                                                        \
83    return ret;                                                         \
84  }                                                                     \
85  inline UV Vec3##ABB make_Vec3##ABB(const UV Vec3##IABB##a v)          \
86  {                                                                     \
87    UV Vec3##ABB ret;                                                   \
88    ret.x = v.x;                                                        \
89    ret.y = v.y;                                                        \
90    ret.z = v.z;                                                        \
91    return ret;                                                         \
92  }                                                                     \
93  inline UV Vec3##ABB make_Vec3##ABB(const UV ITYPE x,                  \
94                                     const UV ITYPE y,                  \
95                                     const UV ITYPE z)                  \
96  {                                                                     \
97    UV Vec3##ABB ret;                                                   \
98    ret.x = x;                                                          \
99    ret.y = y;                                                          \
100    ret.z = z;                                                          \
101    return ret;                                                         \
102  }                                                                     \
103  inline UV Vec3##ABB make_Vec3##ABB(const UV Vec4##IABB v)             \
104  {                                                                     \
105    UV Vec3##ABB ret;                                                   \
106    ret.x = v.x;                                                        \
107    ret.y = v.y;                                                        \
108    ret.z = v.z;                                                        \
109    return ret;                                                         \
110  }                                                                     \
111  /* the '3a' variants */                                               \
112  inline UV Vec3##ABB##a make_Vec3##ABB##a(const UV ITYPE x)            \
113  {                                                                     \
114    UV Vec3##ABB##a ret;                                                \
115    ret.x = x;                                                          \
116    ret.y = x;                                                          \
117    ret.z = x;                                                          \
118    ret.w = 0;                                                          \
119    return ret;                                                         \
120  }                                                                     \
121  inline UV Vec3##ABB##a make_Vec3##ABB##a(const UV Vec3##IABB &v)      \
122  {                                                                     \
123    UV Vec3##ABB##a ret;                                                \
124    ret.x = v.x;                                                        \
125    ret.y = v.y;                                                        \
126    ret.z = v.z;                                                        \
127    ret.w = 0;                                                          \
128    return ret;                                                         \
129  }                                                                     \
130  inline UV Vec3##ABB##a make_Vec3##ABB##a(const UV Vec3##IABB##a v)    \
131  {                                                                     \
132    UV Vec3##ABB##a ret;                                                \
133    ret.x = v.x;                                                        \
134    ret.y = v.y;                                                        \
135    ret.z = v.z;                                                        \
136    ret.w = v.w;                                                        \
137    return ret;                                                         \
138  }                                                                     \
139  inline UV Vec3##ABB##a make_Vec3##ABB##a(const UV ITYPE x,            \
140                                           const UV ITYPE y,            \
141                                           const UV ITYPE z)            \
142  {                                                                     \
143    UV Vec3##ABB##a ret;                                                \
144    ret.x = x;                                                          \
145    ret.y = y;                                                          \
146    ret.z = z;                                                          \
147    ret.w = 0;                                                          \
148    return ret;                                                         \
149  }                                                                     \
150  inline UV Vec3##ABB##a make_Vec3##ABB##a(const UV ITYPE x,            \
151                                           const UV ITYPE y,            \
152                                           const UV ITYPE z,            \
153                                           const UV ITYPE w)            \
154  {                                                                     \
155    UV Vec3##ABB##a ret;                                                \
156    ret.x = x;                                                          \
157    ret.y = y;                                                          \
158    ret.z = z;                                                          \
159    ret.w = w;                                                          \
160    return ret;                                                         \
161  }                                                                     \
162  inline UV Vec3##ABB##a make_Vec3##ABB##a(const UV Vec3##IABB &v,      \
163                                           const UV ITYPE w)            \
164  {                                                                     \
165    UV Vec3##ABB##a ret;                                                \
166    ret.x = v.x;                                                        \
167    ret.y = v.y;                                                        \
168    ret.z = v.z;                                                        \
169    ret.w = w;                                                          \
170    return ret;                                                         \
171  }                                                                     \
172  inline UV Vec3##ABB##a make_Vec3##ABB##a(const UV Vec4##IABB v)       \
173  {                                                                     \
174    UV Vec3##ABB##a ret;                                                \
175    ret.x = v.x;                                                        \
176    ret.y = v.y;                                                        \
177    ret.z = v.z;                                                        \
178    ret.w = v.w;                                                        \
179    return ret;                                                         \
180  }                                                                     \
181
182
183
184
185
186/*! defines all constructors "make_Vec4[T]" for 4-vector type */
187#define __define_ispc_constructors4(UV,TYPE,ABB,ITYPE,IABB)     \
188  /*! construct Vec4 from a single scalar */                    \
189  inline UV Vec4##ABB make_Vec4##ABB(const UV ITYPE f)          \
190  {                                                             \
191    UV Vec4##ABB ret;                                           \
192    ret.x = f;                                                  \
193    ret.y = f;                                                  \
194    ret.z = f;                                                  \
195    ret.w = f;                                                  \
196    return ret;                                                 \
197  }                                                             \
198  /*! construct Vec4 from a 4 scalars */                        \
199  inline UV Vec4##ABB make_Vec4##ABB(const UV ITYPE x,          \
200                                     const UV ITYPE y,          \
201                                     const UV ITYPE z,          \
202                                     const UV ITYPE w)          \
203  {                                                             \
204    UV Vec4##ABB ret;                                           \
205    ret.x = x;                                                  \
206    ret.y = y;                                                  \
207    ret.z = z;                                                  \
208    ret.w = w;                                                  \
209    return ret;                                                 \
210  }                                                             \
211  /*! construct Vec4 from another Vec4 (of another type) */     \
212  inline UV Vec4##ABB make_Vec4##ABB(const UV Vec4##IABB v)     \
213  {                                                             \
214    UV Vec4##ABB ret;                                           \
215    ret.x = v.x;                                                \
216    ret.y = v.y;                                                \
217    ret.z = v.z;                                                \
218    ret.w = v.w;                                                \
219    return ret;                                                 \
220  }                                                             \
221
222
223#define __define_ispc_lift_constructors4(UV,TYPE,ABB)           \
224  /*! lift Vec4 from Vec3; fill in with 0es */                  \
225  inline UV Vec4##ABB make_Vec4##ABB(const UV Vec3##ABB v)      \
226  {                                                             \
227    UV Vec4##ABB ret;                                           \
228    ret.x = (TYPE)v.x;                                          \
229    ret.y = (TYPE)v.y;                                          \
230    ret.z = (TYPE)v.z;                                          \
231    ret.w = (TYPE)0;                                            \
232    return ret;                                                 \
233  }                                                             \
234
235#define __define_ispc_constructors_uv_t(UV,OTYPE,OABB,ITYPE,IABB)       \
236  __define_ispc_constructors2(UV,OTYPE,OABB,ITYPE,IABB)                 \
237  __define_ispc_constructors3(UV,OTYPE,OABB,ITYPE,IABB)                 \
238  __define_ispc_constructors4(UV,OTYPE,OABB,ITYPE,IABB)                 \
239
240#define __define_ispc_constructors_uv(UV,TYPE,ABB)              \
241  __define_ispc_constructors_uv_t(UV,TYPE,ABB,int,i)            \
242  __define_ispc_constructors_uv_t(UV,TYPE,ABB,unsigned int,ui)  \
243  __define_ispc_constructors_uv_t(UV,TYPE,ABB,unsigned int8,uc) \
244  __define_ispc_constructors_uv_t(UV,TYPE,ABB,float,f)          \
245  __define_ispc_lift_constructors4(UV,TYPE,ABB)                 \
246
247#define __define_ispc_constructors(UV)                  \
248  __define_ispc_constructors_uv(UV,unsigned int,ui)     \
249  __define_ispc_constructors_uv(UV,unsigned int8,uc)    \
250  __define_ispc_constructors_uv(UV,int,i)               \
251  __define_ispc_constructors_uv(UV,float,f)             \
252
253__define_ispc_constructors(uniform);
254__define_ispc_constructors(varying);
255
256#undef __define_ispc_constructors2
257#undef __define_ispc_constructors3
258#undef __define_ispc_constructors3a
259#undef __define_ispc_constructors4
260#undef __define_ispc_lift_constructors4
261#undef __define_ispc_constructors_uv
262#undef __define_ispc_constructors
263
264
265// =======================================================
266// define 'lifted' binary operators (min/max/...)
267
268#define __lift_binaryFct(FCT,T)                                         \
269  /* ********************************************************* */       \
270  /*                    ---- Vec2 ----                         */       \
271  /* ********************************************************* */       \
272  /* uniform Vec2 FCT(uniform Vec2, uniform Vec2) */                    \
273  inline uniform Vec2##T FCT(const uniform Vec2##T a,                   \
274                             const uniform Vec2##T b)                   \
275  {  return make_Vec2##T(FCT(a.x,b.x),FCT(a.y,b.y)); }                  \
276  /* Vec2 FCT(Vec2, Vec2) */                                            \
277  inline varying Vec2##T FCT(const varying Vec2##T a,                   \
278                             const varying Vec2##T b)                   \
279  {  return make_Vec2##T(FCT(a.x,b.x),FCT(a.y,b.y)); }                  \
280  /* Vec2 FCT(Vec2, uniform Vec2) */                                    \
281  inline varying Vec2##T FCT(const varying Vec2##T a,                   \
282                             const uniform Vec2##T b)                   \
283  {  return make_Vec2##T(FCT(a.x,b.x),FCT(a.y,b.y)); }                  \
284  /* Vec2 FCT(uniform Vec2, Vec2) */                                    \
285  inline varying Vec2##T FCT(const uniform Vec2##T a,                   \
286                             const varying Vec2##T b)                   \
287  {  return make_Vec2##T(FCT(a.x,b.x),FCT(a.y,b.y)); }                  \
288                                                                        \
289  /* ********************************************************* */       \
290  /*                    ---- Vec3 ----                         */       \
291  /* ********************************************************* */       \
292  /* uniform Vec3 FCT(uniform Vec3, uniform Vec3) */                    \
293  inline uniform Vec3##T FCT(const uniform Vec3##T a,                   \
294                             const uniform Vec3##T b)                   \
295  {  return make_Vec3##T(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z)); }     \
296  /* Vec3 FCT(Vec3, Vec3) */                                            \
297  inline varying Vec3##T FCT(const varying Vec3##T a,                   \
298                             const varying Vec3##T b)                   \
299  {  return make_Vec3##T(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z)); }     \
300  /* Vec3 FCT(uniformVec3, Vec3) */                                     \
301  inline varying Vec3##T FCT(const uniform Vec3##T a,                   \
302                             const varying Vec3##T b)                   \
303  {  return make_Vec3##T(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z)); }     \
304  /* Vec3 FCT(Vec3, uniformVec3) */                                     \
305  inline varying Vec3##T FCT(const varying Vec3##T a,                   \
306                             const uniform Vec3##T b)                   \
307  {  return make_Vec3##T(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z)); }     \
308                                                                        \
309  /* ********************************************************* */       \
310  /*                    ---- Vec3a (from 3a and 3a) ----  */            \
311  /* ********************************************************* */       \
312  /* uniform Vec3a FCT(uniform Vec3a, uniform Vec3a) */                 \
313  inline uniform Vec3##T##a FCT(const uniform Vec3##T##a a,             \
314                                const uniform Vec3##T##a b)             \
315  {  return make_Vec3##T##a(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z),FCT(a.w,b.w)); } \
316  /* Vec3a FCT(Vec3a, Vec3a) */                                         \
317  inline varying Vec3##T##a FCT(const varying Vec3##T##a a,             \
318                                const varying Vec3##T##a b)             \
319  {  return make_Vec3##T##a(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z),FCT(a.w,b.w)); } \
320                                                                        \
321  /* ********************************************************* */       \
322  /*                    ---- Vec3a (from 3 and 3a) ----  */             \
323  /* ********************************************************* */       \
324  /* uniform Vec3a FCT(uniform Vec3a, uniform Vec3a) */                 \
325  inline uniform Vec3##T##a FCT(const uniform Vec3##T a,                \
326                                const uniform Vec3##T##a b)             \
327  {  return make_Vec3##T##a(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z)); }  \
328  /* Vec3a FCT(Vec3a, Vec3a) */                                         \
329  inline varying Vec3##T##a FCT(const varying Vec3##T a,                \
330                                const varying Vec3##T##a b)             \
331  {  return make_Vec3##T##a(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z)); }  \
332                                                                        \
333  /* ********************************************************* */       \
334  /*                    ---- Vec3a (from 3a and 3) ----  */             \
335  /* ********************************************************* */       \
336  /* uniform Vec3a FCT(uniform Vec3a, uniform Vec3a) */                 \
337  inline uniform Vec3##T##a FCT(const uniform Vec3##T##a a,             \
338                                const uniform Vec3##T b)                \
339  {  return make_Vec3##T##a(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z)); }  \
340  /* Vec3a FCT(Vec3a, Vec3a) */                                         \
341  inline varying Vec3##T##a FCT(const varying Vec3##T##a a,             \
342                                const varying Vec3##T b)                \
343  {  return make_Vec3##T##a(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z)); }  \
344                                                                        \
345  /* ********************************************************* */       \
346  /*                    ---- Vec4 ----                         */       \
347  /* ********************************************************* */       \
348  /* uniform Vec4 FCT(uniform Vec4, uniform Vec4) */                    \
349  inline uniform Vec4##T FCT(const uniform Vec4##T a,                   \
350                             const uniform Vec4##T b)                   \
351  {  return make_Vec4##T(FCT(a.x,b.x),FCT(a.y,b.y),                     \
352                         FCT(a.z,b.z),FCT(a.w,b.w)); }                  \
353  /* Vec4 FCT(Vec4, Vec4) */                                            \
354  inline varying Vec4##T FCT(const varying Vec4##T a,                   \
355                             const varying Vec4##T b)                   \
356  {  return make_Vec4##T(FCT(a.x,b.x),FCT(a.y,b.y),                     \
357                         FCT(a.z,b.z),FCT(a.w,b.w)); }                  \
358
359__lift_binaryFct(min,f)
360__lift_binaryFct(max,f)
361__lift_binaryFct(min,i)
362__lift_binaryFct(max,i)
363__lift_binaryFct(min,ui)
364__lift_binaryFct(max,ui)
365
366#undef __lift_binaryFct
367
368// =======================================================
369
370// for now, let's implement those manually - should eventually do those via a macro!
371
372inline uniform Vec3f neg(const uniform Vec3f v)
373{ return make_Vec3f(-v.x,-v.y,-v.z); }
374inline Vec3f neg(const Vec3f v)
375{ return make_Vec3f(-v.x,-v.y,-v.z); }
376inline uniform Vec3f negate(const uniform Vec3f &a)
377{ return(make_Vec3f(-a.x, -a.y, -a.z)); }
378inline varying Vec3f negate(const varying Vec3f &a)
379{ return(make_Vec3f(-a.x, -a.y, -a.z)); }
380
381
382#define __define_binary_operator_typed(opname,op,abb,type)              \
383  /* Vec2##abb */                                                       \
384  inline uniform Vec2##abb opname (const uniform Vec2##abb a,           \
385                                   const uniform Vec2##abb b) {         \
386    return make_Vec2##abb(a.x op b.x, a.y op b.y);                      \
387  }                                                                     \
388  inline Vec2##abb opname (const Vec2##abb a, const Vec2##abb b) {      \
389    return make_Vec2##abb(a.x op b.x, a.y op b.y);                      \
390  }                                                                     \
391  inline uniform Vec2##abb opname (const uniform Vec2##abb a,           \
392                                   const uniform type b) {              \
393    return make_Vec2##abb(a.x op b, a.y op b);                          \
394  }                                                                     \
395  inline Vec2##abb opname (const Vec2##abb a, const type b) {           \
396    return make_Vec2##abb(a.x op b, a.y op b);                          \
397  }                                                                     \
398  inline uniform Vec2##abb opname (const uniform type a,                \
399                                   const uniform Vec2##abb b) {         \
400    return make_Vec2##abb(a op b.x, a op b.y);                          \
401  }                                                                     \
402  inline Vec2##abb opname (const type a, const Vec2##abb b) {           \
403    return make_Vec2##abb(a op b.x, a op b.y);                          \
404  }                                                                     \
405  /* Vec3##abb */                                                       \
406  inline uniform Vec3##abb opname (const uniform Vec3##abb a,           \
407                                   const uniform Vec3##abb b) {         \
408    return make_Vec3##abb(a.x op b.x, a.y op b.y, a.z op b.z);          \
409  }                                                                     \
410  inline Vec3##abb opname (const Vec3##abb a, const Vec3##abb b) {      \
411    return make_Vec3##abb(a.x op b.x, a.y op b.y, a.z op b.z);          \
412  }                                                                     \
413  inline uniform Vec3##abb opname (const uniform Vec3##abb a,           \
414                                   const uniform type b) {              \
415    return make_Vec3##abb(a.x op b, a.y op b, a.z op b);                \
416  }                                                                     \
417  inline Vec3##abb opname (const Vec3##abb a, const type b) {           \
418    return make_Vec3##abb(a.x op b, a.y op b, a.z op b);                \
419  }                                                                     \
420  inline uniform Vec3##abb opname (const uniform type a,                \
421                                   const uniform Vec3##abb b) {         \
422    return make_Vec3##abb(a op b.x, a op b.y, a op b.z);                \
423  }                                                                     \
424  inline Vec3##abb opname (const type a, const Vec3##abb b) {           \
425    return make_Vec3##abb(a op b.x, a op b.y, a op b.z);                \
426  }                                                                     \
427  /* Vec3##abb##a */                                                    \
428  inline uniform Vec3##abb##a opname (const uniform Vec3##abb##a a,     \
429                                      const uniform Vec3##abb##a b) {   \
430    return make_Vec3##abb##a(a.x op b.x, a.y op b.y, a.z op b.z, a.w op b.w); \
431  }                                                                     \
432  inline Vec3##abb##a opname (const Vec3##abb##a a, const Vec3##abb##a b) { \
433    return make_Vec3##abb##a(a.x op b.x, a.y op b.y, a.z op b.z, a.w op b.w); \
434  }                                                                     \
435  inline uniform Vec3##abb##a opname (const uniform Vec3##abb##a a,     \
436                                      const uniform type b) {           \
437    return make_Vec3##abb##a(a.x op b, a.y op b, a.z op b, a.w op b);   \
438  }                                                                     \
439  inline Vec3##abb##a opname (const Vec3##abb##a a, const type b) {     \
440    return make_Vec3##abb##a(a.x op b, a.y op b, a.z op b, a.w op b);   \
441  }                                                                     \
442  inline uniform Vec3##abb##a opname (const uniform type a,             \
443                                      const uniform Vec3##abb##a b) {   \
444    return make_Vec3##abb##a(a op b.x, a op b.y, a op b.z, a op b.w);   \
445  }                                                                     \
446  inline Vec3##abb##a opname (const type a, const Vec3##abb##a b) {     \
447    return make_Vec3##abb##a(a op b.x, a op b.y, a op b.z, a op b.w);   \
448  }                                                                     \
449  /* Vec4##abb */                                                       \
450  inline uniform Vec4##abb opname (const uniform Vec4##abb a,           \
451                                   const uniform Vec4##abb b) {         \
452    return make_Vec4##abb(a.x op b.x, a.y op b.y, a.z op b.z, a.w op b.w); \
453  }                                                                     \
454  inline Vec4##abb opname (const Vec4##abb a, const Vec4##abb b) {      \
455    return make_Vec4##abb(a.x op b.x, a.y op b.y, a.z op b.z, a.w op b.w); \
456  }                                                                     \
457  inline uniform Vec4##abb opname (const uniform Vec4##abb a,           \
458                                   const uniform type b) {              \
459    return make_Vec4##abb(a.x op b, a.y op b, a.z op b, a.w op b);      \
460  }                                                                     \
461  inline Vec4##abb opname (const Vec4##abb a, const type b) {           \
462    return make_Vec4##abb(a.x op b, a.y op b, a.z op b, a.w op b);      \
463  }                                                                     \
464  inline uniform Vec4##abb opname (const uniform type a,                \
465                                   const uniform Vec4##abb b) {         \
466    return make_Vec4##abb(a op b.x, a op b.y, a op b.z, a op b.w);      \
467  }                                                                     \
468  inline Vec4##abb opname (const type a, const Vec4##abb b) {           \
469    return make_Vec4##abb(a op b.x, a op b.y, a op b.z, a op b.w);      \
470  }
471
472#define __define_binary_operator(opname,op)             \
473  __define_binary_operator_typed(opname,op,f,float)     \
474  __define_binary_operator_typed(opname,op,i,int32)     \
475  __define_binary_operator_typed(opname,op,ui,uint32)
476
477
478// define 'regular' operators
479__define_binary_operator( operator+, + );
480__define_binary_operator( operator-, - );
481__define_binary_operator( operator*, * );
482__define_binary_operator( operator/, / );
483
484// define old functional operators as used in the embree path tracer, deprecated
485__define_binary_operator( add, + );
486__define_binary_operator( sub, - );
487__define_binary_operator( mul, * );
488
489#undef __define_binary_operator
490
491inline float reduce_mul(const Vec3f v)
492{ return v.x * v.y * v.z; }
493inline uniform float reduce_mul(const uniform Vec3f v)
494{ return v.x * v.y * v.z; }
495
496inline float reduce_max(const Vec3f v)
497{ return max(max(v.x,v.y),v.z); }
498
499inline float reduce_add(const Vec3f v)
500{ return v.x+v.y+v.z; }
501
502inline uniform float reduce_add(const uniform Vec3f v)
503{ return v.x+v.y+v.z; }
504
505inline float reduce_avg(const Vec3f v)
506{ return (v.x+v.y+v.z)*(1.0f/3.0f); }
507
508inline float luminance(const Vec3f& c)
509{ return 0.212671f*c.x + 0.715160f*c.y + 0.072169f*c.z; }
510
511inline uniform bool eq(const uniform Vec2f a, const uniform Vec2f b)
512{ return a.x==b.x && a.y==b.y; }
513inline bool eq(const Vec2f a, const Vec2f b)
514{ return a.x==b.x & a.y==b.y; }
515inline uniform bool eq(const uniform Vec3f a, const uniform Vec3f b)
516{ return a.x==b.x && a.y==b.y && a.z==b.z; }
517inline bool eq(const Vec3f a, const Vec3f b)
518{ return a.x==b.x & a.y==b.y & a.z==b.z; }
519inline uniform bool eq(const uniform Vec3fa a, const uniform Vec3fa b)
520{ return a.x==b.x && a.y==b.y && a.z==b.z; }
521inline bool eq(const Vec3fa a, const Vec3fa b)
522{ return a.x==b.x & a.y==b.y & a.z==b.z; }
523
524inline uniform bool ne(const uniform Vec2f a, const uniform Vec2f b)
525{ return !eq(a,b); }
526inline bool ne(const Vec2f a, const Vec2f b)
527{ return !eq(a,b); }
528inline uniform bool ne(const uniform Vec3f a, const uniform Vec3f b)
529{ return !eq(a,b); }
530inline bool ne(const Vec3f a, const Vec3f b)
531{ return !eq(a,b); }
532inline uniform bool ne(const uniform Vec3fa a, const uniform Vec3fa b)
533{ return !eq(a,b); }
534inline bool ne(const Vec3fa a, const Vec3fa b)
535{ return !eq(a,b); }
536
537
538// ------------------------------------------------------------------
539// dot product
540// ------------------------------------------------------------------
541/*! computes 3D dot product for *all-uniform* Vec3fs */
542inline uniform float dot(const uniform Vec3f a, const uniform Vec3f b)
543{ return a.x*b.x+a.y*b.y+a.z*b.z; }
544/*! computes 3D dot product for Vec3fs that produce varying results */
545inline float dot(const Vec3f a, const Vec3f b)
546{ return a.x*b.x+a.y*b.y+a.z*b.z; }
547
548inline uniform float length(const uniform Vec3f a) { return sqrtf(dot(a,a)); }
549inline varying float length(const varying Vec3f a) { return sqrtf(dot(a,a)); }
550
551inline uniform float distance(const uniform Vec3f a, const uniform Vec3f b) { return length(a - b); }
552inline varying float distance(const varying Vec3f a, const varying Vec3f b) { return length(a - b); }
553
554
555inline uniform float dot(const uniform Vec3fa a, const uniform Vec3fa b) { return a.x*b.x+a.y*b.y+a.z*b.z; }
556inline varying float dot(const varying Vec3fa a, const varying Vec3fa b) { return a.x*b.x+a.y*b.y+a.z*b.z; }
557
558inline uniform float length(const uniform Vec3fa a) { return sqrtf(dot(a,a)); }
559inline varying float length(const varying Vec3fa a) { return sqrtf(dot(a,a)); }
560
561inline uniform float distance(const uniform Vec3fa a, const uniform Vec3fa b) { return length(a - b); }
562inline varying float distance(const varying Vec3fa a, const varying Vec3fa b) { return length(a - b); }
563
564// ------------------------------------------------------------------
565// cross product
566// ------------------------------------------------------------------
567/*! computes 3D cross product for *all-uniform* Vec3fs */
568inline uniform Vec3f cross(const uniform Vec3f &a, const uniform Vec3f &b)
569{ return make_Vec3f(a.y*b.z-a.z*b.y,
570                    a.z*b.x-a.x*b.z,
571                    a.x*b.y-a.y*b.x); }
572/*! computes 3D cross product for Vec3fs that produce varying results */
573inline Vec3f cross(const Vec3f &a, const Vec3f &b)
574{ return make_Vec3f(a.y*b.z-a.z*b.y,
575                    a.z*b.x-a.x*b.z,
576                    a.x*b.y-a.y*b.x); }
577
578
579// ------------------------------------------------------------------
580// normalize
581// ------------------------------------------------------------------
582/*! compute and return normalized version of uniform Vec3f passed to this fct */
583inline uniform Vec3f normalize(const uniform Vec3f &v)
584{ return v * (1.f/sqrt(dot(v,v))); }
585/*! compute and return normalized version of varying Vec3f passed to this fct */
586inline Vec3f normalize(const Vec3f v)
587{ return v * (1.f/sqrt(dot(v,v))); }
588/*! compute and return normalized version of varying Vec3f passed to this fct */
589inline Vec3f normalize(const Vec3f v, float &len)
590{ len = sqrtf(dot(v,v)); return v * rcpf(len); }
591
592inline Vec3f safe_normalize(const Vec3f v)
593{ return v * (1.f/sqrt(max(1e-6f,dot(v,v)))); }
594
595/*! differentiated normalization */
596inline varying Vec3f dnormalize(const varying Vec3f& p, const varying Vec3f& dp)
597{
598  const float pp  = dot(p,p);
599  const float pdp = dot(p,dp);
600  return (pp*dp-pdp*p)*rcp(pp)*rsqrt(pp);
601}
602
603
604inline uniform Vec3fa normalize(const uniform Vec3fa &v) { return v * (1.f/sqrt(dot(v,v))); }
605inline varying Vec3fa normalize(const varying Vec3fa  v) { return v * (1.f/sqrt(dot(v,v))); }
606
607inline varying Vec3fa dnormalize(const varying Vec3fa& p, const varying Vec3fa& dp)
608{
609  const float pp  = dot(p,p);
610  const float pdp = dot(p,dp);
611  return (pp*dp-pdp*p)*rcp(pp)*rsqrt(pp);
612}
613
614
615#define __lift_unary_fct(F)                             \
616  inline uniform Vec2f F(const uniform Vec2f v)         \
617  { return make_Vec2f(F(v.x),F(v.y)); }                 \
618  inline Vec2f F(const Vec2f v)                         \
619  { return make_Vec2f(F(v.x),F(v.y)); }                 \
620  inline uniform Vec3f F(const uniform Vec3f v)         \
621  { return make_Vec3f(F(v.x),F(v.y),F(v.z)); }          \
622  inline Vec3f F(const Vec3f v)                         \
623  { return make_Vec3f(F(v.x),F(v.y),F(v.z)); }          \
624  inline uniform Vec3fa F(const uniform Vec3fa v)       \
625  { return make_Vec3fa(F(v.x),F(v.y),F(v.z),F(v.w)); }  \
626  inline Vec3fa F(const Vec3fa v)                       \
627  { return make_Vec3fa(F(v.x),F(v.y),F(v.z),F(v.w)); }  \
628  inline uniform Vec4f F(const uniform Vec4f v)         \
629  { return make_Vec4f(F(v.x),F(v.y),F(v.z),F(v.w)); }   \
630  inline Vec4f F(const Vec4f v)                         \
631  { return make_Vec4f(F(v.x),F(v.y),F(v.z),F(v.w)); }
632
633__lift_unary_fct(absf)
634__lift_unary_fct(rcpf)
635__lift_unary_fct(expf)
636__lift_unary_fct(logf)
637
638__lift_unary_fct(floor)
639__lift_unary_fct(abs)
640__lift_unary_fct(rcp)
641__lift_unary_fct(exp)
642__lift_unary_fct(frac)
643__lift_unary_fct(sqr)
644
645#undef __lift_unary_fct
646
647/*! make RGBA from RGB */
648inline Vec4f make_Vec4f(const Vec3f rgb, const float a)
649{ return make_Vec4f(rgb.x,rgb.y,rgb.z,a); }
650
651/*! make RGBA from RGB */
652inline uniform Vec4f make_Vec4f(const uniform Vec3f rgb, const uniform float a)
653{ return make_Vec4f(rgb.x,rgb.y,rgb.z,a); }
654
655// // ------------------------------------------------------------------
656// // vector functions (abs,rcp,...):
657// // ------------------------------------------------------------------
658// /*! return vector of absolute values of input vector */
659// inline uniform Vec3f abs(const uniform Vec3f v)
660// { return make_Vec3f(abs(v.x),abs(v.y),abs(v.z)); }
661// /*! return vector of absolute values of input vector */
662// inline Vec3f abs(const Vec3f v)
663// { return make_Vec3f(abs(v.x),abs(v.y),abs(v.z)); }
664// /*! return vector of reciprocals of input vector */
665// inline uniform Vec3f rcp(const uniform Vec3f v)
666// { return make_Vec3f(rcp(v.x),rcp(v.y),rcp(v.z)); }
667// /*! return vector of reciprocals of input vector */
668// inline Vec3f rcp(const Vec3f v)
669// { return make_Vec3f(rcp(v.x),rcp(v.y),rcp(v.z)); }
670
671#define __define_lerp2(ABB)                                             \
672  inline uniform Vec2##ABB lerp(uniform float factor, const uniform Vec2##ABB a, const uniform Vec2##ABB b) \
673  {                                                                     \
674    return make_Vec2##ABB(lerp(factor, a.x, b.x), lerp(factor, a.y, b.y)); \
675  }                                                                     \
676  inline Vec2##ABB lerp(float factor, const Vec2##ABB a, const Vec2##ABB b) \
677  {                                                                     \
678    return make_Vec2##ABB(lerp(factor, a.x, b.x), lerp(factor, a.y, b.y)); \
679  }
680
681#define __define_lerp3(ABB)                                             \
682  inline uniform Vec3##ABB lerp(uniform float factor, const uniform Vec3##ABB a, const uniform Vec3##ABB b) \
683  {                                                                     \
684    return make_Vec3##ABB(lerp(factor, a.x, b.x), lerp(factor, a.y, b.y), lerp(factor, a.z, b.z)); \
685  }                                                                     \
686  inline Vec3##ABB lerp(float factor, const Vec3##ABB a, const Vec3##ABB b) \
687  {                                                                     \
688    return make_Vec3##ABB(lerp(factor, a.x, b.x), lerp(factor, a.y, b.y), lerp(factor, a.z, b.z)); \
689  }                                                                     \
690
691#define __define_lerp3a(ABB)                                            \
692  inline uniform Vec3##ABB##a lerp(uniform float factor, const uniform Vec3##ABB##a a, const uniform Vec3##ABB##a b) \
693  {                                                                     \
694    return make_Vec3##ABB##a(lerp(factor, a.x, b.x), lerp(factor, a.y, b.y), lerp(factor, a.z, b.z), lerp(factor, a.w, b.w)); \
695  }                                                                     \
696  inline Vec3##ABB##a lerp(float factor, const Vec3##ABB##a a, const Vec3##ABB##a b) \
697  {                                                                     \
698    return make_Vec3##ABB##a(lerp(factor, a.x, b.x), lerp(factor, a.y, b.y), lerp(factor, a.z, b.z), lerp(factor, a.w, b.w)); \
699  }
700
701#define __define_lerp4(ABB)                                             \
702  inline uniform Vec4##ABB lerp(uniform float factor, const uniform Vec4##ABB a, const uniform Vec4##ABB b) \
703  {                                                                     \
704    return make_Vec4##ABB(lerp(factor, a.x, b.x), lerp(factor, a.y, b.y), lerp(factor, a.z, b.z), lerp(factor, a.w, b.w)); \
705  }                                                                     \
706  inline Vec4##ABB lerp(float factor, const Vec4##ABB a, const Vec4##ABB b) \
707  {                                                                     \
708    return make_Vec4##ABB(lerp(factor, a.x, b.x), lerp(factor, a.y, b.y), lerp(factor, a.z, b.z), lerp(factor, a.w, b.w)); \
709  }
710
711__define_lerp2(f)
712__define_lerp2(i)
713__define_lerp2(ui)
714__define_lerp2(uc)
715__define_lerp3(f)
716__define_lerp3(i)
717__define_lerp3(ui)
718__define_lerp3(uc)
719//__define_lerp3a(i)
720//__define_lerp3a(ui)
721//__define_lerp3a(uc)
722__define_lerp4(f)
723__define_lerp4(i)
724__define_lerp4(ui)
725__define_lerp4(uc)
726
727#undef __define_lerp2
728#undef __define_lerp3
729#undef __define_lerp4
730
731inline Vec2i make_Vec2i(const Vec2f &a)
732{ return make_Vec2i((int)a.x, (int)a.y); }
733
734inline Vec2i integer_cast(const Vec2f &a)
735{ return make_Vec2i(a); }
736
737inline Vec2f clamp(const Vec2f &a, const uniform Vec2f &b, const uniform Vec2f &c)
738{ return(make_Vec2f(clamp(a.x, b.x, c.x), clamp(a.y, b.y, c.y))); }
739
740
741inline uniform Vec3i operator*(const uniform Vec3i &a, const uniform int b)
742{ return(make_Vec3i(a.x * b, a.y * b, a.z * b)); }
743
744inline uniform Vec3i operator+(const uniform Vec3i &a, const uniform Vec3i &b)
745{ return(make_Vec3i(a.x + b.x, a.y + b.y, a.z + b.z)); }
746
747inline Vec3i operator+(const varying Vec3i &a, const varying Vec3i &b)
748{ return(make_Vec3i(a.x + b.x, a.y + b.y, a.z + b.z)); }
749
750// Workaround for compiler bug.
751inline Vec3i operator+(const uniform Vec3i &a, const varying Vec3i &b)
752{ return(make_Vec3i(a.x + b.x, a.y + b.y, a.z + b.z)); }
753
754inline Vec3i operator+(const varying Vec3i &a, const varying int32 b)
755{ return(make_Vec3i(a.x + b, a.y + b, a.z + b)); }
756
757inline uniform Vec3i operator+(const uniform Vec3i &a, const uniform int b)
758{ return(make_Vec3i(a.x + b, a.y + b, a.z + b)); }
759
760inline uniform Vec3i operator-(const uniform Vec3i &a, const uniform int b)
761{ return(make_Vec3i(a.x - b, a.y - b, a.z - b)); }
762
763inline Vec3i operator-(const varying Vec3i &a, const uniform Vec3i &b)
764{ return(make_Vec3i(a.x - b.x, a.y - b.y, a.z - b.z)); }
765
766inline Vec3i operator-(const varying Vec3i &a, const varying Vec3i &b)
767{ return(make_Vec3i(a.x - b.x, a.y - b.y, a.z - b.z)); }
768
769inline Vec3i operator-(const varying Vec3i &a, const varying int32 b)
770{ return(make_Vec3i(a.x - b, a.y - b, a.z - b)); }
771
772inline uniform Vec3i operator/(const uniform Vec3i &a, const uniform int b)
773{ return(make_Vec3i(a.x / b, a.y / b, a.z / b)); }
774
775inline Vec3f float_cast(const Vec3i &a)
776{ return make_Vec3f(a); }
777
778inline Vec3i integer_cast(const Vec3f &a)
779{ return make_Vec3i(a); }
780
781inline Vec3i operator>>(const Vec3i &a, const int b)
782{ return(make_Vec3i(a.x >> b, a.y >> b, a.z >> b)); }
783
784inline Vec3i operator<<(const Vec3i &a, const int b)
785{ return(make_Vec3i(a.x << b, a.y << b, a.z << b)); }
786
787inline Vec3i bitwise_AND(const Vec3i &a, const int b)
788{ return(make_Vec3i(a.x & b, a.y & b, a.z &b)); }
789
790inline Vec3f powf(const Vec3f v, const float f)
791{ return make_Vec3f(powf(v.x,f),powf(v.y,f),powf(v.z,f)); }
792
793inline uniform Vec3f powf(const uniform Vec3f v, const uniform float f)
794{ return make_Vec3f(powf(v.x,f),powf(v.y,f),powf(v.z,f)); }
795
796inline Vec3f clamp(const Vec3f &a, const uniform Vec3f &b, const uniform Vec3f &c)
797{ return(make_Vec3f(clamp(a.x, b.x, c.x), clamp(a.y, b.y, c.y), clamp(a.z, b.z, c.z))); }
798
799inline Vec3f clamp(const Vec3f &a, const Vec3f &b, const Vec3f &c)
800{ return(make_Vec3f(clamp(a.x, b.x, c.x), clamp(a.y, b.y, c.y), clamp(a.z, b.z, c.z))); }
801
802inline Vec3i clamp(const Vec3i &a, const uniform Vec3i &b, const uniform Vec3i &c)
803{ return(make_Vec3i(clamp(a.x, b.x, c.x), clamp(a.y, b.y, c.y), clamp(a.z, b.z, c.z))); }
804
805//! The next machine representable number from 'a' in the direction of 'b'.
806inline uniform Vec3f nextafter(const uniform Vec3i &a, const uniform Vec3i &b)
807{ return(make_Vec3f(nextafter(a.x, b.x), nextafter(a.y, b.y), nextafter(a.z, b.z))); }
808
809inline varying float reduce_min(const varying Vec3f &a)
810{ return min(min(a.x, a.y), a.z); }
811
812inline uniform float reduce_min(const uniform Vec3f &a)
813{ return min(min(a.x, a.y), a.z); }
814
815inline uniform float reduce_min(const uniform Vec3i &a)
816{ return min(min(a.x, a.y), a.z); }
817
818inline varying float reduce_min(const varying Vec3i &a)
819{ return min(min(a.x, a.y), a.z); }
820
821inline varying float reduce_min(const varying Vec4f &a)
822{ return min(min(a.x, a.y), min(a.z, a.w)); }
823
824inline uniform float reduce_min(const uniform Vec4f &a)
825{ return min(min(a.x, a.y), min(a.z, a.w)); }
826
827inline uniform float reduce_max(const uniform Vec3i &a)
828{ return max(max(a.x, a.y), a.z); }
829
830inline varying float reduce_max(const varying Vec3i &a)
831{ return max(max(a.x, a.y), a.z); }
832
833inline varying float reduce_max(const varying Vec3f &a)
834{ return max(max(a.x, a.y), a.z); }
835
836inline uniform float reduce_max(const uniform Vec3f &a)
837{ return max(max(a.x, a.y), a.z); }
838
839inline varying float reduce_max(const varying Vec4f &a)
840{ return max(max(a.x, a.y), max(a.z, a.w)); }
841
842inline uniform float reduce_max(const uniform Vec4f &a)
843{ return max(max(a.x, a.y), max(a.z, a.w)); }
844
845inline uniform float reduce_add(const uniform Vec3f &a)
846{ return a.x+a.y+a.z; }
847
848inline uniform float reduce_avg(const uniform Vec3f &a)
849{ return reduce_add(a)*(1.0f/3.0f); }
850
851inline uniform float luminance(const uniform Vec3f& c)
852{ return 0.212671f*c.x + 0.715160f*c.y + 0.072169f*c.z; }
853
854inline varying Vec3f pow(const varying Vec3f &a, const varying float b)
855{ return make_Vec3f(pow(a.x, b), pow(a.y, b), pow(a.z, b)); }
856
857inline varying Vec4f pow(const varying Vec4f &a, const varying float b)
858{ return make_Vec4f(pow(a.x, b), pow(a.y, b), pow(a.z, b), pow(a.w, b)); }
859
860inline uniform bool isnan(uniform Vec3f v)
861{ return isnan(v.x+v.y+v.z); }
862
863inline bool isnan(Vec3f v)
864{ return isnan(v.x+v.y+v.z); }
865
866inline uniform bool isnan(uniform Vec3fa v)
867{ return isnan(v.x+v.y+v.z); }
868
869inline bool isnan(Vec3fa v)
870{ return isnan(v.x+v.y+v.z); }
871
872typedef Vec3fa Vec3ff;
873typedef Vec3f Vec3f_;
874
875inline uniform Vec3f make_Vec3f_(uniform float w) { uniform Vec3f r; r.x = w; r.y = w; r.z = w; return r; }
876inline varying Vec3f make_Vec3f_(varying float w) { varying Vec3f r; r.x = w; r.y = w; r.z = w; return r; }
877
878inline uniform Vec3f make_Vec3f_(uniform Vec3f v) { uniform Vec3f r; r.x = v.x; r.y = v.y; r.z = v.z; return r; }
879inline varying Vec3f make_Vec3f_(varying Vec3f v) { varying Vec3f r; r.x = v.x; r.y = v.y; r.z = v.z; return r; }
880
881inline uniform Vec3f make_Vec3f_(uniform Vec3fa v) { uniform Vec3f r; r.x = v.x; r.y = v.y; r.z = v.z; return r; }
882inline varying Vec3f make_Vec3f_(varying Vec3fa v) { varying Vec3f r; r.x = v.x; r.y = v.y; r.z = v.z; return r; }
883
884inline uniform Vec3ff make_Vec3ff(uniform float w) { uniform Vec3ff r; r.x = w; r.y = w; r.z = w; r.w = w; return r; }
885inline varying Vec3ff make_Vec3ff(varying float w) { varying Vec3ff r; r.x = w; r.y = w; r.z = w; r.w = w; return r; }
886
887inline uniform Vec3ff make_Vec3ff(uniform Vec3f v) { uniform Vec3ff r; r.x = v.x; r.y = v.y; r.z = v.z; r.w = 0.0f; return r; }
888inline varying Vec3ff make_Vec3ff(varying Vec3f v) { varying Vec3ff r; r.x = v.x; r.y = v.y; r.z = v.z; r.w = 0.0f; return r; }
889
890inline uniform Vec3ff make_Vec3ff(uniform Vec3fa v) { uniform Vec3ff r; r.x = v.x; r.y = v.y; r.z = v.z; r.w = 0.0f; return r; }
891inline varying Vec3ff make_Vec3ff(varying Vec3fa v) { varying Vec3ff r; r.x = v.x; r.y = v.y; r.z = v.z; r.w = 0.0f; return r; }
892
893inline uniform Vec3ff make_Vec3ff(uniform Vec3f v, uniform float w) { uniform Vec3ff r; r.x = v.x; r.y = v.y; r.z = v.z; r.w = w; return r; }
894inline varying Vec3ff make_Vec3ff(varying Vec3f v, varying float w) { varying Vec3ff r; r.x = v.x; r.y = v.y; r.z = v.z; r.w = w; return r; }
895
896inline uniform Vec3ff make_Vec3ff(uniform Vec3fa v, uniform float w) { uniform Vec3ff r; r.x = v.x; r.y = v.y; r.z = v.z; r.w = w; return r; }
897inline varying Vec3ff make_Vec3ff(varying Vec3fa v, varying float w) { varying Vec3ff r; r.x = v.x; r.y = v.y; r.z = v.z; r.w = w; return r; }
898
899inline uniform Vec3ff make_Vec3ff(uniform float x, uniform float y, uniform float z, uniform float w) { uniform Vec3ff r; r.x = x; r.y = y; r.z = z; r.w = w; return r; }
900inline varying Vec3ff make_Vec3ff(varying float x, varying float y, varying float z, varying float w) { varying Vec3ff r; r.x = x; r.y = y; r.z = z; r.w = w; return r; }
901
902inline void out(uniform Vec3f v) { print("(%,%,%)",v.x,v.y,v.z); }
903inline void out(Vec3f v) { print("\n(%\n %\n %)",v.x,v.y,v.z); }
904inline void out(uniform Vec3i v) { print("(%,%,%)",v.x,v.y,v.z); }
905inline void out(Vec3i v) { print("\n(%\n %\n %)",v.x,v.y,v.z); }
906
907
908// -------------------------------------------------------
909// set/get functions for vectors
910// should eventually get moved to macros so they work for all types
911// -------------------------------------------------------
912
913/*! set vector 'v's value in dimension 'd' to 'f' */
914inline void set(uniform Vec3f &v, const uniform uint32 dim, const uniform float f)
915{ (&v.x)[dim] = f; }
916
917/*! get vector 'v's value in dimension 'd' */
918inline uniform float get(const uniform Vec3f &v, const uniform uint32 dim)
919{ return (&v.x)[dim]; }
920inline float get(const Vec3f &v, const uniform uint32 dim)
921{ return (&v.x)[dim]; }
922
923
924// -------------------------------------------------------
925// sRGB conversion functions
926// -------------------------------------------------------
927#define APPROXIMATE_SRGB
928
929inline float linear_to_srgb(const float f)
930{
931  const float c = max(f, 0.f);
932#ifdef APPROXIMATE_SRGB
933  return pow(c, 1.f/2.2f);
934#else
935  return c <= 0.0031308f ? 12.92f*c : pow(c, 1.f/2.4f)*1.055f - 0.055f;
936#endif
937}
938
939inline Vec4f linear_to_srgba(const Vec4f c)
940{
941  return make_Vec4f(linear_to_srgb(c.x),
942                    linear_to_srgb(c.y),
943                    linear_to_srgb(c.z),
944                    max(c.w, 0.f)); // alpha is never gamma-corrected
945}
946
947inline uint32 linear_to_srgba8(const Vec4f c)
948{
949#if 1
950  Vec4f l = 255.f * min(linear_to_srgba(c), make_Vec4f(1.f));
951  return
952    ((uint32)l.x << 0)  |
953    ((uint32)l.y << 8)  |
954    ((uint32)l.z << 16) |
955    ((uint32)l.w << 24);
956#else
957//  TODO use ISPC's float_to_srgb8 once it is fixed (issue #1198)
958  return
959    (float_to_srgb8(c.x) << 0)  |
960    (float_to_srgb8(c.y) << 8)  |
961    (float_to_srgb8(c.z) << 16) |
962    ((uint32)clamp(c.w, 0.f, 1.f) << 24); // alpha is never gamma-corrected
963#endif
964}
965
966inline float srgb_to_linear(const float f)
967{
968  const float c = max(f, 0.f);
969#ifdef APPROXIMATE_SRGB
970  return pow(c, 2.2f);
971#else
972  return c <= 0.04045f ? c/12.92f : pow((c + 0.055f)/1.055f, 2.4f);
973#endif
974}
975
976inline Vec4f srgba_to_linear(const Vec4f c)
977{
978  return make_Vec4f(srgb_to_linear(c.x),
979                    srgb_to_linear(c.y),
980                    srgb_to_linear(c.z),
981                    max(c.w, 0.f));  // alpha is never gamma-corrected
982}
983
984// TODO implement srgba8_to_linear with a 256 entry LUT
985
986#undef APPROXIMATE_SRGB
987