1 /** 2 * Copyright: Enalye 3 * License: Zlib 4 * Authors: Enalye 5 */ 6 module grimoire.stdlib.math; 7 8 import std.random, std.math; 9 import std.algorithm.comparison : clamp; 10 import grimoire.assembly, grimoire.compiler, grimoire.runtime; 11 12 package(grimoire.stdlib) void grLoadStdLibMath(GrLibrary library) { 13 library.addVariable("pi", grFloat, PI, true); 14 15 library.addPrimitive(&_min_f, "min", [grFloat, grFloat], [grFloat]); 16 library.addPrimitive(&_min_i, "min", [grInt, grInt], [grInt]); 17 library.addPrimitive(&_max_f, "max", [grFloat, grFloat], [grFloat]); 18 library.addPrimitive(&_max_i, "max", [grInt, grInt], [grInt]); 19 20 library.addPrimitive(&_clamp, "clamp", [grFloat, grFloat, grFloat], [ 21 grFloat 22 ]); 23 24 library.addPrimitive(&_random01, "rand", [], [grFloat]); 25 library.addPrimitive(&_random_f, "rand", [grFloat, grFloat], [grFloat]); 26 library.addPrimitive(&_random_i, "rand", [grInt, grInt], [grInt]); 27 28 library.addPrimitive(&_cos, "cos", [grFloat], [grFloat]); 29 library.addPrimitive(&_sin, "sin", [grFloat], [grFloat]); 30 library.addPrimitive(&_tan, "tan", [grFloat], [grFloat]); 31 library.addPrimitive(&_acos, "acos", [grFloat], [grFloat]); 32 library.addPrimitive(&_asin, "asin", [grFloat], [grFloat]); 33 library.addPrimitive(&_atan, "atan", [grFloat], [grFloat]); 34 library.addPrimitive(&_atan2, "atan2", [grFloat, grFloat], [grFloat]); 35 36 library.addPrimitive(&_exp, "exp", [grFloat], [grFloat]); 37 library.addPrimitive(&_sqrt, "sqrt", [grFloat], [grFloat]); 38 library.addPrimitive(&_pow, "pow", [grFloat, grFloat], [grFloat]); 39 40 library.addPrimitive(&_lerp, "lerp", [grFloat, grFloat, grFloat], [grFloat]); 41 library.addPrimitive(&_rlerp, "rlerp", [grFloat, grFloat, grFloat], [ 42 grFloat 43 ]); 44 45 library.addPrimitive(&_abs_i, "abs", [grInt], [grInt]); 46 library.addPrimitive(&_abs_f, "abs", [grFloat], [grFloat]); 47 library.addPrimitive(&_floor, "floor", [grFloat], [grFloat]); 48 library.addPrimitive(&_ceil, "ceil", [grFloat], [grFloat]); 49 library.addPrimitive(&_round, "round", [grFloat], [grFloat]); 50 library.addPrimitive(&_truncate, "truncate", [grFloat], [grFloat]); 51 library.addPrimitive(&_positive_i, "positive?", [grInt], [grBool]); 52 library.addPrimitive(&_positive_f, "positive?", [grFloat], [grBool]); 53 library.addPrimitive(&_negative_i, "negative?", [grInt], [grBool]); 54 library.addPrimitive(&_negative_f, "negative?", [grFloat], [grBool]); 55 library.addPrimitive(&_zero_i, "zero?", [grInt], [grBool]); 56 library.addPrimitive(&_zero_f, "zero?", [grFloat], [grBool]); 57 library.addPrimitive(&_nan, "nan?", [grFloat], [grBool]); 58 library.addPrimitive(&_even, "even?", [grInt], [grBool]); 59 library.addPrimitive(&_odd, "odd?", [grInt], [grBool]); 60 } 61 62 private void _min_f(GrCall call) { 63 const GrFloat a = call.getFloat(0); 64 const GrFloat b = call.getFloat(1); 65 call.setFloat(a < b ? a : b); 66 } 67 68 private void _min_i(GrCall call) { 69 const GrInt a = call.getInt(0); 70 const GrInt b = call.getInt(1); 71 call.setInt(a < b ? a : b); 72 } 73 74 private void _max_f(GrCall call) { 75 const GrFloat a = call.getFloat(0); 76 const GrFloat b = call.getFloat(1); 77 call.setFloat(a > b ? a : b); 78 } 79 80 private void _max_i(GrCall call) { 81 const GrInt a = call.getInt(0); 82 const GrInt b = call.getInt(1); 83 call.setInt(a > b ? a : b); 84 } 85 86 private void _clamp(GrCall call) { 87 call.setFloat(clamp(call.getFloat(0), call.getFloat(1), call.getFloat(2))); 88 } 89 90 private void _random01(GrCall call) { 91 call.setFloat(uniform01()); 92 } 93 94 private void _random_f(GrCall call) { 95 const GrFloat a = call.getFloat(0); 96 const GrFloat b = call.getFloat(1); 97 if(a < b) 98 call.setFloat(uniform!"[]"(a, b)); 99 else 100 call.setFloat(uniform!"[]"(b, a)); 101 } 102 103 private void _random_i(GrCall call) { 104 const GrInt a = call.getInt(0); 105 const GrInt b = call.getInt(1); 106 if(a < b) 107 call.setInt(uniform!"[]"(a, b)); 108 else 109 call.setInt(uniform!"[]"(b, a)); 110 } 111 112 private void _cos(GrCall call) { 113 call.setFloat(cos(call.getFloat(0))); 114 } 115 116 private void _sin(GrCall call) { 117 call.setFloat(sin(call.getFloat(0))); 118 } 119 120 private void _tan(GrCall call) { 121 call.setFloat(tan(call.getFloat(0))); 122 } 123 124 private void _acos(GrCall call) { 125 call.setFloat(acos(call.getFloat(0))); 126 } 127 128 private void _asin(GrCall call) { 129 call.setFloat(asin(call.getFloat(0))); 130 } 131 132 private void _atan(GrCall call) { 133 call.setFloat(atan(call.getFloat(0))); 134 } 135 136 private void _atan2(GrCall call) { 137 call.setFloat(atan2(call.getFloat(0), call.getFloat(1))); 138 } 139 140 private void _exp(GrCall call) { 141 call.setFloat(exp(call.getFloat(0))); 142 } 143 144 private void _sqrt(GrCall call) { 145 call.setFloat(sqrt(call.getFloat(0))); 146 } 147 148 private void _pow(GrCall call) { 149 call.setFloat(pow(call.getFloat(0), call.getFloat(1))); 150 } 151 152 private void _lerp(GrCall call) { 153 const GrFloat a = call.getFloat(0); 154 const GrFloat b = call.getFloat(1); 155 const GrFloat t = call.getFloat(2); 156 call.setFloat(t * b + (1f - t) * a); 157 } 158 159 private void _rlerp(GrCall call) { 160 const GrFloat a = call.getFloat(0); 161 const GrFloat b = call.getFloat(1); 162 const GrFloat v = call.getFloat(2); 163 if ((b - a) == 0f) { 164 call.setFloat(0f); 165 return; 166 } 167 call.setFloat((v - a) / (b - a)); 168 } 169 170 private void _abs_i(GrCall call) { 171 call.setInt(abs(call.getInt(0))); 172 } 173 174 private void _abs_f(GrCall call) { 175 call.setFloat(abs(call.getFloat(0))); 176 } 177 178 private void _floor(GrCall call) { 179 call.setFloat(floor(call.getFloat(0))); 180 } 181 182 private void _ceil(GrCall call) { 183 call.setFloat(ceil(call.getFloat(0))); 184 } 185 186 private void _round(GrCall call) { 187 call.setFloat(round(call.getFloat(0))); 188 } 189 190 private void _truncate(GrCall call) { 191 call.setFloat(trunc(call.getFloat(0))); 192 } 193 194 private void _positive_i(GrCall call) { 195 call.setBool(call.getInt(0) > 0); 196 } 197 198 private void _positive_f(GrCall call) { 199 call.setBool(call.getFloat(0) > 0); 200 } 201 202 private void _negative_i(GrCall call) { 203 call.setBool(call.getInt(0) < 0); 204 } 205 206 private void _negative_f(GrCall call) { 207 call.setBool(call.getFloat(0) < 0); 208 } 209 210 private void _zero_i(GrCall call) { 211 call.setBool(call.getInt(0) == 0); 212 } 213 214 private void _zero_f(GrCall call) { 215 call.setBool(call.getFloat(0) == 0); 216 } 217 218 private void _nan(GrCall call) { 219 call.setBool(isNaN(call.getFloat(0))); 220 } 221 222 private void _even(GrCall call) { 223 call.setBool(!(call.getInt(0) & 0x1)); 224 } 225 226 private void _odd(GrCall call) { 227 call.setBool(call.getInt(0) & 0x1); 228 }