├── LICENSE ├── README.md ├── deriv_1.glsl ├── deriv_2.glsl ├── grad_2.glsl ├── grad_3.glsl ├── hessian_2.glsl ├── grad_4.glsl ├── hessian_3.glsl ├── hessian_4.glsl ├── deriv_all.glsl └── grad_all.glsl /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 sibaku 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # glsl-autodiff 2 | 3 | Automatic differentiation for glsl 4 | 5 | This is a very simple implementation for forward mode automatic differentiation in glsl. It provides some macros to make initial callings easier. 6 | So far, the following can be evaluated 7 | 8 | * Scalar functions of one variable 9 | * Scalar functions of 2,3,4 variables 10 | * 2,3,4D functions of 2,3,4 variables 11 | 12 | Macros are provided for Gradients, Jacobians and Hessians. For vector valued functions, each component has to be described by its own function. 13 | Scalar variables are stored in a vec2, if only the first derivative is desired and in a vec3 if additionally a second derivative is desired. 14 | To compute gradients, use the GNum2/GNum3/GNum4 types. 15 | If a Hessian matrix needs to be calculated, variables are encapsulated in the structs HNum2/HNum3/HNum4. The function you need to evaluate have to use these types for their computation. Implemented functions on these objects are listed below. 16 | 17 | ## Operations on expressions 18 | 19 | Differentiable expressions are either stored in a vec2, vec3 or one of the GNum2/3/4 or HNum2/3/4 structs, as explained above. On these, a number of operations are defined: 20 | 21 | * var\*(v): Different functions with a postfix corresponding to their type. Used to create variables (identity functions) for that type 22 | * const\*(v): Different functions with a postfix corresponding to their type. Used to create constant value for that type 23 | * add(a,b): a + b, first and second order derivatives (vec2,vec3 types) can also be added by usual addition: a + b 24 | * sub(a,b): a - b, first and second order derivatives (vec2,vec3 types) can also be subtracted by usual subtraction: a - b 25 | * mult(a,b): a * b, first and second order derivatives (vec2,vec3 types) can be multiplied with a constant factor (e.g. a float) with the usual multiplication from left or right. Mult is overloaded to allow constant factor multiplication from left or right for HNum 26 | * div(a,b): a / b, first and second order derivatives (vec2,vec3 types) can be divided by a constant factor (e.g. a float) with the usual division with the vector on the left. Div is overloaded to allow constant factor division on the right of HNum 27 | * a_min(a, b) 28 | * a_max(a, b) 29 | * a_exp2(a) 30 | * a_inversesqrt(a) 31 | * a_atan(a) 32 | * a_sqrt(a) 33 | * a_sinh(a) 34 | * a_ceil(a) 35 | * a_tan(a) 36 | * a_asinh(a) 37 | * a_asin(a) 38 | * a_acosh(a) 39 | * a_abs(a) 40 | * a_exp(a) 41 | * a_cosh(a) 42 | * a_floor(a) 43 | * a_log(a) 44 | * a_atanh(a) 45 | * a_log2(a) 46 | * a_acos(a) 47 | * a_tanh(a) 48 | * a_cos(a) 49 | * a_sin(a) 50 | * a_atan2(y,x) 51 | * a_mix(a,b,t) 52 | * a_pow(a,b): Due to the GLSL implementation of pow, the result is always undefined for a < 0 53 | * a_ipow(a,b): Specialized power funcion for integer exponents that can handle negative input 54 | * neg(a): -a, creates the negation of the input. For vec2 and vec3 types, you can also use -a 55 | * inv(a): 1/a 56 | 57 | For functions that are not differentiable at certain points (such as min, max, abs) no error value will be generated to prevent unpredictable code behavior. min for example will choose the smaller function to return with its derivatives. If both functions have the same value, one is still chosen with its derivatives, which might not exist for the minimum. Basically, one side is extended into the non-differentiable point. 58 | 59 | ## Creating a variable 60 | 61 | Variables have to be created explicitely. You can do it as follows: 62 | 63 | ### First order (Scalar univariate functions) 64 | 65 | For a variable with value val: 66 | 67 | ```glsl 68 | vec2 x = varD1(val); 69 | // or manually 70 | vec2 x = vec2(val,1.0); 71 | ``` 72 | 73 | For a constant with value val: 74 | 75 | ```glsl 76 | vec2 x = constD1(val); 77 | // or manually 78 | vec2 x = vec2(val, 0.0); 79 | ``` 80 | 81 | Constants can also be created by the a_const functions 82 | 83 | ### Second order (Scalar univariate functions) 84 | 85 | Same as with first order, but with the third component always zero 86 | 87 | ```glsl 88 | vec3 variable = varD2(val); 89 | vec3 constant = constD2(val); 90 | // or manually 91 | vec3 variable = vec3(val, 1.0, 0.0); 92 | vec3 constant = vec3(val, 0.0, 0.0); 93 | ``` 94 | 95 | ### Gradients (Scalar multivariate functions) 96 | 97 | Hessian variables contain a value, the gradient and the Hessian. For variables and constants, the Hessian is zero. For constants the gradient is too. For a variable the gradient contains one zero at the variable's position in the function signature, i.e. in f(x,y,z,w) z has the index 2, counting from 0. 98 | The following shows an example for 2D functions. For 3D and 4D only the naming changes (GNum3, GNum4, constG3, varH4w, ...). 99 | 100 | ```glsl 101 | // varG(dim) functions create variables 102 | // Create variable with specified index 103 | GNum2 firstVar = varG2(firstValue, 0); 104 | GNum2 secondVar = varG2(secondValue, 1); 105 | // Create with named variable instead of index 106 | // Indices and names are as follows: 107 | // 0->x, 1->y, 2->z, 3->w 108 | // varH(dim)(name) 109 | GNum2 firstVar = varG2x(firstValue); 110 | GNum2 secondVar = varG2y(secondValue); 111 | // constG(dim) functions create constants 112 | GNum2 constVar = constG2(constValue); 113 | // or manually 114 | // For higher dimensions, the vec dimension also changes accordingly 115 | GNum2 firstVar = GNum2(firstValue, vec2(1.0, 0.0)); 116 | GNum2 secondVar = GNum2(secondValue, vec2(0.0, 1.0)); 117 | GNum2 constVar = GNum2(constValue, vec2(0.0)); 118 | ``` 119 | 120 | ### Hessians (Scalar multivariate functions) 121 | 122 | Gradient variables contain a value and the gradient. For constants the gradient is zero. For a variable the gradient contains one zero at the variable's position in the function signature, i.e. in f(x,y,z,w) z has the index 2, counting from 0. 123 | The following shows an example for 2D functions. For 3D and 4D only the naming changes (HNum3, HNum4, constH3, varH4w, ...). 124 | 125 | ```glsl 126 | // varH(dim) functions create variables 127 | // Create variable with specified index 128 | HNum2 firstVar = varH2(firstValue,0); 129 | HNum2 secondVar = varH2(secondValue,1); 130 | // Create with named variable instead of index 131 | // Indices and names are as follows: 132 | // 0->x, 1->y, 2->z, 3->w 133 | // varH(dim)(name) 134 | HNum2 firstVar = varH2x(firstValue); 135 | HNum2 secondVar = varH2y(secondValue); 136 | // constH(dim) functions create constants 137 | HNum2 constVar = constH2(constValue); 138 | // or manually 139 | // For higher dimensions, the vec and mat dimension also changes accordingly 140 | HNum2 firstVar = HNum2(firstValue, vec2(1.0, 0.0), mat2(0.0)); 141 | HNum2 secondVar = HNum2(secondValue, vec2(0.0, 1.0), mat2(0.0)); 142 | HNum2 constVar = HNum2(constValue, vec2(0.0), mat2(0.0)); 143 | ``` 144 | 145 | ## Example usage 146 | 147 | Here are a few basic examples. Of course you can create more complex functions. The nice thing about autodiff is, that you can derive algorithms, for example loops. 148 | 149 | ### Compute first derivative 150 | 151 | Compute the derivative of sin(exp(x))x^3 at x=3 152 | 153 | Define variable. Variables have their value at the first position and 1 at the second. 154 | 155 | ```glsl 156 | vec2 x = varD1(3.0); 157 | ``` 158 | 159 | Compute the function 160 | 161 | ```glsl 162 | vec2 result = mult(a_sin(a_exp(x)), a_pow(x, 3.0)); 163 | ``` 164 | 165 | The function value can now be accessed as the first component and the value of the derivative as the second 166 | 167 | ```glsl 168 | float funcVal = result.x; 169 | float derivVal = result.y; 170 | ``` 171 | 172 | ### Compute second derivative 173 | 174 | Same example as before 175 | 176 | Define variable. Variables have their value at the first position,1 at the second and 0 at the third 177 | 178 | ```glsl 179 | vec3 x = varD2(3.0); 180 | ``` 181 | 182 | Compute the function 183 | 184 | ```glsl 185 | vec3 result = mult(a_sin(a_exp(x)), a_pow(x, 3.0)); 186 | ``` 187 | 188 | The function value can now be accessed as the first component and the value of the derivative as the second 189 | 190 | ```glsl 191 | float funcVal = result.x; 192 | float derivVal = result.y; 193 | float secondDerivVal = result.z; 194 | ``` 195 | 196 | ### Compute Gradient of 2D function 197 | 198 | Define a function of two variables. The function is x^3 + 4 y^2 199 | 200 | Specialized gradient numbers GNum2, GNum3, GNum4 exist to make this easier. You can also retrieve the value in the val field of the GNum. The gradient is stored in the g field. 201 | 202 | ```glsl 203 | GNum2 exampleFuncGN(in GNum2 x, in GNum2 y) 204 | { 205 | return add(a_pow(x,3.),mult(4.,mult(y,y))); 206 | } 207 | ``` 208 | 209 | The usage is as follows: 210 | 211 | ```glsl 212 | GNum2 gNumExample; 213 | // x and y are the values (float) 214 | GRAD2(exampleFuncGN, x, y, gNumExample); 215 | 216 | float value = gNumExample.val; 217 | vec2 gradient = gNumExample.g; 218 | // You can also compute this easily manually without a macro 219 | gNumExample = exampleFuncGN(varG2x(x), varG2y(y)); 220 | ``` 221 | 222 | ### Compute Jacobi matrix 223 | 224 | As an example, we use a 2D function of two variables u and v: f1 = u^2 + v^2*exp(u), f2 = sin(u) - cos(v)^2 225 | First define both component functions 226 | 227 | ```glsl 228 | GNum2 f1(in GNum2 u, in GNum2 v) 229 | { 230 | return add(mult(u, u), mult(mult(v, v), a_exp(u))); 231 | } 232 | GNum2 f2(in GNum2 u, in GNum2 v) 233 | { 234 | return sub(a_sin(u), a_pow(a_cos(v), 2.0)); 235 | } 236 | ``` 237 | 238 | The Jacobian is a 2x2 matrix. To compute its value at position (u,v) (both floats) first declare a placeholder for the result 239 | 240 | ```glsl 241 | mat2 J; 242 | ``` 243 | 244 | Then call the Jacobian macro 245 | 246 | ```glsl 247 | JACOBI2(f1,f2,u,v,J); 248 | ``` 249 | 250 | The Jacobian is now in J. The rows are the gradients of the component functions. The macro just computes those gradients and stores them in the rows for you. JACOBI3 and JACOBI4 work exactly the same, as do the mixed Jacobians (e.g. JACOBI23, JACOBI42). The result matrix can be any matrix that is large enough to hold the Jacobian. JACOBI(m)(n) corresponds to a resulting mxn matrix. 251 | 252 | There are also macros to retreive the value of the computed functions. These are called the same as the usual Jacobian, but with _VALUE attached, e.g JACOBI2_VALUE and JACOBI2_VALUE. The result will be stored in a vector or array at least the size of the number of functions (m). 253 | 254 | ## Compute Hessian 255 | 256 | We choose a scalar valued function of three variables: x^2 + sin(cos(y+z)) 257 | 258 | Since we have three variables, we have to use the HNum3 type for our function definition. 259 | 260 | ```glsl 261 | HNum3 func(in HNum3 x, in HNum3 y, in HNum3 z) 262 | { 263 | return add(mult(x,cx),ca_sin(a_cos(add(y,cz)))); 264 | } 265 | ``` 266 | 267 | Declare result variable 268 | 269 | ```glsl 270 | HNum3 r; 271 | ``` 272 | 273 | Call HESSIAN3 macro for float input (x,y,z) 274 | 275 | ```glsl 276 | HESSIAN3(func,x,y,z,r); 277 | ``` 278 | 279 | This is equivalent to: 280 | 281 | ```glsl 282 | r = func(varH3x(x), varH3y(y), varH3z(z)); 283 | ``` 284 | 285 | The Hessian is now in r. You can acces the value of the function, gradient and Hessian as follows 286 | 287 | ```glsl 288 | float val = r.val; 289 | vec3 gradient = r.g; 290 | mat3 hessian = r.h; 291 | ``` 292 | 293 | The same procedure applies to HESSIAN2 and HESSIAN4 294 | 295 | ## Changes from version 1 296 | 297 | * Missing math functions added 298 | * Renamed HessianNum to HNum to make it shorter 299 | * Renamed GradNum to GNum to make it shorter 300 | * Removed gradient/Jacobi macros for scalar derivative types. Use GNum instead 301 | * All code is now generated via script 302 | * For easier usage, code is split/duplicated in different units 303 | * deriv_1 contains first order functions 304 | * deriv_2 contains second order functions 305 | * grad_(d) contains (d) dimensional GNum 306 | * hessian_(d) contains (d) dimensional HNum 307 | * \*_all contains everything with the same prefix, i.e. hessian_all contains all HNum (HNum2, HNum3, HNum4) 308 | * autodiff contains everything 309 | 310 | ## Testing/Bugs/Suggestions 311 | 312 | So far, some variations though not all have been tested in WebGL and found to be working. Bug reports/tips/suggestions are always welcome. 313 | -------------------------------------------------------------------------------- /deriv_1.glsl: -------------------------------------------------------------------------------- 1 | #ifndef DERIVATIVES_1_H_ 2 | #define DERIVATIVES_1_H_ 3 | 4 | // This file contains methods to compute the first derivative 5 | // of a scalar function using automatic forward differentiation 6 | 7 | // The data is stored in a vec2 8 | // v[0] contains the value of the function 9 | // v[1] contains the first derivative 10 | 11 | 12 | //-------------------------------- 13 | // Prototypes 14 | //-------------------------------- 15 | 16 | /** 17 | * Creates a constant derivative number 18 | * @param val The current value of the constant 19 | */ 20 | vec2 constD1(in float val); 21 | /** 22 | * Creates a derivative number stored in a vec2 23 | * @param val The current value of the variable 24 | */ 25 | vec2 varD1(in float val); 26 | vec2 add(in vec2 a, in vec2 b); 27 | vec2 add(in vec2 a, in float b); 28 | vec2 add(in float a, in vec2 b); 29 | vec2 sub(in vec2 a, in vec2 b); 30 | vec2 sub(in vec2 a, in float b); 31 | vec2 sub(in float a, in vec2 b); 32 | vec2 mult(in vec2 a, in vec2 b); 33 | vec2 mult(in vec2 a, in float b); 34 | vec2 mult(in float a, in vec2 b); 35 | vec2 neg(in vec2 a); 36 | vec2 div(in vec2 a, in vec2 b); 37 | vec2 div(in vec2 a, in float b); 38 | vec2 div(in float a, in vec2 b); 39 | vec2 inv(in vec2 a); 40 | vec2 a_pow(in vec2 a, in vec2 b); 41 | vec2 a_pow(in vec2 a, in float b); 42 | vec2 a_pow(in float a, in vec2 b); 43 | vec2 a_ipow(in vec2 x, in int n); 44 | vec2 a_min(in vec2 a, in vec2 b); 45 | vec2 a_max(in vec2 a, in vec2 b); 46 | vec2 a_exp2(in vec2 a); 47 | vec2 a_inversesqrt(in vec2 a); 48 | vec2 a_atan(in vec2 a); 49 | vec2 a_sqrt(in vec2 a); 50 | vec2 a_sinh(in vec2 a); 51 | vec2 a_ceil(in vec2 a); 52 | vec2 a_tan(in vec2 a); 53 | vec2 a_asinh(in vec2 a); 54 | vec2 a_asin(in vec2 a); 55 | vec2 a_acosh(in vec2 a); 56 | vec2 a_abs(in vec2 a); 57 | vec2 a_exp(in vec2 a); 58 | vec2 a_cosh(in vec2 a); 59 | vec2 a_floor(in vec2 a); 60 | vec2 a_log(in vec2 a); 61 | vec2 a_atanh(in vec2 a); 62 | vec2 a_log2(in vec2 a); 63 | vec2 a_acos(in vec2 a); 64 | vec2 a_tanh(in vec2 a); 65 | vec2 a_cos(in vec2 a); 66 | vec2 a_sin(in vec2 a); 67 | vec2 a_atan2(in vec2 y, in vec2 x); 68 | vec2 a_atan2(in vec2 y, in float x); 69 | vec2 a_atan2(in float y, in vec2 x); 70 | vec2 a_mix(in vec2 a, in vec2 b, in vec2 t); 71 | vec2 a_mix(in vec2 a, in vec2 b, in float t); 72 | vec2 a_mix(in vec2 a, in float b, in vec2 t); 73 | vec2 a_mix(in vec2 a, in float b, in float t); 74 | vec2 a_mix(in float a, in vec2 b, in vec2 t); 75 | vec2 a_mix(in float a, in vec2 b, in float t); 76 | vec2 a_mix(in float a, in float b, in vec2 t); 77 | 78 | //-------------------------------- 79 | // Implementation 80 | //-------------------------------- 81 | 82 | vec2 constD1(in float val) 83 | { 84 | vec2 c = vec2(0.0); 85 | c[0] = val; 86 | return c; 87 | } 88 | //-------------------------------- 89 | vec2 varD1(in float val) 90 | { 91 | return vec2(val, 1.0); 92 | } 93 | //-------------------------------- 94 | vec2 add(in vec2 a, in vec2 b) 95 | { 96 | return a + b; 97 | } 98 | //-------------------------------- 99 | vec2 add(in vec2 a, in float b) 100 | { 101 | a[0] += b; 102 | return a; 103 | } 104 | //-------------------------------- 105 | vec2 add(in float a, in vec2 b) 106 | { 107 | b[0] += a; 108 | return b; 109 | } 110 | //-------------------------------- 111 | vec2 sub(in vec2 a, in vec2 b) 112 | { 113 | return a - b; 114 | } 115 | //-------------------------------- 116 | vec2 sub(in vec2 a, in float b) 117 | { 118 | a[0] -= b; 119 | return a; 120 | } 121 | //-------------------------------- 122 | vec2 sub(in float a, in vec2 b) 123 | { 124 | b *= -1.0; 125 | b[0] += a; 126 | return b; 127 | } 128 | //-------------------------------- 129 | vec2 mult(in vec2 a, in vec2 b) 130 | { 131 | float v = a[0] * b[0]; 132 | float da = a[0]*b[1] + b[0]*a[1]; 133 | 134 | return vec2(v,da); 135 | } 136 | //-------------------------------- 137 | vec2 mult(in vec2 a, in float b) 138 | { 139 | return a*b; 140 | } 141 | //-------------------------------- 142 | vec2 mult(in float a, in vec2 b) 143 | { 144 | return a*b; 145 | } 146 | //-------------------------------- 147 | vec2 neg(in vec2 a) 148 | { 149 | return mult(-1.0,a); 150 | } 151 | //-------------------------------- 152 | vec2 div(in vec2 a, in vec2 b) 153 | { 154 | float v = a[0] / b[0]; 155 | float b2 = b[0] * b[0]; 156 | float da = a[1]/b[0] - a[0]*b[1]/b2; 157 | 158 | return vec2(v,da); 159 | } 160 | //-------------------------------- 161 | vec2 div(in vec2 a, in float b) 162 | { 163 | return a / b; 164 | } 165 | //-------------------------------- 166 | vec2 div(in float a, in vec2 b) 167 | { 168 | float v = a / b[0]; 169 | float b2 = b[0] * b[0]; 170 | float da = - a*b[1]/b2; 171 | 172 | return vec2(v, da); 173 | } 174 | //-------------------------------- 175 | vec2 inv(in vec2 a) 176 | { 177 | return div(1.0, a); 178 | } 179 | //-------------------------------- 180 | vec2 a_pow(in vec2 a, in vec2 b) 181 | { 182 | return a_exp(mult(b,a_log(a))); 183 | } 184 | //-------------------------------- 185 | vec2 a_pow(in vec2 a, in float b) 186 | { 187 | float v = pow(a[0], b); // value f(a(x)) 188 | float da = b*pow(a[0],b-1.0); // first derivative f'(a(x)) 189 | 190 | return vec2(v, da * a[1]); 191 | } 192 | //-------------------------------- 193 | vec2 a_pow(in float a, in vec2 b) 194 | { 195 | return a_exp(mult(b,log(a))); 196 | } 197 | //-------------------------------- 198 | vec2 a_ipow(in vec2 x, in int n) 199 | { 200 | // based on https://en.wikipedia.org/wiki/Exponentiation_by_squaring 201 | if (n < 0) 202 | { 203 | x = div(1.0,x); 204 | n = -n; 205 | } 206 | if (n == 0) 207 | { 208 | return constD1(1.0); 209 | } 210 | vec2 y = constD1(1.0); 211 | while (n > 1) 212 | { 213 | if (n % 2 == 0) 214 | { 215 | x = mult(x,x); 216 | 217 | } 218 | else 219 | { 220 | y = mult(x, y); 221 | x = mult(x, x); 222 | } 223 | 224 | n = n / 2; 225 | } 226 | 227 | return mult(x, y); 228 | } 229 | 230 | //-------------------------------- 231 | vec2 a_min(in vec2 a, in vec2 b) 232 | { 233 | if(a[0] < b[0]) 234 | { 235 | return a; 236 | } 237 | return b; 238 | } 239 | //-------------------------------- 240 | vec2 a_max(in vec2 a, in vec2 b) 241 | { 242 | if(a[0] > b[0]) 243 | { 244 | return a; 245 | } 246 | return b; 247 | } 248 | //-------------------------------- 249 | vec2 a_exp2(in vec2 a) 250 | { 251 | float v = exp2(a[0]); 252 | float da = log(2.0)*exp2(a[0]); 253 | 254 | return vec2(v, da * a[1]); 255 | } 256 | //-------------------------------- 257 | vec2 a_inversesqrt(in vec2 a) 258 | { 259 | float v = inversesqrt(a[0]); 260 | float da = -0.5/pow(sqrt(a[0]),3.0); 261 | 262 | return vec2(v, da * a[1]); 263 | } 264 | //-------------------------------- 265 | vec2 a_atan(in vec2 a) 266 | { 267 | float v = atan(a[0]); 268 | float da = 1.0/(1.0 + a[0] * a[0]); 269 | 270 | return vec2(v, da * a[1]); 271 | } 272 | //-------------------------------- 273 | vec2 a_sqrt(in vec2 a) 274 | { 275 | float v = sqrt(a[0]); 276 | float da = 0.5/sqrt(a[0]); 277 | 278 | return vec2(v, da * a[1]); 279 | } 280 | //-------------------------------- 281 | vec2 a_sinh(in vec2 a) 282 | { 283 | float v = sinh(a[0]); 284 | float da = cosh(a[0]); 285 | 286 | return vec2(v, da * a[1]); 287 | } 288 | //-------------------------------- 289 | vec2 a_ceil(in vec2 a) 290 | { 291 | float v = ceil(a[0]); 292 | float da = 0.0; 293 | 294 | return vec2(v, da * a[1]); 295 | } 296 | //-------------------------------- 297 | vec2 a_tan(in vec2 a) 298 | { 299 | float v = tan(a[0]); 300 | float da = 1.0 + pow(tan(a[0]),2.0); 301 | 302 | return vec2(v, da * a[1]); 303 | } 304 | //-------------------------------- 305 | vec2 a_asinh(in vec2 a) 306 | { 307 | float v = asinh(a[0]); 308 | float da = 1.0/sqrt(1.0 + a[0] * a[0]); 309 | 310 | return vec2(v, da * a[1]); 311 | } 312 | //-------------------------------- 313 | vec2 a_asin(in vec2 a) 314 | { 315 | float v = asin(a[0]); 316 | float da = 1.0/sqrt(1.0 - a[0] * a[0]); 317 | 318 | return vec2(v, da * a[1]); 319 | } 320 | //-------------------------------- 321 | vec2 a_acosh(in vec2 a) 322 | { 323 | float v = acosh(a[0]); 324 | float da = 1.0/sqrt(-1.0 + a[0] * a[0]); 325 | 326 | return vec2(v, da * a[1]); 327 | } 328 | //-------------------------------- 329 | vec2 a_abs(in vec2 a) 330 | { 331 | float v = abs(a[0]); 332 | float da = a[0] < 0.0 ? -1.0 : 1.0; 333 | 334 | return vec2(v, da * a[1]); 335 | } 336 | //-------------------------------- 337 | vec2 a_exp(in vec2 a) 338 | { 339 | float v = exp(a[0]); 340 | float da = exp(a[0]); 341 | 342 | return vec2(v, da * a[1]); 343 | } 344 | //-------------------------------- 345 | vec2 a_cosh(in vec2 a) 346 | { 347 | float v = cosh(a[0]); 348 | float da = sinh(a[0]); 349 | 350 | return vec2(v, da * a[1]); 351 | } 352 | //-------------------------------- 353 | vec2 a_floor(in vec2 a) 354 | { 355 | float v = floor(a[0]); 356 | float da = 0.0; 357 | 358 | return vec2(v, da * a[1]); 359 | } 360 | //-------------------------------- 361 | vec2 a_log(in vec2 a) 362 | { 363 | float v = log(a[0]); 364 | float da = 1.0/a[0]; 365 | 366 | return vec2(v, da * a[1]); 367 | } 368 | //-------------------------------- 369 | vec2 a_atanh(in vec2 a) 370 | { 371 | float v = atanh(a[0]); 372 | float da = 1.0/(1.0 - a[0] * a[0]); 373 | 374 | return vec2(v, da * a[1]); 375 | } 376 | //-------------------------------- 377 | vec2 a_log2(in vec2 a) 378 | { 379 | float v = log2(a[0]); 380 | float da = 1.0/(a[0] * log(2.0)); 381 | 382 | return vec2(v, da * a[1]); 383 | } 384 | //-------------------------------- 385 | vec2 a_acos(in vec2 a) 386 | { 387 | float v = acos(a[0]); 388 | float da = -1.0/sqrt(1.0 - a[0] * a[0]); 389 | 390 | return vec2(v, da * a[1]); 391 | } 392 | //-------------------------------- 393 | vec2 a_tanh(in vec2 a) 394 | { 395 | float v = tanh(a[0]); 396 | float da = 1.0 - pow(tanh(a[0]),2.0); 397 | 398 | return vec2(v, da * a[1]); 399 | } 400 | //-------------------------------- 401 | vec2 a_cos(in vec2 a) 402 | { 403 | float v = cos(a[0]); 404 | float da = -sin(a[0]); 405 | 406 | return vec2(v, da * a[1]); 407 | } 408 | //-------------------------------- 409 | vec2 a_sin(in vec2 a) 410 | { 411 | float v = sin(a[0]); 412 | float da = cos(a[0]); 413 | 414 | return vec2(v, da * a[1]); 415 | } 416 | //-------------------------------- 417 | vec2 a_atan2(in vec2 y, in vec2 x) 418 | { 419 | const float pi = 3.14159265; 420 | // from https://en.wikipedia.org/wiki/Atan2 421 | if(x[0] > 0.0) 422 | { 423 | vec2 n = a_sqrt(add(mult(x,x),mult(y,y))); 424 | vec2 inner = div(y, add(n,x)); 425 | 426 | return mult(2.0,a_atan(inner)); 427 | 428 | }else if(x[0] <= 0.0 && abs(y[0]) > 1E-6) 429 | { 430 | vec2 n = a_sqrt(add(mult(x,x),mult(y,y))); 431 | vec2 inner = div(sub(n,x),y); 432 | return mult(2.0,a_atan(inner)); 433 | }else if(x[0] < 0.0 && abs(y[0]) <= 1E-6) 434 | { 435 | return constD1(pi); 436 | } 437 | // return 0 for undefined 438 | return constD1(0.0); 439 | } 440 | //-------------------------------- 441 | vec2 a_atan2(in vec2 y, in float x) 442 | { 443 | return a_atan2(y,constD1(x)); 444 | } 445 | //-------------------------------- 446 | vec2 a_atan2(in float y, in vec2 x) 447 | { 448 | return a_atan2(constD1(y),x); 449 | } 450 | //-------------------------------- 451 | vec2 a_mix(in vec2 a, in vec2 b, in vec2 t) 452 | { 453 | return add(mult(a, sub(1.0, t)), mult(b, t)); 454 | } 455 | 456 | //-------------------------------- 457 | vec2 a_mix(in vec2 a, in vec2 b, in float t) 458 | { 459 | return add(mult(a, 1.0 - t), mult(b, t)); 460 | } 461 | 462 | //-------------------------------- 463 | vec2 a_mix(in vec2 a, in float b, in vec2 t) 464 | { 465 | return add(mult(a, sub(1.0, t)), mult(b, t)); 466 | } 467 | 468 | //-------------------------------- 469 | vec2 a_mix(in vec2 a, in float b, in float t) 470 | { 471 | return add(mult(a, 1.0 - t), b*t); 472 | } 473 | 474 | //-------------------------------- 475 | vec2 a_mix(in float a, in vec2 b, in vec2 t) 476 | { 477 | return add(mult(a, sub(1.0, t)), mult(b, t)); 478 | } 479 | 480 | //-------------------------------- 481 | vec2 a_mix(in float a, in vec2 b, in float t) 482 | { 483 | return add(a * (1.0 - t), mult(b, t)); 484 | } 485 | 486 | //-------------------------------- 487 | vec2 a_mix(in float a, in float b, in vec2 t) 488 | { 489 | return add(mult(a, sub(1.0, t)), mult(b, t)); 490 | } 491 | 492 | 493 | #endif // DERIVATIVES_1_H_ -------------------------------------------------------------------------------- /deriv_2.glsl: -------------------------------------------------------------------------------- 1 | #ifndef DERIVATIVES_2_H_ 2 | #define DERIVATIVES_2_H_ 3 | 4 | // This file contains methods to compute the first and second order derivative 5 | // of a scalar function using automatic forward differentiation 6 | 7 | // The data is stored in a vec3 8 | // v[0] contains the value of the function 9 | // v[1] contains the first derivative 10 | // v[2] contains the second derivative 11 | 12 | //-------------------------------- 13 | // Prototypes 14 | //-------------------------------- 15 | 16 | /** 17 | * Creates a constant derivative number 18 | * @param val The current value of the constant 19 | */ 20 | vec3 constD2(in float val); 21 | /** 22 | * Creates a derivative number stored in a vec3 23 | * @param val The current value of the variable 24 | */ 25 | vec3 varD2(in float val); 26 | vec3 add(in vec3 a, in vec3 b); 27 | vec3 add(in vec3 a, in float b); 28 | vec3 add(in float a, in vec3 b); 29 | vec3 sub(in vec3 a, in vec3 b); 30 | vec3 sub(in vec3 a, in float b); 31 | vec3 sub(in float a, in vec3 b); 32 | vec3 mult(in vec3 a, in vec3 b); 33 | vec3 mult(in vec3 a, in float b); 34 | vec3 mult(in float a, in vec3 b); 35 | vec3 neg(in vec3 a); 36 | vec3 div(in vec3 a, in vec3 b); 37 | vec3 div(in vec3 a, in float b); 38 | vec3 div(in float a, in vec3 b); 39 | vec3 inv(in vec3 a); 40 | vec3 a_pow(in vec3 a, in vec3 b); 41 | vec3 a_pow(in vec3 a, in float b); 42 | vec3 a_pow(in float a, in vec3 b); 43 | vec3 a_ipow(in vec3 x, in int n); 44 | vec3 a_min(in vec3 a, in vec3 b); 45 | vec3 a_max(in vec3 a, in vec3 b); 46 | vec3 a_exp2(in vec3 a); 47 | vec3 a_inversesqrt(in vec3 a); 48 | vec3 a_atan(in vec3 a); 49 | vec3 a_sqrt(in vec3 a); 50 | vec3 a_sinh(in vec3 a); 51 | vec3 a_ceil(in vec3 a); 52 | vec3 a_tan(in vec3 a); 53 | vec3 a_asinh(in vec3 a); 54 | vec3 a_asin(in vec3 a); 55 | vec3 a_acosh(in vec3 a); 56 | vec3 a_abs(in vec3 a); 57 | vec3 a_exp(in vec3 a); 58 | vec3 a_cosh(in vec3 a); 59 | vec3 a_floor(in vec3 a); 60 | vec3 a_log(in vec3 a); 61 | vec3 a_atanh(in vec3 a); 62 | vec3 a_log2(in vec3 a); 63 | vec3 a_acos(in vec3 a); 64 | vec3 a_tanh(in vec3 a); 65 | vec3 a_cos(in vec3 a); 66 | vec3 a_sin(in vec3 a); 67 | vec3 a_atan2(in vec3 y, in vec3 x); 68 | vec3 a_atan2(in vec3 y, in float x); 69 | vec3 a_atan2(in float y, in vec3 x); 70 | vec3 a_mix(in vec3 a, in vec3 b, in vec3 t); 71 | vec3 a_mix(in vec3 a, in vec3 b, in float t); 72 | vec3 a_mix(in vec3 a, in float b, in vec3 t); 73 | vec3 a_mix(in vec3 a, in float b, in float t); 74 | vec3 a_mix(in float a, in vec3 b, in vec3 t); 75 | vec3 a_mix(in float a, in vec3 b, in float t); 76 | vec3 a_mix(in float a, in float b, in vec3 t); 77 | 78 | //-------------------------------- 79 | // Implementation 80 | //-------------------------------- 81 | 82 | vec3 constD2(in float val) 83 | { 84 | vec3 c = vec3(0.0); 85 | c[0] = val; 86 | return c; 87 | } 88 | //-------------------------------- 89 | vec3 varD2(in float val) 90 | { 91 | return vec3(val, 1.0, 0.0); 92 | } 93 | //-------------------------------- 94 | vec3 add(in vec3 a, in vec3 b) 95 | { 96 | return a + b; 97 | } 98 | //-------------------------------- 99 | vec3 add(in vec3 a, in float b) 100 | { 101 | a[0] += b; 102 | return a; 103 | } 104 | //-------------------------------- 105 | vec3 add(in float a, in vec3 b) 106 | { 107 | b[0] += a; 108 | return b; 109 | } 110 | //-------------------------------- 111 | vec3 sub(in vec3 a, in vec3 b) 112 | { 113 | return a - b; 114 | } 115 | //-------------------------------- 116 | vec3 sub(in vec3 a, in float b) 117 | { 118 | a[0] -= b; 119 | return a; 120 | } 121 | //-------------------------------- 122 | vec3 sub(in float a, in vec3 b) 123 | { 124 | b *= -1.0; 125 | b[0] += a; 126 | return b; 127 | } 128 | //-------------------------------- 129 | vec3 mult(in vec3 a, in vec3 b) 130 | { 131 | float v = a[0] * b[0]; 132 | float da = a[0]*b[1] + b[0]*a[1]; 133 | float dda = a[2]*b[0] + 2.0*a[1]*b[1] + a[0]*b[2]; 134 | 135 | return vec3(v,da,dda); 136 | } 137 | //-------------------------------- 138 | vec3 mult(in vec3 a, in float b) 139 | { 140 | return a*b; 141 | } 142 | //-------------------------------- 143 | vec3 mult(in float a, in vec3 b) 144 | { 145 | return a*b; 146 | } 147 | //-------------------------------- 148 | vec3 neg(in vec3 a) 149 | { 150 | return mult(-1.0,a); 151 | } 152 | //-------------------------------- 153 | vec3 div(in vec3 a, in vec3 b) 154 | { 155 | float v = a[0] / b[0]; 156 | float b2 = b[0] * b[0]; 157 | float da = a[1]/b[0] - a[0]*b[1]/b2; 158 | float b3 = b2 * b[0]; 159 | float dda = a[2]/b[0] - 2.0*a[1]*b[1]/b2 - a[0]*b[2]/b2 + 2.0*a[0]*(b[1]*b[1])/b3; 160 | 161 | return vec3(v,da,dda); 162 | } 163 | //-------------------------------- 164 | vec3 div(in vec3 a, in float b) 165 | { 166 | return a / b; 167 | } 168 | //-------------------------------- 169 | vec3 div(in float a, in vec3 b) 170 | { 171 | float v = a / b[0]; 172 | float b2 = b[0] * b[0]; 173 | float da = - a*b[1]/b2; 174 | float b3 = b2 * b[0]; 175 | float dda = - a*b[2]/b2 + 2.0*a*(b[1]*b[1])/b3; 176 | 177 | return vec3(v, da, dda); 178 | } 179 | //-------------------------------- 180 | vec3 inv(in vec3 a) 181 | { 182 | return div(1.0, a); 183 | } 184 | //-------------------------------- 185 | vec3 a_pow(in vec3 a, in vec3 b) 186 | { 187 | return a_exp(mult(b,a_log(a))); 188 | } 189 | //-------------------------------- 190 | vec3 a_pow(in vec3 a, in float b) 191 | { 192 | float v = pow(a[0], b); // value f(a(x)) 193 | float da = b*pow(a[0],b-1.0); // first derivative f'(a(x)) 194 | float dda = b*(b-1.0)*pow(a[0],b-2.0); // second derivative f''(a(x)) 195 | 196 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 197 | } 198 | //-------------------------------- 199 | vec3 a_pow(in float a, in vec3 b) 200 | { 201 | return a_exp(mult(b,log(a))); 202 | } 203 | //-------------------------------- 204 | vec3 a_ipow(in vec3 x, in int n) 205 | { 206 | // based on https://en.wikipedia.org/wiki/Exponentiation_by_squaring 207 | if (n < 0) 208 | { 209 | x = div(1.0,x); 210 | n = -n; 211 | } 212 | if (n == 0) 213 | { 214 | return constD2(1.0); 215 | } 216 | vec3 y = constD2(1.0); 217 | while (n > 1) 218 | { 219 | if (n % 2 == 0) 220 | { 221 | x = mult(x,x); 222 | 223 | } 224 | else 225 | { 226 | y = mult(x, y); 227 | x = mult(x, x); 228 | } 229 | 230 | n = n / 2; 231 | } 232 | 233 | return mult(x, y); 234 | } 235 | 236 | //-------------------------------- 237 | vec3 a_min(in vec3 a, in vec3 b) 238 | { 239 | if(a[0] < b[0]) 240 | { 241 | return a; 242 | } 243 | return b; 244 | } 245 | //-------------------------------- 246 | vec3 a_max(in vec3 a, in vec3 b) 247 | { 248 | if(a[0] > b[0]) 249 | { 250 | return a; 251 | } 252 | return b; 253 | } 254 | //-------------------------------- 255 | vec3 a_exp2(in vec3 a) 256 | { 257 | float v = exp2(a[0]); 258 | float da = log(2.0)*exp2(a[0]); 259 | float dda = log(2.0)*log(2.0)*exp2(a[0]); 260 | 261 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 262 | } 263 | //-------------------------------- 264 | vec3 a_inversesqrt(in vec3 a) 265 | { 266 | float v = inversesqrt(a[0]); 267 | float da = -0.5/pow(sqrt(a[0]),3.0); 268 | float dda = 0.75/pow(sqrt(a[0]),5.0); 269 | 270 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 271 | } 272 | //-------------------------------- 273 | vec3 a_atan(in vec3 a) 274 | { 275 | float v = atan(a[0]); 276 | float da = 1.0/(1.0 + a[0] * a[0]); 277 | float dda = -2.0*a[0]/pow(1.0 + a[0] * a[0], 2.0); 278 | 279 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 280 | } 281 | //-------------------------------- 282 | vec3 a_sqrt(in vec3 a) 283 | { 284 | float v = sqrt(a[0]); 285 | float da = 0.5/sqrt(a[0]); 286 | float dda = -0.25/pow(sqrt(a[0]),3.0); 287 | 288 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 289 | } 290 | //-------------------------------- 291 | vec3 a_sinh(in vec3 a) 292 | { 293 | float v = sinh(a[0]); 294 | float da = cosh(a[0]); 295 | float dda = sinh(a[0]); 296 | 297 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 298 | } 299 | //-------------------------------- 300 | vec3 a_ceil(in vec3 a) 301 | { 302 | float v = ceil(a[0]); 303 | float da = 0.0; 304 | float dda = 0.0; 305 | 306 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 307 | } 308 | //-------------------------------- 309 | vec3 a_tan(in vec3 a) 310 | { 311 | float v = tan(a[0]); 312 | float da = 1.0 + pow(tan(a[0]),2.0); 313 | float dda = 2.0*tan(a[0])*(1.0 + pow(tan(a[0]),2.0)); 314 | 315 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 316 | } 317 | //-------------------------------- 318 | vec3 a_asinh(in vec3 a) 319 | { 320 | float v = asinh(a[0]); 321 | float da = 1.0/sqrt(1.0 + a[0] * a[0]); 322 | float dda = -a[0]/pow(sqrt(1.0 + a[0] * a[0]),3.0); 323 | 324 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 325 | } 326 | //-------------------------------- 327 | vec3 a_asin(in vec3 a) 328 | { 329 | float v = asin(a[0]); 330 | float da = 1.0/sqrt(1.0 - a[0] * a[0]); 331 | float dda = a[0]/pow(sqrt(1.0 - a[0] * a[0]),3.0); 332 | 333 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 334 | } 335 | //-------------------------------- 336 | vec3 a_acosh(in vec3 a) 337 | { 338 | float v = acosh(a[0]); 339 | float da = 1.0/sqrt(-1.0 + a[0] * a[0]); 340 | float dda = -a[0]/pow(sqrt(-1.0 + a[0] * a[0]),3.0); 341 | 342 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 343 | } 344 | //-------------------------------- 345 | vec3 a_abs(in vec3 a) 346 | { 347 | float v = abs(a[0]); 348 | float da = a[0] < 0.0 ? -1.0 : 1.0; 349 | float dda = 0.0; 350 | 351 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 352 | } 353 | //-------------------------------- 354 | vec3 a_exp(in vec3 a) 355 | { 356 | float v = exp(a[0]); 357 | float da = exp(a[0]); 358 | float dda = exp(a[0]); 359 | 360 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 361 | } 362 | //-------------------------------- 363 | vec3 a_cosh(in vec3 a) 364 | { 365 | float v = cosh(a[0]); 366 | float da = sinh(a[0]); 367 | float dda = cosh(a[0]); 368 | 369 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 370 | } 371 | //-------------------------------- 372 | vec3 a_floor(in vec3 a) 373 | { 374 | float v = floor(a[0]); 375 | float da = 0.0; 376 | float dda = 0.0; 377 | 378 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 379 | } 380 | //-------------------------------- 381 | vec3 a_log(in vec3 a) 382 | { 383 | float v = log(a[0]); 384 | float da = 1.0/a[0]; 385 | float dda = -1.0/(a[0] * a[0]); 386 | 387 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 388 | } 389 | //-------------------------------- 390 | vec3 a_atanh(in vec3 a) 391 | { 392 | float v = atanh(a[0]); 393 | float da = 1.0/(1.0 - a[0] * a[0]); 394 | float dda = 2.0*a[0]/pow(1.0 - a[0] * a[0],2.0); 395 | 396 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 397 | } 398 | //-------------------------------- 399 | vec3 a_log2(in vec3 a) 400 | { 401 | float v = log2(a[0]); 402 | float da = 1.0/(a[0] * log(2.0)); 403 | float dda = -1.0/(a[0] * a[0] * log(2.0)); 404 | 405 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 406 | } 407 | //-------------------------------- 408 | vec3 a_acos(in vec3 a) 409 | { 410 | float v = acos(a[0]); 411 | float da = -1.0/sqrt(1.0 - a[0] * a[0]); 412 | float dda = -a[0]/pow(sqrt(1.0 - a[0] * a[0]),3.0); 413 | 414 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 415 | } 416 | //-------------------------------- 417 | vec3 a_tanh(in vec3 a) 418 | { 419 | float v = tanh(a[0]); 420 | float da = 1.0 - pow(tanh(a[0]),2.0); 421 | float dda = -2.0*tanh(a[0])*(1.0 - pow(tanh(a[0]),2.0)); 422 | 423 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 424 | } 425 | //-------------------------------- 426 | vec3 a_cos(in vec3 a) 427 | { 428 | float v = cos(a[0]); 429 | float da = -sin(a[0]); 430 | float dda = -cos(a[0]); 431 | 432 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 433 | } 434 | //-------------------------------- 435 | vec3 a_sin(in vec3 a) 436 | { 437 | float v = sin(a[0]); 438 | float da = cos(a[0]); 439 | float dda = -sin(a[0]); 440 | 441 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 442 | } 443 | //-------------------------------- 444 | vec3 a_atan2(in vec3 y, in vec3 x) 445 | { 446 | const float pi = 3.14159265; 447 | // from https://en.wikipedia.org/wiki/Atan2 448 | if(x[0] > 0.0) 449 | { 450 | vec3 n = a_sqrt(add(mult(x,x),mult(y,y))); 451 | vec3 inner = div(y, add(n,x)); 452 | 453 | return mult(2.0,a_atan(inner)); 454 | 455 | }else if(x[0] <= 0.0 && abs(y[0]) > 1E-6) 456 | { 457 | vec3 n = a_sqrt(add(mult(x,x),mult(y,y))); 458 | vec3 inner = div(sub(n,x),y); 459 | return mult(2.0,a_atan(inner)); 460 | }else if(x[0] < 0.0 && abs(y[0]) <= 1E-6) 461 | { 462 | return constD2(pi); 463 | } 464 | // return 0 for undefined 465 | return constD2(0.0); 466 | } 467 | //-------------------------------- 468 | vec3 a_atan2(in vec3 y, in float x) 469 | { 470 | return a_atan2(y,constD2(x)); 471 | } 472 | //-------------------------------- 473 | vec3 a_atan2(in float y, in vec3 x) 474 | { 475 | return a_atan2(constD2(y),x); 476 | } 477 | //-------------------------------- 478 | vec3 a_mix(in vec3 a, in vec3 b, in vec3 t) 479 | { 480 | return add(mult(a, sub(1.0, t)), mult(b, t)); 481 | } 482 | 483 | //-------------------------------- 484 | vec3 a_mix(in vec3 a, in vec3 b, in float t) 485 | { 486 | return add(mult(a, 1.0 - t), mult(b, t)); 487 | } 488 | 489 | //-------------------------------- 490 | vec3 a_mix(in vec3 a, in float b, in vec3 t) 491 | { 492 | return add(mult(a, sub(1.0, t)), mult(b, t)); 493 | } 494 | 495 | //-------------------------------- 496 | vec3 a_mix(in vec3 a, in float b, in float t) 497 | { 498 | return add(mult(a, 1.0 - t), b*t); 499 | } 500 | 501 | //-------------------------------- 502 | vec3 a_mix(in float a, in vec3 b, in vec3 t) 503 | { 504 | return add(mult(a, sub(1.0, t)), mult(b, t)); 505 | } 506 | 507 | //-------------------------------- 508 | vec3 a_mix(in float a, in vec3 b, in float t) 509 | { 510 | return add(a * (1.0 - t), mult(b, t)); 511 | } 512 | 513 | //-------------------------------- 514 | vec3 a_mix(in float a, in float b, in vec3 t) 515 | { 516 | return add(mult(a, sub(1.0, t)), mult(b, t)); 517 | } 518 | 519 | 520 | #endif // DERIVATIVES_2_H_ -------------------------------------------------------------------------------- /grad_2.glsl: -------------------------------------------------------------------------------- 1 | #ifndef GRADNUM_2_H_ 2 | #define GRADNUM_2_H_ 3 | 4 | // This file contains methods to compute the gradient of a scalar valued 2 dimensional 5 | // function using automatic forward differentiation 6 | 7 | //-------------------------------- 8 | // Types 9 | //-------------------------------- 10 | 11 | // Data type to hold information about a scalar valued 2 dimensional function 12 | // These should be created by the constG2 (for constants) and varG2 (for variables) helpers 13 | struct GNum2 14 | { 15 | // The current value 16 | float val; 17 | // The current gradient 18 | vec2 g; 19 | }; 20 | 21 | //-------------------------------- 22 | // Prototypes 23 | //-------------------------------- 24 | 25 | /** 26 | * Creates a constant GNum2 27 | * @param val The current value of the constant 28 | */ 29 | GNum2 constG2(in float val); 30 | GNum2 varG2(in float val, in int index); 31 | GNum2 varG2x(in float val); 32 | GNum2 varG2y(in float val); 33 | GNum2 add(in GNum2 a, in GNum2 b); 34 | GNum2 add(in GNum2 a, in float b); 35 | GNum2 add(in float a, in GNum2 b); 36 | GNum2 sub(in GNum2 a, in GNum2 b); 37 | GNum2 sub(in GNum2 a, in float b); 38 | GNum2 sub(in float a, in GNum2 b); 39 | GNum2 mult(in GNum2 a, in GNum2 b); 40 | GNum2 mult(in GNum2 a, in float b); 41 | GNum2 mult(in float a, in GNum2 b); 42 | GNum2 neg(in GNum2 a); 43 | GNum2 div(in GNum2 a, in GNum2 b); 44 | GNum2 div(in GNum2 a, in float b); 45 | GNum2 div(in float a, in GNum2 b); 46 | GNum2 inv(in GNum2 a); 47 | GNum2 a_pow(in GNum2 a, in GNum2 b); 48 | GNum2 a_pow(in GNum2 a, in float b); 49 | GNum2 a_pow(in float a, in GNum2 b); 50 | GNum2 a_ipow(in GNum2 x, in int n); 51 | GNum2 a_min(in GNum2 a, in GNum2 b); 52 | GNum2 a_max(in GNum2 a, in GNum2 b); 53 | GNum2 a_exp2(in GNum2 a); 54 | GNum2 a_inversesqrt(in GNum2 a); 55 | GNum2 a_atan(in GNum2 a); 56 | GNum2 a_sqrt(in GNum2 a); 57 | GNum2 a_sinh(in GNum2 a); 58 | GNum2 a_ceil(in GNum2 a); 59 | GNum2 a_tan(in GNum2 a); 60 | GNum2 a_asinh(in GNum2 a); 61 | GNum2 a_asin(in GNum2 a); 62 | GNum2 a_acosh(in GNum2 a); 63 | GNum2 a_abs(in GNum2 a); 64 | GNum2 a_exp(in GNum2 a); 65 | GNum2 a_cosh(in GNum2 a); 66 | GNum2 a_floor(in GNum2 a); 67 | GNum2 a_log(in GNum2 a); 68 | GNum2 a_atanh(in GNum2 a); 69 | GNum2 a_log2(in GNum2 a); 70 | GNum2 a_acos(in GNum2 a); 71 | GNum2 a_tanh(in GNum2 a); 72 | GNum2 a_cos(in GNum2 a); 73 | GNum2 a_sin(in GNum2 a); 74 | GNum2 a_atan2(in GNum2 y, in GNum2 x); 75 | GNum2 a_atan2(in GNum2 y, in float x); 76 | GNum2 a_atan2(in float y, in GNum2 x); 77 | GNum2 a_mix(in GNum2 a, in GNum2 b, in GNum2 t); 78 | GNum2 a_mix(in GNum2 a, in GNum2 b, in float t); 79 | GNum2 a_mix(in GNum2 a, in float b, in GNum2 t); 80 | GNum2 a_mix(in GNum2 a, in float b, in float t); 81 | GNum2 a_mix(in float a, in GNum2 b, in GNum2 t); 82 | GNum2 a_mix(in float a, in GNum2 b, in float t); 83 | GNum2 a_mix(in float a, in float b, in GNum2 t); 84 | 85 | //-------------------------------- 86 | // Macros 87 | //-------------------------------- 88 | 89 | #define GRAD2(f,x, y,result) { result = f(varG2x(x), varG2y(y)); } 90 | //-------------------------------- 91 | #define JACOBI2(f1, f2, x, y, result) { GNum2 gradResult; GRAD2(f1, x, y, gradResult); result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; GRAD2(f2, x, y, gradResult); result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; } 92 | //-------------------------------- 93 | #define JACOBI2_VALUE(f1, f2, x, y, result, value) { GNum2 gradResult; GRAD2(f1, x, y, gradResult); value[0] = gradResult.val; result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; GRAD2(f2, x, y, gradResult); value[1] = gradResult.val; result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; } 94 | //-------------------------------- 95 | #define JACOBI32(f1, f2, f3, x, y, result) { GNum2 gradResult; GRAD2(f1, x, y, gradResult); result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; GRAD2(f2, x, y, gradResult); result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; GRAD2(f3, x, y, gradResult); result[0][2] = gradResult.g[0]; result[1][2] = gradResult.g[1]; } 96 | //-------------------------------- 97 | #define JACOBI32_VALUE(f1, f2, f3, x, y, result, value) { GNum2 gradResult; GRAD2(f1, x, y, gradResult); value[0] = gradResult.val; result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; GRAD2(f2, x, y, gradResult); value[1] = gradResult.val; result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; GRAD2(f3, x, y, gradResult); value[2] = gradResult.val; result[0][2] = gradResult.g[0]; result[1][2] = gradResult.g[1]; } 98 | //-------------------------------- 99 | #define JACOBI42(f1, f2, f3, f4, x, y, result) { GNum2 gradResult; GRAD2(f1, x, y, gradResult); result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; GRAD2(f2, x, y, gradResult); result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; GRAD2(f3, x, y, gradResult); result[0][2] = gradResult.g[0]; result[1][2] = gradResult.g[1]; GRAD2(f4, x, y, gradResult); result[0][3] = gradResult.g[0]; result[1][3] = gradResult.g[1]; } 100 | //-------------------------------- 101 | #define JACOBI42_VALUE(f1, f2, f3, f4, x, y, result, value) { GNum2 gradResult; GRAD2(f1, x, y, gradResult); value[0] = gradResult.val; result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; GRAD2(f2, x, y, gradResult); value[1] = gradResult.val; result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; GRAD2(f3, x, y, gradResult); value[2] = gradResult.val; result[0][2] = gradResult.g[0]; result[1][2] = gradResult.g[1]; GRAD2(f4, x, y, gradResult); value[3] = gradResult.val; result[0][3] = gradResult.g[0]; result[1][3] = gradResult.g[1]; } 102 | 103 | //-------------------------------- 104 | // Implementation 105 | //-------------------------------- 106 | 107 | GNum2 constG2(in float val) 108 | { 109 | return GNum2(val, vec2(0.0)); 110 | } 111 | //-------------------------------- 112 | GNum2 varG2(in float val, in int index) 113 | { 114 | vec2 g = vec2(0.0); 115 | g[index] = 1.0; 116 | return GNum2(val, g); 117 | } 118 | //-------------------------------- 119 | GNum2 varG2x(in float val) 120 | { 121 | vec2 g = vec2(0.0); 122 | g[0] = 1.0; 123 | return GNum2(val, g); 124 | } 125 | //-------------------------------- 126 | GNum2 varG2y(in float val) 127 | { 128 | vec2 g = vec2(0.0); 129 | g[1] = 1.0; 130 | return GNum2(val, g); 131 | } 132 | //-------------------------------- 133 | GNum2 add(in GNum2 a, in GNum2 b) 134 | { 135 | return GNum2(a.val + b.val, a.g + b.g); 136 | } 137 | //-------------------------------- 138 | GNum2 add(in GNum2 a, in float b) 139 | { 140 | return GNum2(a.val + b, a.g); 141 | } 142 | //-------------------------------- 143 | GNum2 add(in float a, in GNum2 b) 144 | { 145 | return GNum2(a + b.val, b.g); 146 | } 147 | //-------------------------------- 148 | GNum2 sub(in GNum2 a, in GNum2 b) 149 | { 150 | return GNum2(a.val - b.val, a.g - b.g); 151 | } 152 | //-------------------------------- 153 | GNum2 sub(in GNum2 a, in float b) 154 | { 155 | return GNum2(a.val - b, a.g); 156 | } 157 | //-------------------------------- 158 | GNum2 sub(in float a, in GNum2 b) 159 | { 160 | return GNum2(a - b.val, -b.g); 161 | } 162 | //-------------------------------- 163 | GNum2 mult(in GNum2 a, in GNum2 b) 164 | { 165 | return GNum2(a.val * b.val, 166 | a.val*b.g + b.val*a.g 167 | ); 168 | } 169 | //-------------------------------- 170 | GNum2 mult(in GNum2 a, in float b) 171 | { 172 | return GNum2(a.val * b, b*a.g); 173 | } 174 | //-------------------------------- 175 | GNum2 mult(in float a, in GNum2 b) 176 | { 177 | return GNum2(a * b.val, a*b.g); 178 | } 179 | //-------------------------------- 180 | GNum2 neg(in GNum2 a) 181 | { 182 | return mult(-1.0,a); 183 | } 184 | //-------------------------------- 185 | GNum2 div(in GNum2 a, in GNum2 b) 186 | { 187 | float b1 = b.val; 188 | float b2 = b1*b1; 189 | 190 | return GNum2(a.val / b.val , 191 | (b.val*a.g - a.val*b.g)/b2 192 | ); 193 | } 194 | //-------------------------------- 195 | GNum2 div(in GNum2 a, in float b) 196 | { 197 | return GNum2(a.val / b, a.g/b); 198 | } 199 | //-------------------------------- 200 | GNum2 div(in float a, in GNum2 b) 201 | { 202 | float b1 = b.val; 203 | float b2 = b1*b1; 204 | 205 | return GNum2(a / b.val, 206 | -a*b.g/b2 207 | ); 208 | } 209 | //-------------------------------- 210 | GNum2 inv(in GNum2 a) 211 | { 212 | return div(1.0, a); 213 | } 214 | //-------------------------------- 215 | GNum2 a_pow(in GNum2 a, in GNum2 b) 216 | { 217 | return a_exp(mult(b,a_log(a))); 218 | } 219 | //-------------------------------- 220 | GNum2 a_pow(in GNum2 a, in float b) 221 | { 222 | // constant exponent -> make special case 223 | float v = pow(a.val, b); // value f(a(x)) 224 | float da = b*pow(a.val,b-1.0); // first derivative f'(a(x)) 225 | return GNum2(v , da * a.g); 226 | } 227 | //-------------------------------- 228 | GNum2 a_pow(in float a, in GNum2 b) 229 | { 230 | return a_exp(mult(b,log(a))); 231 | } 232 | //-------------------------------- 233 | GNum2 a_ipow(in GNum2 x, in int n) 234 | { 235 | // based on https://en.wikipedia.org/wiki/Exponentiation_by_squaring 236 | if (n < 0) 237 | { 238 | x = div(1.0,x); 239 | n = -n; 240 | } 241 | if (n == 0) 242 | { 243 | return constG2(1.0); 244 | } 245 | GNum2 y = constG2(1.0); 246 | while (n > 1) 247 | { 248 | if (n % 2 == 0) 249 | { 250 | x = mult(x,x); 251 | 252 | } 253 | else 254 | { 255 | y = mult(x, y); 256 | x = mult(x, x); 257 | } 258 | 259 | n = n / 2; 260 | } 261 | 262 | return mult(x, y); 263 | } 264 | 265 | //-------------------------------- 266 | GNum2 a_min(in GNum2 a, in GNum2 b) 267 | { 268 | if(a.val < b.val) 269 | { 270 | return a; 271 | } 272 | return b; 273 | } 274 | //-------------------------------- 275 | GNum2 a_max(in GNum2 a, in GNum2 b) 276 | { 277 | if(a.val > b.val) 278 | { 279 | return a; 280 | } 281 | return b; 282 | } 283 | //-------------------------------- 284 | GNum2 a_exp2(in GNum2 a) 285 | { 286 | float v = exp2(a.val); // value f(a(x)) 287 | float da = log(2.0)*exp2(a.val); // first derivative f'(a(x)) 288 | 289 | return GNum2(v , da * a.g); 290 | } 291 | //-------------------------------- 292 | GNum2 a_inversesqrt(in GNum2 a) 293 | { 294 | float v = inversesqrt(a.val); // value f(a(x)) 295 | float da = -0.5/pow(sqrt(a.val),3.0); // first derivative f'(a(x)) 296 | 297 | return GNum2(v , da * a.g); 298 | } 299 | //-------------------------------- 300 | GNum2 a_atan(in GNum2 a) 301 | { 302 | float v = atan(a.val); // value f(a(x)) 303 | float da = 1.0/(1.0 + a.val * a.val); // first derivative f'(a(x)) 304 | 305 | return GNum2(v , da * a.g); 306 | } 307 | //-------------------------------- 308 | GNum2 a_sqrt(in GNum2 a) 309 | { 310 | float v = sqrt(a.val); // value f(a(x)) 311 | float da = 0.5/sqrt(a.val); // first derivative f'(a(x)) 312 | 313 | return GNum2(v , da * a.g); 314 | } 315 | //-------------------------------- 316 | GNum2 a_sinh(in GNum2 a) 317 | { 318 | float v = sinh(a.val); // value f(a(x)) 319 | float da = cosh(a.val); // first derivative f'(a(x)) 320 | 321 | return GNum2(v , da * a.g); 322 | } 323 | //-------------------------------- 324 | GNum2 a_ceil(in GNum2 a) 325 | { 326 | float v = ceil(a.val); // value f(a(x)) 327 | float da = 0.0; // first derivative f'(a(x)) 328 | 329 | return GNum2(v , da * a.g); 330 | } 331 | //-------------------------------- 332 | GNum2 a_tan(in GNum2 a) 333 | { 334 | float v = tan(a.val); // value f(a(x)) 335 | float da = 1.0 + pow(tan(a.val),2.0); // first derivative f'(a(x)) 336 | 337 | return GNum2(v , da * a.g); 338 | } 339 | //-------------------------------- 340 | GNum2 a_asinh(in GNum2 a) 341 | { 342 | float v = asinh(a.val); // value f(a(x)) 343 | float da = 1.0/sqrt(1.0 + a.val * a.val); // first derivative f'(a(x)) 344 | 345 | return GNum2(v , da * a.g); 346 | } 347 | //-------------------------------- 348 | GNum2 a_asin(in GNum2 a) 349 | { 350 | float v = asin(a.val); // value f(a(x)) 351 | float da = 1.0/sqrt(1.0 - a.val * a.val); // first derivative f'(a(x)) 352 | 353 | return GNum2(v , da * a.g); 354 | } 355 | //-------------------------------- 356 | GNum2 a_acosh(in GNum2 a) 357 | { 358 | float v = acosh(a.val); // value f(a(x)) 359 | float da = 1.0/sqrt(-1.0 + a.val * a.val); // first derivative f'(a(x)) 360 | 361 | return GNum2(v , da * a.g); 362 | } 363 | //-------------------------------- 364 | GNum2 a_abs(in GNum2 a) 365 | { 366 | float v = abs(a.val); // value f(a(x)) 367 | float da = a.val < 0.0 ? -1.0 : 1.0; // first derivative f'(a(x)) 368 | 369 | return GNum2(v , da * a.g); 370 | } 371 | //-------------------------------- 372 | GNum2 a_exp(in GNum2 a) 373 | { 374 | float v = exp(a.val); // value f(a(x)) 375 | float da = exp(a.val); // first derivative f'(a(x)) 376 | 377 | return GNum2(v , da * a.g); 378 | } 379 | //-------------------------------- 380 | GNum2 a_cosh(in GNum2 a) 381 | { 382 | float v = cosh(a.val); // value f(a(x)) 383 | float da = sinh(a.val); // first derivative f'(a(x)) 384 | 385 | return GNum2(v , da * a.g); 386 | } 387 | //-------------------------------- 388 | GNum2 a_floor(in GNum2 a) 389 | { 390 | float v = floor(a.val); // value f(a(x)) 391 | float da = 0.0; // first derivative f'(a(x)) 392 | 393 | return GNum2(v , da * a.g); 394 | } 395 | //-------------------------------- 396 | GNum2 a_log(in GNum2 a) 397 | { 398 | float v = log(a.val); // value f(a(x)) 399 | float da = 1.0/a.val; // first derivative f'(a(x)) 400 | 401 | return GNum2(v , da * a.g); 402 | } 403 | //-------------------------------- 404 | GNum2 a_atanh(in GNum2 a) 405 | { 406 | float v = atanh(a.val); // value f(a(x)) 407 | float da = 1.0/(1.0 - a.val * a.val); // first derivative f'(a(x)) 408 | 409 | return GNum2(v , da * a.g); 410 | } 411 | //-------------------------------- 412 | GNum2 a_log2(in GNum2 a) 413 | { 414 | float v = log2(a.val); // value f(a(x)) 415 | float da = 1.0/(a.val * log(2.0)); // first derivative f'(a(x)) 416 | 417 | return GNum2(v , da * a.g); 418 | } 419 | //-------------------------------- 420 | GNum2 a_acos(in GNum2 a) 421 | { 422 | float v = acos(a.val); // value f(a(x)) 423 | float da = -1.0/sqrt(1.0 - a.val * a.val); // first derivative f'(a(x)) 424 | 425 | return GNum2(v , da * a.g); 426 | } 427 | //-------------------------------- 428 | GNum2 a_tanh(in GNum2 a) 429 | { 430 | float v = tanh(a.val); // value f(a(x)) 431 | float da = 1.0 - pow(tanh(a.val),2.0); // first derivative f'(a(x)) 432 | 433 | return GNum2(v , da * a.g); 434 | } 435 | //-------------------------------- 436 | GNum2 a_cos(in GNum2 a) 437 | { 438 | float v = cos(a.val); // value f(a(x)) 439 | float da = -sin(a.val); // first derivative f'(a(x)) 440 | 441 | return GNum2(v , da * a.g); 442 | } 443 | //-------------------------------- 444 | GNum2 a_sin(in GNum2 a) 445 | { 446 | float v = sin(a.val); // value f(a(x)) 447 | float da = cos(a.val); // first derivative f'(a(x)) 448 | 449 | return GNum2(v , da * a.g); 450 | } 451 | //-------------------------------- 452 | GNum2 a_atan2(in GNum2 y, in GNum2 x) 453 | { 454 | const float pi = 3.14159265; 455 | // from https://en.wikipedia.org/wiki/Atan2 456 | if(x.val > 0.0) 457 | { 458 | GNum2 n = a_sqrt(add(mult(x,x),mult(y,y))); 459 | GNum2 inner = div(y, add(n,x)); 460 | 461 | return mult(2.0,a_atan(inner)); 462 | 463 | }else if(x.val <= 0.0 && abs(y.val) > 1E-6) 464 | { 465 | GNum2 n = a_sqrt(add(mult(x,x),mult(y,y))); 466 | GNum2 inner = div(sub(n,x),y); 467 | return mult(2.0,a_atan(inner)); 468 | }else if(x.val < 0.0 && abs(y.val) <= 1E-6) 469 | { 470 | return constG2(pi); 471 | } 472 | // return 0 for undefined 473 | return constG2(0.0); 474 | } 475 | //-------------------------------- 476 | GNum2 a_atan2(in GNum2 y, in float x) 477 | { 478 | return a_atan2(y,constG2(x)); 479 | } 480 | //-------------------------------- 481 | GNum2 a_atan2(in float y, in GNum2 x) 482 | { 483 | return a_atan2(constG2(y),x); 484 | } 485 | //-------------------------------- 486 | GNum2 a_mix(in GNum2 a, in GNum2 b, in GNum2 t) 487 | { 488 | return add(mult(a, sub(1.0, t)), mult(b, t)); 489 | } 490 | 491 | //-------------------------------- 492 | GNum2 a_mix(in GNum2 a, in GNum2 b, in float t) 493 | { 494 | return add(mult(a, 1.0 - t), mult(b, t)); 495 | } 496 | 497 | //-------------------------------- 498 | GNum2 a_mix(in GNum2 a, in float b, in GNum2 t) 499 | { 500 | return add(mult(a, sub(1.0, t)), mult(b, t)); 501 | } 502 | 503 | //-------------------------------- 504 | GNum2 a_mix(in GNum2 a, in float b, in float t) 505 | { 506 | return add(mult(a, 1.0 - t), b*t); 507 | } 508 | 509 | //-------------------------------- 510 | GNum2 a_mix(in float a, in GNum2 b, in GNum2 t) 511 | { 512 | return add(mult(a, sub(1.0, t)), mult(b, t)); 513 | } 514 | 515 | //-------------------------------- 516 | GNum2 a_mix(in float a, in GNum2 b, in float t) 517 | { 518 | return add(a * (1.0 - t), mult(b, t)); 519 | } 520 | 521 | //-------------------------------- 522 | GNum2 a_mix(in float a, in float b, in GNum2 t) 523 | { 524 | return add(mult(a, sub(1.0, t)), mult(b, t)); 525 | } 526 | 527 | 528 | #endif // GRADNUM_2_H_ -------------------------------------------------------------------------------- /grad_3.glsl: -------------------------------------------------------------------------------- 1 | #ifndef GRADNUM_3_H_ 2 | #define GRADNUM_3_H_ 3 | 4 | // This file contains methods to compute the gradient of a scalar valued 3 dimensional 5 | // function using automatic forward differentiation 6 | 7 | //-------------------------------- 8 | // Types 9 | //-------------------------------- 10 | 11 | // Data type to hold information about a scalar valued 3 dimensional function 12 | // These should be created by the constG3 (for constants) and varG3 (for variables) helpers 13 | struct GNum3 14 | { 15 | // The current value 16 | float val; 17 | // The current gradient 18 | vec3 g; 19 | }; 20 | 21 | //-------------------------------- 22 | // Prototypes 23 | //-------------------------------- 24 | 25 | /** 26 | * Creates a constant GNum3 27 | * @param val The current value of the constant 28 | */ 29 | GNum3 constG3(in float val); 30 | GNum3 varG3(in float val, in int index); 31 | GNum3 varG3x(in float val); 32 | GNum3 varG3y(in float val); 33 | GNum3 varG3z(in float val); 34 | GNum3 add(in GNum3 a, in GNum3 b); 35 | GNum3 add(in GNum3 a, in float b); 36 | GNum3 add(in float a, in GNum3 b); 37 | GNum3 sub(in GNum3 a, in GNum3 b); 38 | GNum3 sub(in GNum3 a, in float b); 39 | GNum3 sub(in float a, in GNum3 b); 40 | GNum3 mult(in GNum3 a, in GNum3 b); 41 | GNum3 mult(in GNum3 a, in float b); 42 | GNum3 mult(in float a, in GNum3 b); 43 | GNum3 neg(in GNum3 a); 44 | GNum3 div(in GNum3 a, in GNum3 b); 45 | GNum3 div(in GNum3 a, in float b); 46 | GNum3 div(in float a, in GNum3 b); 47 | GNum3 inv(in GNum3 a); 48 | GNum3 a_pow(in GNum3 a, in GNum3 b); 49 | GNum3 a_pow(in GNum3 a, in float b); 50 | GNum3 a_pow(in float a, in GNum3 b); 51 | GNum3 a_ipow(in GNum3 x, in int n); 52 | GNum3 a_min(in GNum3 a, in GNum3 b); 53 | GNum3 a_max(in GNum3 a, in GNum3 b); 54 | GNum3 a_exp2(in GNum3 a); 55 | GNum3 a_inversesqrt(in GNum3 a); 56 | GNum3 a_atan(in GNum3 a); 57 | GNum3 a_sqrt(in GNum3 a); 58 | GNum3 a_sinh(in GNum3 a); 59 | GNum3 a_ceil(in GNum3 a); 60 | GNum3 a_tan(in GNum3 a); 61 | GNum3 a_asinh(in GNum3 a); 62 | GNum3 a_asin(in GNum3 a); 63 | GNum3 a_acosh(in GNum3 a); 64 | GNum3 a_abs(in GNum3 a); 65 | GNum3 a_exp(in GNum3 a); 66 | GNum3 a_cosh(in GNum3 a); 67 | GNum3 a_floor(in GNum3 a); 68 | GNum3 a_log(in GNum3 a); 69 | GNum3 a_atanh(in GNum3 a); 70 | GNum3 a_log2(in GNum3 a); 71 | GNum3 a_acos(in GNum3 a); 72 | GNum3 a_tanh(in GNum3 a); 73 | GNum3 a_cos(in GNum3 a); 74 | GNum3 a_sin(in GNum3 a); 75 | GNum3 a_atan2(in GNum3 y, in GNum3 x); 76 | GNum3 a_atan2(in GNum3 y, in float x); 77 | GNum3 a_atan2(in float y, in GNum3 x); 78 | GNum3 a_mix(in GNum3 a, in GNum3 b, in GNum3 t); 79 | GNum3 a_mix(in GNum3 a, in GNum3 b, in float t); 80 | GNum3 a_mix(in GNum3 a, in float b, in GNum3 t); 81 | GNum3 a_mix(in GNum3 a, in float b, in float t); 82 | GNum3 a_mix(in float a, in GNum3 b, in GNum3 t); 83 | GNum3 a_mix(in float a, in GNum3 b, in float t); 84 | GNum3 a_mix(in float a, in float b, in GNum3 t); 85 | 86 | //-------------------------------- 87 | // Macros 88 | //-------------------------------- 89 | 90 | #define GRAD3(f,x, y, z,result) { result = f(varG3x(x), varG3y(y), varG3z(z)); } 91 | //-------------------------------- 92 | #define JACOBI23(f1, f2, x, y, z, result) { GNum3 gradResult; GRAD3(f1, x, y, z, gradResult); result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; result[2][0] = gradResult.g[2]; GRAD3(f2, x, y, z, gradResult); result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; result[2][1] = gradResult.g[2]; } 93 | //-------------------------------- 94 | #define JACOBI23_VALUE(f1, f2, x, y, z, result, value) { GNum3 gradResult; GRAD3(f1, x, y, z, gradResult); value[0] = gradResult.val; result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; result[2][0] = gradResult.g[2]; GRAD3(f2, x, y, z, gradResult); value[1] = gradResult.val; result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; result[2][1] = gradResult.g[2]; } 95 | //-------------------------------- 96 | #define JACOBI3(f1, f2, f3, x, y, z, result) { GNum3 gradResult; GRAD3(f1, x, y, z, gradResult); result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; result[2][0] = gradResult.g[2]; GRAD3(f2, x, y, z, gradResult); result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; result[2][1] = gradResult.g[2]; GRAD3(f3, x, y, z, gradResult); result[0][2] = gradResult.g[0]; result[1][2] = gradResult.g[1]; result[2][2] = gradResult.g[2]; } 97 | //-------------------------------- 98 | #define JACOBI3_VALUE(f1, f2, f3, x, y, z, result, value) { GNum3 gradResult; GRAD3(f1, x, y, z, gradResult); value[0] = gradResult.val; result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; result[2][0] = gradResult.g[2]; GRAD3(f2, x, y, z, gradResult); value[1] = gradResult.val; result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; result[2][1] = gradResult.g[2]; GRAD3(f3, x, y, z, gradResult); value[2] = gradResult.val; result[0][2] = gradResult.g[0]; result[1][2] = gradResult.g[1]; result[2][2] = gradResult.g[2]; } 99 | //-------------------------------- 100 | #define JACOBI43(f1, f2, f3, f4, x, y, z, result) { GNum3 gradResult; GRAD3(f1, x, y, z, gradResult); result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; result[2][0] = gradResult.g[2]; GRAD3(f2, x, y, z, gradResult); result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; result[2][1] = gradResult.g[2]; GRAD3(f3, x, y, z, gradResult); result[0][2] = gradResult.g[0]; result[1][2] = gradResult.g[1]; result[2][2] = gradResult.g[2]; GRAD3(f4, x, y, z, gradResult); result[0][3] = gradResult.g[0]; result[1][3] = gradResult.g[1]; result[2][3] = gradResult.g[2]; } 101 | //-------------------------------- 102 | #define JACOBI43_VALUE(f1, f2, f3, f4, x, y, z, result, value) { GNum3 gradResult; GRAD3(f1, x, y, z, gradResult); value[0] = gradResult.val; result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; result[2][0] = gradResult.g[2]; GRAD3(f2, x, y, z, gradResult); value[1] = gradResult.val; result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; result[2][1] = gradResult.g[2]; GRAD3(f3, x, y, z, gradResult); value[2] = gradResult.val; result[0][2] = gradResult.g[0]; result[1][2] = gradResult.g[1]; result[2][2] = gradResult.g[2]; GRAD3(f4, x, y, z, gradResult); value[3] = gradResult.val; result[0][3] = gradResult.g[0]; result[1][3] = gradResult.g[1]; result[2][3] = gradResult.g[2]; } 103 | 104 | //-------------------------------- 105 | // Implementation 106 | //-------------------------------- 107 | 108 | GNum3 constG3(in float val) 109 | { 110 | return GNum3(val, vec3(0.0)); 111 | } 112 | //-------------------------------- 113 | GNum3 varG3(in float val, in int index) 114 | { 115 | vec3 g = vec3(0.0); 116 | g[index] = 1.0; 117 | return GNum3(val, g); 118 | } 119 | //-------------------------------- 120 | GNum3 varG3x(in float val) 121 | { 122 | vec3 g = vec3(0.0); 123 | g[0] = 1.0; 124 | return GNum3(val, g); 125 | } 126 | //-------------------------------- 127 | GNum3 varG3y(in float val) 128 | { 129 | vec3 g = vec3(0.0); 130 | g[1] = 1.0; 131 | return GNum3(val, g); 132 | } 133 | //-------------------------------- 134 | GNum3 varG3z(in float val) 135 | { 136 | vec3 g = vec3(0.0); 137 | g[2] = 1.0; 138 | return GNum3(val, g); 139 | } 140 | //-------------------------------- 141 | GNum3 add(in GNum3 a, in GNum3 b) 142 | { 143 | return GNum3(a.val + b.val, a.g + b.g); 144 | } 145 | //-------------------------------- 146 | GNum3 add(in GNum3 a, in float b) 147 | { 148 | return GNum3(a.val + b, a.g); 149 | } 150 | //-------------------------------- 151 | GNum3 add(in float a, in GNum3 b) 152 | { 153 | return GNum3(a + b.val, b.g); 154 | } 155 | //-------------------------------- 156 | GNum3 sub(in GNum3 a, in GNum3 b) 157 | { 158 | return GNum3(a.val - b.val, a.g - b.g); 159 | } 160 | //-------------------------------- 161 | GNum3 sub(in GNum3 a, in float b) 162 | { 163 | return GNum3(a.val - b, a.g); 164 | } 165 | //-------------------------------- 166 | GNum3 sub(in float a, in GNum3 b) 167 | { 168 | return GNum3(a - b.val, -b.g); 169 | } 170 | //-------------------------------- 171 | GNum3 mult(in GNum3 a, in GNum3 b) 172 | { 173 | return GNum3(a.val * b.val, 174 | a.val*b.g + b.val*a.g 175 | ); 176 | } 177 | //-------------------------------- 178 | GNum3 mult(in GNum3 a, in float b) 179 | { 180 | return GNum3(a.val * b, b*a.g); 181 | } 182 | //-------------------------------- 183 | GNum3 mult(in float a, in GNum3 b) 184 | { 185 | return GNum3(a * b.val, a*b.g); 186 | } 187 | //-------------------------------- 188 | GNum3 neg(in GNum3 a) 189 | { 190 | return mult(-1.0,a); 191 | } 192 | //-------------------------------- 193 | GNum3 div(in GNum3 a, in GNum3 b) 194 | { 195 | float b1 = b.val; 196 | float b2 = b1*b1; 197 | 198 | return GNum3(a.val / b.val , 199 | (b.val*a.g - a.val*b.g)/b2 200 | ); 201 | } 202 | //-------------------------------- 203 | GNum3 div(in GNum3 a, in float b) 204 | { 205 | return GNum3(a.val / b, a.g/b); 206 | } 207 | //-------------------------------- 208 | GNum3 div(in float a, in GNum3 b) 209 | { 210 | float b1 = b.val; 211 | float b2 = b1*b1; 212 | 213 | return GNum3(a / b.val, 214 | -a*b.g/b2 215 | ); 216 | } 217 | //-------------------------------- 218 | GNum3 inv(in GNum3 a) 219 | { 220 | return div(1.0, a); 221 | } 222 | //-------------------------------- 223 | GNum3 a_pow(in GNum3 a, in GNum3 b) 224 | { 225 | return a_exp(mult(b,a_log(a))); 226 | } 227 | //-------------------------------- 228 | GNum3 a_pow(in GNum3 a, in float b) 229 | { 230 | // constant exponent -> make special case 231 | float v = pow(a.val, b); // value f(a(x)) 232 | float da = b*pow(a.val,b-1.0); // first derivative f'(a(x)) 233 | return GNum3(v , da * a.g); 234 | } 235 | //-------------------------------- 236 | GNum3 a_pow(in float a, in GNum3 b) 237 | { 238 | return a_exp(mult(b,log(a))); 239 | } 240 | //-------------------------------- 241 | GNum3 a_ipow(in GNum3 x, in int n) 242 | { 243 | // based on https://en.wikipedia.org/wiki/Exponentiation_by_squaring 244 | if (n < 0) 245 | { 246 | x = div(1.0,x); 247 | n = -n; 248 | } 249 | if (n == 0) 250 | { 251 | return constG3(1.0); 252 | } 253 | GNum3 y = constG3(1.0); 254 | while (n > 1) 255 | { 256 | if (n % 2 == 0) 257 | { 258 | x = mult(x,x); 259 | 260 | } 261 | else 262 | { 263 | y = mult(x, y); 264 | x = mult(x, x); 265 | } 266 | 267 | n = n / 2; 268 | } 269 | 270 | return mult(x, y); 271 | } 272 | 273 | //-------------------------------- 274 | GNum3 a_min(in GNum3 a, in GNum3 b) 275 | { 276 | if(a.val < b.val) 277 | { 278 | return a; 279 | } 280 | return b; 281 | } 282 | //-------------------------------- 283 | GNum3 a_max(in GNum3 a, in GNum3 b) 284 | { 285 | if(a.val > b.val) 286 | { 287 | return a; 288 | } 289 | return b; 290 | } 291 | //-------------------------------- 292 | GNum3 a_exp2(in GNum3 a) 293 | { 294 | float v = exp2(a.val); // value f(a(x)) 295 | float da = log(2.0)*exp2(a.val); // first derivative f'(a(x)) 296 | 297 | return GNum3(v , da * a.g); 298 | } 299 | //-------------------------------- 300 | GNum3 a_inversesqrt(in GNum3 a) 301 | { 302 | float v = inversesqrt(a.val); // value f(a(x)) 303 | float da = -0.5/pow(sqrt(a.val),3.0); // first derivative f'(a(x)) 304 | 305 | return GNum3(v , da * a.g); 306 | } 307 | //-------------------------------- 308 | GNum3 a_atan(in GNum3 a) 309 | { 310 | float v = atan(a.val); // value f(a(x)) 311 | float da = 1.0/(1.0 + a.val * a.val); // first derivative f'(a(x)) 312 | 313 | return GNum3(v , da * a.g); 314 | } 315 | //-------------------------------- 316 | GNum3 a_sqrt(in GNum3 a) 317 | { 318 | float v = sqrt(a.val); // value f(a(x)) 319 | float da = 0.5/sqrt(a.val); // first derivative f'(a(x)) 320 | 321 | return GNum3(v , da * a.g); 322 | } 323 | //-------------------------------- 324 | GNum3 a_sinh(in GNum3 a) 325 | { 326 | float v = sinh(a.val); // value f(a(x)) 327 | float da = cosh(a.val); // first derivative f'(a(x)) 328 | 329 | return GNum3(v , da * a.g); 330 | } 331 | //-------------------------------- 332 | GNum3 a_ceil(in GNum3 a) 333 | { 334 | float v = ceil(a.val); // value f(a(x)) 335 | float da = 0.0; // first derivative f'(a(x)) 336 | 337 | return GNum3(v , da * a.g); 338 | } 339 | //-------------------------------- 340 | GNum3 a_tan(in GNum3 a) 341 | { 342 | float v = tan(a.val); // value f(a(x)) 343 | float da = 1.0 + pow(tan(a.val),2.0); // first derivative f'(a(x)) 344 | 345 | return GNum3(v , da * a.g); 346 | } 347 | //-------------------------------- 348 | GNum3 a_asinh(in GNum3 a) 349 | { 350 | float v = asinh(a.val); // value f(a(x)) 351 | float da = 1.0/sqrt(1.0 + a.val * a.val); // first derivative f'(a(x)) 352 | 353 | return GNum3(v , da * a.g); 354 | } 355 | //-------------------------------- 356 | GNum3 a_asin(in GNum3 a) 357 | { 358 | float v = asin(a.val); // value f(a(x)) 359 | float da = 1.0/sqrt(1.0 - a.val * a.val); // first derivative f'(a(x)) 360 | 361 | return GNum3(v , da * a.g); 362 | } 363 | //-------------------------------- 364 | GNum3 a_acosh(in GNum3 a) 365 | { 366 | float v = acosh(a.val); // value f(a(x)) 367 | float da = 1.0/sqrt(-1.0 + a.val * a.val); // first derivative f'(a(x)) 368 | 369 | return GNum3(v , da * a.g); 370 | } 371 | //-------------------------------- 372 | GNum3 a_abs(in GNum3 a) 373 | { 374 | float v = abs(a.val); // value f(a(x)) 375 | float da = a.val < 0.0 ? -1.0 : 1.0; // first derivative f'(a(x)) 376 | 377 | return GNum3(v , da * a.g); 378 | } 379 | //-------------------------------- 380 | GNum3 a_exp(in GNum3 a) 381 | { 382 | float v = exp(a.val); // value f(a(x)) 383 | float da = exp(a.val); // first derivative f'(a(x)) 384 | 385 | return GNum3(v , da * a.g); 386 | } 387 | //-------------------------------- 388 | GNum3 a_cosh(in GNum3 a) 389 | { 390 | float v = cosh(a.val); // value f(a(x)) 391 | float da = sinh(a.val); // first derivative f'(a(x)) 392 | 393 | return GNum3(v , da * a.g); 394 | } 395 | //-------------------------------- 396 | GNum3 a_floor(in GNum3 a) 397 | { 398 | float v = floor(a.val); // value f(a(x)) 399 | float da = 0.0; // first derivative f'(a(x)) 400 | 401 | return GNum3(v , da * a.g); 402 | } 403 | //-------------------------------- 404 | GNum3 a_log(in GNum3 a) 405 | { 406 | float v = log(a.val); // value f(a(x)) 407 | float da = 1.0/a.val; // first derivative f'(a(x)) 408 | 409 | return GNum3(v , da * a.g); 410 | } 411 | //-------------------------------- 412 | GNum3 a_atanh(in GNum3 a) 413 | { 414 | float v = atanh(a.val); // value f(a(x)) 415 | float da = 1.0/(1.0 - a.val * a.val); // first derivative f'(a(x)) 416 | 417 | return GNum3(v , da * a.g); 418 | } 419 | //-------------------------------- 420 | GNum3 a_log2(in GNum3 a) 421 | { 422 | float v = log2(a.val); // value f(a(x)) 423 | float da = 1.0/(a.val * log(2.0)); // first derivative f'(a(x)) 424 | 425 | return GNum3(v , da * a.g); 426 | } 427 | //-------------------------------- 428 | GNum3 a_acos(in GNum3 a) 429 | { 430 | float v = acos(a.val); // value f(a(x)) 431 | float da = -1.0/sqrt(1.0 - a.val * a.val); // first derivative f'(a(x)) 432 | 433 | return GNum3(v , da * a.g); 434 | } 435 | //-------------------------------- 436 | GNum3 a_tanh(in GNum3 a) 437 | { 438 | float v = tanh(a.val); // value f(a(x)) 439 | float da = 1.0 - pow(tanh(a.val),2.0); // first derivative f'(a(x)) 440 | 441 | return GNum3(v , da * a.g); 442 | } 443 | //-------------------------------- 444 | GNum3 a_cos(in GNum3 a) 445 | { 446 | float v = cos(a.val); // value f(a(x)) 447 | float da = -sin(a.val); // first derivative f'(a(x)) 448 | 449 | return GNum3(v , da * a.g); 450 | } 451 | //-------------------------------- 452 | GNum3 a_sin(in GNum3 a) 453 | { 454 | float v = sin(a.val); // value f(a(x)) 455 | float da = cos(a.val); // first derivative f'(a(x)) 456 | 457 | return GNum3(v , da * a.g); 458 | } 459 | //-------------------------------- 460 | GNum3 a_atan2(in GNum3 y, in GNum3 x) 461 | { 462 | const float pi = 3.14159265; 463 | // from https://en.wikipedia.org/wiki/Atan2 464 | if(x.val > 0.0) 465 | { 466 | GNum3 n = a_sqrt(add(mult(x,x),mult(y,y))); 467 | GNum3 inner = div(y, add(n,x)); 468 | 469 | return mult(2.0,a_atan(inner)); 470 | 471 | }else if(x.val <= 0.0 && abs(y.val) > 1E-6) 472 | { 473 | GNum3 n = a_sqrt(add(mult(x,x),mult(y,y))); 474 | GNum3 inner = div(sub(n,x),y); 475 | return mult(2.0,a_atan(inner)); 476 | }else if(x.val < 0.0 && abs(y.val) <= 1E-6) 477 | { 478 | return constG3(pi); 479 | } 480 | // return 0 for undefined 481 | return constG3(0.0); 482 | } 483 | //-------------------------------- 484 | GNum3 a_atan2(in GNum3 y, in float x) 485 | { 486 | return a_atan2(y,constG3(x)); 487 | } 488 | //-------------------------------- 489 | GNum3 a_atan2(in float y, in GNum3 x) 490 | { 491 | return a_atan2(constG3(y),x); 492 | } 493 | //-------------------------------- 494 | GNum3 a_mix(in GNum3 a, in GNum3 b, in GNum3 t) 495 | { 496 | return add(mult(a, sub(1.0, t)), mult(b, t)); 497 | } 498 | 499 | //-------------------------------- 500 | GNum3 a_mix(in GNum3 a, in GNum3 b, in float t) 501 | { 502 | return add(mult(a, 1.0 - t), mult(b, t)); 503 | } 504 | 505 | //-------------------------------- 506 | GNum3 a_mix(in GNum3 a, in float b, in GNum3 t) 507 | { 508 | return add(mult(a, sub(1.0, t)), mult(b, t)); 509 | } 510 | 511 | //-------------------------------- 512 | GNum3 a_mix(in GNum3 a, in float b, in float t) 513 | { 514 | return add(mult(a, 1.0 - t), b*t); 515 | } 516 | 517 | //-------------------------------- 518 | GNum3 a_mix(in float a, in GNum3 b, in GNum3 t) 519 | { 520 | return add(mult(a, sub(1.0, t)), mult(b, t)); 521 | } 522 | 523 | //-------------------------------- 524 | GNum3 a_mix(in float a, in GNum3 b, in float t) 525 | { 526 | return add(a * (1.0 - t), mult(b, t)); 527 | } 528 | 529 | //-------------------------------- 530 | GNum3 a_mix(in float a, in float b, in GNum3 t) 531 | { 532 | return add(mult(a, sub(1.0, t)), mult(b, t)); 533 | } 534 | 535 | 536 | #endif // GRADNUM_3_H_ -------------------------------------------------------------------------------- /hessian_2.glsl: -------------------------------------------------------------------------------- 1 | #ifndef HESSNUM_2_H_ 2 | #define HESSNUM_2_H_ 3 | 4 | // This file contains methods to compute the gradient and hessian 5 | // of a scalar valued 2 dimensional function using automatic forward differentiation 6 | 7 | //-------------------------------- 8 | // Types 9 | //-------------------------------- 10 | 11 | // Data type to hold information about a scalar valued 2 dimensional function 12 | // These should be created by the constH2 (for constants) and varH2 (for variables) helpers 13 | struct HNum2 14 | { 15 | // The current value 16 | float val; 17 | // The current gradient 18 | vec2 g; 19 | // The current hessian 20 | mat2 h; 21 | }; 22 | 23 | //-------------------------------- 24 | // Prototypes 25 | //-------------------------------- 26 | 27 | /** 28 | * Creates a constant HNum2 29 | * @param val The current value of the constant 30 | */ 31 | HNum2 constH2(in float val); 32 | /** 33 | * Creates a HNum2 corresponding to the variable with the given index 34 | * @param val The current value of the variable 35 | * @param index The variable's index 36 | */ 37 | HNum2 varH2(in float val, in int index); 38 | /** 39 | * Creates a HNum2 corresponding to the variable x (index = 0) 40 | * @param val The current value of the variable 41 | */ 42 | HNum2 varH2x(in float val); 43 | /** 44 | * Creates a HNum2 corresponding to the variable y (index = 1) 45 | * @param val The current value of the variable 46 | */ 47 | HNum2 varH2y(in float val); 48 | HNum2 add(in HNum2 a, in HNum2 b); 49 | HNum2 add(in HNum2 a, in float b); 50 | HNum2 add(in float a, in HNum2 b); 51 | HNum2 sub(in HNum2 a, in HNum2 b); 52 | HNum2 sub(in HNum2 a, in float b); 53 | HNum2 sub(in float a, in HNum2 b); 54 | HNum2 mult(in HNum2 a, in HNum2 b); 55 | HNum2 mult(in HNum2 a, in float b); 56 | HNum2 mult(in float a, in HNum2 b); 57 | HNum2 neg(in HNum2 a); 58 | HNum2 div(in HNum2 a, in HNum2 b); 59 | HNum2 div(in HNum2 a, in float b); 60 | HNum2 div(in float a, in HNum2 b); 61 | HNum2 inv(in HNum2 a); 62 | HNum2 a_pow(in HNum2 a, in HNum2 b); 63 | HNum2 a_pow(in HNum2 a, in float b); 64 | HNum2 a_pow(in float a, in HNum2 b); 65 | HNum2 a_ipow(in HNum2 x, in int n); 66 | HNum2 a_min(in HNum2 a, in HNum2 b); 67 | HNum2 a_max(in HNum2 a, in HNum2 b); 68 | HNum2 a_exp2(in HNum2 a); 69 | HNum2 a_inversesqrt(in HNum2 a); 70 | HNum2 a_atan(in HNum2 a); 71 | HNum2 a_sqrt(in HNum2 a); 72 | HNum2 a_sinh(in HNum2 a); 73 | HNum2 a_ceil(in HNum2 a); 74 | HNum2 a_tan(in HNum2 a); 75 | HNum2 a_asinh(in HNum2 a); 76 | HNum2 a_asin(in HNum2 a); 77 | HNum2 a_acosh(in HNum2 a); 78 | HNum2 a_abs(in HNum2 a); 79 | HNum2 a_exp(in HNum2 a); 80 | HNum2 a_cosh(in HNum2 a); 81 | HNum2 a_floor(in HNum2 a); 82 | HNum2 a_log(in HNum2 a); 83 | HNum2 a_atanh(in HNum2 a); 84 | HNum2 a_log2(in HNum2 a); 85 | HNum2 a_acos(in HNum2 a); 86 | HNum2 a_tanh(in HNum2 a); 87 | HNum2 a_cos(in HNum2 a); 88 | HNum2 a_sin(in HNum2 a); 89 | HNum2 a_atan2(in HNum2 y, in HNum2 x); 90 | HNum2 a_atan2(in HNum2 y, in float x); 91 | HNum2 a_atan2(in float y, in HNum2 x); 92 | HNum2 a_mix(in HNum2 a, in HNum2 b, in HNum2 t); 93 | HNum2 a_mix(in HNum2 a, in HNum2 b, in float t); 94 | HNum2 a_mix(in HNum2 a, in float b, in HNum2 t); 95 | HNum2 a_mix(in HNum2 a, in float b, in float t); 96 | HNum2 a_mix(in float a, in HNum2 b, in HNum2 t); 97 | HNum2 a_mix(in float a, in HNum2 b, in float t); 98 | HNum2 a_mix(in float a, in float b, in HNum2 t); 99 | 100 | //-------------------------------- 101 | // Macros 102 | //-------------------------------- 103 | 104 | #define HESSIAN2(f,x, y,result) { result = f(varH2x(x), varH2y(y)); } 105 | 106 | //-------------------------------- 107 | // Utilities prototypes 108 | //-------------------------------- 109 | 110 | mat2 a_outerProduct(in vec2 a, in vec2 b); 111 | 112 | //-------------------------------- 113 | // Implementation 114 | //-------------------------------- 115 | 116 | HNum2 constH2(in float val) 117 | { 118 | return HNum2(val, vec2(0.0), mat2(0.0)); 119 | } 120 | //-------------------------------- 121 | HNum2 varH2(in float val, in int index) 122 | { 123 | vec2 g = vec2(0.0); 124 | g[index] = 1.0; 125 | return HNum2(val, g, mat2(0.0)); 126 | } 127 | //-------------------------------- 128 | HNum2 varH2x(in float val) 129 | { 130 | vec2 g = vec2(0.0); 131 | g[0] = 1.0; 132 | return HNum2(val, g, mat2(0.0)); 133 | } 134 | //-------------------------------- 135 | HNum2 varH2y(in float val) 136 | { 137 | vec2 g = vec2(0.0); 138 | g[1] = 1.0; 139 | return HNum2(val, g, mat2(0.0)); 140 | } 141 | //-------------------------------- 142 | HNum2 add(in HNum2 a, in HNum2 b) 143 | { 144 | return HNum2(a.val + b.val , a.g + b.g, a.h + b.h); 145 | } 146 | //-------------------------------- 147 | HNum2 add(in HNum2 a, in float b) 148 | { 149 | return HNum2(a.val + b , a.g, a.h); 150 | } 151 | //-------------------------------- 152 | HNum2 add(in float a, in HNum2 b) 153 | { 154 | return HNum2(a + b.val , b.g, b.h); 155 | } 156 | //-------------------------------- 157 | HNum2 sub(in HNum2 a, in HNum2 b) 158 | { 159 | return HNum2(a.val - b.val , a.g - b.g, a.h - b.h); 160 | } 161 | //-------------------------------- 162 | HNum2 sub(in HNum2 a, in float b) 163 | { 164 | return HNum2(a.val - b , a.g, a.h); 165 | } 166 | //-------------------------------- 167 | HNum2 sub(in float a, in HNum2 b) 168 | { 169 | return HNum2(a - b.val , - b.g, - b.h); 170 | } 171 | //-------------------------------- 172 | HNum2 mult(in HNum2 a, in HNum2 b) 173 | { 174 | return HNum2(a.val * b.val, 175 | a.val*b.g + b.val*a.g, 176 | a.val*b.h + b.val*a.h + a_outerProduct(b.g,a.g) + a_outerProduct(a.g,b.g) 177 | ); 178 | } 179 | //-------------------------------- 180 | HNum2 mult(in HNum2 a, in float b) 181 | { 182 | return HNum2(a.val * b, b*a.g, b*a.h); 183 | } 184 | //-------------------------------- 185 | HNum2 mult(in float a, in HNum2 b) 186 | { 187 | return HNum2(a * b.val, a*b.g, a*b.h); 188 | } 189 | //-------------------------------- 190 | HNum2 neg(in HNum2 a) 191 | { 192 | return mult(-1.0,a); 193 | } 194 | //-------------------------------- 195 | HNum2 div(in HNum2 a, in HNum2 b) 196 | { 197 | float b1 = b.val; 198 | float b2 = b1*b1; 199 | float b3 = b2*b1; 200 | 201 | return HNum2(a.val / b.val , 202 | (b.val*a.g - a.val*b.g)/b2, 203 | 2.0*a.val/b3*a_outerProduct(b.g,b.g) 204 | - a.val/b2*b.h 205 | + a.h/b1 206 | - a_outerProduct(b.g/b2, a.g) 207 | - a_outerProduct(a.g/b2, b.g) 208 | ); 209 | } 210 | //-------------------------------- 211 | HNum2 div(in HNum2 a, in float b) 212 | { 213 | return HNum2(a.val / b, a.g/b, a.h/b); 214 | } 215 | //-------------------------------- 216 | HNum2 div(in float a, in HNum2 b) 217 | { 218 | float b1 = b.val; 219 | float b2 = b1*b1; 220 | float b3 = b2*b1; 221 | 222 | return HNum2(a / b.val, 223 | -a*b.g/b2, 224 | 2.0*a/b3*a_outerProduct(b.g,b.g) - a/b2*b.h 225 | ); 226 | } 227 | //-------------------------------- 228 | HNum2 inv(in HNum2 a) 229 | { 230 | return div(1.0, a); 231 | } 232 | //-------------------------------- 233 | HNum2 a_pow(in HNum2 a, in HNum2 b) 234 | { 235 | return a_exp(mult(b,a_log(a))); 236 | } 237 | //-------------------------------- 238 | HNum2 a_pow(in HNum2 a, in float b) 239 | { 240 | // constant exponent -> make special case 241 | float v = pow(a.val, b); // value f(a(x)) 242 | float da = b*pow(a.val,b-1.0); // first derivative f'(a(x)) 243 | float dda = b*(b-1.0)*pow(a.val,b-2.0); // second derivative f''(a(x)) 244 | return HNum2(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 245 | } 246 | //-------------------------------- 247 | HNum2 a_pow(in float a, in HNum2 b) 248 | { 249 | return a_exp(mult(b,log(a))); 250 | } 251 | //-------------------------------- 252 | HNum2 a_ipow(in HNum2 x, in int n) 253 | { 254 | // based on https://en.wikipedia.org/wiki/Exponentiation_by_squaring 255 | if (n < 0) 256 | { 257 | x = div(1.0,x); 258 | n = -n; 259 | } 260 | if (n == 0) 261 | { 262 | return constH2(1.0); 263 | } 264 | HNum2 y = constH2(1.0); 265 | while (n > 1) 266 | { 267 | if (n % 2 == 0) 268 | { 269 | x = mult(x,x); 270 | 271 | } 272 | else 273 | { 274 | y = mult(x, y); 275 | x = mult(x, x); 276 | } 277 | 278 | n = n / 2; 279 | } 280 | 281 | return mult(x, y); 282 | } 283 | 284 | //-------------------------------- 285 | HNum2 a_min(in HNum2 a, in HNum2 b) 286 | { 287 | if(a.val < b.val) 288 | { 289 | return a; 290 | } 291 | return b; 292 | } 293 | //-------------------------------- 294 | HNum2 a_max(in HNum2 a, in HNum2 b) 295 | { 296 | if(a.val > b.val) 297 | { 298 | return a; 299 | } 300 | return b; 301 | } 302 | //-------------------------------- 303 | HNum2 a_exp2(in HNum2 a) 304 | { 305 | float v = exp2(a.val); // value f(a(x)) 306 | float da = log(2.0)*exp2(a.val); // first derivative f'(a(x)) 307 | float dda = log(2.0)*log(2.0)*exp2(a.val); // second derivative f''(a(x)) 308 | 309 | return HNum2(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 310 | } 311 | //-------------------------------- 312 | HNum2 a_inversesqrt(in HNum2 a) 313 | { 314 | float v = inversesqrt(a.val); // value f(a(x)) 315 | float da = -0.5/pow(sqrt(a.val),3.0); // first derivative f'(a(x)) 316 | float dda = 0.75/pow(sqrt(a.val),5.0); // second derivative f''(a(x)) 317 | 318 | return HNum2(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 319 | } 320 | //-------------------------------- 321 | HNum2 a_atan(in HNum2 a) 322 | { 323 | float v = atan(a.val); // value f(a(x)) 324 | float da = 1.0/(1.0 + a.val * a.val); // first derivative f'(a(x)) 325 | float dda = -2.0*a.val/pow(1.0 + a.val * a.val, 2.0); // second derivative f''(a(x)) 326 | 327 | return HNum2(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 328 | } 329 | //-------------------------------- 330 | HNum2 a_sqrt(in HNum2 a) 331 | { 332 | float v = sqrt(a.val); // value f(a(x)) 333 | float da = 0.5/sqrt(a.val); // first derivative f'(a(x)) 334 | float dda = -0.25/pow(sqrt(a.val),3.0); // second derivative f''(a(x)) 335 | 336 | return HNum2(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 337 | } 338 | //-------------------------------- 339 | HNum2 a_sinh(in HNum2 a) 340 | { 341 | float v = sinh(a.val); // value f(a(x)) 342 | float da = cosh(a.val); // first derivative f'(a(x)) 343 | float dda = sinh(a.val); // second derivative f''(a(x)) 344 | 345 | return HNum2(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 346 | } 347 | //-------------------------------- 348 | HNum2 a_ceil(in HNum2 a) 349 | { 350 | float v = ceil(a.val); // value f(a(x)) 351 | float da = 0.0; // first derivative f'(a(x)) 352 | float dda = 0.0; // second derivative f''(a(x)) 353 | 354 | return HNum2(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 355 | } 356 | //-------------------------------- 357 | HNum2 a_tan(in HNum2 a) 358 | { 359 | float v = tan(a.val); // value f(a(x)) 360 | float da = 1.0 + pow(tan(a.val),2.0); // first derivative f'(a(x)) 361 | float dda = 2.0*tan(a.val)*(1.0 + pow(tan(a.val),2.0)); // second derivative f''(a(x)) 362 | 363 | return HNum2(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 364 | } 365 | //-------------------------------- 366 | HNum2 a_asinh(in HNum2 a) 367 | { 368 | float v = asinh(a.val); // value f(a(x)) 369 | float da = 1.0/sqrt(1.0 + a.val * a.val); // first derivative f'(a(x)) 370 | float dda = -a.val/pow(sqrt(1.0 + a.val * a.val),3.0); // second derivative f''(a(x)) 371 | 372 | return HNum2(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 373 | } 374 | //-------------------------------- 375 | HNum2 a_asin(in HNum2 a) 376 | { 377 | float v = asin(a.val); // value f(a(x)) 378 | float da = 1.0/sqrt(1.0 - a.val * a.val); // first derivative f'(a(x)) 379 | float dda = a.val/pow(sqrt(1.0 - a.val * a.val),3.0); // second derivative f''(a(x)) 380 | 381 | return HNum2(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 382 | } 383 | //-------------------------------- 384 | HNum2 a_acosh(in HNum2 a) 385 | { 386 | float v = acosh(a.val); // value f(a(x)) 387 | float da = 1.0/sqrt(-1.0 + a.val * a.val); // first derivative f'(a(x)) 388 | float dda = -a.val/pow(sqrt(-1.0 + a.val * a.val),3.0); // second derivative f''(a(x)) 389 | 390 | return HNum2(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 391 | } 392 | //-------------------------------- 393 | HNum2 a_abs(in HNum2 a) 394 | { 395 | float v = abs(a.val); // value f(a(x)) 396 | float da = a.val < 0.0 ? -1.0 : 1.0; // first derivative f'(a(x)) 397 | float dda = 0.0; // second derivative f''(a(x)) 398 | 399 | return HNum2(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 400 | } 401 | //-------------------------------- 402 | HNum2 a_exp(in HNum2 a) 403 | { 404 | float v = exp(a.val); // value f(a(x)) 405 | float da = exp(a.val); // first derivative f'(a(x)) 406 | float dda = exp(a.val); // second derivative f''(a(x)) 407 | 408 | return HNum2(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 409 | } 410 | //-------------------------------- 411 | HNum2 a_cosh(in HNum2 a) 412 | { 413 | float v = cosh(a.val); // value f(a(x)) 414 | float da = sinh(a.val); // first derivative f'(a(x)) 415 | float dda = cosh(a.val); // second derivative f''(a(x)) 416 | 417 | return HNum2(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 418 | } 419 | //-------------------------------- 420 | HNum2 a_floor(in HNum2 a) 421 | { 422 | float v = floor(a.val); // value f(a(x)) 423 | float da = 0.0; // first derivative f'(a(x)) 424 | float dda = 0.0; // second derivative f''(a(x)) 425 | 426 | return HNum2(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 427 | } 428 | //-------------------------------- 429 | HNum2 a_log(in HNum2 a) 430 | { 431 | float v = log(a.val); // value f(a(x)) 432 | float da = 1.0/a.val; // first derivative f'(a(x)) 433 | float dda = -1.0/(a.val * a.val); // second derivative f''(a(x)) 434 | 435 | return HNum2(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 436 | } 437 | //-------------------------------- 438 | HNum2 a_atanh(in HNum2 a) 439 | { 440 | float v = atanh(a.val); // value f(a(x)) 441 | float da = 1.0/(1.0 - a.val * a.val); // first derivative f'(a(x)) 442 | float dda = 2.0*a.val/pow(1.0 - a.val * a.val,2.0); // second derivative f''(a(x)) 443 | 444 | return HNum2(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 445 | } 446 | //-------------------------------- 447 | HNum2 a_log2(in HNum2 a) 448 | { 449 | float v = log2(a.val); // value f(a(x)) 450 | float da = 1.0/(a.val * log(2.0)); // first derivative f'(a(x)) 451 | float dda = -1.0/(a.val * a.val * log(2.0)); // second derivative f''(a(x)) 452 | 453 | return HNum2(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 454 | } 455 | //-------------------------------- 456 | HNum2 a_acos(in HNum2 a) 457 | { 458 | float v = acos(a.val); // value f(a(x)) 459 | float da = -1.0/sqrt(1.0 - a.val * a.val); // first derivative f'(a(x)) 460 | float dda = -a.val/pow(sqrt(1.0 - a.val * a.val),3.0); // second derivative f''(a(x)) 461 | 462 | return HNum2(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 463 | } 464 | //-------------------------------- 465 | HNum2 a_tanh(in HNum2 a) 466 | { 467 | float v = tanh(a.val); // value f(a(x)) 468 | float da = 1.0 - pow(tanh(a.val),2.0); // first derivative f'(a(x)) 469 | float dda = -2.0*tanh(a.val)*(1.0 - pow(tanh(a.val),2.0)); // second derivative f''(a(x)) 470 | 471 | return HNum2(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 472 | } 473 | //-------------------------------- 474 | HNum2 a_cos(in HNum2 a) 475 | { 476 | float v = cos(a.val); // value f(a(x)) 477 | float da = -sin(a.val); // first derivative f'(a(x)) 478 | float dda = -cos(a.val); // second derivative f''(a(x)) 479 | 480 | return HNum2(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 481 | } 482 | //-------------------------------- 483 | HNum2 a_sin(in HNum2 a) 484 | { 485 | float v = sin(a.val); // value f(a(x)) 486 | float da = cos(a.val); // first derivative f'(a(x)) 487 | float dda = -sin(a.val); // second derivative f''(a(x)) 488 | 489 | return HNum2(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 490 | } 491 | //-------------------------------- 492 | HNum2 a_atan2(in HNum2 y, in HNum2 x) 493 | { 494 | const float pi = 3.14159265; 495 | // from https://en.wikipedia.org/wiki/Atan2 496 | if(x.val > 0.0) 497 | { 498 | HNum2 n = a_sqrt(add(mult(x,x),mult(y,y))); 499 | HNum2 inner = div(y, add(n,x)); 500 | 501 | return mult(2.0,a_atan(inner)); 502 | 503 | }else if(x.val <= 0.0 && abs(y.val) > 1E-6) 504 | { 505 | HNum2 n = a_sqrt(add(mult(x,x),mult(y,y))); 506 | HNum2 inner = div(sub(n,x),y); 507 | return mult(2.0,a_atan(inner)); 508 | }else if(x.val < 0.0 && abs(y.val) <= 1E-6) 509 | { 510 | return constH2(pi); 511 | } 512 | // return 0 for undefined 513 | return constH2(0.0); 514 | } 515 | //-------------------------------- 516 | HNum2 a_atan2(in HNum2 y, in float x) 517 | { 518 | return a_atan2(y,constH2(x)); 519 | } 520 | //-------------------------------- 521 | HNum2 a_atan2(in float y, in HNum2 x) 522 | { 523 | return a_atan2(constH2(y),x); 524 | } 525 | //-------------------------------- 526 | HNum2 a_mix(in HNum2 a, in HNum2 b, in HNum2 t) 527 | { 528 | return add(mult(a, sub(1.0, t)), mult(b, t)); 529 | } 530 | 531 | //-------------------------------- 532 | HNum2 a_mix(in HNum2 a, in HNum2 b, in float t) 533 | { 534 | return add(mult(a, 1.0 - t), mult(b, t)); 535 | } 536 | 537 | //-------------------------------- 538 | HNum2 a_mix(in HNum2 a, in float b, in HNum2 t) 539 | { 540 | return add(mult(a, sub(1.0, t)), mult(b, t)); 541 | } 542 | 543 | //-------------------------------- 544 | HNum2 a_mix(in HNum2 a, in float b, in float t) 545 | { 546 | return add(mult(a, 1.0 - t), b*t); 547 | } 548 | 549 | //-------------------------------- 550 | HNum2 a_mix(in float a, in HNum2 b, in HNum2 t) 551 | { 552 | return add(mult(a, sub(1.0, t)), mult(b, t)); 553 | } 554 | 555 | //-------------------------------- 556 | HNum2 a_mix(in float a, in HNum2 b, in float t) 557 | { 558 | return add(a * (1.0 - t), mult(b, t)); 559 | } 560 | 561 | //-------------------------------- 562 | HNum2 a_mix(in float a, in float b, in HNum2 t) 563 | { 564 | return add(mult(a, sub(1.0, t)), mult(b, t)); 565 | } 566 | 567 | 568 | //-------------------------------- 569 | // Implementation prototypes 570 | //-------------------------------- 571 | 572 | mat2 a_outerProduct(in vec2 a, in vec2 b) 573 | { 574 | return mat2(a * b[0], a * b[1]); 575 | } 576 | 577 | 578 | #endif // HESSNUM_2_H_ -------------------------------------------------------------------------------- /grad_4.glsl: -------------------------------------------------------------------------------- 1 | #ifndef GRADNUM_4_H_ 2 | #define GRADNUM_4_H_ 3 | 4 | // This file contains methods to compute the gradient of a scalar valued 4 dimensional 5 | // function using automatic forward differentiation 6 | 7 | //-------------------------------- 8 | // Types 9 | //-------------------------------- 10 | 11 | // Data type to hold information about a scalar valued 4 dimensional function 12 | // These should be created by the constG4 (for constants) and varG4 (for variables) helpers 13 | struct GNum4 14 | { 15 | // The current value 16 | float val; 17 | // The current gradient 18 | vec4 g; 19 | }; 20 | 21 | //-------------------------------- 22 | // Prototypes 23 | //-------------------------------- 24 | 25 | /** 26 | * Creates a constant GNum4 27 | * @param val The current value of the constant 28 | */ 29 | GNum4 constG4(in float val); 30 | GNum4 varG4(in float val, in int index); 31 | GNum4 varG4x(in float val); 32 | GNum4 varG4y(in float val); 33 | GNum4 varG4z(in float val); 34 | GNum4 varG4w(in float val); 35 | GNum4 add(in GNum4 a, in GNum4 b); 36 | GNum4 add(in GNum4 a, in float b); 37 | GNum4 add(in float a, in GNum4 b); 38 | GNum4 sub(in GNum4 a, in GNum4 b); 39 | GNum4 sub(in GNum4 a, in float b); 40 | GNum4 sub(in float a, in GNum4 b); 41 | GNum4 mult(in GNum4 a, in GNum4 b); 42 | GNum4 mult(in GNum4 a, in float b); 43 | GNum4 mult(in float a, in GNum4 b); 44 | GNum4 neg(in GNum4 a); 45 | GNum4 div(in GNum4 a, in GNum4 b); 46 | GNum4 div(in GNum4 a, in float b); 47 | GNum4 div(in float a, in GNum4 b); 48 | GNum4 inv(in GNum4 a); 49 | GNum4 a_pow(in GNum4 a, in GNum4 b); 50 | GNum4 a_pow(in GNum4 a, in float b); 51 | GNum4 a_pow(in float a, in GNum4 b); 52 | GNum4 a_ipow(in GNum4 x, in int n); 53 | GNum4 a_min(in GNum4 a, in GNum4 b); 54 | GNum4 a_max(in GNum4 a, in GNum4 b); 55 | GNum4 a_exp2(in GNum4 a); 56 | GNum4 a_inversesqrt(in GNum4 a); 57 | GNum4 a_atan(in GNum4 a); 58 | GNum4 a_sqrt(in GNum4 a); 59 | GNum4 a_sinh(in GNum4 a); 60 | GNum4 a_ceil(in GNum4 a); 61 | GNum4 a_tan(in GNum4 a); 62 | GNum4 a_asinh(in GNum4 a); 63 | GNum4 a_asin(in GNum4 a); 64 | GNum4 a_acosh(in GNum4 a); 65 | GNum4 a_abs(in GNum4 a); 66 | GNum4 a_exp(in GNum4 a); 67 | GNum4 a_cosh(in GNum4 a); 68 | GNum4 a_floor(in GNum4 a); 69 | GNum4 a_log(in GNum4 a); 70 | GNum4 a_atanh(in GNum4 a); 71 | GNum4 a_log2(in GNum4 a); 72 | GNum4 a_acos(in GNum4 a); 73 | GNum4 a_tanh(in GNum4 a); 74 | GNum4 a_cos(in GNum4 a); 75 | GNum4 a_sin(in GNum4 a); 76 | GNum4 a_atan2(in GNum4 y, in GNum4 x); 77 | GNum4 a_atan2(in GNum4 y, in float x); 78 | GNum4 a_atan2(in float y, in GNum4 x); 79 | GNum4 a_mix(in GNum4 a, in GNum4 b, in GNum4 t); 80 | GNum4 a_mix(in GNum4 a, in GNum4 b, in float t); 81 | GNum4 a_mix(in GNum4 a, in float b, in GNum4 t); 82 | GNum4 a_mix(in GNum4 a, in float b, in float t); 83 | GNum4 a_mix(in float a, in GNum4 b, in GNum4 t); 84 | GNum4 a_mix(in float a, in GNum4 b, in float t); 85 | GNum4 a_mix(in float a, in float b, in GNum4 t); 86 | 87 | //-------------------------------- 88 | // Macros 89 | //-------------------------------- 90 | 91 | #define GRAD4(f,x, y, z, w,result) { result = f(varG4x(x), varG4y(y), varG4z(z), varG4w(w)); } 92 | //-------------------------------- 93 | #define JACOBI24(f1, f2, x, y, z, w, result) { GNum4 gradResult; GRAD4(f1, x, y, z, w, gradResult); result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; result[2][0] = gradResult.g[2]; result[3][0] = gradResult.g[3]; GRAD4(f2, x, y, z, w, gradResult); result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; result[2][1] = gradResult.g[2]; result[3][1] = gradResult.g[3]; } 94 | //-------------------------------- 95 | #define JACOBI24_VALUE(f1, f2, x, y, z, w, result, value) { GNum4 gradResult; GRAD4(f1, x, y, z, w, gradResult); value[0] = gradResult.val; result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; result[2][0] = gradResult.g[2]; result[3][0] = gradResult.g[3]; GRAD4(f2, x, y, z, w, gradResult); value[1] = gradResult.val; result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; result[2][1] = gradResult.g[2]; result[3][1] = gradResult.g[3]; } 96 | //-------------------------------- 97 | #define JACOBI34(f1, f2, f3, x, y, z, w, result) { GNum4 gradResult; GRAD4(f1, x, y, z, w, gradResult); result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; result[2][0] = gradResult.g[2]; result[3][0] = gradResult.g[3]; GRAD4(f2, x, y, z, w, gradResult); result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; result[2][1] = gradResult.g[2]; result[3][1] = gradResult.g[3]; GRAD4(f3, x, y, z, w, gradResult); result[0][2] = gradResult.g[0]; result[1][2] = gradResult.g[1]; result[2][2] = gradResult.g[2]; result[3][2] = gradResult.g[3]; } 98 | //-------------------------------- 99 | #define JACOBI34_VALUE(f1, f2, f3, x, y, z, w, result, value) { GNum4 gradResult; GRAD4(f1, x, y, z, w, gradResult); value[0] = gradResult.val; result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; result[2][0] = gradResult.g[2]; result[3][0] = gradResult.g[3]; GRAD4(f2, x, y, z, w, gradResult); value[1] = gradResult.val; result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; result[2][1] = gradResult.g[2]; result[3][1] = gradResult.g[3]; GRAD4(f3, x, y, z, w, gradResult); value[2] = gradResult.val; result[0][2] = gradResult.g[0]; result[1][2] = gradResult.g[1]; result[2][2] = gradResult.g[2]; result[3][2] = gradResult.g[3]; } 100 | //-------------------------------- 101 | #define JACOBI4(f1, f2, f3, f4, x, y, z, w, result) { GNum4 gradResult; GRAD4(f1, x, y, z, w, gradResult); result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; result[2][0] = gradResult.g[2]; result[3][0] = gradResult.g[3]; GRAD4(f2, x, y, z, w, gradResult); result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; result[2][1] = gradResult.g[2]; result[3][1] = gradResult.g[3]; GRAD4(f3, x, y, z, w, gradResult); result[0][2] = gradResult.g[0]; result[1][2] = gradResult.g[1]; result[2][2] = gradResult.g[2]; result[3][2] = gradResult.g[3]; GRAD4(f4, x, y, z, w, gradResult); result[0][3] = gradResult.g[0]; result[1][3] = gradResult.g[1]; result[2][3] = gradResult.g[2]; result[3][3] = gradResult.g[3]; } 102 | //-------------------------------- 103 | #define JACOBI4_VALUE(f1, f2, f3, f4, x, y, z, w, result, value) { GNum4 gradResult; GRAD4(f1, x, y, z, w, gradResult); value[0] = gradResult.val; result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; result[2][0] = gradResult.g[2]; result[3][0] = gradResult.g[3]; GRAD4(f2, x, y, z, w, gradResult); value[1] = gradResult.val; result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; result[2][1] = gradResult.g[2]; result[3][1] = gradResult.g[3]; GRAD4(f3, x, y, z, w, gradResult); value[2] = gradResult.val; result[0][2] = gradResult.g[0]; result[1][2] = gradResult.g[1]; result[2][2] = gradResult.g[2]; result[3][2] = gradResult.g[3]; GRAD4(f4, x, y, z, w, gradResult); value[3] = gradResult.val; result[0][3] = gradResult.g[0]; result[1][3] = gradResult.g[1]; result[2][3] = gradResult.g[2]; result[3][3] = gradResult.g[3]; } 104 | 105 | //-------------------------------- 106 | // Implementation 107 | //-------------------------------- 108 | 109 | GNum4 constG4(in float val) 110 | { 111 | return GNum4(val, vec4(0.0)); 112 | } 113 | //-------------------------------- 114 | GNum4 varG4(in float val, in int index) 115 | { 116 | vec4 g = vec4(0.0); 117 | g[index] = 1.0; 118 | return GNum4(val, g); 119 | } 120 | //-------------------------------- 121 | GNum4 varG4x(in float val) 122 | { 123 | vec4 g = vec4(0.0); 124 | g[0] = 1.0; 125 | return GNum4(val, g); 126 | } 127 | //-------------------------------- 128 | GNum4 varG4y(in float val) 129 | { 130 | vec4 g = vec4(0.0); 131 | g[1] = 1.0; 132 | return GNum4(val, g); 133 | } 134 | //-------------------------------- 135 | GNum4 varG4z(in float val) 136 | { 137 | vec4 g = vec4(0.0); 138 | g[2] = 1.0; 139 | return GNum4(val, g); 140 | } 141 | //-------------------------------- 142 | GNum4 varG4w(in float val) 143 | { 144 | vec4 g = vec4(0.0); 145 | g[3] = 1.0; 146 | return GNum4(val, g); 147 | } 148 | //-------------------------------- 149 | GNum4 add(in GNum4 a, in GNum4 b) 150 | { 151 | return GNum4(a.val + b.val, a.g + b.g); 152 | } 153 | //-------------------------------- 154 | GNum4 add(in GNum4 a, in float b) 155 | { 156 | return GNum4(a.val + b, a.g); 157 | } 158 | //-------------------------------- 159 | GNum4 add(in float a, in GNum4 b) 160 | { 161 | return GNum4(a + b.val, b.g); 162 | } 163 | //-------------------------------- 164 | GNum4 sub(in GNum4 a, in GNum4 b) 165 | { 166 | return GNum4(a.val - b.val, a.g - b.g); 167 | } 168 | //-------------------------------- 169 | GNum4 sub(in GNum4 a, in float b) 170 | { 171 | return GNum4(a.val - b, a.g); 172 | } 173 | //-------------------------------- 174 | GNum4 sub(in float a, in GNum4 b) 175 | { 176 | return GNum4(a - b.val, -b.g); 177 | } 178 | //-------------------------------- 179 | GNum4 mult(in GNum4 a, in GNum4 b) 180 | { 181 | return GNum4(a.val * b.val, 182 | a.val*b.g + b.val*a.g 183 | ); 184 | } 185 | //-------------------------------- 186 | GNum4 mult(in GNum4 a, in float b) 187 | { 188 | return GNum4(a.val * b, b*a.g); 189 | } 190 | //-------------------------------- 191 | GNum4 mult(in float a, in GNum4 b) 192 | { 193 | return GNum4(a * b.val, a*b.g); 194 | } 195 | //-------------------------------- 196 | GNum4 neg(in GNum4 a) 197 | { 198 | return mult(-1.0,a); 199 | } 200 | //-------------------------------- 201 | GNum4 div(in GNum4 a, in GNum4 b) 202 | { 203 | float b1 = b.val; 204 | float b2 = b1*b1; 205 | 206 | return GNum4(a.val / b.val , 207 | (b.val*a.g - a.val*b.g)/b2 208 | ); 209 | } 210 | //-------------------------------- 211 | GNum4 div(in GNum4 a, in float b) 212 | { 213 | return GNum4(a.val / b, a.g/b); 214 | } 215 | //-------------------------------- 216 | GNum4 div(in float a, in GNum4 b) 217 | { 218 | float b1 = b.val; 219 | float b2 = b1*b1; 220 | 221 | return GNum4(a / b.val, 222 | -a*b.g/b2 223 | ); 224 | } 225 | //-------------------------------- 226 | GNum4 inv(in GNum4 a) 227 | { 228 | return div(1.0, a); 229 | } 230 | //-------------------------------- 231 | GNum4 a_pow(in GNum4 a, in GNum4 b) 232 | { 233 | return a_exp(mult(b,a_log(a))); 234 | } 235 | //-------------------------------- 236 | GNum4 a_pow(in GNum4 a, in float b) 237 | { 238 | // constant exponent -> make special case 239 | float v = pow(a.val, b); // value f(a(x)) 240 | float da = b*pow(a.val,b-1.0); // first derivative f'(a(x)) 241 | return GNum4(v , da * a.g); 242 | } 243 | //-------------------------------- 244 | GNum4 a_pow(in float a, in GNum4 b) 245 | { 246 | return a_exp(mult(b,log(a))); 247 | } 248 | //-------------------------------- 249 | GNum4 a_ipow(in GNum4 x, in int n) 250 | { 251 | // based on https://en.wikipedia.org/wiki/Exponentiation_by_squaring 252 | if (n < 0) 253 | { 254 | x = div(1.0,x); 255 | n = -n; 256 | } 257 | if (n == 0) 258 | { 259 | return constG4(1.0); 260 | } 261 | GNum4 y = constG4(1.0); 262 | while (n > 1) 263 | { 264 | if (n % 2 == 0) 265 | { 266 | x = mult(x,x); 267 | 268 | } 269 | else 270 | { 271 | y = mult(x, y); 272 | x = mult(x, x); 273 | } 274 | 275 | n = n / 2; 276 | } 277 | 278 | return mult(x, y); 279 | } 280 | 281 | //-------------------------------- 282 | GNum4 a_min(in GNum4 a, in GNum4 b) 283 | { 284 | if(a.val < b.val) 285 | { 286 | return a; 287 | } 288 | return b; 289 | } 290 | //-------------------------------- 291 | GNum4 a_max(in GNum4 a, in GNum4 b) 292 | { 293 | if(a.val > b.val) 294 | { 295 | return a; 296 | } 297 | return b; 298 | } 299 | //-------------------------------- 300 | GNum4 a_exp2(in GNum4 a) 301 | { 302 | float v = exp2(a.val); // value f(a(x)) 303 | float da = log(2.0)*exp2(a.val); // first derivative f'(a(x)) 304 | 305 | return GNum4(v , da * a.g); 306 | } 307 | //-------------------------------- 308 | GNum4 a_inversesqrt(in GNum4 a) 309 | { 310 | float v = inversesqrt(a.val); // value f(a(x)) 311 | float da = -0.5/pow(sqrt(a.val),3.0); // first derivative f'(a(x)) 312 | 313 | return GNum4(v , da * a.g); 314 | } 315 | //-------------------------------- 316 | GNum4 a_atan(in GNum4 a) 317 | { 318 | float v = atan(a.val); // value f(a(x)) 319 | float da = 1.0/(1.0 + a.val * a.val); // first derivative f'(a(x)) 320 | 321 | return GNum4(v , da * a.g); 322 | } 323 | //-------------------------------- 324 | GNum4 a_sqrt(in GNum4 a) 325 | { 326 | float v = sqrt(a.val); // value f(a(x)) 327 | float da = 0.5/sqrt(a.val); // first derivative f'(a(x)) 328 | 329 | return GNum4(v , da * a.g); 330 | } 331 | //-------------------------------- 332 | GNum4 a_sinh(in GNum4 a) 333 | { 334 | float v = sinh(a.val); // value f(a(x)) 335 | float da = cosh(a.val); // first derivative f'(a(x)) 336 | 337 | return GNum4(v , da * a.g); 338 | } 339 | //-------------------------------- 340 | GNum4 a_ceil(in GNum4 a) 341 | { 342 | float v = ceil(a.val); // value f(a(x)) 343 | float da = 0.0; // first derivative f'(a(x)) 344 | 345 | return GNum4(v , da * a.g); 346 | } 347 | //-------------------------------- 348 | GNum4 a_tan(in GNum4 a) 349 | { 350 | float v = tan(a.val); // value f(a(x)) 351 | float da = 1.0 + pow(tan(a.val),2.0); // first derivative f'(a(x)) 352 | 353 | return GNum4(v , da * a.g); 354 | } 355 | //-------------------------------- 356 | GNum4 a_asinh(in GNum4 a) 357 | { 358 | float v = asinh(a.val); // value f(a(x)) 359 | float da = 1.0/sqrt(1.0 + a.val * a.val); // first derivative f'(a(x)) 360 | 361 | return GNum4(v , da * a.g); 362 | } 363 | //-------------------------------- 364 | GNum4 a_asin(in GNum4 a) 365 | { 366 | float v = asin(a.val); // value f(a(x)) 367 | float da = 1.0/sqrt(1.0 - a.val * a.val); // first derivative f'(a(x)) 368 | 369 | return GNum4(v , da * a.g); 370 | } 371 | //-------------------------------- 372 | GNum4 a_acosh(in GNum4 a) 373 | { 374 | float v = acosh(a.val); // value f(a(x)) 375 | float da = 1.0/sqrt(-1.0 + a.val * a.val); // first derivative f'(a(x)) 376 | 377 | return GNum4(v , da * a.g); 378 | } 379 | //-------------------------------- 380 | GNum4 a_abs(in GNum4 a) 381 | { 382 | float v = abs(a.val); // value f(a(x)) 383 | float da = a.val < 0.0 ? -1.0 : 1.0; // first derivative f'(a(x)) 384 | 385 | return GNum4(v , da * a.g); 386 | } 387 | //-------------------------------- 388 | GNum4 a_exp(in GNum4 a) 389 | { 390 | float v = exp(a.val); // value f(a(x)) 391 | float da = exp(a.val); // first derivative f'(a(x)) 392 | 393 | return GNum4(v , da * a.g); 394 | } 395 | //-------------------------------- 396 | GNum4 a_cosh(in GNum4 a) 397 | { 398 | float v = cosh(a.val); // value f(a(x)) 399 | float da = sinh(a.val); // first derivative f'(a(x)) 400 | 401 | return GNum4(v , da * a.g); 402 | } 403 | //-------------------------------- 404 | GNum4 a_floor(in GNum4 a) 405 | { 406 | float v = floor(a.val); // value f(a(x)) 407 | float da = 0.0; // first derivative f'(a(x)) 408 | 409 | return GNum4(v , da * a.g); 410 | } 411 | //-------------------------------- 412 | GNum4 a_log(in GNum4 a) 413 | { 414 | float v = log(a.val); // value f(a(x)) 415 | float da = 1.0/a.val; // first derivative f'(a(x)) 416 | 417 | return GNum4(v , da * a.g); 418 | } 419 | //-------------------------------- 420 | GNum4 a_atanh(in GNum4 a) 421 | { 422 | float v = atanh(a.val); // value f(a(x)) 423 | float da = 1.0/(1.0 - a.val * a.val); // first derivative f'(a(x)) 424 | 425 | return GNum4(v , da * a.g); 426 | } 427 | //-------------------------------- 428 | GNum4 a_log2(in GNum4 a) 429 | { 430 | float v = log2(a.val); // value f(a(x)) 431 | float da = 1.0/(a.val * log(2.0)); // first derivative f'(a(x)) 432 | 433 | return GNum4(v , da * a.g); 434 | } 435 | //-------------------------------- 436 | GNum4 a_acos(in GNum4 a) 437 | { 438 | float v = acos(a.val); // value f(a(x)) 439 | float da = -1.0/sqrt(1.0 - a.val * a.val); // first derivative f'(a(x)) 440 | 441 | return GNum4(v , da * a.g); 442 | } 443 | //-------------------------------- 444 | GNum4 a_tanh(in GNum4 a) 445 | { 446 | float v = tanh(a.val); // value f(a(x)) 447 | float da = 1.0 - pow(tanh(a.val),2.0); // first derivative f'(a(x)) 448 | 449 | return GNum4(v , da * a.g); 450 | } 451 | //-------------------------------- 452 | GNum4 a_cos(in GNum4 a) 453 | { 454 | float v = cos(a.val); // value f(a(x)) 455 | float da = -sin(a.val); // first derivative f'(a(x)) 456 | 457 | return GNum4(v , da * a.g); 458 | } 459 | //-------------------------------- 460 | GNum4 a_sin(in GNum4 a) 461 | { 462 | float v = sin(a.val); // value f(a(x)) 463 | float da = cos(a.val); // first derivative f'(a(x)) 464 | 465 | return GNum4(v , da * a.g); 466 | } 467 | //-------------------------------- 468 | GNum4 a_atan2(in GNum4 y, in GNum4 x) 469 | { 470 | const float pi = 3.14159265; 471 | // from https://en.wikipedia.org/wiki/Atan2 472 | if(x.val > 0.0) 473 | { 474 | GNum4 n = a_sqrt(add(mult(x,x),mult(y,y))); 475 | GNum4 inner = div(y, add(n,x)); 476 | 477 | return mult(2.0,a_atan(inner)); 478 | 479 | }else if(x.val <= 0.0 && abs(y.val) > 1E-6) 480 | { 481 | GNum4 n = a_sqrt(add(mult(x,x),mult(y,y))); 482 | GNum4 inner = div(sub(n,x),y); 483 | return mult(2.0,a_atan(inner)); 484 | }else if(x.val < 0.0 && abs(y.val) <= 1E-6) 485 | { 486 | return constG4(pi); 487 | } 488 | // return 0 for undefined 489 | return constG4(0.0); 490 | } 491 | //-------------------------------- 492 | GNum4 a_atan2(in GNum4 y, in float x) 493 | { 494 | return a_atan2(y,constG4(x)); 495 | } 496 | //-------------------------------- 497 | GNum4 a_atan2(in float y, in GNum4 x) 498 | { 499 | return a_atan2(constG4(y),x); 500 | } 501 | //-------------------------------- 502 | GNum4 a_mix(in GNum4 a, in GNum4 b, in GNum4 t) 503 | { 504 | return add(mult(a, sub(1.0, t)), mult(b, t)); 505 | } 506 | 507 | //-------------------------------- 508 | GNum4 a_mix(in GNum4 a, in GNum4 b, in float t) 509 | { 510 | return add(mult(a, 1.0 - t), mult(b, t)); 511 | } 512 | 513 | //-------------------------------- 514 | GNum4 a_mix(in GNum4 a, in float b, in GNum4 t) 515 | { 516 | return add(mult(a, sub(1.0, t)), mult(b, t)); 517 | } 518 | 519 | //-------------------------------- 520 | GNum4 a_mix(in GNum4 a, in float b, in float t) 521 | { 522 | return add(mult(a, 1.0 - t), b*t); 523 | } 524 | 525 | //-------------------------------- 526 | GNum4 a_mix(in float a, in GNum4 b, in GNum4 t) 527 | { 528 | return add(mult(a, sub(1.0, t)), mult(b, t)); 529 | } 530 | 531 | //-------------------------------- 532 | GNum4 a_mix(in float a, in GNum4 b, in float t) 533 | { 534 | return add(a * (1.0 - t), mult(b, t)); 535 | } 536 | 537 | //-------------------------------- 538 | GNum4 a_mix(in float a, in float b, in GNum4 t) 539 | { 540 | return add(mult(a, sub(1.0, t)), mult(b, t)); 541 | } 542 | 543 | 544 | #endif // GRADNUM_4_H_ -------------------------------------------------------------------------------- /hessian_3.glsl: -------------------------------------------------------------------------------- 1 | #ifndef HESSNUM_3_H_ 2 | #define HESSNUM_3_H_ 3 | 4 | // This file contains methods to compute the gradient and hessian 5 | // of a scalar valued 3 dimensional function using automatic forward differentiation 6 | 7 | //-------------------------------- 8 | // Types 9 | //-------------------------------- 10 | 11 | // Data type to hold information about a scalar valued 3 dimensional function 12 | // These should be created by the constH3 (for constants) and varH3 (for variables) helpers 13 | struct HNum3 14 | { 15 | // The current value 16 | float val; 17 | // The current gradient 18 | vec3 g; 19 | // The current hessian 20 | mat3 h; 21 | }; 22 | 23 | //-------------------------------- 24 | // Prototypes 25 | //-------------------------------- 26 | 27 | /** 28 | * Creates a constant HNum3 29 | * @param val The current value of the constant 30 | */ 31 | HNum3 constH3(in float val); 32 | /** 33 | * Creates a HNum3 corresponding to the variable with the given index 34 | * @param val The current value of the variable 35 | * @param index The variable's index 36 | */ 37 | HNum3 varH3(in float val, in int index); 38 | /** 39 | * Creates a HNum3 corresponding to the variable x (index = 0) 40 | * @param val The current value of the variable 41 | */ 42 | HNum3 varH3x(in float val); 43 | /** 44 | * Creates a HNum3 corresponding to the variable y (index = 1) 45 | * @param val The current value of the variable 46 | */ 47 | HNum3 varH3y(in float val); 48 | /** 49 | * Creates a HNum3 corresponding to the variable z (index = 2) 50 | * @param val The current value of the variable 51 | */ 52 | HNum3 varH3z(in float val); 53 | HNum3 add(in HNum3 a, in HNum3 b); 54 | HNum3 add(in HNum3 a, in float b); 55 | HNum3 add(in float a, in HNum3 b); 56 | HNum3 sub(in HNum3 a, in HNum3 b); 57 | HNum3 sub(in HNum3 a, in float b); 58 | HNum3 sub(in float a, in HNum3 b); 59 | HNum3 mult(in HNum3 a, in HNum3 b); 60 | HNum3 mult(in HNum3 a, in float b); 61 | HNum3 mult(in float a, in HNum3 b); 62 | HNum3 neg(in HNum3 a); 63 | HNum3 div(in HNum3 a, in HNum3 b); 64 | HNum3 div(in HNum3 a, in float b); 65 | HNum3 div(in float a, in HNum3 b); 66 | HNum3 inv(in HNum3 a); 67 | HNum3 a_pow(in HNum3 a, in HNum3 b); 68 | HNum3 a_pow(in HNum3 a, in float b); 69 | HNum3 a_pow(in float a, in HNum3 b); 70 | HNum3 a_ipow(in HNum3 x, in int n); 71 | HNum3 a_min(in HNum3 a, in HNum3 b); 72 | HNum3 a_max(in HNum3 a, in HNum3 b); 73 | HNum3 a_exp2(in HNum3 a); 74 | HNum3 a_inversesqrt(in HNum3 a); 75 | HNum3 a_atan(in HNum3 a); 76 | HNum3 a_sqrt(in HNum3 a); 77 | HNum3 a_sinh(in HNum3 a); 78 | HNum3 a_ceil(in HNum3 a); 79 | HNum3 a_tan(in HNum3 a); 80 | HNum3 a_asinh(in HNum3 a); 81 | HNum3 a_asin(in HNum3 a); 82 | HNum3 a_acosh(in HNum3 a); 83 | HNum3 a_abs(in HNum3 a); 84 | HNum3 a_exp(in HNum3 a); 85 | HNum3 a_cosh(in HNum3 a); 86 | HNum3 a_floor(in HNum3 a); 87 | HNum3 a_log(in HNum3 a); 88 | HNum3 a_atanh(in HNum3 a); 89 | HNum3 a_log2(in HNum3 a); 90 | HNum3 a_acos(in HNum3 a); 91 | HNum3 a_tanh(in HNum3 a); 92 | HNum3 a_cos(in HNum3 a); 93 | HNum3 a_sin(in HNum3 a); 94 | HNum3 a_atan2(in HNum3 y, in HNum3 x); 95 | HNum3 a_atan2(in HNum3 y, in float x); 96 | HNum3 a_atan2(in float y, in HNum3 x); 97 | HNum3 a_mix(in HNum3 a, in HNum3 b, in HNum3 t); 98 | HNum3 a_mix(in HNum3 a, in HNum3 b, in float t); 99 | HNum3 a_mix(in HNum3 a, in float b, in HNum3 t); 100 | HNum3 a_mix(in HNum3 a, in float b, in float t); 101 | HNum3 a_mix(in float a, in HNum3 b, in HNum3 t); 102 | HNum3 a_mix(in float a, in HNum3 b, in float t); 103 | HNum3 a_mix(in float a, in float b, in HNum3 t); 104 | 105 | //-------------------------------- 106 | // Macros 107 | //-------------------------------- 108 | 109 | #define HESSIAN3(f,x, y, z,result) { result = f(varH3x(x), varH3y(y), varH3z(z)); } 110 | 111 | //-------------------------------- 112 | // Utilities prototypes 113 | //-------------------------------- 114 | 115 | mat3 a_outerProduct(in vec3 a, in vec3 b); 116 | 117 | //-------------------------------- 118 | // Implementation 119 | //-------------------------------- 120 | 121 | HNum3 constH3(in float val) 122 | { 123 | return HNum3(val, vec3(0.0), mat3(0.0)); 124 | } 125 | //-------------------------------- 126 | HNum3 varH3(in float val, in int index) 127 | { 128 | vec3 g = vec3(0.0); 129 | g[index] = 1.0; 130 | return HNum3(val, g, mat3(0.0)); 131 | } 132 | //-------------------------------- 133 | HNum3 varH3x(in float val) 134 | { 135 | vec3 g = vec3(0.0); 136 | g[0] = 1.0; 137 | return HNum3(val, g, mat3(0.0)); 138 | } 139 | //-------------------------------- 140 | HNum3 varH3y(in float val) 141 | { 142 | vec3 g = vec3(0.0); 143 | g[1] = 1.0; 144 | return HNum3(val, g, mat3(0.0)); 145 | } 146 | //-------------------------------- 147 | HNum3 varH3z(in float val) 148 | { 149 | vec3 g = vec3(0.0); 150 | g[2] = 1.0; 151 | return HNum3(val, g, mat3(0.0)); 152 | } 153 | //-------------------------------- 154 | HNum3 add(in HNum3 a, in HNum3 b) 155 | { 156 | return HNum3(a.val + b.val , a.g + b.g, a.h + b.h); 157 | } 158 | //-------------------------------- 159 | HNum3 add(in HNum3 a, in float b) 160 | { 161 | return HNum3(a.val + b , a.g, a.h); 162 | } 163 | //-------------------------------- 164 | HNum3 add(in float a, in HNum3 b) 165 | { 166 | return HNum3(a + b.val , b.g, b.h); 167 | } 168 | //-------------------------------- 169 | HNum3 sub(in HNum3 a, in HNum3 b) 170 | { 171 | return HNum3(a.val - b.val , a.g - b.g, a.h - b.h); 172 | } 173 | //-------------------------------- 174 | HNum3 sub(in HNum3 a, in float b) 175 | { 176 | return HNum3(a.val - b , a.g, a.h); 177 | } 178 | //-------------------------------- 179 | HNum3 sub(in float a, in HNum3 b) 180 | { 181 | return HNum3(a - b.val , - b.g, - b.h); 182 | } 183 | //-------------------------------- 184 | HNum3 mult(in HNum3 a, in HNum3 b) 185 | { 186 | return HNum3(a.val * b.val, 187 | a.val*b.g + b.val*a.g, 188 | a.val*b.h + b.val*a.h + a_outerProduct(b.g,a.g) + a_outerProduct(a.g,b.g) 189 | ); 190 | } 191 | //-------------------------------- 192 | HNum3 mult(in HNum3 a, in float b) 193 | { 194 | return HNum3(a.val * b, b*a.g, b*a.h); 195 | } 196 | //-------------------------------- 197 | HNum3 mult(in float a, in HNum3 b) 198 | { 199 | return HNum3(a * b.val, a*b.g, a*b.h); 200 | } 201 | //-------------------------------- 202 | HNum3 neg(in HNum3 a) 203 | { 204 | return mult(-1.0,a); 205 | } 206 | //-------------------------------- 207 | HNum3 div(in HNum3 a, in HNum3 b) 208 | { 209 | float b1 = b.val; 210 | float b2 = b1*b1; 211 | float b3 = b2*b1; 212 | 213 | return HNum3(a.val / b.val , 214 | (b.val*a.g - a.val*b.g)/b2, 215 | 2.0*a.val/b3*a_outerProduct(b.g,b.g) 216 | - a.val/b2*b.h 217 | + a.h/b1 218 | - a_outerProduct(b.g/b2, a.g) 219 | - a_outerProduct(a.g/b2, b.g) 220 | ); 221 | } 222 | //-------------------------------- 223 | HNum3 div(in HNum3 a, in float b) 224 | { 225 | return HNum3(a.val / b, a.g/b, a.h/b); 226 | } 227 | //-------------------------------- 228 | HNum3 div(in float a, in HNum3 b) 229 | { 230 | float b1 = b.val; 231 | float b2 = b1*b1; 232 | float b3 = b2*b1; 233 | 234 | return HNum3(a / b.val, 235 | -a*b.g/b2, 236 | 2.0*a/b3*a_outerProduct(b.g,b.g) - a/b2*b.h 237 | ); 238 | } 239 | //-------------------------------- 240 | HNum3 inv(in HNum3 a) 241 | { 242 | return div(1.0, a); 243 | } 244 | //-------------------------------- 245 | HNum3 a_pow(in HNum3 a, in HNum3 b) 246 | { 247 | return a_exp(mult(b,a_log(a))); 248 | } 249 | //-------------------------------- 250 | HNum3 a_pow(in HNum3 a, in float b) 251 | { 252 | // constant exponent -> make special case 253 | float v = pow(a.val, b); // value f(a(x)) 254 | float da = b*pow(a.val,b-1.0); // first derivative f'(a(x)) 255 | float dda = b*(b-1.0)*pow(a.val,b-2.0); // second derivative f''(a(x)) 256 | return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 257 | } 258 | //-------------------------------- 259 | HNum3 a_pow(in float a, in HNum3 b) 260 | { 261 | return a_exp(mult(b,log(a))); 262 | } 263 | //-------------------------------- 264 | HNum3 a_ipow(in HNum3 x, in int n) 265 | { 266 | // based on https://en.wikipedia.org/wiki/Exponentiation_by_squaring 267 | if (n < 0) 268 | { 269 | x = div(1.0,x); 270 | n = -n; 271 | } 272 | if (n == 0) 273 | { 274 | return constH3(1.0); 275 | } 276 | HNum3 y = constH3(1.0); 277 | while (n > 1) 278 | { 279 | if (n % 2 == 0) 280 | { 281 | x = mult(x,x); 282 | 283 | } 284 | else 285 | { 286 | y = mult(x, y); 287 | x = mult(x, x); 288 | } 289 | 290 | n = n / 2; 291 | } 292 | 293 | return mult(x, y); 294 | } 295 | 296 | //-------------------------------- 297 | HNum3 a_min(in HNum3 a, in HNum3 b) 298 | { 299 | if(a.val < b.val) 300 | { 301 | return a; 302 | } 303 | return b; 304 | } 305 | //-------------------------------- 306 | HNum3 a_max(in HNum3 a, in HNum3 b) 307 | { 308 | if(a.val > b.val) 309 | { 310 | return a; 311 | } 312 | return b; 313 | } 314 | //-------------------------------- 315 | HNum3 a_exp2(in HNum3 a) 316 | { 317 | float v = exp2(a.val); // value f(a(x)) 318 | float da = log(2.0)*exp2(a.val); // first derivative f'(a(x)) 319 | float dda = log(2.0)*log(2.0)*exp2(a.val); // second derivative f''(a(x)) 320 | 321 | return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 322 | } 323 | //-------------------------------- 324 | HNum3 a_inversesqrt(in HNum3 a) 325 | { 326 | float v = inversesqrt(a.val); // value f(a(x)) 327 | float da = -0.5/pow(sqrt(a.val),3.0); // first derivative f'(a(x)) 328 | float dda = 0.75/pow(sqrt(a.val),5.0); // second derivative f''(a(x)) 329 | 330 | return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 331 | } 332 | //-------------------------------- 333 | HNum3 a_atan(in HNum3 a) 334 | { 335 | float v = atan(a.val); // value f(a(x)) 336 | float da = 1.0/(1.0 + a.val * a.val); // first derivative f'(a(x)) 337 | float dda = -2.0*a.val/pow(1.0 + a.val * a.val, 2.0); // second derivative f''(a(x)) 338 | 339 | return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 340 | } 341 | //-------------------------------- 342 | HNum3 a_sqrt(in HNum3 a) 343 | { 344 | float v = sqrt(a.val); // value f(a(x)) 345 | float da = 0.5/sqrt(a.val); // first derivative f'(a(x)) 346 | float dda = -0.25/pow(sqrt(a.val),3.0); // second derivative f''(a(x)) 347 | 348 | return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 349 | } 350 | //-------------------------------- 351 | HNum3 a_sinh(in HNum3 a) 352 | { 353 | float v = sinh(a.val); // value f(a(x)) 354 | float da = cosh(a.val); // first derivative f'(a(x)) 355 | float dda = sinh(a.val); // second derivative f''(a(x)) 356 | 357 | return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 358 | } 359 | //-------------------------------- 360 | HNum3 a_ceil(in HNum3 a) 361 | { 362 | float v = ceil(a.val); // value f(a(x)) 363 | float da = 0.0; // first derivative f'(a(x)) 364 | float dda = 0.0; // second derivative f''(a(x)) 365 | 366 | return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 367 | } 368 | //-------------------------------- 369 | HNum3 a_tan(in HNum3 a) 370 | { 371 | float v = tan(a.val); // value f(a(x)) 372 | float da = 1.0 + pow(tan(a.val),2.0); // first derivative f'(a(x)) 373 | float dda = 2.0*tan(a.val)*(1.0 + pow(tan(a.val),2.0)); // second derivative f''(a(x)) 374 | 375 | return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 376 | } 377 | //-------------------------------- 378 | HNum3 a_asinh(in HNum3 a) 379 | { 380 | float v = asinh(a.val); // value f(a(x)) 381 | float da = 1.0/sqrt(1.0 + a.val * a.val); // first derivative f'(a(x)) 382 | float dda = -a.val/pow(sqrt(1.0 + a.val * a.val),3.0); // second derivative f''(a(x)) 383 | 384 | return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 385 | } 386 | //-------------------------------- 387 | HNum3 a_asin(in HNum3 a) 388 | { 389 | float v = asin(a.val); // value f(a(x)) 390 | float da = 1.0/sqrt(1.0 - a.val * a.val); // first derivative f'(a(x)) 391 | float dda = a.val/pow(sqrt(1.0 - a.val * a.val),3.0); // second derivative f''(a(x)) 392 | 393 | return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 394 | } 395 | //-------------------------------- 396 | HNum3 a_acosh(in HNum3 a) 397 | { 398 | float v = acosh(a.val); // value f(a(x)) 399 | float da = 1.0/sqrt(-1.0 + a.val * a.val); // first derivative f'(a(x)) 400 | float dda = -a.val/pow(sqrt(-1.0 + a.val * a.val),3.0); // second derivative f''(a(x)) 401 | 402 | return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 403 | } 404 | //-------------------------------- 405 | HNum3 a_abs(in HNum3 a) 406 | { 407 | float v = abs(a.val); // value f(a(x)) 408 | float da = a.val < 0.0 ? -1.0 : 1.0; // first derivative f'(a(x)) 409 | float dda = 0.0; // second derivative f''(a(x)) 410 | 411 | return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 412 | } 413 | //-------------------------------- 414 | HNum3 a_exp(in HNum3 a) 415 | { 416 | float v = exp(a.val); // value f(a(x)) 417 | float da = exp(a.val); // first derivative f'(a(x)) 418 | float dda = exp(a.val); // second derivative f''(a(x)) 419 | 420 | return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 421 | } 422 | //-------------------------------- 423 | HNum3 a_cosh(in HNum3 a) 424 | { 425 | float v = cosh(a.val); // value f(a(x)) 426 | float da = sinh(a.val); // first derivative f'(a(x)) 427 | float dda = cosh(a.val); // second derivative f''(a(x)) 428 | 429 | return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 430 | } 431 | //-------------------------------- 432 | HNum3 a_floor(in HNum3 a) 433 | { 434 | float v = floor(a.val); // value f(a(x)) 435 | float da = 0.0; // first derivative f'(a(x)) 436 | float dda = 0.0; // second derivative f''(a(x)) 437 | 438 | return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 439 | } 440 | //-------------------------------- 441 | HNum3 a_log(in HNum3 a) 442 | { 443 | float v = log(a.val); // value f(a(x)) 444 | float da = 1.0/a.val; // first derivative f'(a(x)) 445 | float dda = -1.0/(a.val * a.val); // second derivative f''(a(x)) 446 | 447 | return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 448 | } 449 | //-------------------------------- 450 | HNum3 a_atanh(in HNum3 a) 451 | { 452 | float v = atanh(a.val); // value f(a(x)) 453 | float da = 1.0/(1.0 - a.val * a.val); // first derivative f'(a(x)) 454 | float dda = 2.0*a.val/pow(1.0 - a.val * a.val,2.0); // second derivative f''(a(x)) 455 | 456 | return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 457 | } 458 | //-------------------------------- 459 | HNum3 a_log2(in HNum3 a) 460 | { 461 | float v = log2(a.val); // value f(a(x)) 462 | float da = 1.0/(a.val * log(2.0)); // first derivative f'(a(x)) 463 | float dda = -1.0/(a.val * a.val * log(2.0)); // second derivative f''(a(x)) 464 | 465 | return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 466 | } 467 | //-------------------------------- 468 | HNum3 a_acos(in HNum3 a) 469 | { 470 | float v = acos(a.val); // value f(a(x)) 471 | float da = -1.0/sqrt(1.0 - a.val * a.val); // first derivative f'(a(x)) 472 | float dda = -a.val/pow(sqrt(1.0 - a.val * a.val),3.0); // second derivative f''(a(x)) 473 | 474 | return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 475 | } 476 | //-------------------------------- 477 | HNum3 a_tanh(in HNum3 a) 478 | { 479 | float v = tanh(a.val); // value f(a(x)) 480 | float da = 1.0 - pow(tanh(a.val),2.0); // first derivative f'(a(x)) 481 | float dda = -2.0*tanh(a.val)*(1.0 - pow(tanh(a.val),2.0)); // second derivative f''(a(x)) 482 | 483 | return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 484 | } 485 | //-------------------------------- 486 | HNum3 a_cos(in HNum3 a) 487 | { 488 | float v = cos(a.val); // value f(a(x)) 489 | float da = -sin(a.val); // first derivative f'(a(x)) 490 | float dda = -cos(a.val); // second derivative f''(a(x)) 491 | 492 | return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 493 | } 494 | //-------------------------------- 495 | HNum3 a_sin(in HNum3 a) 496 | { 497 | float v = sin(a.val); // value f(a(x)) 498 | float da = cos(a.val); // first derivative f'(a(x)) 499 | float dda = -sin(a.val); // second derivative f''(a(x)) 500 | 501 | return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 502 | } 503 | //-------------------------------- 504 | HNum3 a_atan2(in HNum3 y, in HNum3 x) 505 | { 506 | const float pi = 3.14159265; 507 | // from https://en.wikipedia.org/wiki/Atan2 508 | if(x.val > 0.0) 509 | { 510 | HNum3 n = a_sqrt(add(mult(x,x),mult(y,y))); 511 | HNum3 inner = div(y, add(n,x)); 512 | 513 | return mult(2.0,a_atan(inner)); 514 | 515 | }else if(x.val <= 0.0 && abs(y.val) > 1E-6) 516 | { 517 | HNum3 n = a_sqrt(add(mult(x,x),mult(y,y))); 518 | HNum3 inner = div(sub(n,x),y); 519 | return mult(2.0,a_atan(inner)); 520 | }else if(x.val < 0.0 && abs(y.val) <= 1E-6) 521 | { 522 | return constH3(pi); 523 | } 524 | // return 0 for undefined 525 | return constH3(0.0); 526 | } 527 | //-------------------------------- 528 | HNum3 a_atan2(in HNum3 y, in float x) 529 | { 530 | return a_atan2(y,constH3(x)); 531 | } 532 | //-------------------------------- 533 | HNum3 a_atan2(in float y, in HNum3 x) 534 | { 535 | return a_atan2(constH3(y),x); 536 | } 537 | //-------------------------------- 538 | HNum3 a_mix(in HNum3 a, in HNum3 b, in HNum3 t) 539 | { 540 | return add(mult(a, sub(1.0, t)), mult(b, t)); 541 | } 542 | 543 | //-------------------------------- 544 | HNum3 a_mix(in HNum3 a, in HNum3 b, in float t) 545 | { 546 | return add(mult(a, 1.0 - t), mult(b, t)); 547 | } 548 | 549 | //-------------------------------- 550 | HNum3 a_mix(in HNum3 a, in float b, in HNum3 t) 551 | { 552 | return add(mult(a, sub(1.0, t)), mult(b, t)); 553 | } 554 | 555 | //-------------------------------- 556 | HNum3 a_mix(in HNum3 a, in float b, in float t) 557 | { 558 | return add(mult(a, 1.0 - t), b*t); 559 | } 560 | 561 | //-------------------------------- 562 | HNum3 a_mix(in float a, in HNum3 b, in HNum3 t) 563 | { 564 | return add(mult(a, sub(1.0, t)), mult(b, t)); 565 | } 566 | 567 | //-------------------------------- 568 | HNum3 a_mix(in float a, in HNum3 b, in float t) 569 | { 570 | return add(a * (1.0 - t), mult(b, t)); 571 | } 572 | 573 | //-------------------------------- 574 | HNum3 a_mix(in float a, in float b, in HNum3 t) 575 | { 576 | return add(mult(a, sub(1.0, t)), mult(b, t)); 577 | } 578 | 579 | 580 | //-------------------------------- 581 | // Implementation prototypes 582 | //-------------------------------- 583 | 584 | mat3 a_outerProduct(in vec3 a, in vec3 b) 585 | { 586 | return mat3(a * b[0], a * b[1], a * b[2]); 587 | } 588 | 589 | 590 | #endif // HESSNUM_3_H_ -------------------------------------------------------------------------------- /hessian_4.glsl: -------------------------------------------------------------------------------- 1 | #ifndef HESSNUM_4_H_ 2 | #define HESSNUM_4_H_ 3 | 4 | // This file contains methods to compute the gradient and hessian 5 | // of a scalar valued 4 dimensional function using automatic forward differentiation 6 | 7 | //-------------------------------- 8 | // Types 9 | //-------------------------------- 10 | 11 | // Data type to hold information about a scalar valued 4 dimensional function 12 | // These should be created by the constH4 (for constants) and varH4 (for variables) helpers 13 | struct HNum4 14 | { 15 | // The current value 16 | float val; 17 | // The current gradient 18 | vec4 g; 19 | // The current hessian 20 | mat4 h; 21 | }; 22 | 23 | //-------------------------------- 24 | // Prototypes 25 | //-------------------------------- 26 | 27 | /** 28 | * Creates a constant HNum4 29 | * @param val The current value of the constant 30 | */ 31 | HNum4 constH4(in float val); 32 | /** 33 | * Creates a HNum4 corresponding to the variable with the given index 34 | * @param val The current value of the variable 35 | * @param index The variable's index 36 | */ 37 | HNum4 varH4(in float val, in int index); 38 | /** 39 | * Creates a HNum4 corresponding to the variable x (index = 0) 40 | * @param val The current value of the variable 41 | */ 42 | HNum4 varH4x(in float val); 43 | /** 44 | * Creates a HNum4 corresponding to the variable y (index = 1) 45 | * @param val The current value of the variable 46 | */ 47 | HNum4 varH4y(in float val); 48 | /** 49 | * Creates a HNum4 corresponding to the variable z (index = 2) 50 | * @param val The current value of the variable 51 | */ 52 | HNum4 varH4z(in float val); 53 | /** 54 | * Creates a HNum4 corresponding to the variable w (index = 3) 55 | * @param val The current value of the variable 56 | */ 57 | HNum4 varH4w(in float val); 58 | HNum4 add(in HNum4 a, in HNum4 b); 59 | HNum4 add(in HNum4 a, in float b); 60 | HNum4 add(in float a, in HNum4 b); 61 | HNum4 sub(in HNum4 a, in HNum4 b); 62 | HNum4 sub(in HNum4 a, in float b); 63 | HNum4 sub(in float a, in HNum4 b); 64 | HNum4 mult(in HNum4 a, in HNum4 b); 65 | HNum4 mult(in HNum4 a, in float b); 66 | HNum4 mult(in float a, in HNum4 b); 67 | HNum4 neg(in HNum4 a); 68 | HNum4 div(in HNum4 a, in HNum4 b); 69 | HNum4 div(in HNum4 a, in float b); 70 | HNum4 div(in float a, in HNum4 b); 71 | HNum4 inv(in HNum4 a); 72 | HNum4 a_pow(in HNum4 a, in HNum4 b); 73 | HNum4 a_pow(in HNum4 a, in float b); 74 | HNum4 a_pow(in float a, in HNum4 b); 75 | HNum4 a_ipow(in HNum4 x, in int n); 76 | HNum4 a_min(in HNum4 a, in HNum4 b); 77 | HNum4 a_max(in HNum4 a, in HNum4 b); 78 | HNum4 a_exp2(in HNum4 a); 79 | HNum4 a_inversesqrt(in HNum4 a); 80 | HNum4 a_atan(in HNum4 a); 81 | HNum4 a_sqrt(in HNum4 a); 82 | HNum4 a_sinh(in HNum4 a); 83 | HNum4 a_ceil(in HNum4 a); 84 | HNum4 a_tan(in HNum4 a); 85 | HNum4 a_asinh(in HNum4 a); 86 | HNum4 a_asin(in HNum4 a); 87 | HNum4 a_acosh(in HNum4 a); 88 | HNum4 a_abs(in HNum4 a); 89 | HNum4 a_exp(in HNum4 a); 90 | HNum4 a_cosh(in HNum4 a); 91 | HNum4 a_floor(in HNum4 a); 92 | HNum4 a_log(in HNum4 a); 93 | HNum4 a_atanh(in HNum4 a); 94 | HNum4 a_log2(in HNum4 a); 95 | HNum4 a_acos(in HNum4 a); 96 | HNum4 a_tanh(in HNum4 a); 97 | HNum4 a_cos(in HNum4 a); 98 | HNum4 a_sin(in HNum4 a); 99 | HNum4 a_atan2(in HNum4 y, in HNum4 x); 100 | HNum4 a_atan2(in HNum4 y, in float x); 101 | HNum4 a_atan2(in float y, in HNum4 x); 102 | HNum4 a_mix(in HNum4 a, in HNum4 b, in HNum4 t); 103 | HNum4 a_mix(in HNum4 a, in HNum4 b, in float t); 104 | HNum4 a_mix(in HNum4 a, in float b, in HNum4 t); 105 | HNum4 a_mix(in HNum4 a, in float b, in float t); 106 | HNum4 a_mix(in float a, in HNum4 b, in HNum4 t); 107 | HNum4 a_mix(in float a, in HNum4 b, in float t); 108 | HNum4 a_mix(in float a, in float b, in HNum4 t); 109 | 110 | //-------------------------------- 111 | // Macros 112 | //-------------------------------- 113 | 114 | #define HESSIAN4(f,x, y, z, w,result) { result = f(varH4x(x), varH4y(y), varH4z(z), varH4w(w)); } 115 | 116 | //-------------------------------- 117 | // Utilities prototypes 118 | //-------------------------------- 119 | 120 | mat4 a_outerProduct(in vec4 a, in vec4 b); 121 | 122 | //-------------------------------- 123 | // Implementation 124 | //-------------------------------- 125 | 126 | HNum4 constH4(in float val) 127 | { 128 | return HNum4(val, vec4(0.0), mat4(0.0)); 129 | } 130 | //-------------------------------- 131 | HNum4 varH4(in float val, in int index) 132 | { 133 | vec4 g = vec4(0.0); 134 | g[index] = 1.0; 135 | return HNum4(val, g, mat4(0.0)); 136 | } 137 | //-------------------------------- 138 | HNum4 varH4x(in float val) 139 | { 140 | vec4 g = vec4(0.0); 141 | g[0] = 1.0; 142 | return HNum4(val, g, mat4(0.0)); 143 | } 144 | //-------------------------------- 145 | HNum4 varH4y(in float val) 146 | { 147 | vec4 g = vec4(0.0); 148 | g[1] = 1.0; 149 | return HNum4(val, g, mat4(0.0)); 150 | } 151 | //-------------------------------- 152 | HNum4 varH4z(in float val) 153 | { 154 | vec4 g = vec4(0.0); 155 | g[2] = 1.0; 156 | return HNum4(val, g, mat4(0.0)); 157 | } 158 | //-------------------------------- 159 | HNum4 varH4w(in float val) 160 | { 161 | vec4 g = vec4(0.0); 162 | g[3] = 1.0; 163 | return HNum4(val, g, mat4(0.0)); 164 | } 165 | //-------------------------------- 166 | HNum4 add(in HNum4 a, in HNum4 b) 167 | { 168 | return HNum4(a.val + b.val , a.g + b.g, a.h + b.h); 169 | } 170 | //-------------------------------- 171 | HNum4 add(in HNum4 a, in float b) 172 | { 173 | return HNum4(a.val + b , a.g, a.h); 174 | } 175 | //-------------------------------- 176 | HNum4 add(in float a, in HNum4 b) 177 | { 178 | return HNum4(a + b.val , b.g, b.h); 179 | } 180 | //-------------------------------- 181 | HNum4 sub(in HNum4 a, in HNum4 b) 182 | { 183 | return HNum4(a.val - b.val , a.g - b.g, a.h - b.h); 184 | } 185 | //-------------------------------- 186 | HNum4 sub(in HNum4 a, in float b) 187 | { 188 | return HNum4(a.val - b , a.g, a.h); 189 | } 190 | //-------------------------------- 191 | HNum4 sub(in float a, in HNum4 b) 192 | { 193 | return HNum4(a - b.val , - b.g, - b.h); 194 | } 195 | //-------------------------------- 196 | HNum4 mult(in HNum4 a, in HNum4 b) 197 | { 198 | return HNum4(a.val * b.val, 199 | a.val*b.g + b.val*a.g, 200 | a.val*b.h + b.val*a.h + a_outerProduct(b.g,a.g) + a_outerProduct(a.g,b.g) 201 | ); 202 | } 203 | //-------------------------------- 204 | HNum4 mult(in HNum4 a, in float b) 205 | { 206 | return HNum4(a.val * b, b*a.g, b*a.h); 207 | } 208 | //-------------------------------- 209 | HNum4 mult(in float a, in HNum4 b) 210 | { 211 | return HNum4(a * b.val, a*b.g, a*b.h); 212 | } 213 | //-------------------------------- 214 | HNum4 neg(in HNum4 a) 215 | { 216 | return mult(-1.0,a); 217 | } 218 | //-------------------------------- 219 | HNum4 div(in HNum4 a, in HNum4 b) 220 | { 221 | float b1 = b.val; 222 | float b2 = b1*b1; 223 | float b3 = b2*b1; 224 | 225 | return HNum4(a.val / b.val , 226 | (b.val*a.g - a.val*b.g)/b2, 227 | 2.0*a.val/b3*a_outerProduct(b.g,b.g) 228 | - a.val/b2*b.h 229 | + a.h/b1 230 | - a_outerProduct(b.g/b2, a.g) 231 | - a_outerProduct(a.g/b2, b.g) 232 | ); 233 | } 234 | //-------------------------------- 235 | HNum4 div(in HNum4 a, in float b) 236 | { 237 | return HNum4(a.val / b, a.g/b, a.h/b); 238 | } 239 | //-------------------------------- 240 | HNum4 div(in float a, in HNum4 b) 241 | { 242 | float b1 = b.val; 243 | float b2 = b1*b1; 244 | float b3 = b2*b1; 245 | 246 | return HNum4(a / b.val, 247 | -a*b.g/b2, 248 | 2.0*a/b3*a_outerProduct(b.g,b.g) - a/b2*b.h 249 | ); 250 | } 251 | //-------------------------------- 252 | HNum4 inv(in HNum4 a) 253 | { 254 | return div(1.0, a); 255 | } 256 | //-------------------------------- 257 | HNum4 a_pow(in HNum4 a, in HNum4 b) 258 | { 259 | return a_exp(mult(b,a_log(a))); 260 | } 261 | //-------------------------------- 262 | HNum4 a_pow(in HNum4 a, in float b) 263 | { 264 | // constant exponent -> make special case 265 | float v = pow(a.val, b); // value f(a(x)) 266 | float da = b*pow(a.val,b-1.0); // first derivative f'(a(x)) 267 | float dda = b*(b-1.0)*pow(a.val,b-2.0); // second derivative f''(a(x)) 268 | return HNum4(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 269 | } 270 | //-------------------------------- 271 | HNum4 a_pow(in float a, in HNum4 b) 272 | { 273 | return a_exp(mult(b,log(a))); 274 | } 275 | //-------------------------------- 276 | HNum4 a_ipow(in HNum4 x, in int n) 277 | { 278 | // based on https://en.wikipedia.org/wiki/Exponentiation_by_squaring 279 | if (n < 0) 280 | { 281 | x = div(1.0,x); 282 | n = -n; 283 | } 284 | if (n == 0) 285 | { 286 | return constH4(1.0); 287 | } 288 | HNum4 y = constH4(1.0); 289 | while (n > 1) 290 | { 291 | if (n % 2 == 0) 292 | { 293 | x = mult(x,x); 294 | 295 | } 296 | else 297 | { 298 | y = mult(x, y); 299 | x = mult(x, x); 300 | } 301 | 302 | n = n / 2; 303 | } 304 | 305 | return mult(x, y); 306 | } 307 | 308 | //-------------------------------- 309 | HNum4 a_min(in HNum4 a, in HNum4 b) 310 | { 311 | if(a.val < b.val) 312 | { 313 | return a; 314 | } 315 | return b; 316 | } 317 | //-------------------------------- 318 | HNum4 a_max(in HNum4 a, in HNum4 b) 319 | { 320 | if(a.val > b.val) 321 | { 322 | return a; 323 | } 324 | return b; 325 | } 326 | //-------------------------------- 327 | HNum4 a_exp2(in HNum4 a) 328 | { 329 | float v = exp2(a.val); // value f(a(x)) 330 | float da = log(2.0)*exp2(a.val); // first derivative f'(a(x)) 331 | float dda = log(2.0)*log(2.0)*exp2(a.val); // second derivative f''(a(x)) 332 | 333 | return HNum4(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 334 | } 335 | //-------------------------------- 336 | HNum4 a_inversesqrt(in HNum4 a) 337 | { 338 | float v = inversesqrt(a.val); // value f(a(x)) 339 | float da = -0.5/pow(sqrt(a.val),3.0); // first derivative f'(a(x)) 340 | float dda = 0.75/pow(sqrt(a.val),5.0); // second derivative f''(a(x)) 341 | 342 | return HNum4(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 343 | } 344 | //-------------------------------- 345 | HNum4 a_atan(in HNum4 a) 346 | { 347 | float v = atan(a.val); // value f(a(x)) 348 | float da = 1.0/(1.0 + a.val * a.val); // first derivative f'(a(x)) 349 | float dda = -2.0*a.val/pow(1.0 + a.val * a.val, 2.0); // second derivative f''(a(x)) 350 | 351 | return HNum4(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 352 | } 353 | //-------------------------------- 354 | HNum4 a_sqrt(in HNum4 a) 355 | { 356 | float v = sqrt(a.val); // value f(a(x)) 357 | float da = 0.5/sqrt(a.val); // first derivative f'(a(x)) 358 | float dda = -0.25/pow(sqrt(a.val),3.0); // second derivative f''(a(x)) 359 | 360 | return HNum4(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 361 | } 362 | //-------------------------------- 363 | HNum4 a_sinh(in HNum4 a) 364 | { 365 | float v = sinh(a.val); // value f(a(x)) 366 | float da = cosh(a.val); // first derivative f'(a(x)) 367 | float dda = sinh(a.val); // second derivative f''(a(x)) 368 | 369 | return HNum4(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 370 | } 371 | //-------------------------------- 372 | HNum4 a_ceil(in HNum4 a) 373 | { 374 | float v = ceil(a.val); // value f(a(x)) 375 | float da = 0.0; // first derivative f'(a(x)) 376 | float dda = 0.0; // second derivative f''(a(x)) 377 | 378 | return HNum4(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 379 | } 380 | //-------------------------------- 381 | HNum4 a_tan(in HNum4 a) 382 | { 383 | float v = tan(a.val); // value f(a(x)) 384 | float da = 1.0 + pow(tan(a.val),2.0); // first derivative f'(a(x)) 385 | float dda = 2.0*tan(a.val)*(1.0 + pow(tan(a.val),2.0)); // second derivative f''(a(x)) 386 | 387 | return HNum4(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 388 | } 389 | //-------------------------------- 390 | HNum4 a_asinh(in HNum4 a) 391 | { 392 | float v = asinh(a.val); // value f(a(x)) 393 | float da = 1.0/sqrt(1.0 + a.val * a.val); // first derivative f'(a(x)) 394 | float dda = -a.val/pow(sqrt(1.0 + a.val * a.val),3.0); // second derivative f''(a(x)) 395 | 396 | return HNum4(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 397 | } 398 | //-------------------------------- 399 | HNum4 a_asin(in HNum4 a) 400 | { 401 | float v = asin(a.val); // value f(a(x)) 402 | float da = 1.0/sqrt(1.0 - a.val * a.val); // first derivative f'(a(x)) 403 | float dda = a.val/pow(sqrt(1.0 - a.val * a.val),3.0); // second derivative f''(a(x)) 404 | 405 | return HNum4(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 406 | } 407 | //-------------------------------- 408 | HNum4 a_acosh(in HNum4 a) 409 | { 410 | float v = acosh(a.val); // value f(a(x)) 411 | float da = 1.0/sqrt(-1.0 + a.val * a.val); // first derivative f'(a(x)) 412 | float dda = -a.val/pow(sqrt(-1.0 + a.val * a.val),3.0); // second derivative f''(a(x)) 413 | 414 | return HNum4(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 415 | } 416 | //-------------------------------- 417 | HNum4 a_abs(in HNum4 a) 418 | { 419 | float v = abs(a.val); // value f(a(x)) 420 | float da = a.val < 0.0 ? -1.0 : 1.0; // first derivative f'(a(x)) 421 | float dda = 0.0; // second derivative f''(a(x)) 422 | 423 | return HNum4(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 424 | } 425 | //-------------------------------- 426 | HNum4 a_exp(in HNum4 a) 427 | { 428 | float v = exp(a.val); // value f(a(x)) 429 | float da = exp(a.val); // first derivative f'(a(x)) 430 | float dda = exp(a.val); // second derivative f''(a(x)) 431 | 432 | return HNum4(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 433 | } 434 | //-------------------------------- 435 | HNum4 a_cosh(in HNum4 a) 436 | { 437 | float v = cosh(a.val); // value f(a(x)) 438 | float da = sinh(a.val); // first derivative f'(a(x)) 439 | float dda = cosh(a.val); // second derivative f''(a(x)) 440 | 441 | return HNum4(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 442 | } 443 | //-------------------------------- 444 | HNum4 a_floor(in HNum4 a) 445 | { 446 | float v = floor(a.val); // value f(a(x)) 447 | float da = 0.0; // first derivative f'(a(x)) 448 | float dda = 0.0; // second derivative f''(a(x)) 449 | 450 | return HNum4(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 451 | } 452 | //-------------------------------- 453 | HNum4 a_log(in HNum4 a) 454 | { 455 | float v = log(a.val); // value f(a(x)) 456 | float da = 1.0/a.val; // first derivative f'(a(x)) 457 | float dda = -1.0/(a.val * a.val); // second derivative f''(a(x)) 458 | 459 | return HNum4(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 460 | } 461 | //-------------------------------- 462 | HNum4 a_atanh(in HNum4 a) 463 | { 464 | float v = atanh(a.val); // value f(a(x)) 465 | float da = 1.0/(1.0 - a.val * a.val); // first derivative f'(a(x)) 466 | float dda = 2.0*a.val/pow(1.0 - a.val * a.val,2.0); // second derivative f''(a(x)) 467 | 468 | return HNum4(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 469 | } 470 | //-------------------------------- 471 | HNum4 a_log2(in HNum4 a) 472 | { 473 | float v = log2(a.val); // value f(a(x)) 474 | float da = 1.0/(a.val * log(2.0)); // first derivative f'(a(x)) 475 | float dda = -1.0/(a.val * a.val * log(2.0)); // second derivative f''(a(x)) 476 | 477 | return HNum4(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 478 | } 479 | //-------------------------------- 480 | HNum4 a_acos(in HNum4 a) 481 | { 482 | float v = acos(a.val); // value f(a(x)) 483 | float da = -1.0/sqrt(1.0 - a.val * a.val); // first derivative f'(a(x)) 484 | float dda = -a.val/pow(sqrt(1.0 - a.val * a.val),3.0); // second derivative f''(a(x)) 485 | 486 | return HNum4(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 487 | } 488 | //-------------------------------- 489 | HNum4 a_tanh(in HNum4 a) 490 | { 491 | float v = tanh(a.val); // value f(a(x)) 492 | float da = 1.0 - pow(tanh(a.val),2.0); // first derivative f'(a(x)) 493 | float dda = -2.0*tanh(a.val)*(1.0 - pow(tanh(a.val),2.0)); // second derivative f''(a(x)) 494 | 495 | return HNum4(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 496 | } 497 | //-------------------------------- 498 | HNum4 a_cos(in HNum4 a) 499 | { 500 | float v = cos(a.val); // value f(a(x)) 501 | float da = -sin(a.val); // first derivative f'(a(x)) 502 | float dda = -cos(a.val); // second derivative f''(a(x)) 503 | 504 | return HNum4(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 505 | } 506 | //-------------------------------- 507 | HNum4 a_sin(in HNum4 a) 508 | { 509 | float v = sin(a.val); // value f(a(x)) 510 | float da = cos(a.val); // first derivative f'(a(x)) 511 | float dda = -sin(a.val); // second derivative f''(a(x)) 512 | 513 | return HNum4(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g)); 514 | } 515 | //-------------------------------- 516 | HNum4 a_atan2(in HNum4 y, in HNum4 x) 517 | { 518 | const float pi = 3.14159265; 519 | // from https://en.wikipedia.org/wiki/Atan2 520 | if(x.val > 0.0) 521 | { 522 | HNum4 n = a_sqrt(add(mult(x,x),mult(y,y))); 523 | HNum4 inner = div(y, add(n,x)); 524 | 525 | return mult(2.0,a_atan(inner)); 526 | 527 | }else if(x.val <= 0.0 && abs(y.val) > 1E-6) 528 | { 529 | HNum4 n = a_sqrt(add(mult(x,x),mult(y,y))); 530 | HNum4 inner = div(sub(n,x),y); 531 | return mult(2.0,a_atan(inner)); 532 | }else if(x.val < 0.0 && abs(y.val) <= 1E-6) 533 | { 534 | return constH4(pi); 535 | } 536 | // return 0 for undefined 537 | return constH4(0.0); 538 | } 539 | //-------------------------------- 540 | HNum4 a_atan2(in HNum4 y, in float x) 541 | { 542 | return a_atan2(y,constH4(x)); 543 | } 544 | //-------------------------------- 545 | HNum4 a_atan2(in float y, in HNum4 x) 546 | { 547 | return a_atan2(constH4(y),x); 548 | } 549 | //-------------------------------- 550 | HNum4 a_mix(in HNum4 a, in HNum4 b, in HNum4 t) 551 | { 552 | return add(mult(a, sub(1.0, t)), mult(b, t)); 553 | } 554 | 555 | //-------------------------------- 556 | HNum4 a_mix(in HNum4 a, in HNum4 b, in float t) 557 | { 558 | return add(mult(a, 1.0 - t), mult(b, t)); 559 | } 560 | 561 | //-------------------------------- 562 | HNum4 a_mix(in HNum4 a, in float b, in HNum4 t) 563 | { 564 | return add(mult(a, sub(1.0, t)), mult(b, t)); 565 | } 566 | 567 | //-------------------------------- 568 | HNum4 a_mix(in HNum4 a, in float b, in float t) 569 | { 570 | return add(mult(a, 1.0 - t), b*t); 571 | } 572 | 573 | //-------------------------------- 574 | HNum4 a_mix(in float a, in HNum4 b, in HNum4 t) 575 | { 576 | return add(mult(a, sub(1.0, t)), mult(b, t)); 577 | } 578 | 579 | //-------------------------------- 580 | HNum4 a_mix(in float a, in HNum4 b, in float t) 581 | { 582 | return add(a * (1.0 - t), mult(b, t)); 583 | } 584 | 585 | //-------------------------------- 586 | HNum4 a_mix(in float a, in float b, in HNum4 t) 587 | { 588 | return add(mult(a, sub(1.0, t)), mult(b, t)); 589 | } 590 | 591 | 592 | //-------------------------------- 593 | // Implementation prototypes 594 | //-------------------------------- 595 | 596 | mat4 a_outerProduct(in vec4 a, in vec4 b) 597 | { 598 | return mat4(a * b[0], a * b[1], a * b[2], a * b[3]); 599 | } 600 | 601 | 602 | #endif // HESSNUM_4_H_ -------------------------------------------------------------------------------- /deriv_all.glsl: -------------------------------------------------------------------------------- 1 | #ifndef DERIVATIVES_H_ 2 | #define DERIVATIVES_H_ 3 | 4 | // This file contains methods to compute the first and second order derivative 5 | // of a scalar function using automatic forward differentiation 6 | 7 | // The data is stored in a vec2 for first order and vec3 for second order derivatives 8 | // v[0] contains the value of the function 9 | // v[1] contains the first derivative 10 | // v[2] contains the second derivative 11 | 12 | //-------------------------------- 13 | // Prototypes 14 | //-------------------------------- 15 | 16 | /** 17 | * Creates a constant derivative number 18 | * @param val The current value of the constant 19 | */ 20 | vec2 constD1(in float val); 21 | /** 22 | * Creates a derivative number stored in a vec2 23 | * @param val The current value of the variable 24 | */ 25 | vec2 varD1(in float val); 26 | vec2 add(in vec2 a, in vec2 b); 27 | vec2 add(in vec2 a, in float b); 28 | vec2 add(in float a, in vec2 b); 29 | vec2 sub(in vec2 a, in vec2 b); 30 | vec2 sub(in vec2 a, in float b); 31 | vec2 sub(in float a, in vec2 b); 32 | vec2 mult(in vec2 a, in vec2 b); 33 | vec2 mult(in vec2 a, in float b); 34 | vec2 mult(in float a, in vec2 b); 35 | vec2 neg(in vec2 a); 36 | vec2 div(in vec2 a, in vec2 b); 37 | vec2 div(in vec2 a, in float b); 38 | vec2 div(in float a, in vec2 b); 39 | vec2 inv(in vec2 a); 40 | vec2 a_pow(in vec2 a, in vec2 b); 41 | vec2 a_pow(in vec2 a, in float b); 42 | vec2 a_pow(in float a, in vec2 b); 43 | vec2 a_ipow(in vec2 x, in int n); 44 | vec2 a_min(in vec2 a, in vec2 b); 45 | vec2 a_max(in vec2 a, in vec2 b); 46 | vec2 a_exp2(in vec2 a); 47 | vec2 a_inversesqrt(in vec2 a); 48 | vec2 a_atan(in vec2 a); 49 | vec2 a_sqrt(in vec2 a); 50 | vec2 a_sinh(in vec2 a); 51 | vec2 a_ceil(in vec2 a); 52 | vec2 a_tan(in vec2 a); 53 | vec2 a_asinh(in vec2 a); 54 | vec2 a_asin(in vec2 a); 55 | vec2 a_acosh(in vec2 a); 56 | vec2 a_abs(in vec2 a); 57 | vec2 a_exp(in vec2 a); 58 | vec2 a_cosh(in vec2 a); 59 | vec2 a_floor(in vec2 a); 60 | vec2 a_log(in vec2 a); 61 | vec2 a_atanh(in vec2 a); 62 | vec2 a_log2(in vec2 a); 63 | vec2 a_acos(in vec2 a); 64 | vec2 a_tanh(in vec2 a); 65 | vec2 a_cos(in vec2 a); 66 | vec2 a_sin(in vec2 a); 67 | vec2 a_atan2(in vec2 y, in vec2 x); 68 | vec2 a_atan2(in vec2 y, in float x); 69 | vec2 a_atan2(in float y, in vec2 x); 70 | vec2 a_mix(in vec2 a, in vec2 b, in vec2 t); 71 | vec2 a_mix(in vec2 a, in vec2 b, in float t); 72 | vec2 a_mix(in vec2 a, in float b, in vec2 t); 73 | vec2 a_mix(in vec2 a, in float b, in float t); 74 | vec2 a_mix(in float a, in vec2 b, in vec2 t); 75 | vec2 a_mix(in float a, in vec2 b, in float t); 76 | vec2 a_mix(in float a, in float b, in vec2 t); 77 | /** 78 | * Creates a constant derivative number 79 | * @param val The current value of the constant 80 | */ 81 | vec3 constD2(in float val); 82 | /** 83 | * Creates a derivative number stored in a vec3 84 | * @param val The current value of the variable 85 | */ 86 | vec3 varD2(in float val); 87 | vec3 add(in vec3 a, in vec3 b); 88 | vec3 add(in vec3 a, in float b); 89 | vec3 add(in float a, in vec3 b); 90 | vec3 sub(in vec3 a, in vec3 b); 91 | vec3 sub(in vec3 a, in float b); 92 | vec3 sub(in float a, in vec3 b); 93 | vec3 mult(in vec3 a, in vec3 b); 94 | vec3 mult(in vec3 a, in float b); 95 | vec3 mult(in float a, in vec3 b); 96 | vec3 neg(in vec3 a); 97 | vec3 div(in vec3 a, in vec3 b); 98 | vec3 div(in vec3 a, in float b); 99 | vec3 div(in float a, in vec3 b); 100 | vec3 inv(in vec3 a); 101 | vec3 a_pow(in vec3 a, in vec3 b); 102 | vec3 a_pow(in vec3 a, in float b); 103 | vec3 a_pow(in float a, in vec3 b); 104 | vec3 a_ipow(in vec3 x, in int n); 105 | vec3 a_min(in vec3 a, in vec3 b); 106 | vec3 a_max(in vec3 a, in vec3 b); 107 | vec3 a_exp2(in vec3 a); 108 | vec3 a_inversesqrt(in vec3 a); 109 | vec3 a_atan(in vec3 a); 110 | vec3 a_sqrt(in vec3 a); 111 | vec3 a_sinh(in vec3 a); 112 | vec3 a_ceil(in vec3 a); 113 | vec3 a_tan(in vec3 a); 114 | vec3 a_asinh(in vec3 a); 115 | vec3 a_asin(in vec3 a); 116 | vec3 a_acosh(in vec3 a); 117 | vec3 a_abs(in vec3 a); 118 | vec3 a_exp(in vec3 a); 119 | vec3 a_cosh(in vec3 a); 120 | vec3 a_floor(in vec3 a); 121 | vec3 a_log(in vec3 a); 122 | vec3 a_atanh(in vec3 a); 123 | vec3 a_log2(in vec3 a); 124 | vec3 a_acos(in vec3 a); 125 | vec3 a_tanh(in vec3 a); 126 | vec3 a_cos(in vec3 a); 127 | vec3 a_sin(in vec3 a); 128 | vec3 a_atan2(in vec3 y, in vec3 x); 129 | vec3 a_atan2(in vec3 y, in float x); 130 | vec3 a_atan2(in float y, in vec3 x); 131 | vec3 a_mix(in vec3 a, in vec3 b, in vec3 t); 132 | vec3 a_mix(in vec3 a, in vec3 b, in float t); 133 | vec3 a_mix(in vec3 a, in float b, in vec3 t); 134 | vec3 a_mix(in vec3 a, in float b, in float t); 135 | vec3 a_mix(in float a, in vec3 b, in vec3 t); 136 | vec3 a_mix(in float a, in vec3 b, in float t); 137 | vec3 a_mix(in float a, in float b, in vec3 t); 138 | 139 | //-------------------------------- 140 | // Implementation 141 | //-------------------------------- 142 | 143 | vec2 constD1(in float val) 144 | { 145 | vec2 c = vec2(0.0); 146 | c[0] = val; 147 | return c; 148 | } 149 | //-------------------------------- 150 | vec2 varD1(in float val) 151 | { 152 | return vec2(val, 1.0); 153 | } 154 | //-------------------------------- 155 | vec2 add(in vec2 a, in vec2 b) 156 | { 157 | return a + b; 158 | } 159 | //-------------------------------- 160 | vec2 add(in vec2 a, in float b) 161 | { 162 | a[0] += b; 163 | return a; 164 | } 165 | //-------------------------------- 166 | vec2 add(in float a, in vec2 b) 167 | { 168 | b[0] += a; 169 | return b; 170 | } 171 | //-------------------------------- 172 | vec2 sub(in vec2 a, in vec2 b) 173 | { 174 | return a - b; 175 | } 176 | //-------------------------------- 177 | vec2 sub(in vec2 a, in float b) 178 | { 179 | a[0] -= b; 180 | return a; 181 | } 182 | //-------------------------------- 183 | vec2 sub(in float a, in vec2 b) 184 | { 185 | b *= -1.0; 186 | b[0] += a; 187 | return b; 188 | } 189 | //-------------------------------- 190 | vec2 mult(in vec2 a, in vec2 b) 191 | { 192 | float v = a[0] * b[0]; 193 | float da = a[0]*b[1] + b[0]*a[1]; 194 | 195 | return vec2(v,da); 196 | } 197 | //-------------------------------- 198 | vec2 mult(in vec2 a, in float b) 199 | { 200 | return a*b; 201 | } 202 | //-------------------------------- 203 | vec2 mult(in float a, in vec2 b) 204 | { 205 | return a*b; 206 | } 207 | //-------------------------------- 208 | vec2 neg(in vec2 a) 209 | { 210 | return mult(-1.0,a); 211 | } 212 | //-------------------------------- 213 | vec2 div(in vec2 a, in vec2 b) 214 | { 215 | float v = a[0] / b[0]; 216 | float b2 = b[0] * b[0]; 217 | float da = a[1]/b[0] - a[0]*b[1]/b2; 218 | 219 | return vec2(v,da); 220 | } 221 | //-------------------------------- 222 | vec2 div(in vec2 a, in float b) 223 | { 224 | return a / b; 225 | } 226 | //-------------------------------- 227 | vec2 div(in float a, in vec2 b) 228 | { 229 | float v = a / b[0]; 230 | float b2 = b[0] * b[0]; 231 | float da = - a*b[1]/b2; 232 | 233 | return vec2(v, da); 234 | } 235 | //-------------------------------- 236 | vec2 inv(in vec2 a) 237 | { 238 | return div(1.0, a); 239 | } 240 | //-------------------------------- 241 | vec2 a_pow(in vec2 a, in vec2 b) 242 | { 243 | return a_exp(mult(b,a_log(a))); 244 | } 245 | //-------------------------------- 246 | vec2 a_pow(in vec2 a, in float b) 247 | { 248 | float v = pow(a[0], b); // value f(a(x)) 249 | float da = b*pow(a[0],b-1.0); // first derivative f'(a(x)) 250 | 251 | return vec2(v, da * a[1]); 252 | } 253 | //-------------------------------- 254 | vec2 a_pow(in float a, in vec2 b) 255 | { 256 | return a_exp(mult(b,log(a))); 257 | } 258 | //-------------------------------- 259 | vec2 a_ipow(in vec2 x, in int n) 260 | { 261 | // based on https://en.wikipedia.org/wiki/Exponentiation_by_squaring 262 | if (n < 0) 263 | { 264 | x = div(1.0,x); 265 | n = -n; 266 | } 267 | if (n == 0) 268 | { 269 | return constD1(1.0); 270 | } 271 | vec2 y = constD1(1.0); 272 | while (n > 1) 273 | { 274 | if (n % 2 == 0) 275 | { 276 | x = mult(x,x); 277 | 278 | } 279 | else 280 | { 281 | y = mult(x, y); 282 | x = mult(x, x); 283 | } 284 | 285 | n = n / 2; 286 | } 287 | 288 | return mult(x, y); 289 | } 290 | 291 | //-------------------------------- 292 | vec2 a_min(in vec2 a, in vec2 b) 293 | { 294 | if(a[0] < b[0]) 295 | { 296 | return a; 297 | } 298 | return b; 299 | } 300 | //-------------------------------- 301 | vec2 a_max(in vec2 a, in vec2 b) 302 | { 303 | if(a[0] > b[0]) 304 | { 305 | return a; 306 | } 307 | return b; 308 | } 309 | //-------------------------------- 310 | vec2 a_exp2(in vec2 a) 311 | { 312 | float v = exp2(a[0]); 313 | float da = log(2.0)*exp2(a[0]); 314 | 315 | return vec2(v, da * a[1]); 316 | } 317 | //-------------------------------- 318 | vec2 a_inversesqrt(in vec2 a) 319 | { 320 | float v = inversesqrt(a[0]); 321 | float da = -0.5/pow(sqrt(a[0]),3.0); 322 | 323 | return vec2(v, da * a[1]); 324 | } 325 | //-------------------------------- 326 | vec2 a_atan(in vec2 a) 327 | { 328 | float v = atan(a[0]); 329 | float da = 1.0/(1.0 + a[0] * a[0]); 330 | 331 | return vec2(v, da * a[1]); 332 | } 333 | //-------------------------------- 334 | vec2 a_sqrt(in vec2 a) 335 | { 336 | float v = sqrt(a[0]); 337 | float da = 0.5/sqrt(a[0]); 338 | 339 | return vec2(v, da * a[1]); 340 | } 341 | //-------------------------------- 342 | vec2 a_sinh(in vec2 a) 343 | { 344 | float v = sinh(a[0]); 345 | float da = cosh(a[0]); 346 | 347 | return vec2(v, da * a[1]); 348 | } 349 | //-------------------------------- 350 | vec2 a_ceil(in vec2 a) 351 | { 352 | float v = ceil(a[0]); 353 | float da = 0.0; 354 | 355 | return vec2(v, da * a[1]); 356 | } 357 | //-------------------------------- 358 | vec2 a_tan(in vec2 a) 359 | { 360 | float v = tan(a[0]); 361 | float da = 1.0 + pow(tan(a[0]),2.0); 362 | 363 | return vec2(v, da * a[1]); 364 | } 365 | //-------------------------------- 366 | vec2 a_asinh(in vec2 a) 367 | { 368 | float v = asinh(a[0]); 369 | float da = 1.0/sqrt(1.0 + a[0] * a[0]); 370 | 371 | return vec2(v, da * a[1]); 372 | } 373 | //-------------------------------- 374 | vec2 a_asin(in vec2 a) 375 | { 376 | float v = asin(a[0]); 377 | float da = 1.0/sqrt(1.0 - a[0] * a[0]); 378 | 379 | return vec2(v, da * a[1]); 380 | } 381 | //-------------------------------- 382 | vec2 a_acosh(in vec2 a) 383 | { 384 | float v = acosh(a[0]); 385 | float da = 1.0/sqrt(-1.0 + a[0] * a[0]); 386 | 387 | return vec2(v, da * a[1]); 388 | } 389 | //-------------------------------- 390 | vec2 a_abs(in vec2 a) 391 | { 392 | float v = abs(a[0]); 393 | float da = a[0] < 0.0 ? -1.0 : 1.0; 394 | 395 | return vec2(v, da * a[1]); 396 | } 397 | //-------------------------------- 398 | vec2 a_exp(in vec2 a) 399 | { 400 | float v = exp(a[0]); 401 | float da = exp(a[0]); 402 | 403 | return vec2(v, da * a[1]); 404 | } 405 | //-------------------------------- 406 | vec2 a_cosh(in vec2 a) 407 | { 408 | float v = cosh(a[0]); 409 | float da = sinh(a[0]); 410 | 411 | return vec2(v, da * a[1]); 412 | } 413 | //-------------------------------- 414 | vec2 a_floor(in vec2 a) 415 | { 416 | float v = floor(a[0]); 417 | float da = 0.0; 418 | 419 | return vec2(v, da * a[1]); 420 | } 421 | //-------------------------------- 422 | vec2 a_log(in vec2 a) 423 | { 424 | float v = log(a[0]); 425 | float da = 1.0/a[0]; 426 | 427 | return vec2(v, da * a[1]); 428 | } 429 | //-------------------------------- 430 | vec2 a_atanh(in vec2 a) 431 | { 432 | float v = atanh(a[0]); 433 | float da = 1.0/(1.0 - a[0] * a[0]); 434 | 435 | return vec2(v, da * a[1]); 436 | } 437 | //-------------------------------- 438 | vec2 a_log2(in vec2 a) 439 | { 440 | float v = log2(a[0]); 441 | float da = 1.0/(a[0] * log(2.0)); 442 | 443 | return vec2(v, da * a[1]); 444 | } 445 | //-------------------------------- 446 | vec2 a_acos(in vec2 a) 447 | { 448 | float v = acos(a[0]); 449 | float da = -1.0/sqrt(1.0 - a[0] * a[0]); 450 | 451 | return vec2(v, da * a[1]); 452 | } 453 | //-------------------------------- 454 | vec2 a_tanh(in vec2 a) 455 | { 456 | float v = tanh(a[0]); 457 | float da = 1.0 - pow(tanh(a[0]),2.0); 458 | 459 | return vec2(v, da * a[1]); 460 | } 461 | //-------------------------------- 462 | vec2 a_cos(in vec2 a) 463 | { 464 | float v = cos(a[0]); 465 | float da = -sin(a[0]); 466 | 467 | return vec2(v, da * a[1]); 468 | } 469 | //-------------------------------- 470 | vec2 a_sin(in vec2 a) 471 | { 472 | float v = sin(a[0]); 473 | float da = cos(a[0]); 474 | 475 | return vec2(v, da * a[1]); 476 | } 477 | //-------------------------------- 478 | vec2 a_atan2(in vec2 y, in vec2 x) 479 | { 480 | const float pi = 3.14159265; 481 | // from https://en.wikipedia.org/wiki/Atan2 482 | if(x[0] > 0.0) 483 | { 484 | vec2 n = a_sqrt(add(mult(x,x),mult(y,y))); 485 | vec2 inner = div(y, add(n,x)); 486 | 487 | return mult(2.0,a_atan(inner)); 488 | 489 | }else if(x[0] <= 0.0 && abs(y[0]) > 1E-6) 490 | { 491 | vec2 n = a_sqrt(add(mult(x,x),mult(y,y))); 492 | vec2 inner = div(sub(n,x),y); 493 | return mult(2.0,a_atan(inner)); 494 | }else if(x[0] < 0.0 && abs(y[0]) <= 1E-6) 495 | { 496 | return constD1(pi); 497 | } 498 | // return 0 for undefined 499 | return constD1(0.0); 500 | } 501 | //-------------------------------- 502 | vec2 a_atan2(in vec2 y, in float x) 503 | { 504 | return a_atan2(y,constD1(x)); 505 | } 506 | //-------------------------------- 507 | vec2 a_atan2(in float y, in vec2 x) 508 | { 509 | return a_atan2(constD1(y),x); 510 | } 511 | //-------------------------------- 512 | vec2 a_mix(in vec2 a, in vec2 b, in vec2 t) 513 | { 514 | return add(mult(a, sub(1.0, t)), mult(b, t)); 515 | } 516 | 517 | //-------------------------------- 518 | vec2 a_mix(in vec2 a, in vec2 b, in float t) 519 | { 520 | return add(mult(a, 1.0 - t), mult(b, t)); 521 | } 522 | 523 | //-------------------------------- 524 | vec2 a_mix(in vec2 a, in float b, in vec2 t) 525 | { 526 | return add(mult(a, sub(1.0, t)), mult(b, t)); 527 | } 528 | 529 | //-------------------------------- 530 | vec2 a_mix(in vec2 a, in float b, in float t) 531 | { 532 | return add(mult(a, 1.0 - t), b*t); 533 | } 534 | 535 | //-------------------------------- 536 | vec2 a_mix(in float a, in vec2 b, in vec2 t) 537 | { 538 | return add(mult(a, sub(1.0, t)), mult(b, t)); 539 | } 540 | 541 | //-------------------------------- 542 | vec2 a_mix(in float a, in vec2 b, in float t) 543 | { 544 | return add(a * (1.0 - t), mult(b, t)); 545 | } 546 | 547 | //-------------------------------- 548 | vec2 a_mix(in float a, in float b, in vec2 t) 549 | { 550 | return add(mult(a, sub(1.0, t)), mult(b, t)); 551 | } 552 | 553 | //-------------------------------- 554 | vec3 constD2(in float val) 555 | { 556 | vec3 c = vec3(0.0); 557 | c[0] = val; 558 | return c; 559 | } 560 | //-------------------------------- 561 | vec3 varD2(in float val) 562 | { 563 | return vec3(val, 1.0, 0.0); 564 | } 565 | //-------------------------------- 566 | vec3 add(in vec3 a, in vec3 b) 567 | { 568 | return a + b; 569 | } 570 | //-------------------------------- 571 | vec3 add(in vec3 a, in float b) 572 | { 573 | a[0] += b; 574 | return a; 575 | } 576 | //-------------------------------- 577 | vec3 add(in float a, in vec3 b) 578 | { 579 | b[0] += a; 580 | return b; 581 | } 582 | //-------------------------------- 583 | vec3 sub(in vec3 a, in vec3 b) 584 | { 585 | return a - b; 586 | } 587 | //-------------------------------- 588 | vec3 sub(in vec3 a, in float b) 589 | { 590 | a[0] -= b; 591 | return a; 592 | } 593 | //-------------------------------- 594 | vec3 sub(in float a, in vec3 b) 595 | { 596 | b *= -1.0; 597 | b[0] += a; 598 | return b; 599 | } 600 | //-------------------------------- 601 | vec3 mult(in vec3 a, in vec3 b) 602 | { 603 | float v = a[0] * b[0]; 604 | float da = a[0]*b[1] + b[0]*a[1]; 605 | float dda = a[2]*b[0] + 2.0*a[1]*b[1] + a[0]*b[2]; 606 | 607 | return vec3(v,da,dda); 608 | } 609 | //-------------------------------- 610 | vec3 mult(in vec3 a, in float b) 611 | { 612 | return a*b; 613 | } 614 | //-------------------------------- 615 | vec3 mult(in float a, in vec3 b) 616 | { 617 | return a*b; 618 | } 619 | //-------------------------------- 620 | vec3 neg(in vec3 a) 621 | { 622 | return mult(-1.0,a); 623 | } 624 | //-------------------------------- 625 | vec3 div(in vec3 a, in vec3 b) 626 | { 627 | float v = a[0] / b[0]; 628 | float b2 = b[0] * b[0]; 629 | float da = a[1]/b[0] - a[0]*b[1]/b2; 630 | float b3 = b2 * b[0]; 631 | float dda = a[2]/b[0] - 2.0*a[1]*b[1]/b2 - a[0]*b[2]/b2 + 2.0*a[0]*(b[1]*b[1])/b3; 632 | 633 | return vec3(v,da,dda); 634 | } 635 | //-------------------------------- 636 | vec3 div(in vec3 a, in float b) 637 | { 638 | return a / b; 639 | } 640 | //-------------------------------- 641 | vec3 div(in float a, in vec3 b) 642 | { 643 | float v = a / b[0]; 644 | float b2 = b[0] * b[0]; 645 | float da = - a*b[1]/b2; 646 | float b3 = b2 * b[0]; 647 | float dda = - a*b[2]/b2 + 2.0*a*(b[1]*b[1])/b3; 648 | 649 | return vec3(v, da, dda); 650 | } 651 | //-------------------------------- 652 | vec3 inv(in vec3 a) 653 | { 654 | return div(1.0, a); 655 | } 656 | //-------------------------------- 657 | vec3 a_pow(in vec3 a, in vec3 b) 658 | { 659 | return a_exp(mult(b,a_log(a))); 660 | } 661 | //-------------------------------- 662 | vec3 a_pow(in vec3 a, in float b) 663 | { 664 | float v = pow(a[0], b); // value f(a(x)) 665 | float da = b*pow(a[0],b-1.0); // first derivative f'(a(x)) 666 | float dda = b*(b-1.0)*pow(a[0],b-2.0); // second derivative f''(a(x)) 667 | 668 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 669 | } 670 | //-------------------------------- 671 | vec3 a_pow(in float a, in vec3 b) 672 | { 673 | return a_exp(mult(b,log(a))); 674 | } 675 | //-------------------------------- 676 | vec3 a_ipow(in vec3 x, in int n) 677 | { 678 | // based on https://en.wikipedia.org/wiki/Exponentiation_by_squaring 679 | if (n < 0) 680 | { 681 | x = div(1.0,x); 682 | n = -n; 683 | } 684 | if (n == 0) 685 | { 686 | return constD2(1.0); 687 | } 688 | vec3 y = constD2(1.0); 689 | while (n > 1) 690 | { 691 | if (n % 2 == 0) 692 | { 693 | x = mult(x,x); 694 | 695 | } 696 | else 697 | { 698 | y = mult(x, y); 699 | x = mult(x, x); 700 | } 701 | 702 | n = n / 2; 703 | } 704 | 705 | return mult(x, y); 706 | } 707 | 708 | //-------------------------------- 709 | vec3 a_min(in vec3 a, in vec3 b) 710 | { 711 | if(a[0] < b[0]) 712 | { 713 | return a; 714 | } 715 | return b; 716 | } 717 | //-------------------------------- 718 | vec3 a_max(in vec3 a, in vec3 b) 719 | { 720 | if(a[0] > b[0]) 721 | { 722 | return a; 723 | } 724 | return b; 725 | } 726 | //-------------------------------- 727 | vec3 a_exp2(in vec3 a) 728 | { 729 | float v = exp2(a[0]); 730 | float da = log(2.0)*exp2(a[0]); 731 | float dda = log(2.0)*log(2.0)*exp2(a[0]); 732 | 733 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 734 | } 735 | //-------------------------------- 736 | vec3 a_inversesqrt(in vec3 a) 737 | { 738 | float v = inversesqrt(a[0]); 739 | float da = -0.5/pow(sqrt(a[0]),3.0); 740 | float dda = 0.75/pow(sqrt(a[0]),5.0); 741 | 742 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 743 | } 744 | //-------------------------------- 745 | vec3 a_atan(in vec3 a) 746 | { 747 | float v = atan(a[0]); 748 | float da = 1.0/(1.0 + a[0] * a[0]); 749 | float dda = -2.0*a[0]/pow(1.0 + a[0] * a[0], 2.0); 750 | 751 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 752 | } 753 | //-------------------------------- 754 | vec3 a_sqrt(in vec3 a) 755 | { 756 | float v = sqrt(a[0]); 757 | float da = 0.5/sqrt(a[0]); 758 | float dda = -0.25/pow(sqrt(a[0]),3.0); 759 | 760 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 761 | } 762 | //-------------------------------- 763 | vec3 a_sinh(in vec3 a) 764 | { 765 | float v = sinh(a[0]); 766 | float da = cosh(a[0]); 767 | float dda = sinh(a[0]); 768 | 769 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 770 | } 771 | //-------------------------------- 772 | vec3 a_ceil(in vec3 a) 773 | { 774 | float v = ceil(a[0]); 775 | float da = 0.0; 776 | float dda = 0.0; 777 | 778 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 779 | } 780 | //-------------------------------- 781 | vec3 a_tan(in vec3 a) 782 | { 783 | float v = tan(a[0]); 784 | float da = 1.0 + pow(tan(a[0]),2.0); 785 | float dda = 2.0*tan(a[0])*(1.0 + pow(tan(a[0]),2.0)); 786 | 787 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 788 | } 789 | //-------------------------------- 790 | vec3 a_asinh(in vec3 a) 791 | { 792 | float v = asinh(a[0]); 793 | float da = 1.0/sqrt(1.0 + a[0] * a[0]); 794 | float dda = -a[0]/pow(sqrt(1.0 + a[0] * a[0]),3.0); 795 | 796 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 797 | } 798 | //-------------------------------- 799 | vec3 a_asin(in vec3 a) 800 | { 801 | float v = asin(a[0]); 802 | float da = 1.0/sqrt(1.0 - a[0] * a[0]); 803 | float dda = a[0]/pow(sqrt(1.0 - a[0] * a[0]),3.0); 804 | 805 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 806 | } 807 | //-------------------------------- 808 | vec3 a_acosh(in vec3 a) 809 | { 810 | float v = acosh(a[0]); 811 | float da = 1.0/sqrt(-1.0 + a[0] * a[0]); 812 | float dda = -a[0]/pow(sqrt(-1.0 + a[0] * a[0]),3.0); 813 | 814 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 815 | } 816 | //-------------------------------- 817 | vec3 a_abs(in vec3 a) 818 | { 819 | float v = abs(a[0]); 820 | float da = a[0] < 0.0 ? -1.0 : 1.0; 821 | float dda = 0.0; 822 | 823 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 824 | } 825 | //-------------------------------- 826 | vec3 a_exp(in vec3 a) 827 | { 828 | float v = exp(a[0]); 829 | float da = exp(a[0]); 830 | float dda = exp(a[0]); 831 | 832 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 833 | } 834 | //-------------------------------- 835 | vec3 a_cosh(in vec3 a) 836 | { 837 | float v = cosh(a[0]); 838 | float da = sinh(a[0]); 839 | float dda = cosh(a[0]); 840 | 841 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 842 | } 843 | //-------------------------------- 844 | vec3 a_floor(in vec3 a) 845 | { 846 | float v = floor(a[0]); 847 | float da = 0.0; 848 | float dda = 0.0; 849 | 850 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 851 | } 852 | //-------------------------------- 853 | vec3 a_log(in vec3 a) 854 | { 855 | float v = log(a[0]); 856 | float da = 1.0/a[0]; 857 | float dda = -1.0/(a[0] * a[0]); 858 | 859 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 860 | } 861 | //-------------------------------- 862 | vec3 a_atanh(in vec3 a) 863 | { 864 | float v = atanh(a[0]); 865 | float da = 1.0/(1.0 - a[0] * a[0]); 866 | float dda = 2.0*a[0]/pow(1.0 - a[0] * a[0],2.0); 867 | 868 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 869 | } 870 | //-------------------------------- 871 | vec3 a_log2(in vec3 a) 872 | { 873 | float v = log2(a[0]); 874 | float da = 1.0/(a[0] * log(2.0)); 875 | float dda = -1.0/(a[0] * a[0] * log(2.0)); 876 | 877 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 878 | } 879 | //-------------------------------- 880 | vec3 a_acos(in vec3 a) 881 | { 882 | float v = acos(a[0]); 883 | float da = -1.0/sqrt(1.0 - a[0] * a[0]); 884 | float dda = -a[0]/pow(sqrt(1.0 - a[0] * a[0]),3.0); 885 | 886 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 887 | } 888 | //-------------------------------- 889 | vec3 a_tanh(in vec3 a) 890 | { 891 | float v = tanh(a[0]); 892 | float da = 1.0 - pow(tanh(a[0]),2.0); 893 | float dda = -2.0*tanh(a[0])*(1.0 - pow(tanh(a[0]),2.0)); 894 | 895 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 896 | } 897 | //-------------------------------- 898 | vec3 a_cos(in vec3 a) 899 | { 900 | float v = cos(a[0]); 901 | float da = -sin(a[0]); 902 | float dda = -cos(a[0]); 903 | 904 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 905 | } 906 | //-------------------------------- 907 | vec3 a_sin(in vec3 a) 908 | { 909 | float v = sin(a[0]); 910 | float da = cos(a[0]); 911 | float dda = -sin(a[0]); 912 | 913 | return vec3(v, da * a[1], da * a[2] + dda * a[1]*a[1]); 914 | } 915 | //-------------------------------- 916 | vec3 a_atan2(in vec3 y, in vec3 x) 917 | { 918 | const float pi = 3.14159265; 919 | // from https://en.wikipedia.org/wiki/Atan2 920 | if(x[0] > 0.0) 921 | { 922 | vec3 n = a_sqrt(add(mult(x,x),mult(y,y))); 923 | vec3 inner = div(y, add(n,x)); 924 | 925 | return mult(2.0,a_atan(inner)); 926 | 927 | }else if(x[0] <= 0.0 && abs(y[0]) > 1E-6) 928 | { 929 | vec3 n = a_sqrt(add(mult(x,x),mult(y,y))); 930 | vec3 inner = div(sub(n,x),y); 931 | return mult(2.0,a_atan(inner)); 932 | }else if(x[0] < 0.0 && abs(y[0]) <= 1E-6) 933 | { 934 | return constD2(pi); 935 | } 936 | // return 0 for undefined 937 | return constD2(0.0); 938 | } 939 | //-------------------------------- 940 | vec3 a_atan2(in vec3 y, in float x) 941 | { 942 | return a_atan2(y,constD2(x)); 943 | } 944 | //-------------------------------- 945 | vec3 a_atan2(in float y, in vec3 x) 946 | { 947 | return a_atan2(constD2(y),x); 948 | } 949 | //-------------------------------- 950 | vec3 a_mix(in vec3 a, in vec3 b, in vec3 t) 951 | { 952 | return add(mult(a, sub(1.0, t)), mult(b, t)); 953 | } 954 | 955 | //-------------------------------- 956 | vec3 a_mix(in vec3 a, in vec3 b, in float t) 957 | { 958 | return add(mult(a, 1.0 - t), mult(b, t)); 959 | } 960 | 961 | //-------------------------------- 962 | vec3 a_mix(in vec3 a, in float b, in vec3 t) 963 | { 964 | return add(mult(a, sub(1.0, t)), mult(b, t)); 965 | } 966 | 967 | //-------------------------------- 968 | vec3 a_mix(in vec3 a, in float b, in float t) 969 | { 970 | return add(mult(a, 1.0 - t), b*t); 971 | } 972 | 973 | //-------------------------------- 974 | vec3 a_mix(in float a, in vec3 b, in vec3 t) 975 | { 976 | return add(mult(a, sub(1.0, t)), mult(b, t)); 977 | } 978 | 979 | //-------------------------------- 980 | vec3 a_mix(in float a, in vec3 b, in float t) 981 | { 982 | return add(a * (1.0 - t), mult(b, t)); 983 | } 984 | 985 | //-------------------------------- 986 | vec3 a_mix(in float a, in float b, in vec3 t) 987 | { 988 | return add(mult(a, sub(1.0, t)), mult(b, t)); 989 | } 990 | 991 | 992 | #endif // DERIVATIVES_H_ -------------------------------------------------------------------------------- /grad_all.glsl: -------------------------------------------------------------------------------- 1 | #ifndef GRAD_H_ 2 | #define GRAD_H_ 3 | 4 | // This file contains methods to compute the gradient of a scalar valued 5 | // function (2-4 variables) using automatic forward differentiation 6 | 7 | //-------------------------------- 8 | // Types 9 | //-------------------------------- 10 | 11 | // Data type to hold information about a scalar valued 2 dimensional function 12 | // These should be created by the constG2 (for constants) and varG2 (for variables) helpers 13 | struct GNum2 14 | { 15 | // The current value 16 | float val; 17 | // The current gradient 18 | vec2 g; 19 | }; 20 | //-------------------------------- 21 | // Data type to hold information about a scalar valued 3 dimensional function 22 | // These should be created by the constG3 (for constants) and varG3 (for variables) helpers 23 | struct GNum3 24 | { 25 | // The current value 26 | float val; 27 | // The current gradient 28 | vec3 g; 29 | }; 30 | //-------------------------------- 31 | // Data type to hold information about a scalar valued 4 dimensional function 32 | // These should be created by the constG4 (for constants) and varG4 (for variables) helpers 33 | struct GNum4 34 | { 35 | // The current value 36 | float val; 37 | // The current gradient 38 | vec4 g; 39 | }; 40 | 41 | //-------------------------------- 42 | // Prototypes 43 | //-------------------------------- 44 | 45 | /** 46 | * Creates a constant GNum2 47 | * @param val The current value of the constant 48 | */ 49 | GNum2 constG2(in float val); 50 | GNum2 varG2(in float val, in int index); 51 | GNum2 varG2x(in float val); 52 | GNum2 varG2y(in float val); 53 | GNum2 add(in GNum2 a, in GNum2 b); 54 | GNum2 add(in GNum2 a, in float b); 55 | GNum2 add(in float a, in GNum2 b); 56 | GNum2 sub(in GNum2 a, in GNum2 b); 57 | GNum2 sub(in GNum2 a, in float b); 58 | GNum2 sub(in float a, in GNum2 b); 59 | GNum2 mult(in GNum2 a, in GNum2 b); 60 | GNum2 mult(in GNum2 a, in float b); 61 | GNum2 mult(in float a, in GNum2 b); 62 | GNum2 neg(in GNum2 a); 63 | GNum2 div(in GNum2 a, in GNum2 b); 64 | GNum2 div(in GNum2 a, in float b); 65 | GNum2 div(in float a, in GNum2 b); 66 | GNum2 inv(in GNum2 a); 67 | GNum2 a_pow(in GNum2 a, in GNum2 b); 68 | GNum2 a_pow(in GNum2 a, in float b); 69 | GNum2 a_pow(in float a, in GNum2 b); 70 | GNum2 a_ipow(in GNum2 x, in int n); 71 | GNum2 a_min(in GNum2 a, in GNum2 b); 72 | GNum2 a_max(in GNum2 a, in GNum2 b); 73 | GNum2 a_exp2(in GNum2 a); 74 | GNum2 a_inversesqrt(in GNum2 a); 75 | GNum2 a_atan(in GNum2 a); 76 | GNum2 a_sqrt(in GNum2 a); 77 | GNum2 a_sinh(in GNum2 a); 78 | GNum2 a_ceil(in GNum2 a); 79 | GNum2 a_tan(in GNum2 a); 80 | GNum2 a_asinh(in GNum2 a); 81 | GNum2 a_asin(in GNum2 a); 82 | GNum2 a_acosh(in GNum2 a); 83 | GNum2 a_abs(in GNum2 a); 84 | GNum2 a_exp(in GNum2 a); 85 | GNum2 a_cosh(in GNum2 a); 86 | GNum2 a_floor(in GNum2 a); 87 | GNum2 a_log(in GNum2 a); 88 | GNum2 a_atanh(in GNum2 a); 89 | GNum2 a_log2(in GNum2 a); 90 | GNum2 a_acos(in GNum2 a); 91 | GNum2 a_tanh(in GNum2 a); 92 | GNum2 a_cos(in GNum2 a); 93 | GNum2 a_sin(in GNum2 a); 94 | GNum2 a_atan2(in GNum2 y, in GNum2 x); 95 | GNum2 a_atan2(in GNum2 y, in float x); 96 | GNum2 a_atan2(in float y, in GNum2 x); 97 | GNum2 a_mix(in GNum2 a, in GNum2 b, in GNum2 t); 98 | GNum2 a_mix(in GNum2 a, in GNum2 b, in float t); 99 | GNum2 a_mix(in GNum2 a, in float b, in GNum2 t); 100 | GNum2 a_mix(in GNum2 a, in float b, in float t); 101 | GNum2 a_mix(in float a, in GNum2 b, in GNum2 t); 102 | GNum2 a_mix(in float a, in GNum2 b, in float t); 103 | GNum2 a_mix(in float a, in float b, in GNum2 t); 104 | /** 105 | * Creates a constant GNum3 106 | * @param val The current value of the constant 107 | */ 108 | GNum3 constG3(in float val); 109 | GNum3 varG3(in float val, in int index); 110 | GNum3 varG3x(in float val); 111 | GNum3 varG3y(in float val); 112 | GNum3 varG3z(in float val); 113 | GNum3 add(in GNum3 a, in GNum3 b); 114 | GNum3 add(in GNum3 a, in float b); 115 | GNum3 add(in float a, in GNum3 b); 116 | GNum3 sub(in GNum3 a, in GNum3 b); 117 | GNum3 sub(in GNum3 a, in float b); 118 | GNum3 sub(in float a, in GNum3 b); 119 | GNum3 mult(in GNum3 a, in GNum3 b); 120 | GNum3 mult(in GNum3 a, in float b); 121 | GNum3 mult(in float a, in GNum3 b); 122 | GNum3 neg(in GNum3 a); 123 | GNum3 div(in GNum3 a, in GNum3 b); 124 | GNum3 div(in GNum3 a, in float b); 125 | GNum3 div(in float a, in GNum3 b); 126 | GNum3 inv(in GNum3 a); 127 | GNum3 a_pow(in GNum3 a, in GNum3 b); 128 | GNum3 a_pow(in GNum3 a, in float b); 129 | GNum3 a_pow(in float a, in GNum3 b); 130 | GNum3 a_ipow(in GNum3 x, in int n); 131 | GNum3 a_min(in GNum3 a, in GNum3 b); 132 | GNum3 a_max(in GNum3 a, in GNum3 b); 133 | GNum3 a_exp2(in GNum3 a); 134 | GNum3 a_inversesqrt(in GNum3 a); 135 | GNum3 a_atan(in GNum3 a); 136 | GNum3 a_sqrt(in GNum3 a); 137 | GNum3 a_sinh(in GNum3 a); 138 | GNum3 a_ceil(in GNum3 a); 139 | GNum3 a_tan(in GNum3 a); 140 | GNum3 a_asinh(in GNum3 a); 141 | GNum3 a_asin(in GNum3 a); 142 | GNum3 a_acosh(in GNum3 a); 143 | GNum3 a_abs(in GNum3 a); 144 | GNum3 a_exp(in GNum3 a); 145 | GNum3 a_cosh(in GNum3 a); 146 | GNum3 a_floor(in GNum3 a); 147 | GNum3 a_log(in GNum3 a); 148 | GNum3 a_atanh(in GNum3 a); 149 | GNum3 a_log2(in GNum3 a); 150 | GNum3 a_acos(in GNum3 a); 151 | GNum3 a_tanh(in GNum3 a); 152 | GNum3 a_cos(in GNum3 a); 153 | GNum3 a_sin(in GNum3 a); 154 | GNum3 a_atan2(in GNum3 y, in GNum3 x); 155 | GNum3 a_atan2(in GNum3 y, in float x); 156 | GNum3 a_atan2(in float y, in GNum3 x); 157 | GNum3 a_mix(in GNum3 a, in GNum3 b, in GNum3 t); 158 | GNum3 a_mix(in GNum3 a, in GNum3 b, in float t); 159 | GNum3 a_mix(in GNum3 a, in float b, in GNum3 t); 160 | GNum3 a_mix(in GNum3 a, in float b, in float t); 161 | GNum3 a_mix(in float a, in GNum3 b, in GNum3 t); 162 | GNum3 a_mix(in float a, in GNum3 b, in float t); 163 | GNum3 a_mix(in float a, in float b, in GNum3 t); 164 | /** 165 | * Creates a constant GNum4 166 | * @param val The current value of the constant 167 | */ 168 | GNum4 constG4(in float val); 169 | GNum4 varG4(in float val, in int index); 170 | GNum4 varG4x(in float val); 171 | GNum4 varG4y(in float val); 172 | GNum4 varG4z(in float val); 173 | GNum4 varG4w(in float val); 174 | GNum4 add(in GNum4 a, in GNum4 b); 175 | GNum4 add(in GNum4 a, in float b); 176 | GNum4 add(in float a, in GNum4 b); 177 | GNum4 sub(in GNum4 a, in GNum4 b); 178 | GNum4 sub(in GNum4 a, in float b); 179 | GNum4 sub(in float a, in GNum4 b); 180 | GNum4 mult(in GNum4 a, in GNum4 b); 181 | GNum4 mult(in GNum4 a, in float b); 182 | GNum4 mult(in float a, in GNum4 b); 183 | GNum4 neg(in GNum4 a); 184 | GNum4 div(in GNum4 a, in GNum4 b); 185 | GNum4 div(in GNum4 a, in float b); 186 | GNum4 div(in float a, in GNum4 b); 187 | GNum4 inv(in GNum4 a); 188 | GNum4 a_pow(in GNum4 a, in GNum4 b); 189 | GNum4 a_pow(in GNum4 a, in float b); 190 | GNum4 a_pow(in float a, in GNum4 b); 191 | GNum4 a_ipow(in GNum4 x, in int n); 192 | GNum4 a_min(in GNum4 a, in GNum4 b); 193 | GNum4 a_max(in GNum4 a, in GNum4 b); 194 | GNum4 a_exp2(in GNum4 a); 195 | GNum4 a_inversesqrt(in GNum4 a); 196 | GNum4 a_atan(in GNum4 a); 197 | GNum4 a_sqrt(in GNum4 a); 198 | GNum4 a_sinh(in GNum4 a); 199 | GNum4 a_ceil(in GNum4 a); 200 | GNum4 a_tan(in GNum4 a); 201 | GNum4 a_asinh(in GNum4 a); 202 | GNum4 a_asin(in GNum4 a); 203 | GNum4 a_acosh(in GNum4 a); 204 | GNum4 a_abs(in GNum4 a); 205 | GNum4 a_exp(in GNum4 a); 206 | GNum4 a_cosh(in GNum4 a); 207 | GNum4 a_floor(in GNum4 a); 208 | GNum4 a_log(in GNum4 a); 209 | GNum4 a_atanh(in GNum4 a); 210 | GNum4 a_log2(in GNum4 a); 211 | GNum4 a_acos(in GNum4 a); 212 | GNum4 a_tanh(in GNum4 a); 213 | GNum4 a_cos(in GNum4 a); 214 | GNum4 a_sin(in GNum4 a); 215 | GNum4 a_atan2(in GNum4 y, in GNum4 x); 216 | GNum4 a_atan2(in GNum4 y, in float x); 217 | GNum4 a_atan2(in float y, in GNum4 x); 218 | GNum4 a_mix(in GNum4 a, in GNum4 b, in GNum4 t); 219 | GNum4 a_mix(in GNum4 a, in GNum4 b, in float t); 220 | GNum4 a_mix(in GNum4 a, in float b, in GNum4 t); 221 | GNum4 a_mix(in GNum4 a, in float b, in float t); 222 | GNum4 a_mix(in float a, in GNum4 b, in GNum4 t); 223 | GNum4 a_mix(in float a, in GNum4 b, in float t); 224 | GNum4 a_mix(in float a, in float b, in GNum4 t); 225 | 226 | //-------------------------------- 227 | // Macros 228 | //-------------------------------- 229 | 230 | #define GRAD2(f,x, y,result) { result = f(varG2x(x), varG2y(y)); } 231 | //-------------------------------- 232 | #define JACOBI2(f1, f2, x, y, result) { GNum2 gradResult; GRAD2(f1, x, y, gradResult); result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; GRAD2(f2, x, y, gradResult); result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; } 233 | //-------------------------------- 234 | #define JACOBI2_VALUE(f1, f2, x, y, result, value) { GNum2 gradResult; GRAD2(f1, x, y, gradResult); value[0] = gradResult.val; result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; GRAD2(f2, x, y, gradResult); value[1] = gradResult.val; result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; } 235 | //-------------------------------- 236 | #define JACOBI32(f1, f2, f3, x, y, result) { GNum2 gradResult; GRAD2(f1, x, y, gradResult); result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; GRAD2(f2, x, y, gradResult); result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; GRAD2(f3, x, y, gradResult); result[0][2] = gradResult.g[0]; result[1][2] = gradResult.g[1]; } 237 | //-------------------------------- 238 | #define JACOBI32_VALUE(f1, f2, f3, x, y, result, value) { GNum2 gradResult; GRAD2(f1, x, y, gradResult); value[0] = gradResult.val; result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; GRAD2(f2, x, y, gradResult); value[1] = gradResult.val; result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; GRAD2(f3, x, y, gradResult); value[2] = gradResult.val; result[0][2] = gradResult.g[0]; result[1][2] = gradResult.g[1]; } 239 | //-------------------------------- 240 | #define JACOBI42(f1, f2, f3, f4, x, y, result) { GNum2 gradResult; GRAD2(f1, x, y, gradResult); result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; GRAD2(f2, x, y, gradResult); result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; GRAD2(f3, x, y, gradResult); result[0][2] = gradResult.g[0]; result[1][2] = gradResult.g[1]; GRAD2(f4, x, y, gradResult); result[0][3] = gradResult.g[0]; result[1][3] = gradResult.g[1]; } 241 | //-------------------------------- 242 | #define JACOBI42_VALUE(f1, f2, f3, f4, x, y, result, value) { GNum2 gradResult; GRAD2(f1, x, y, gradResult); value[0] = gradResult.val; result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; GRAD2(f2, x, y, gradResult); value[1] = gradResult.val; result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; GRAD2(f3, x, y, gradResult); value[2] = gradResult.val; result[0][2] = gradResult.g[0]; result[1][2] = gradResult.g[1]; GRAD2(f4, x, y, gradResult); value[3] = gradResult.val; result[0][3] = gradResult.g[0]; result[1][3] = gradResult.g[1]; } 243 | //-------------------------------- 244 | #define GRAD3(f,x, y, z,result) { result = f(varG3x(x), varG3y(y), varG3z(z)); } 245 | //-------------------------------- 246 | #define JACOBI23(f1, f2, x, y, z, result) { GNum3 gradResult; GRAD3(f1, x, y, z, gradResult); result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; result[2][0] = gradResult.g[2]; GRAD3(f2, x, y, z, gradResult); result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; result[2][1] = gradResult.g[2]; } 247 | //-------------------------------- 248 | #define JACOBI23_VALUE(f1, f2, x, y, z, result, value) { GNum3 gradResult; GRAD3(f1, x, y, z, gradResult); value[0] = gradResult.val; result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; result[2][0] = gradResult.g[2]; GRAD3(f2, x, y, z, gradResult); value[1] = gradResult.val; result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; result[2][1] = gradResult.g[2]; } 249 | //-------------------------------- 250 | #define JACOBI3(f1, f2, f3, x, y, z, result) { GNum3 gradResult; GRAD3(f1, x, y, z, gradResult); result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; result[2][0] = gradResult.g[2]; GRAD3(f2, x, y, z, gradResult); result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; result[2][1] = gradResult.g[2]; GRAD3(f3, x, y, z, gradResult); result[0][2] = gradResult.g[0]; result[1][2] = gradResult.g[1]; result[2][2] = gradResult.g[2]; } 251 | //-------------------------------- 252 | #define JACOBI3_VALUE(f1, f2, f3, x, y, z, result, value) { GNum3 gradResult; GRAD3(f1, x, y, z, gradResult); value[0] = gradResult.val; result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; result[2][0] = gradResult.g[2]; GRAD3(f2, x, y, z, gradResult); value[1] = gradResult.val; result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; result[2][1] = gradResult.g[2]; GRAD3(f3, x, y, z, gradResult); value[2] = gradResult.val; result[0][2] = gradResult.g[0]; result[1][2] = gradResult.g[1]; result[2][2] = gradResult.g[2]; } 253 | //-------------------------------- 254 | #define JACOBI43(f1, f2, f3, f4, x, y, z, result) { GNum3 gradResult; GRAD3(f1, x, y, z, gradResult); result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; result[2][0] = gradResult.g[2]; GRAD3(f2, x, y, z, gradResult); result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; result[2][1] = gradResult.g[2]; GRAD3(f3, x, y, z, gradResult); result[0][2] = gradResult.g[0]; result[1][2] = gradResult.g[1]; result[2][2] = gradResult.g[2]; GRAD3(f4, x, y, z, gradResult); result[0][3] = gradResult.g[0]; result[1][3] = gradResult.g[1]; result[2][3] = gradResult.g[2]; } 255 | //-------------------------------- 256 | #define JACOBI43_VALUE(f1, f2, f3, f4, x, y, z, result, value) { GNum3 gradResult; GRAD3(f1, x, y, z, gradResult); value[0] = gradResult.val; result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; result[2][0] = gradResult.g[2]; GRAD3(f2, x, y, z, gradResult); value[1] = gradResult.val; result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; result[2][1] = gradResult.g[2]; GRAD3(f3, x, y, z, gradResult); value[2] = gradResult.val; result[0][2] = gradResult.g[0]; result[1][2] = gradResult.g[1]; result[2][2] = gradResult.g[2]; GRAD3(f4, x, y, z, gradResult); value[3] = gradResult.val; result[0][3] = gradResult.g[0]; result[1][3] = gradResult.g[1]; result[2][3] = gradResult.g[2]; } 257 | //-------------------------------- 258 | #define GRAD4(f,x, y, z, w,result) { result = f(varG4x(x), varG4y(y), varG4z(z), varG4w(w)); } 259 | //-------------------------------- 260 | #define JACOBI24(f1, f2, x, y, z, w, result) { GNum4 gradResult; GRAD4(f1, x, y, z, w, gradResult); result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; result[2][0] = gradResult.g[2]; result[3][0] = gradResult.g[3]; GRAD4(f2, x, y, z, w, gradResult); result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; result[2][1] = gradResult.g[2]; result[3][1] = gradResult.g[3]; } 261 | //-------------------------------- 262 | #define JACOBI24_VALUE(f1, f2, x, y, z, w, result, value) { GNum4 gradResult; GRAD4(f1, x, y, z, w, gradResult); value[0] = gradResult.val; result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; result[2][0] = gradResult.g[2]; result[3][0] = gradResult.g[3]; GRAD4(f2, x, y, z, w, gradResult); value[1] = gradResult.val; result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; result[2][1] = gradResult.g[2]; result[3][1] = gradResult.g[3]; } 263 | //-------------------------------- 264 | #define JACOBI34(f1, f2, f3, x, y, z, w, result) { GNum4 gradResult; GRAD4(f1, x, y, z, w, gradResult); result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; result[2][0] = gradResult.g[2]; result[3][0] = gradResult.g[3]; GRAD4(f2, x, y, z, w, gradResult); result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; result[2][1] = gradResult.g[2]; result[3][1] = gradResult.g[3]; GRAD4(f3, x, y, z, w, gradResult); result[0][2] = gradResult.g[0]; result[1][2] = gradResult.g[1]; result[2][2] = gradResult.g[2]; result[3][2] = gradResult.g[3]; } 265 | //-------------------------------- 266 | #define JACOBI34_VALUE(f1, f2, f3, x, y, z, w, result, value) { GNum4 gradResult; GRAD4(f1, x, y, z, w, gradResult); value[0] = gradResult.val; result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; result[2][0] = gradResult.g[2]; result[3][0] = gradResult.g[3]; GRAD4(f2, x, y, z, w, gradResult); value[1] = gradResult.val; result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; result[2][1] = gradResult.g[2]; result[3][1] = gradResult.g[3]; GRAD4(f3, x, y, z, w, gradResult); value[2] = gradResult.val; result[0][2] = gradResult.g[0]; result[1][2] = gradResult.g[1]; result[2][2] = gradResult.g[2]; result[3][2] = gradResult.g[3]; } 267 | //-------------------------------- 268 | #define JACOBI4(f1, f2, f3, f4, x, y, z, w, result) { GNum4 gradResult; GRAD4(f1, x, y, z, w, gradResult); result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; result[2][0] = gradResult.g[2]; result[3][0] = gradResult.g[3]; GRAD4(f2, x, y, z, w, gradResult); result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; result[2][1] = gradResult.g[2]; result[3][1] = gradResult.g[3]; GRAD4(f3, x, y, z, w, gradResult); result[0][2] = gradResult.g[0]; result[1][2] = gradResult.g[1]; result[2][2] = gradResult.g[2]; result[3][2] = gradResult.g[3]; GRAD4(f4, x, y, z, w, gradResult); result[0][3] = gradResult.g[0]; result[1][3] = gradResult.g[1]; result[2][3] = gradResult.g[2]; result[3][3] = gradResult.g[3]; } 269 | //-------------------------------- 270 | #define JACOBI4_VALUE(f1, f2, f3, f4, x, y, z, w, result, value) { GNum4 gradResult; GRAD4(f1, x, y, z, w, gradResult); value[0] = gradResult.val; result[0][0] = gradResult.g[0]; result[1][0] = gradResult.g[1]; result[2][0] = gradResult.g[2]; result[3][0] = gradResult.g[3]; GRAD4(f2, x, y, z, w, gradResult); value[1] = gradResult.val; result[0][1] = gradResult.g[0]; result[1][1] = gradResult.g[1]; result[2][1] = gradResult.g[2]; result[3][1] = gradResult.g[3]; GRAD4(f3, x, y, z, w, gradResult); value[2] = gradResult.val; result[0][2] = gradResult.g[0]; result[1][2] = gradResult.g[1]; result[2][2] = gradResult.g[2]; result[3][2] = gradResult.g[3]; GRAD4(f4, x, y, z, w, gradResult); value[3] = gradResult.val; result[0][3] = gradResult.g[0]; result[1][3] = gradResult.g[1]; result[2][3] = gradResult.g[2]; result[3][3] = gradResult.g[3]; } 271 | 272 | //-------------------------------- 273 | // Implementation 274 | //-------------------------------- 275 | 276 | GNum2 constG2(in float val) 277 | { 278 | return GNum2(val, vec2(0.0)); 279 | } 280 | //-------------------------------- 281 | GNum2 varG2(in float val, in int index) 282 | { 283 | vec2 g = vec2(0.0); 284 | g[index] = 1.0; 285 | return GNum2(val, g); 286 | } 287 | //-------------------------------- 288 | GNum2 varG2x(in float val) 289 | { 290 | vec2 g = vec2(0.0); 291 | g[0] = 1.0; 292 | return GNum2(val, g); 293 | } 294 | //-------------------------------- 295 | GNum2 varG2y(in float val) 296 | { 297 | vec2 g = vec2(0.0); 298 | g[1] = 1.0; 299 | return GNum2(val, g); 300 | } 301 | //-------------------------------- 302 | GNum2 add(in GNum2 a, in GNum2 b) 303 | { 304 | return GNum2(a.val + b.val, a.g + b.g); 305 | } 306 | //-------------------------------- 307 | GNum2 add(in GNum2 a, in float b) 308 | { 309 | return GNum2(a.val + b, a.g); 310 | } 311 | //-------------------------------- 312 | GNum2 add(in float a, in GNum2 b) 313 | { 314 | return GNum2(a + b.val, b.g); 315 | } 316 | //-------------------------------- 317 | GNum2 sub(in GNum2 a, in GNum2 b) 318 | { 319 | return GNum2(a.val - b.val, a.g - b.g); 320 | } 321 | //-------------------------------- 322 | GNum2 sub(in GNum2 a, in float b) 323 | { 324 | return GNum2(a.val - b, a.g); 325 | } 326 | //-------------------------------- 327 | GNum2 sub(in float a, in GNum2 b) 328 | { 329 | return GNum2(a - b.val, -b.g); 330 | } 331 | //-------------------------------- 332 | GNum2 mult(in GNum2 a, in GNum2 b) 333 | { 334 | return GNum2(a.val * b.val, 335 | a.val*b.g + b.val*a.g 336 | ); 337 | } 338 | //-------------------------------- 339 | GNum2 mult(in GNum2 a, in float b) 340 | { 341 | return GNum2(a.val * b, b*a.g); 342 | } 343 | //-------------------------------- 344 | GNum2 mult(in float a, in GNum2 b) 345 | { 346 | return GNum2(a * b.val, a*b.g); 347 | } 348 | //-------------------------------- 349 | GNum2 neg(in GNum2 a) 350 | { 351 | return mult(-1.0,a); 352 | } 353 | //-------------------------------- 354 | GNum2 div(in GNum2 a, in GNum2 b) 355 | { 356 | float b1 = b.val; 357 | float b2 = b1*b1; 358 | 359 | return GNum2(a.val / b.val , 360 | (b.val*a.g - a.val*b.g)/b2 361 | ); 362 | } 363 | //-------------------------------- 364 | GNum2 div(in GNum2 a, in float b) 365 | { 366 | return GNum2(a.val / b, a.g/b); 367 | } 368 | //-------------------------------- 369 | GNum2 div(in float a, in GNum2 b) 370 | { 371 | float b1 = b.val; 372 | float b2 = b1*b1; 373 | 374 | return GNum2(a / b.val, 375 | -a*b.g/b2 376 | ); 377 | } 378 | //-------------------------------- 379 | GNum2 inv(in GNum2 a) 380 | { 381 | return div(1.0, a); 382 | } 383 | //-------------------------------- 384 | GNum2 a_pow(in GNum2 a, in GNum2 b) 385 | { 386 | return a_exp(mult(b,a_log(a))); 387 | } 388 | //-------------------------------- 389 | GNum2 a_pow(in GNum2 a, in float b) 390 | { 391 | // constant exponent -> make special case 392 | float v = pow(a.val, b); // value f(a(x)) 393 | float da = b*pow(a.val,b-1.0); // first derivative f'(a(x)) 394 | return GNum2(v , da * a.g); 395 | } 396 | //-------------------------------- 397 | GNum2 a_pow(in float a, in GNum2 b) 398 | { 399 | return a_exp(mult(b,log(a))); 400 | } 401 | //-------------------------------- 402 | GNum2 a_ipow(in GNum2 x, in int n) 403 | { 404 | // based on https://en.wikipedia.org/wiki/Exponentiation_by_squaring 405 | if (n < 0) 406 | { 407 | x = div(1.0,x); 408 | n = -n; 409 | } 410 | if (n == 0) 411 | { 412 | return constG2(1.0); 413 | } 414 | GNum2 y = constG2(1.0); 415 | while (n > 1) 416 | { 417 | if (n % 2 == 0) 418 | { 419 | x = mult(x,x); 420 | 421 | } 422 | else 423 | { 424 | y = mult(x, y); 425 | x = mult(x, x); 426 | } 427 | 428 | n = n / 2; 429 | } 430 | 431 | return mult(x, y); 432 | } 433 | 434 | //-------------------------------- 435 | GNum2 a_min(in GNum2 a, in GNum2 b) 436 | { 437 | if(a.val < b.val) 438 | { 439 | return a; 440 | } 441 | return b; 442 | } 443 | //-------------------------------- 444 | GNum2 a_max(in GNum2 a, in GNum2 b) 445 | { 446 | if(a.val > b.val) 447 | { 448 | return a; 449 | } 450 | return b; 451 | } 452 | //-------------------------------- 453 | GNum2 a_exp2(in GNum2 a) 454 | { 455 | float v = exp2(a.val); // value f(a(x)) 456 | float da = log(2.0)*exp2(a.val); // first derivative f'(a(x)) 457 | 458 | return GNum2(v , da * a.g); 459 | } 460 | //-------------------------------- 461 | GNum2 a_inversesqrt(in GNum2 a) 462 | { 463 | float v = inversesqrt(a.val); // value f(a(x)) 464 | float da = -0.5/pow(sqrt(a.val),3.0); // first derivative f'(a(x)) 465 | 466 | return GNum2(v , da * a.g); 467 | } 468 | //-------------------------------- 469 | GNum2 a_atan(in GNum2 a) 470 | { 471 | float v = atan(a.val); // value f(a(x)) 472 | float da = 1.0/(1.0 + a.val * a.val); // first derivative f'(a(x)) 473 | 474 | return GNum2(v , da * a.g); 475 | } 476 | //-------------------------------- 477 | GNum2 a_sqrt(in GNum2 a) 478 | { 479 | float v = sqrt(a.val); // value f(a(x)) 480 | float da = 0.5/sqrt(a.val); // first derivative f'(a(x)) 481 | 482 | return GNum2(v , da * a.g); 483 | } 484 | //-------------------------------- 485 | GNum2 a_sinh(in GNum2 a) 486 | { 487 | float v = sinh(a.val); // value f(a(x)) 488 | float da = cosh(a.val); // first derivative f'(a(x)) 489 | 490 | return GNum2(v , da * a.g); 491 | } 492 | //-------------------------------- 493 | GNum2 a_ceil(in GNum2 a) 494 | { 495 | float v = ceil(a.val); // value f(a(x)) 496 | float da = 0.0; // first derivative f'(a(x)) 497 | 498 | return GNum2(v , da * a.g); 499 | } 500 | //-------------------------------- 501 | GNum2 a_tan(in GNum2 a) 502 | { 503 | float v = tan(a.val); // value f(a(x)) 504 | float da = 1.0 + pow(tan(a.val),2.0); // first derivative f'(a(x)) 505 | 506 | return GNum2(v , da * a.g); 507 | } 508 | //-------------------------------- 509 | GNum2 a_asinh(in GNum2 a) 510 | { 511 | float v = asinh(a.val); // value f(a(x)) 512 | float da = 1.0/sqrt(1.0 + a.val * a.val); // first derivative f'(a(x)) 513 | 514 | return GNum2(v , da * a.g); 515 | } 516 | //-------------------------------- 517 | GNum2 a_asin(in GNum2 a) 518 | { 519 | float v = asin(a.val); // value f(a(x)) 520 | float da = 1.0/sqrt(1.0 - a.val * a.val); // first derivative f'(a(x)) 521 | 522 | return GNum2(v , da * a.g); 523 | } 524 | //-------------------------------- 525 | GNum2 a_acosh(in GNum2 a) 526 | { 527 | float v = acosh(a.val); // value f(a(x)) 528 | float da = 1.0/sqrt(-1.0 + a.val * a.val); // first derivative f'(a(x)) 529 | 530 | return GNum2(v , da * a.g); 531 | } 532 | //-------------------------------- 533 | GNum2 a_abs(in GNum2 a) 534 | { 535 | float v = abs(a.val); // value f(a(x)) 536 | float da = a.val < 0.0 ? -1.0 : 1.0; // first derivative f'(a(x)) 537 | 538 | return GNum2(v , da * a.g); 539 | } 540 | //-------------------------------- 541 | GNum2 a_exp(in GNum2 a) 542 | { 543 | float v = exp(a.val); // value f(a(x)) 544 | float da = exp(a.val); // first derivative f'(a(x)) 545 | 546 | return GNum2(v , da * a.g); 547 | } 548 | //-------------------------------- 549 | GNum2 a_cosh(in GNum2 a) 550 | { 551 | float v = cosh(a.val); // value f(a(x)) 552 | float da = sinh(a.val); // first derivative f'(a(x)) 553 | 554 | return GNum2(v , da * a.g); 555 | } 556 | //-------------------------------- 557 | GNum2 a_floor(in GNum2 a) 558 | { 559 | float v = floor(a.val); // value f(a(x)) 560 | float da = 0.0; // first derivative f'(a(x)) 561 | 562 | return GNum2(v , da * a.g); 563 | } 564 | //-------------------------------- 565 | GNum2 a_log(in GNum2 a) 566 | { 567 | float v = log(a.val); // value f(a(x)) 568 | float da = 1.0/a.val; // first derivative f'(a(x)) 569 | 570 | return GNum2(v , da * a.g); 571 | } 572 | //-------------------------------- 573 | GNum2 a_atanh(in GNum2 a) 574 | { 575 | float v = atanh(a.val); // value f(a(x)) 576 | float da = 1.0/(1.0 - a.val * a.val); // first derivative f'(a(x)) 577 | 578 | return GNum2(v , da * a.g); 579 | } 580 | //-------------------------------- 581 | GNum2 a_log2(in GNum2 a) 582 | { 583 | float v = log2(a.val); // value f(a(x)) 584 | float da = 1.0/(a.val * log(2.0)); // first derivative f'(a(x)) 585 | 586 | return GNum2(v , da * a.g); 587 | } 588 | //-------------------------------- 589 | GNum2 a_acos(in GNum2 a) 590 | { 591 | float v = acos(a.val); // value f(a(x)) 592 | float da = -1.0/sqrt(1.0 - a.val * a.val); // first derivative f'(a(x)) 593 | 594 | return GNum2(v , da * a.g); 595 | } 596 | //-------------------------------- 597 | GNum2 a_tanh(in GNum2 a) 598 | { 599 | float v = tanh(a.val); // value f(a(x)) 600 | float da = 1.0 - pow(tanh(a.val),2.0); // first derivative f'(a(x)) 601 | 602 | return GNum2(v , da * a.g); 603 | } 604 | //-------------------------------- 605 | GNum2 a_cos(in GNum2 a) 606 | { 607 | float v = cos(a.val); // value f(a(x)) 608 | float da = -sin(a.val); // first derivative f'(a(x)) 609 | 610 | return GNum2(v , da * a.g); 611 | } 612 | //-------------------------------- 613 | GNum2 a_sin(in GNum2 a) 614 | { 615 | float v = sin(a.val); // value f(a(x)) 616 | float da = cos(a.val); // first derivative f'(a(x)) 617 | 618 | return GNum2(v , da * a.g); 619 | } 620 | //-------------------------------- 621 | GNum2 a_atan2(in GNum2 y, in GNum2 x) 622 | { 623 | const float pi = 3.14159265; 624 | // from https://en.wikipedia.org/wiki/Atan2 625 | if(x.val > 0.0) 626 | { 627 | GNum2 n = a_sqrt(add(mult(x,x),mult(y,y))); 628 | GNum2 inner = div(y, add(n,x)); 629 | 630 | return mult(2.0,a_atan(inner)); 631 | 632 | }else if(x.val <= 0.0 && abs(y.val) > 1E-6) 633 | { 634 | GNum2 n = a_sqrt(add(mult(x,x),mult(y,y))); 635 | GNum2 inner = div(sub(n,x),y); 636 | return mult(2.0,a_atan(inner)); 637 | }else if(x.val < 0.0 && abs(y.val) <= 1E-6) 638 | { 639 | return constG2(pi); 640 | } 641 | // return 0 for undefined 642 | return constG2(0.0); 643 | } 644 | //-------------------------------- 645 | GNum2 a_atan2(in GNum2 y, in float x) 646 | { 647 | return a_atan2(y,constG2(x)); 648 | } 649 | //-------------------------------- 650 | GNum2 a_atan2(in float y, in GNum2 x) 651 | { 652 | return a_atan2(constG2(y),x); 653 | } 654 | //-------------------------------- 655 | GNum2 a_mix(in GNum2 a, in GNum2 b, in GNum2 t) 656 | { 657 | return add(mult(a, sub(1.0, t)), mult(b, t)); 658 | } 659 | 660 | //-------------------------------- 661 | GNum2 a_mix(in GNum2 a, in GNum2 b, in float t) 662 | { 663 | return add(mult(a, 1.0 - t), mult(b, t)); 664 | } 665 | 666 | //-------------------------------- 667 | GNum2 a_mix(in GNum2 a, in float b, in GNum2 t) 668 | { 669 | return add(mult(a, sub(1.0, t)), mult(b, t)); 670 | } 671 | 672 | //-------------------------------- 673 | GNum2 a_mix(in GNum2 a, in float b, in float t) 674 | { 675 | return add(mult(a, 1.0 - t), b*t); 676 | } 677 | 678 | //-------------------------------- 679 | GNum2 a_mix(in float a, in GNum2 b, in GNum2 t) 680 | { 681 | return add(mult(a, sub(1.0, t)), mult(b, t)); 682 | } 683 | 684 | //-------------------------------- 685 | GNum2 a_mix(in float a, in GNum2 b, in float t) 686 | { 687 | return add(a * (1.0 - t), mult(b, t)); 688 | } 689 | 690 | //-------------------------------- 691 | GNum2 a_mix(in float a, in float b, in GNum2 t) 692 | { 693 | return add(mult(a, sub(1.0, t)), mult(b, t)); 694 | } 695 | 696 | //-------------------------------- 697 | GNum3 constG3(in float val) 698 | { 699 | return GNum3(val, vec3(0.0)); 700 | } 701 | //-------------------------------- 702 | GNum3 varG3(in float val, in int index) 703 | { 704 | vec3 g = vec3(0.0); 705 | g[index] = 1.0; 706 | return GNum3(val, g); 707 | } 708 | //-------------------------------- 709 | GNum3 varG3x(in float val) 710 | { 711 | vec3 g = vec3(0.0); 712 | g[0] = 1.0; 713 | return GNum3(val, g); 714 | } 715 | //-------------------------------- 716 | GNum3 varG3y(in float val) 717 | { 718 | vec3 g = vec3(0.0); 719 | g[1] = 1.0; 720 | return GNum3(val, g); 721 | } 722 | //-------------------------------- 723 | GNum3 varG3z(in float val) 724 | { 725 | vec3 g = vec3(0.0); 726 | g[2] = 1.0; 727 | return GNum3(val, g); 728 | } 729 | //-------------------------------- 730 | GNum3 add(in GNum3 a, in GNum3 b) 731 | { 732 | return GNum3(a.val + b.val, a.g + b.g); 733 | } 734 | //-------------------------------- 735 | GNum3 add(in GNum3 a, in float b) 736 | { 737 | return GNum3(a.val + b, a.g); 738 | } 739 | //-------------------------------- 740 | GNum3 add(in float a, in GNum3 b) 741 | { 742 | return GNum3(a + b.val, b.g); 743 | } 744 | //-------------------------------- 745 | GNum3 sub(in GNum3 a, in GNum3 b) 746 | { 747 | return GNum3(a.val - b.val, a.g - b.g); 748 | } 749 | //-------------------------------- 750 | GNum3 sub(in GNum3 a, in float b) 751 | { 752 | return GNum3(a.val - b, a.g); 753 | } 754 | //-------------------------------- 755 | GNum3 sub(in float a, in GNum3 b) 756 | { 757 | return GNum3(a - b.val, -b.g); 758 | } 759 | //-------------------------------- 760 | GNum3 mult(in GNum3 a, in GNum3 b) 761 | { 762 | return GNum3(a.val * b.val, 763 | a.val*b.g + b.val*a.g 764 | ); 765 | } 766 | //-------------------------------- 767 | GNum3 mult(in GNum3 a, in float b) 768 | { 769 | return GNum3(a.val * b, b*a.g); 770 | } 771 | //-------------------------------- 772 | GNum3 mult(in float a, in GNum3 b) 773 | { 774 | return GNum3(a * b.val, a*b.g); 775 | } 776 | //-------------------------------- 777 | GNum3 neg(in GNum3 a) 778 | { 779 | return mult(-1.0,a); 780 | } 781 | //-------------------------------- 782 | GNum3 div(in GNum3 a, in GNum3 b) 783 | { 784 | float b1 = b.val; 785 | float b2 = b1*b1; 786 | 787 | return GNum3(a.val / b.val , 788 | (b.val*a.g - a.val*b.g)/b2 789 | ); 790 | } 791 | //-------------------------------- 792 | GNum3 div(in GNum3 a, in float b) 793 | { 794 | return GNum3(a.val / b, a.g/b); 795 | } 796 | //-------------------------------- 797 | GNum3 div(in float a, in GNum3 b) 798 | { 799 | float b1 = b.val; 800 | float b2 = b1*b1; 801 | 802 | return GNum3(a / b.val, 803 | -a*b.g/b2 804 | ); 805 | } 806 | //-------------------------------- 807 | GNum3 inv(in GNum3 a) 808 | { 809 | return div(1.0, a); 810 | } 811 | //-------------------------------- 812 | GNum3 a_pow(in GNum3 a, in GNum3 b) 813 | { 814 | return a_exp(mult(b,a_log(a))); 815 | } 816 | //-------------------------------- 817 | GNum3 a_pow(in GNum3 a, in float b) 818 | { 819 | // constant exponent -> make special case 820 | float v = pow(a.val, b); // value f(a(x)) 821 | float da = b*pow(a.val,b-1.0); // first derivative f'(a(x)) 822 | return GNum3(v , da * a.g); 823 | } 824 | //-------------------------------- 825 | GNum3 a_pow(in float a, in GNum3 b) 826 | { 827 | return a_exp(mult(b,log(a))); 828 | } 829 | //-------------------------------- 830 | GNum3 a_ipow(in GNum3 x, in int n) 831 | { 832 | // based on https://en.wikipedia.org/wiki/Exponentiation_by_squaring 833 | if (n < 0) 834 | { 835 | x = div(1.0,x); 836 | n = -n; 837 | } 838 | if (n == 0) 839 | { 840 | return constG3(1.0); 841 | } 842 | GNum3 y = constG3(1.0); 843 | while (n > 1) 844 | { 845 | if (n % 2 == 0) 846 | { 847 | x = mult(x,x); 848 | 849 | } 850 | else 851 | { 852 | y = mult(x, y); 853 | x = mult(x, x); 854 | } 855 | 856 | n = n / 2; 857 | } 858 | 859 | return mult(x, y); 860 | } 861 | 862 | //-------------------------------- 863 | GNum3 a_min(in GNum3 a, in GNum3 b) 864 | { 865 | if(a.val < b.val) 866 | { 867 | return a; 868 | } 869 | return b; 870 | } 871 | //-------------------------------- 872 | GNum3 a_max(in GNum3 a, in GNum3 b) 873 | { 874 | if(a.val > b.val) 875 | { 876 | return a; 877 | } 878 | return b; 879 | } 880 | //-------------------------------- 881 | GNum3 a_exp2(in GNum3 a) 882 | { 883 | float v = exp2(a.val); // value f(a(x)) 884 | float da = log(2.0)*exp2(a.val); // first derivative f'(a(x)) 885 | 886 | return GNum3(v , da * a.g); 887 | } 888 | //-------------------------------- 889 | GNum3 a_inversesqrt(in GNum3 a) 890 | { 891 | float v = inversesqrt(a.val); // value f(a(x)) 892 | float da = -0.5/pow(sqrt(a.val),3.0); // first derivative f'(a(x)) 893 | 894 | return GNum3(v , da * a.g); 895 | } 896 | //-------------------------------- 897 | GNum3 a_atan(in GNum3 a) 898 | { 899 | float v = atan(a.val); // value f(a(x)) 900 | float da = 1.0/(1.0 + a.val * a.val); // first derivative f'(a(x)) 901 | 902 | return GNum3(v , da * a.g); 903 | } 904 | //-------------------------------- 905 | GNum3 a_sqrt(in GNum3 a) 906 | { 907 | float v = sqrt(a.val); // value f(a(x)) 908 | float da = 0.5/sqrt(a.val); // first derivative f'(a(x)) 909 | 910 | return GNum3(v , da * a.g); 911 | } 912 | //-------------------------------- 913 | GNum3 a_sinh(in GNum3 a) 914 | { 915 | float v = sinh(a.val); // value f(a(x)) 916 | float da = cosh(a.val); // first derivative f'(a(x)) 917 | 918 | return GNum3(v , da * a.g); 919 | } 920 | //-------------------------------- 921 | GNum3 a_ceil(in GNum3 a) 922 | { 923 | float v = ceil(a.val); // value f(a(x)) 924 | float da = 0.0; // first derivative f'(a(x)) 925 | 926 | return GNum3(v , da * a.g); 927 | } 928 | //-------------------------------- 929 | GNum3 a_tan(in GNum3 a) 930 | { 931 | float v = tan(a.val); // value f(a(x)) 932 | float da = 1.0 + pow(tan(a.val),2.0); // first derivative f'(a(x)) 933 | 934 | return GNum3(v , da * a.g); 935 | } 936 | //-------------------------------- 937 | GNum3 a_asinh(in GNum3 a) 938 | { 939 | float v = asinh(a.val); // value f(a(x)) 940 | float da = 1.0/sqrt(1.0 + a.val * a.val); // first derivative f'(a(x)) 941 | 942 | return GNum3(v , da * a.g); 943 | } 944 | //-------------------------------- 945 | GNum3 a_asin(in GNum3 a) 946 | { 947 | float v = asin(a.val); // value f(a(x)) 948 | float da = 1.0/sqrt(1.0 - a.val * a.val); // first derivative f'(a(x)) 949 | 950 | return GNum3(v , da * a.g); 951 | } 952 | //-------------------------------- 953 | GNum3 a_acosh(in GNum3 a) 954 | { 955 | float v = acosh(a.val); // value f(a(x)) 956 | float da = 1.0/sqrt(-1.0 + a.val * a.val); // first derivative f'(a(x)) 957 | 958 | return GNum3(v , da * a.g); 959 | } 960 | //-------------------------------- 961 | GNum3 a_abs(in GNum3 a) 962 | { 963 | float v = abs(a.val); // value f(a(x)) 964 | float da = a.val < 0.0 ? -1.0 : 1.0; // first derivative f'(a(x)) 965 | 966 | return GNum3(v , da * a.g); 967 | } 968 | //-------------------------------- 969 | GNum3 a_exp(in GNum3 a) 970 | { 971 | float v = exp(a.val); // value f(a(x)) 972 | float da = exp(a.val); // first derivative f'(a(x)) 973 | 974 | return GNum3(v , da * a.g); 975 | } 976 | //-------------------------------- 977 | GNum3 a_cosh(in GNum3 a) 978 | { 979 | float v = cosh(a.val); // value f(a(x)) 980 | float da = sinh(a.val); // first derivative f'(a(x)) 981 | 982 | return GNum3(v , da * a.g); 983 | } 984 | //-------------------------------- 985 | GNum3 a_floor(in GNum3 a) 986 | { 987 | float v = floor(a.val); // value f(a(x)) 988 | float da = 0.0; // first derivative f'(a(x)) 989 | 990 | return GNum3(v , da * a.g); 991 | } 992 | //-------------------------------- 993 | GNum3 a_log(in GNum3 a) 994 | { 995 | float v = log(a.val); // value f(a(x)) 996 | float da = 1.0/a.val; // first derivative f'(a(x)) 997 | 998 | return GNum3(v , da * a.g); 999 | } 1000 | //-------------------------------- 1001 | GNum3 a_atanh(in GNum3 a) 1002 | { 1003 | float v = atanh(a.val); // value f(a(x)) 1004 | float da = 1.0/(1.0 - a.val * a.val); // first derivative f'(a(x)) 1005 | 1006 | return GNum3(v , da * a.g); 1007 | } 1008 | //-------------------------------- 1009 | GNum3 a_log2(in GNum3 a) 1010 | { 1011 | float v = log2(a.val); // value f(a(x)) 1012 | float da = 1.0/(a.val * log(2.0)); // first derivative f'(a(x)) 1013 | 1014 | return GNum3(v , da * a.g); 1015 | } 1016 | //-------------------------------- 1017 | GNum3 a_acos(in GNum3 a) 1018 | { 1019 | float v = acos(a.val); // value f(a(x)) 1020 | float da = -1.0/sqrt(1.0 - a.val * a.val); // first derivative f'(a(x)) 1021 | 1022 | return GNum3(v , da * a.g); 1023 | } 1024 | //-------------------------------- 1025 | GNum3 a_tanh(in GNum3 a) 1026 | { 1027 | float v = tanh(a.val); // value f(a(x)) 1028 | float da = 1.0 - pow(tanh(a.val),2.0); // first derivative f'(a(x)) 1029 | 1030 | return GNum3(v , da * a.g); 1031 | } 1032 | //-------------------------------- 1033 | GNum3 a_cos(in GNum3 a) 1034 | { 1035 | float v = cos(a.val); // value f(a(x)) 1036 | float da = -sin(a.val); // first derivative f'(a(x)) 1037 | 1038 | return GNum3(v , da * a.g); 1039 | } 1040 | //-------------------------------- 1041 | GNum3 a_sin(in GNum3 a) 1042 | { 1043 | float v = sin(a.val); // value f(a(x)) 1044 | float da = cos(a.val); // first derivative f'(a(x)) 1045 | 1046 | return GNum3(v , da * a.g); 1047 | } 1048 | //-------------------------------- 1049 | GNum3 a_atan2(in GNum3 y, in GNum3 x) 1050 | { 1051 | const float pi = 3.14159265; 1052 | // from https://en.wikipedia.org/wiki/Atan2 1053 | if(x.val > 0.0) 1054 | { 1055 | GNum3 n = a_sqrt(add(mult(x,x),mult(y,y))); 1056 | GNum3 inner = div(y, add(n,x)); 1057 | 1058 | return mult(2.0,a_atan(inner)); 1059 | 1060 | }else if(x.val <= 0.0 && abs(y.val) > 1E-6) 1061 | { 1062 | GNum3 n = a_sqrt(add(mult(x,x),mult(y,y))); 1063 | GNum3 inner = div(sub(n,x),y); 1064 | return mult(2.0,a_atan(inner)); 1065 | }else if(x.val < 0.0 && abs(y.val) <= 1E-6) 1066 | { 1067 | return constG3(pi); 1068 | } 1069 | // return 0 for undefined 1070 | return constG3(0.0); 1071 | } 1072 | //-------------------------------- 1073 | GNum3 a_atan2(in GNum3 y, in float x) 1074 | { 1075 | return a_atan2(y,constG3(x)); 1076 | } 1077 | //-------------------------------- 1078 | GNum3 a_atan2(in float y, in GNum3 x) 1079 | { 1080 | return a_atan2(constG3(y),x); 1081 | } 1082 | //-------------------------------- 1083 | GNum3 a_mix(in GNum3 a, in GNum3 b, in GNum3 t) 1084 | { 1085 | return add(mult(a, sub(1.0, t)), mult(b, t)); 1086 | } 1087 | 1088 | //-------------------------------- 1089 | GNum3 a_mix(in GNum3 a, in GNum3 b, in float t) 1090 | { 1091 | return add(mult(a, 1.0 - t), mult(b, t)); 1092 | } 1093 | 1094 | //-------------------------------- 1095 | GNum3 a_mix(in GNum3 a, in float b, in GNum3 t) 1096 | { 1097 | return add(mult(a, sub(1.0, t)), mult(b, t)); 1098 | } 1099 | 1100 | //-------------------------------- 1101 | GNum3 a_mix(in GNum3 a, in float b, in float t) 1102 | { 1103 | return add(mult(a, 1.0 - t), b*t); 1104 | } 1105 | 1106 | //-------------------------------- 1107 | GNum3 a_mix(in float a, in GNum3 b, in GNum3 t) 1108 | { 1109 | return add(mult(a, sub(1.0, t)), mult(b, t)); 1110 | } 1111 | 1112 | //-------------------------------- 1113 | GNum3 a_mix(in float a, in GNum3 b, in float t) 1114 | { 1115 | return add(a * (1.0 - t), mult(b, t)); 1116 | } 1117 | 1118 | //-------------------------------- 1119 | GNum3 a_mix(in float a, in float b, in GNum3 t) 1120 | { 1121 | return add(mult(a, sub(1.0, t)), mult(b, t)); 1122 | } 1123 | 1124 | //-------------------------------- 1125 | GNum4 constG4(in float val) 1126 | { 1127 | return GNum4(val, vec4(0.0)); 1128 | } 1129 | //-------------------------------- 1130 | GNum4 varG4(in float val, in int index) 1131 | { 1132 | vec4 g = vec4(0.0); 1133 | g[index] = 1.0; 1134 | return GNum4(val, g); 1135 | } 1136 | //-------------------------------- 1137 | GNum4 varG4x(in float val) 1138 | { 1139 | vec4 g = vec4(0.0); 1140 | g[0] = 1.0; 1141 | return GNum4(val, g); 1142 | } 1143 | //-------------------------------- 1144 | GNum4 varG4y(in float val) 1145 | { 1146 | vec4 g = vec4(0.0); 1147 | g[1] = 1.0; 1148 | return GNum4(val, g); 1149 | } 1150 | //-------------------------------- 1151 | GNum4 varG4z(in float val) 1152 | { 1153 | vec4 g = vec4(0.0); 1154 | g[2] = 1.0; 1155 | return GNum4(val, g); 1156 | } 1157 | //-------------------------------- 1158 | GNum4 varG4w(in float val) 1159 | { 1160 | vec4 g = vec4(0.0); 1161 | g[3] = 1.0; 1162 | return GNum4(val, g); 1163 | } 1164 | //-------------------------------- 1165 | GNum4 add(in GNum4 a, in GNum4 b) 1166 | { 1167 | return GNum4(a.val + b.val, a.g + b.g); 1168 | } 1169 | //-------------------------------- 1170 | GNum4 add(in GNum4 a, in float b) 1171 | { 1172 | return GNum4(a.val + b, a.g); 1173 | } 1174 | //-------------------------------- 1175 | GNum4 add(in float a, in GNum4 b) 1176 | { 1177 | return GNum4(a + b.val, b.g); 1178 | } 1179 | //-------------------------------- 1180 | GNum4 sub(in GNum4 a, in GNum4 b) 1181 | { 1182 | return GNum4(a.val - b.val, a.g - b.g); 1183 | } 1184 | //-------------------------------- 1185 | GNum4 sub(in GNum4 a, in float b) 1186 | { 1187 | return GNum4(a.val - b, a.g); 1188 | } 1189 | //-------------------------------- 1190 | GNum4 sub(in float a, in GNum4 b) 1191 | { 1192 | return GNum4(a - b.val, -b.g); 1193 | } 1194 | //-------------------------------- 1195 | GNum4 mult(in GNum4 a, in GNum4 b) 1196 | { 1197 | return GNum4(a.val * b.val, 1198 | a.val*b.g + b.val*a.g 1199 | ); 1200 | } 1201 | //-------------------------------- 1202 | GNum4 mult(in GNum4 a, in float b) 1203 | { 1204 | return GNum4(a.val * b, b*a.g); 1205 | } 1206 | //-------------------------------- 1207 | GNum4 mult(in float a, in GNum4 b) 1208 | { 1209 | return GNum4(a * b.val, a*b.g); 1210 | } 1211 | //-------------------------------- 1212 | GNum4 neg(in GNum4 a) 1213 | { 1214 | return mult(-1.0,a); 1215 | } 1216 | //-------------------------------- 1217 | GNum4 div(in GNum4 a, in GNum4 b) 1218 | { 1219 | float b1 = b.val; 1220 | float b2 = b1*b1; 1221 | 1222 | return GNum4(a.val / b.val , 1223 | (b.val*a.g - a.val*b.g)/b2 1224 | ); 1225 | } 1226 | //-------------------------------- 1227 | GNum4 div(in GNum4 a, in float b) 1228 | { 1229 | return GNum4(a.val / b, a.g/b); 1230 | } 1231 | //-------------------------------- 1232 | GNum4 div(in float a, in GNum4 b) 1233 | { 1234 | float b1 = b.val; 1235 | float b2 = b1*b1; 1236 | 1237 | return GNum4(a / b.val, 1238 | -a*b.g/b2 1239 | ); 1240 | } 1241 | //-------------------------------- 1242 | GNum4 inv(in GNum4 a) 1243 | { 1244 | return div(1.0, a); 1245 | } 1246 | //-------------------------------- 1247 | GNum4 a_pow(in GNum4 a, in GNum4 b) 1248 | { 1249 | return a_exp(mult(b,a_log(a))); 1250 | } 1251 | //-------------------------------- 1252 | GNum4 a_pow(in GNum4 a, in float b) 1253 | { 1254 | // constant exponent -> make special case 1255 | float v = pow(a.val, b); // value f(a(x)) 1256 | float da = b*pow(a.val,b-1.0); // first derivative f'(a(x)) 1257 | return GNum4(v , da * a.g); 1258 | } 1259 | //-------------------------------- 1260 | GNum4 a_pow(in float a, in GNum4 b) 1261 | { 1262 | return a_exp(mult(b,log(a))); 1263 | } 1264 | //-------------------------------- 1265 | GNum4 a_ipow(in GNum4 x, in int n) 1266 | { 1267 | // based on https://en.wikipedia.org/wiki/Exponentiation_by_squaring 1268 | if (n < 0) 1269 | { 1270 | x = div(1.0,x); 1271 | n = -n; 1272 | } 1273 | if (n == 0) 1274 | { 1275 | return constG4(1.0); 1276 | } 1277 | GNum4 y = constG4(1.0); 1278 | while (n > 1) 1279 | { 1280 | if (n % 2 == 0) 1281 | { 1282 | x = mult(x,x); 1283 | 1284 | } 1285 | else 1286 | { 1287 | y = mult(x, y); 1288 | x = mult(x, x); 1289 | } 1290 | 1291 | n = n / 2; 1292 | } 1293 | 1294 | return mult(x, y); 1295 | } 1296 | 1297 | //-------------------------------- 1298 | GNum4 a_min(in GNum4 a, in GNum4 b) 1299 | { 1300 | if(a.val < b.val) 1301 | { 1302 | return a; 1303 | } 1304 | return b; 1305 | } 1306 | //-------------------------------- 1307 | GNum4 a_max(in GNum4 a, in GNum4 b) 1308 | { 1309 | if(a.val > b.val) 1310 | { 1311 | return a; 1312 | } 1313 | return b; 1314 | } 1315 | //-------------------------------- 1316 | GNum4 a_exp2(in GNum4 a) 1317 | { 1318 | float v = exp2(a.val); // value f(a(x)) 1319 | float da = log(2.0)*exp2(a.val); // first derivative f'(a(x)) 1320 | 1321 | return GNum4(v , da * a.g); 1322 | } 1323 | //-------------------------------- 1324 | GNum4 a_inversesqrt(in GNum4 a) 1325 | { 1326 | float v = inversesqrt(a.val); // value f(a(x)) 1327 | float da = -0.5/pow(sqrt(a.val),3.0); // first derivative f'(a(x)) 1328 | 1329 | return GNum4(v , da * a.g); 1330 | } 1331 | //-------------------------------- 1332 | GNum4 a_atan(in GNum4 a) 1333 | { 1334 | float v = atan(a.val); // value f(a(x)) 1335 | float da = 1.0/(1.0 + a.val * a.val); // first derivative f'(a(x)) 1336 | 1337 | return GNum4(v , da * a.g); 1338 | } 1339 | //-------------------------------- 1340 | GNum4 a_sqrt(in GNum4 a) 1341 | { 1342 | float v = sqrt(a.val); // value f(a(x)) 1343 | float da = 0.5/sqrt(a.val); // first derivative f'(a(x)) 1344 | 1345 | return GNum4(v , da * a.g); 1346 | } 1347 | //-------------------------------- 1348 | GNum4 a_sinh(in GNum4 a) 1349 | { 1350 | float v = sinh(a.val); // value f(a(x)) 1351 | float da = cosh(a.val); // first derivative f'(a(x)) 1352 | 1353 | return GNum4(v , da * a.g); 1354 | } 1355 | //-------------------------------- 1356 | GNum4 a_ceil(in GNum4 a) 1357 | { 1358 | float v = ceil(a.val); // value f(a(x)) 1359 | float da = 0.0; // first derivative f'(a(x)) 1360 | 1361 | return GNum4(v , da * a.g); 1362 | } 1363 | //-------------------------------- 1364 | GNum4 a_tan(in GNum4 a) 1365 | { 1366 | float v = tan(a.val); // value f(a(x)) 1367 | float da = 1.0 + pow(tan(a.val),2.0); // first derivative f'(a(x)) 1368 | 1369 | return GNum4(v , da * a.g); 1370 | } 1371 | //-------------------------------- 1372 | GNum4 a_asinh(in GNum4 a) 1373 | { 1374 | float v = asinh(a.val); // value f(a(x)) 1375 | float da = 1.0/sqrt(1.0 + a.val * a.val); // first derivative f'(a(x)) 1376 | 1377 | return GNum4(v , da * a.g); 1378 | } 1379 | //-------------------------------- 1380 | GNum4 a_asin(in GNum4 a) 1381 | { 1382 | float v = asin(a.val); // value f(a(x)) 1383 | float da = 1.0/sqrt(1.0 - a.val * a.val); // first derivative f'(a(x)) 1384 | 1385 | return GNum4(v , da * a.g); 1386 | } 1387 | //-------------------------------- 1388 | GNum4 a_acosh(in GNum4 a) 1389 | { 1390 | float v = acosh(a.val); // value f(a(x)) 1391 | float da = 1.0/sqrt(-1.0 + a.val * a.val); // first derivative f'(a(x)) 1392 | 1393 | return GNum4(v , da * a.g); 1394 | } 1395 | //-------------------------------- 1396 | GNum4 a_abs(in GNum4 a) 1397 | { 1398 | float v = abs(a.val); // value f(a(x)) 1399 | float da = a.val < 0.0 ? -1.0 : 1.0; // first derivative f'(a(x)) 1400 | 1401 | return GNum4(v , da * a.g); 1402 | } 1403 | //-------------------------------- 1404 | GNum4 a_exp(in GNum4 a) 1405 | { 1406 | float v = exp(a.val); // value f(a(x)) 1407 | float da = exp(a.val); // first derivative f'(a(x)) 1408 | 1409 | return GNum4(v , da * a.g); 1410 | } 1411 | //-------------------------------- 1412 | GNum4 a_cosh(in GNum4 a) 1413 | { 1414 | float v = cosh(a.val); // value f(a(x)) 1415 | float da = sinh(a.val); // first derivative f'(a(x)) 1416 | 1417 | return GNum4(v , da * a.g); 1418 | } 1419 | //-------------------------------- 1420 | GNum4 a_floor(in GNum4 a) 1421 | { 1422 | float v = floor(a.val); // value f(a(x)) 1423 | float da = 0.0; // first derivative f'(a(x)) 1424 | 1425 | return GNum4(v , da * a.g); 1426 | } 1427 | //-------------------------------- 1428 | GNum4 a_log(in GNum4 a) 1429 | { 1430 | float v = log(a.val); // value f(a(x)) 1431 | float da = 1.0/a.val; // first derivative f'(a(x)) 1432 | 1433 | return GNum4(v , da * a.g); 1434 | } 1435 | //-------------------------------- 1436 | GNum4 a_atanh(in GNum4 a) 1437 | { 1438 | float v = atanh(a.val); // value f(a(x)) 1439 | float da = 1.0/(1.0 - a.val * a.val); // first derivative f'(a(x)) 1440 | 1441 | return GNum4(v , da * a.g); 1442 | } 1443 | //-------------------------------- 1444 | GNum4 a_log2(in GNum4 a) 1445 | { 1446 | float v = log2(a.val); // value f(a(x)) 1447 | float da = 1.0/(a.val * log(2.0)); // first derivative f'(a(x)) 1448 | 1449 | return GNum4(v , da * a.g); 1450 | } 1451 | //-------------------------------- 1452 | GNum4 a_acos(in GNum4 a) 1453 | { 1454 | float v = acos(a.val); // value f(a(x)) 1455 | float da = -1.0/sqrt(1.0 - a.val * a.val); // first derivative f'(a(x)) 1456 | 1457 | return GNum4(v , da * a.g); 1458 | } 1459 | //-------------------------------- 1460 | GNum4 a_tanh(in GNum4 a) 1461 | { 1462 | float v = tanh(a.val); // value f(a(x)) 1463 | float da = 1.0 - pow(tanh(a.val),2.0); // first derivative f'(a(x)) 1464 | 1465 | return GNum4(v , da * a.g); 1466 | } 1467 | //-------------------------------- 1468 | GNum4 a_cos(in GNum4 a) 1469 | { 1470 | float v = cos(a.val); // value f(a(x)) 1471 | float da = -sin(a.val); // first derivative f'(a(x)) 1472 | 1473 | return GNum4(v , da * a.g); 1474 | } 1475 | //-------------------------------- 1476 | GNum4 a_sin(in GNum4 a) 1477 | { 1478 | float v = sin(a.val); // value f(a(x)) 1479 | float da = cos(a.val); // first derivative f'(a(x)) 1480 | 1481 | return GNum4(v , da * a.g); 1482 | } 1483 | //-------------------------------- 1484 | GNum4 a_atan2(in GNum4 y, in GNum4 x) 1485 | { 1486 | const float pi = 3.14159265; 1487 | // from https://en.wikipedia.org/wiki/Atan2 1488 | if(x.val > 0.0) 1489 | { 1490 | GNum4 n = a_sqrt(add(mult(x,x),mult(y,y))); 1491 | GNum4 inner = div(y, add(n,x)); 1492 | 1493 | return mult(2.0,a_atan(inner)); 1494 | 1495 | }else if(x.val <= 0.0 && abs(y.val) > 1E-6) 1496 | { 1497 | GNum4 n = a_sqrt(add(mult(x,x),mult(y,y))); 1498 | GNum4 inner = div(sub(n,x),y); 1499 | return mult(2.0,a_atan(inner)); 1500 | }else if(x.val < 0.0 && abs(y.val) <= 1E-6) 1501 | { 1502 | return constG4(pi); 1503 | } 1504 | // return 0 for undefined 1505 | return constG4(0.0); 1506 | } 1507 | //-------------------------------- 1508 | GNum4 a_atan2(in GNum4 y, in float x) 1509 | { 1510 | return a_atan2(y,constG4(x)); 1511 | } 1512 | //-------------------------------- 1513 | GNum4 a_atan2(in float y, in GNum4 x) 1514 | { 1515 | return a_atan2(constG4(y),x); 1516 | } 1517 | //-------------------------------- 1518 | GNum4 a_mix(in GNum4 a, in GNum4 b, in GNum4 t) 1519 | { 1520 | return add(mult(a, sub(1.0, t)), mult(b, t)); 1521 | } 1522 | 1523 | //-------------------------------- 1524 | GNum4 a_mix(in GNum4 a, in GNum4 b, in float t) 1525 | { 1526 | return add(mult(a, 1.0 - t), mult(b, t)); 1527 | } 1528 | 1529 | //-------------------------------- 1530 | GNum4 a_mix(in GNum4 a, in float b, in GNum4 t) 1531 | { 1532 | return add(mult(a, sub(1.0, t)), mult(b, t)); 1533 | } 1534 | 1535 | //-------------------------------- 1536 | GNum4 a_mix(in GNum4 a, in float b, in float t) 1537 | { 1538 | return add(mult(a, 1.0 - t), b*t); 1539 | } 1540 | 1541 | //-------------------------------- 1542 | GNum4 a_mix(in float a, in GNum4 b, in GNum4 t) 1543 | { 1544 | return add(mult(a, sub(1.0, t)), mult(b, t)); 1545 | } 1546 | 1547 | //-------------------------------- 1548 | GNum4 a_mix(in float a, in GNum4 b, in float t) 1549 | { 1550 | return add(a * (1.0 - t), mult(b, t)); 1551 | } 1552 | 1553 | //-------------------------------- 1554 | GNum4 a_mix(in float a, in float b, in GNum4 t) 1555 | { 1556 | return add(mult(a, sub(1.0, t)), mult(b, t)); 1557 | } 1558 | 1559 | 1560 | #endif // GRAD_H_ --------------------------------------------------------------------------------