1 /*
2  * This software is licensed under the terms of the MIT License.
3  * See COPYING for further information.
4  * ---
5  * Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>.
6  * Copyright (c) 2012-2019, Andrei Alexeyev <akari@taisei-project.org>.
7  */
8 
9 #include "taisei.h"
10 
11 #include "miscmath.h"
12 #include "assert.h"
13 
lerp(double v0,double v1,double f)14 double lerp(double v0, double v1, double f) {
15 	return f * (v1 - v0) + v0;
16 }
17 
clerp(cmplx v0,cmplx v1,double f)18 cmplx clerp(cmplx v0, cmplx v1, double f) {
19 	return f * (v1 - v0) + v0;
20 }
21 
approach(double v,double t,double d)22 double approach(double v, double t, double d) {
23 	if(v < t) {
24 		v += d;
25 		if(v > t)
26 			return t;
27 	} else if(v > t) {
28 		v -= d;
29 		if(v < t)
30 			return t;
31 	}
32 
33 	return v;
34 }
35 
fapproach(float v,float t,float d)36 float fapproach(float v, float t, float d) {
37 	if(v < t) {
38 		v += d;
39 		if(v > t)
40 			return t;
41 	} else if(v > t) {
42 		v -= d;
43 		if(v < t)
44 			return t;
45 	}
46 
47 	return v;
48 }
49 
approach_p(double * v,double t,double d)50 void approach_p(double *v, double t, double d) {
51 	*v = approach(*v, t, d);
52 }
53 
fapproach_p(float * v,float t,float d)54 void fapproach_p(float *v, float t, float d) {
55 	*v = fapproach(*v, t, d);
56 }
57 
approach_asymptotic(double val,double target,double rate,double epsilon)58 double approach_asymptotic(double val, double target, double rate, double epsilon) {
59 	if(fabs(val - target) < epsilon || rate >= 1) {
60 		return target;
61 	}
62 
63 	return val + (target - val) * rate;
64 }
65 
fapproach_asymptotic(float val,float target,float rate,float epsilon)66 float fapproach_asymptotic(float val, float target, float rate, float epsilon) {
67 	if(fabsf(val - target) < epsilon || rate >= 1) {
68 		return target;
69 	}
70 
71 	return val + (target - val) * rate;
72 }
73 
capproach_asymptotic(cmplx val,cmplx target,double rate,double epsilon)74 cmplx capproach_asymptotic(cmplx val, cmplx target, double rate, double epsilon) {
75 	if(cabs(val - target) < epsilon || rate >= 1) {
76 		return target;
77 	}
78 
79 	return val + (target - val) * rate;
80 }
81 
approach_asymptotic_p(double * val,double target,double rate,double epsilon)82 void approach_asymptotic_p(double *val, double target, double rate, double epsilon) {
83 	*val = approach_asymptotic(*val, target, rate, epsilon);
84 }
85 
fapproach_asymptotic_p(float * val,float target,float rate,float epsilon)86 void fapproach_asymptotic_p(float *val, float target, float rate, float epsilon) {
87 	*val = fapproach_asymptotic(*val, target, rate, epsilon);
88 }
89 
capproach_asymptotic_p(cmplx * val,cmplx target,double rate,double epsilon)90 void capproach_asymptotic_p(cmplx *val, cmplx target, double rate, double epsilon) {
91 	*val = capproach_asymptotic(*val, target, rate, epsilon);
92 }
93 
psin(double x)94 double psin(double x) {
95 	return 0.5 + 0.5 * sin(x);
96 }
97 
min(double a,double b)98 double min(double a, double b) {
99 	return (a < b) ? a : b;
100 }
101 
max(double a,double b)102 double max(double a, double b) {
103 	return (a > b) ? a : b;
104 }
105 
imin(intmax_t a,intmax_t b)106 intmax_t imin(intmax_t a, intmax_t b) {
107 	return (a < b) ? a : b;
108 }
109 
imax(intmax_t a,intmax_t b)110 intmax_t imax(intmax_t a, intmax_t b) {
111 	return (a > b) ? a : b;
112 }
113 
umin(uintmax_t a,uintmax_t b)114 uintmax_t umin(uintmax_t a, uintmax_t b) {
115 	return (a < b) ? a : b;
116 }
117 
umax(uintmax_t a,uintmax_t b)118 uintmax_t umax(uintmax_t a, uintmax_t b) {
119 	return (a > b) ? a : b;
120 }
121 
clamp(double f,double lower,double upper)122 double clamp(double f, double lower, double upper) {
123 	assert(lower <= upper);
124 
125 	if(f < lower) {
126 		return lower;
127 	}
128 
129 	if(f > upper) {
130 		return upper;
131 	}
132 
133 	return f;
134 }
135 
iclamp(intmax_t f,intmax_t lower,intmax_t upper)136 intmax_t iclamp(intmax_t f, intmax_t lower, intmax_t upper) {
137 	assert(lower <= upper);
138 
139 	if(f < lower) {
140 		return lower;
141 	}
142 
143 	if(f > upper) {
144 		return upper;
145 	}
146 
147 	return f;
148 }
149 
smoothstep(double edge0,double edge1,double x)150 double smoothstep(double edge0, double edge1, double x) {
151 	x = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
152 	return x * x * (3 - 2 * x);
153 }
154 
smoothmin(double a,double b,double k)155 double smoothmin(double a, double b, double k) {
156   float h = clamp(0.5 + 0.5 * (b - a) / k, 0.0, 1.0);
157   return lerp(b, a, h) - k * h * (1.0 - h);
158 }
159 
sign(double x)160 int sign(double x) {
161 	return (x > 0) - (x < 0);
162 }
163 
swing(double x,double s)164 double swing(double x, double s) {
165 	if(x <= 0.5) {
166 		x *= 2;
167 		return x * x * ((s + 1) * x - s) / 2;
168 	}
169 
170 	x--;
171 	x *= 2;
172 
173 	return x * x * ((s + 1) * x + s) / 2 + 1;
174 }
175 
topow2_u32(uint32_t x)176 uint32_t topow2_u32(uint32_t x) {
177 	x -= 1;
178 	x |= (x >> 1);
179 	x |= (x >> 2);
180 	x |= (x >> 4);
181 	x |= (x >> 8);
182 	x |= (x >> 16);
183 	return x + 1;
184 }
185 
topow2_u64(uint64_t x)186 uint64_t topow2_u64(uint64_t x) {
187 	x -= 1;
188 	x |= (x >> 1);
189 	x |= (x >> 2);
190 	x |= (x >> 4);
191 	x |= (x >> 8);
192 	x |= (x >> 16);
193 	x |= (x >> 32);
194 	return x + 1;
195 }
196 
ftopow2(float x)197 float ftopow2(float x) {
198 	// NOTE: obviously this isn't the smallest possible power of two, but for our purposes, it could as well be.
199 	float y = 0.0625;
200 	while(y < x) y *= 2;
201 	return y;
202 }
203 
smooth(float x)204 float smooth(float x) {
205 	return 1.0 - (0.5 * cos(M_PI * x) + 0.5);
206 }
207 
smoothreclamp(float x,float old_min,float old_max,float new_min,float new_max)208 float smoothreclamp(float x, float old_min, float old_max, float new_min, float new_max) {
209 	x = (x - old_min) / (old_max - old_min);
210 	return new_min + (new_max - new_min) * smooth(x);
211 }
212 
sanitize_scale(float scale)213 float sanitize_scale(float scale) {
214 	return max(0.1, scale);
215 }
216 
normpdf(float x,float sigma)217 float normpdf(float x, float sigma) {
218     return 0.39894 * exp(-0.5 * pow(x, 2) / pow(sigma, 2)) / sigma;
219 }
220 
gaussian_kernel_1d(size_t size,float sigma,float kernel[size])221 void gaussian_kernel_1d(size_t size, float sigma, float kernel[size]) {
222 	assert(size & 1);
223 
224 	double sum = 0.0;
225 	size_t halfsize = size / 2;
226 
227 	kernel[halfsize] = normpdf(0, sigma);
228 	sum += kernel[halfsize];
229 
230 	for(size_t i = 1; i <= halfsize; ++i) {
231 		float k = normpdf(i, sigma);
232 		kernel[halfsize + i] = kernel[halfsize - i] = k;
233 		sum += k * 2;
234 
235 	}
236 
237 	for(size_t i = 0; i < size; ++i) {
238 		kernel[i] /= sum;
239 	}
240 }
241 
242 static const uint64_t upow10_table[] = {
243 	1ull,
244 	10ull,
245 	100ull,
246 	1000ull,
247 	10000ull,
248 	100000ull,
249 	1000000ull,
250 	10000000ull,
251 	100000000ull,
252 	1000000000ull,
253 	10000000000ull,
254 	100000000000ull,
255 	1000000000000ull,
256 	10000000000000ull,
257 	100000000000000ull,
258 	1000000000000000ull,
259 	10000000000000000ull,
260 	100000000000000000ull,
261 	1000000000000000000ull,
262 	10000000000000000000ull,
263 };
264 
upow10(uint n)265 uint64_t upow10(uint n) {
266 	assert(n < sizeof(upow10_table)/sizeof(*upow10_table));
267 	return upow10_table[n];
268 }
269 
digitcnt(uint64_t x)270 uint digitcnt(uint64_t x) {
271 	if(x == 0) {
272 		return 1;
273 	}
274 
275 	uint low = 0;
276 	uint high = sizeof(upow10_table)/sizeof(*upow10_table) - 1;
277 
278 	for(;;) {
279 		uint mid = (low + high) / 2;
280 
281 		if(x >= upow10_table[mid]) {
282 			if(low == mid) {
283 				return mid + 1;
284 			}
285 
286 			low = mid;
287 		} else {
288 			high = mid;
289 		}
290 	}
291 
292 	UNREACHABLE;
293 }
294 
295 typedef struct int128_bits {
296 	uint64_t hi;
297 	uint64_t lo;
298 } int128_bits_t;
299 
300 INLINE attr_unused
udiv_128_64(int128_bits_t divident,uint64_t divisor,uint64_t * out_quotient)301 void udiv_128_64(int128_bits_t divident, uint64_t divisor, uint64_t *out_quotient) {
302 	/*
303 	if(!divident.hi) {
304 		*out_quotient = divident.lo / divisor;
305 		return;
306 	}
307 	*/
308 
309 	uint64_t quotient = divident.lo << 1;
310 	uint64_t remainder = divident.hi;
311 	uint64_t carry = divident.lo >> 63;
312 	uint64_t temp_carry = 0;
313 
314 	for(int i = 0; i < 64; i++) {
315 		temp_carry = remainder >> 63;
316 		remainder <<= 1;
317 		remainder |= carry;
318 		carry = temp_carry;
319 
320 		if(carry == 0) {
321 			if(remainder >= divisor) {
322 				carry = 1;
323 			} else {
324 				temp_carry = quotient >> 63;
325 				quotient <<= 1;
326 				quotient |= carry;
327 				carry = temp_carry;
328 				continue;
329 			}
330 		}
331 
332 		remainder -= divisor;
333 		remainder -= (1 - carry);
334 		carry = 1;
335 		temp_carry = quotient >> 63;
336 		quotient <<= 1;
337 		quotient |= carry;
338 		carry = temp_carry;
339 	}
340 
341 	*out_quotient = quotient;
342 }
343 
344 INLINE attr_unused
umul_128_64(uint64_t multiplicant,uint64_t multiplier,int128_bits_t * result)345 void umul_128_64(uint64_t multiplicant, uint64_t multiplier, int128_bits_t *result) {
346 #if defined(__GNUC__) && (defined(__x86_64) || defined(__x86_64__))
347     __asm__ (
348         "mulq %3"
349         : "=a,a" (result->lo),   "=d,d" (result->hi)
350         : "%0,0" (multiplicant), "r,m"  (multiplier)
351         : "cc"
352     );
353 #else
354 	uint64_t u1 = (multiplicant & 0xffffffff);
355 	uint64_t v1 = (multiplier & 0xffffffff);
356 	uint64_t t = (u1 * v1);
357 	uint64_t w3 = (t & 0xffffffff);
358 	uint64_t k = (t >> 32);
359 
360 	multiplicant >>= 32;
361 	t = (multiplicant * v1) + k;
362 	k = (t & 0xffffffff);
363 	uint64_t w1 = (t >> 32);
364 
365 	multiplier >>= 32;
366 	t = (u1 * multiplier) + k;
367 	k = (t >> 32);
368 
369 	result->hi = (multiplicant * multiplier) + w1 + k;
370 	result->lo = (t << 32) + w3;
371 #endif
372 }
373 
374 INLINE attr_unused
_umuldiv64_slow(uint64_t x,uint64_t multiplier,uint64_t divisor)375 uint64_t _umuldiv64_slow(uint64_t x, uint64_t multiplier, uint64_t divisor) {
376 	int128_bits_t intermediate;
377 	uint64_t result;
378 	umul_128_64(x, multiplier, &intermediate);
379 	udiv_128_64(intermediate, divisor, &result);
380 	return result;
381 }
382 
383 #include "util.h"
384 
385 INLINE
_umuldiv64(uint64_t x,uint64_t multiplier,uint64_t divisor)386 uint64_t _umuldiv64(uint64_t x, uint64_t multiplier, uint64_t divisor) {
387 #if defined(TAISEI_BUILDCONF_HAVE_INT128)
388 	__extension__ typedef unsigned __int128 uint128_t;
389 	return ((uint128_t)x * (uint128_t)multiplier) / divisor;
390 #elif defined(TAISEI_BUILDCONF_HAVE_LONG_DOUBLE)
391 	#define UMULDIV64_SANITY_CHECK
392 	return ((float64x)x * (float64x)multiplier) / (float64x)divisor;
393 #else
394 	return _umuldiv64_slow(x, multiplier, divisor);
395 #endif
396 }
397 
umuldiv64(uint64_t x,uint64_t multiplier,uint64_t divisor)398 uint64_t umuldiv64(uint64_t x, uint64_t multiplier, uint64_t divisor) {
399 #ifdef UMULDIV64_SANITY_CHECK
400 	static signed char sanity = -1;
401 
402 	if(sanity < 0) {
403 		sanity = (_umuldiv64(UINT64_MAX, UINT64_MAX, UINT64_MAX) == UINT64_MAX);
404 	}
405 
406 	return (sanity ? _umuldiv64 : _umuldiv64_slow)(x, multiplier, divisor);
407 #else
408 	return _umuldiv64(x, multiplier, divisor);
409 #endif
410 }
411