1 #include "Geometry.hpp"
2
3 START_NAMESPACE_DISTRHO
4
5 namespace wolf
6 {
7 template <typename T,
8 typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
9 T clamp(const T &value, const T &min, const T &max)
10 {
11 return std::max(min, std::min(value, max));
12 }
13
14 template <typename T>
mirror(const T & value,const T & max)15 T mirror(const T &value, const T &max)
16 {
17 return max - value;
18 }
19
20 template <typename T>
mirror(const T & value,const T & min,const T & max)21 T mirror(const T &value, const T &min, const T &max)
22 {
23 return max - value + min;
24 }
25
normalize(const float & value,const float & max)26 float normalize(const float &value, const float &max)
27 {
28 return value / max;
29 }
30
logScale(const float value,const float min,const float max)31 float logScale(const float value, const float min, const float max)
32 {
33 if (value < min)
34 return min;
35 if (value > max)
36 return max;
37
38 const float b = std::log(max / min) / (max - min);
39 const float a = max / std::exp(max * b);
40
41 return a * std::exp(b * value);
42 }
43
invLogScale(const float value,const float min,const float max)44 float invLogScale(const float value, const float min, const float max)
45 {
46 if (value < min)
47 return min;
48 if (value > max)
49 return max;
50
51 const float b = std::log(max / min) / (max - min);
52 const float a = max / std::exp(max * b);
53
54 return std::log(value / a) / b;
55 }
56
randomNumber(const float min,const float max)57 float randomNumber(const float min, const float max)
58 {
59 return ((float)std::rand() / (float)RAND_MAX * (max - min)) + min;
60 }
61
lerp(float a,float b,float f)62 float lerp(float a, float b, float f)
63 {
64 f = clamp(f, 0.0f, 1.0f);
65
66 return a * (1.0 - f) + (b * f);
67 }
68
69 /* Hexfloat stuff------------------------------------- */
70
71 // Adapted from https://cs.chromium.org/chromium/src/v8/src/conversions.cc
72 // Copyright 2015 The Chromium Authors. All rights reserved.
73 //
74 // Redistribution and use in source and binary forms, with or without
75 // modification, are permitted provided that the following conditions are
76 // met:
77 //
78 // * Redistributions of source code must retain the above copyright
79 // notice, this list of conditions and the following disclaimer.
80 // * Redistributions in binary form must reproduce the above
81 // copyright notice, this list of conditions and the following disclaimer
82 // in the documentation and/or other materials provided with the
83 // distribution.
84 // * Neither the name of Google Inc. nor the names of its
85 // contributors may be used to endorse or promote products derived from
86 // this software without specific prior written permission.
87 //
88 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
89 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
90 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
91 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
92 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
93 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
94 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
95 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
96 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
97 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
98 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
99
doubleToRadixCString(char * buf,double value,int radix)100 int doubleToRadixCString(char *buf, double value, int radix)
101 {
102 const char chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
103
104 // Temporary buffer for the result. We start with the decimal point in the
105 // middle and write to the left for the integer part and to the right for the
106 // fractional part. 1024 characters for the exponent and 52 for the mantissa
107 // either way, with additional space for sign, decimal point and string
108 // termination should be sufficient.
109 const int kBufferSize = 2200;
110 char buffer[kBufferSize];
111
112 int integer_cursor = kBufferSize / 2;
113 int fraction_cursor = integer_cursor;
114
115 bool negative = value < 0;
116
117 if (negative)
118 value = -value;
119
120 // Split the value into an integer part and a fractional part.
121 double integer = std::floor(value);
122 double fraction = value - integer;
123
124 // We only compute fractional digits up to the input double's precision.
125 double delta = 0.0;
126
127 if (fraction > delta)
128 {
129 // Insert decimal point.
130 buffer[fraction_cursor++] = '.';
131 do
132 {
133 // Shift up by one digit.
134 fraction *= radix;
135 delta *= radix;
136
137 // Write digit.
138 int digit = static_cast<int>(fraction);
139 buffer[fraction_cursor++] = chars[digit];
140
141 // Calculate remainder.
142 fraction -= digit;
143
144 // Round to even.
145 if (fraction > 0.5 || (fraction == 0.5 && (digit & 1)))
146 {
147 if (fraction + delta > 1)
148 {
149 // We need to back trace already written digits in case of carry-over.
150 while (true)
151 {
152 fraction_cursor--;
153 if (fraction_cursor == kBufferSize / 2)
154 {
155 // Carry over to the integer part.
156 integer += 1;
157 break;
158 }
159 char c = buffer[fraction_cursor];
160
161 // Reconstruct digit.
162 int digit = c > '9' ? (c - 'a' + 10) : (c - '0');
163
164 if (digit + 1 < radix)
165 {
166 buffer[fraction_cursor++] = chars[digit + 1];
167 break;
168 }
169 }
170 break;
171 }
172 }
173 } while (fraction > delta);
174 }
175
176 int exponent;
177 std::frexp(integer / radix, &exponent);
178
179 // Compute integer digits. Fill unrepresented digits with zero.
180 while (exponent > 0)
181 {
182 integer /= radix;
183 buffer[--integer_cursor] = '0';
184 std::frexp(integer / radix, &exponent);
185 }
186
187 do
188 {
189 const double rem = std::fmod(integer, radix);
190 buffer[--integer_cursor] = chars[static_cast<int>(rem)];
191 integer = (integer - rem) / radix;
192 } while (integer > 0);
193
194 // Add sign and terminate string.
195 if (negative)
196 buffer[--integer_cursor] = '-';
197
198 buffer[fraction_cursor++] = '\0';
199
200 const int len = fraction_cursor - integer_cursor;
201
202 memcpy(buf, buffer + integer_cursor, len * sizeof(char) + 1);
203
204 return len - 1;
205 }
206
207 //Adapted from https://github.com/dankogai/js-hexfloat
208 /*Copyright (c) 2016 Dan Kogai
209
210 Permission is hereby granted, free of charge, to any person obtaining a copy
211 of this software and associated documentation files (the "Software"), to deal
212 in the Software without restriction, including without limitation the rights
213 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
214 copies of the Software, and to permit persons to whom the Software is
215 furnished to do so, subject to the following conditions:
216
217 The above copyright notice and this permission notice shall be included in all
218 copies or substantial portions of the Software.
219
220 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
221 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
222 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
223 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
224 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
225 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
226 SOFTWARE.*/
227
toHexFloat(char * buffer,const double value)228 int toHexFloat(char *buffer, const double value)
229 {
230 if (value == +0.0)
231 {
232 return std::sprintf(buffer, "0x0p+0");
233 }
234 else if (value == -0.0)
235 {
236 return std::sprintf(buffer, "-0x0p+0");
237 }
238
239 const char sign = value < 0 ? '-' : '\0';
240
241 double hexDigits = std::abs(value);
242 int exponent = 0;
243
244 if (hexDigits < 1)
245 {
246 while (hexDigits < 1)
247 {
248 hexDigits *= 2;
249 --exponent;
250 }
251 }
252 else
253 {
254 while (hexDigits >= 2)
255 {
256 hexDigits /= 2;
257 ++exponent;
258 }
259 }
260
261 const char exponentSign = exponent < 0 ? '\0' : '+';
262
263 int length;
264
265 if (sign)
266 length = std::sprintf(buffer, "%c0x", sign);
267 else
268 length = std::sprintf(buffer, "0x");
269
270 length += doubleToRadixCString(buffer + length, hexDigits, 16);
271
272 if (exponentSign)
273 return length + std::sprintf(buffer + length, "p%c%d", exponentSign, exponent);
274 else
275 return length + std::sprintf(buffer + length, "p%d", exponent);
276 }
277
278 //following functions adapted from ispc
279 /*
280 Copyright (c) 2010-2011, Intel Corporation
281 All rights reserved.
282
283 Redistribution and use in source and binary forms, with or without
284 modification, are permitted provided that the following conditions are
285 met:
286
287 * Redistributions of source code must retain the above copyright
288 notice, this list of conditions and the following disclaimer.
289
290 * Redistributions in binary form must reproduce the above copyright
291 notice, this list of conditions and the following disclaimer in the
292 documentation and/or other materials provided with the distribution.
293
294 * Neither the name of Intel Corporation nor the names of its
295 contributors may be used to endorse or promote products derived from
296 this software without specific prior written permission.
297
298
299 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
300 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
301 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
302 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
303 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
304 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
305 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
306 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
307 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
308 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
309 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
310 */
311
312 /*
313 * Compute the value 2^n, where the exponent is given as an integer.
314 */
ipow2(int exponent)315 double ipow2(int exponent)
316 {
317 if (exponent < 0)
318 return 1.0 / ipow2(-exponent);
319
320 double ret = 1.0;
321
322 while (exponent > 16)
323 {
324 ret *= 65536.0;
325 exponent -= 16;
326 }
327
328 while (exponent-- > 0)
329 ret *= 2.0;
330
331 return ret;
332 }
333
334 /*
335 * Parse a hexadecimal-formatted floating-point number (C99 hex float constant-style).
336 */
parseHexFloat(char const * ptr,char ** endPointer)337 double parseHexFloat(char const *ptr, char **endPointer)
338 {
339 DISTRHO_SAFE_ASSERT_RETURN(ptr != NULL, 0);
340 DISTRHO_SAFE_ASSERT_RETURN((ptr[0] == '0' && ptr[1] == 'x') || (ptr[0] == '-' && ptr[1] == '0' && ptr[2] == 'x'), 0);
341
342 double sign;
343
344 if (ptr[0] == '-')
345 {
346 sign = -1.0;
347 ptr += 3;
348 }
349 else
350 {
351 sign = 1.0;
352 ptr += 2;
353 }
354
355 // Start initializing the mantissa
356 DISTRHO_SAFE_ASSERT_RETURN(*ptr == '0' || *ptr == '1', 0);
357 double mantissa = (*ptr == '1') ? 1.0 : 0.0;
358
359 ++ptr;
360
361 if (*ptr == '.')
362 {
363 // Is there a fraction part? If so, the i'th digit we encounter
364 // gives the 1/(16^i) component of the mantissa.
365 ++ptr;
366
367 double scale = 1.0 / 16.0;
368
369 // Keep going until we come to the 'p', which indicates that we've
370 // come to the exponent
371 while (*ptr != 'p')
372 {
373 // Figure out the raw value from 0-15
374
375 int digit;
376
377 if (*ptr >= '0' && *ptr <= '9')
378 {
379 digit = *ptr - '0';
380 }
381 else if (*ptr >= 'a' && *ptr <= 'f')
382 {
383 digit = 10 + *ptr - 'a';
384 }
385 else
386 {
387 fprintf(stderr, "Error while parsing hexfloat: invalid digit");
388 return 0;
389 }
390
391 // And add its contribution to the mantissa
392 mantissa += scale * digit;
393 scale /= 16.0;
394 ++ptr;
395 }
396 }
397 else
398 {
399 // If there's not a '.', then we better be going straight to the
400 // exponent
401 DISTRHO_SAFE_ASSERT_RETURN(*ptr == 'p', 0);
402 }
403
404 ++ptr; // skip the 'p'
405
406 // interestingly enough, the exponent is provided base 10..
407 int exponent = (int)std::strtol(ptr, endPointer, 10);
408
409 // Does stdlib exp2() guarantee exact results for integer n where can
410 // be represented exactly as doubles? I would hope so but am not sure,
411 // so let's be sure.
412 return sign * (mantissa * ipow2(exponent));
413 }
414 } // namespace wolf
415
416 END_NAMESPACE_DISTRHO
417