taisei/src/util/miscmath.h
2024-05-17 04:58:47 +02:00

175 lines
6.3 KiB
C

/*
* This software is licensed under the terms of the MIT License.
* See COPYING for further information.
* ---
* Copyright (c) 2011-2024, Lukas Weber <laochailan@web.de>.
* Copyright (c) 2012-2024, Andrei Alexeyev <akari@taisei-project.org>.
*/
#pragma once
#include "taisei.h"
#define DEG2RAD (M_PI / 180.0)
#define RAD2DEG (180.0 / M_PI)
#define GOLDEN_RATIO 1.618033988749895
#define M_TAU (M_PI * 2)
#define re(z) (__real__ (z))
#define im(z) (__imag__ (z))
double (creal)(cmplx z) attr_deprecated("Use re() instead");
double (cimag)(cmplx z) attr_deprecated("Use im() instead");
float (crealf)(cmplxf z) attr_deprecated("Use re() instead");
float (cimagf)(cmplxf z) attr_deprecated("Use im() instead");
float fminf(float x, float y) attr_deprecated("Use min() instead");
double fmin(double x, double y) attr_deprecated("Use min() instead");
float fmaxf(float x, float y) attr_deprecated("Use max() instead");
double fmax(double x, double y) attr_deprecated("Use max() instead");
#define min(a, b) ({ \
typeof((a)+(b)) _temp_a = (a); \
typeof((a)+(b)) _temp_b = (b); \
_temp_a > _temp_b ? _temp_b : _temp_a; \
})
#define max(a, b) ({ \
typeof((a)+(b)) _temp_a = (a); \
typeof((a)+(b)) _temp_b = (b); \
_temp_a > _temp_b ? _temp_a : _temp_b; \
})
#define clamp(x, a, b) min(max(x, a), b)
double lerp(double v0, double v1, double f) attr_const;
float lerpf(float v0, float v1, float f) attr_const;
cmplx clerp(cmplx v0, cmplx v1, double f) attr_const;
cmplxf clerpf(cmplxf v0, cmplxf v1, float f) attr_const;
intmax_t imin(intmax_t, intmax_t) attr_const attr_deprecated("Use min() instead");
intmax_t imax(intmax_t, intmax_t) attr_const attr_deprecated("Use max() instead");
uintmax_t umin(uintmax_t, uintmax_t) attr_const attr_deprecated("Use min() instead");
uintmax_t umax(uintmax_t, uintmax_t) attr_const attr_deprecated("Use max() instead");
intmax_t iclamp(intmax_t, intmax_t, intmax_t) attr_const attr_deprecated("Use clamp() instead");
float clampf(float, float, float) attr_const attr_deprecated("Use clamp() instead");
double smoothstep(double edge0, double edge1, double x) attr_const;
double smoothmin(double a, double b, double k) attr_const;
double approach(double v, double t, double d) attr_const;
float fapproach(float v, float t, float d) attr_const;
double approach_p(double *v, double t, double d);
float fapproach_p(float *v, float t, float d);
double approach_asymptotic(double val, double target, double rate, double epsilon) attr_const;
float fapproach_asymptotic(float val, float target, float rate, float epsilon) attr_const;
cmplx capproach_asymptotic(cmplx val, cmplx target, double rate, double epsilon) attr_const;
double approach_asymptotic_p(double *val, double target, double rate, double epsilon);
float fapproach_asymptotic_p(float *val, float target, float rate, float epsilon);
cmplx capproach_asymptotic_p(cmplx *val, cmplx target, double rate, double epsilon);
cmplx cnormalize(cmplx c) attr_const;
cmplx cclampabs(cmplx c, double maxabs) attr_const;
cmplx cwclamp(cmplx c, cmplx cmin, cmplx cmax) attr_const;
cmplx cdir(double angle) attr_const;
cmplx cwmul(cmplx c0, cmplx c1) attr_const;
cmplxf cwmulf(cmplxf c0, cmplxf c1) attr_const;
cmplx cwdiv(cmplx c0, cmplx c1) attr_const;
cmplxf cwdivf(cmplxf c0, cmplxf c1) attr_const;
cmplx cswap(cmplx c) attr_const;
cmplxf cswapf(cmplxf c) attr_const;
double ccross(cmplx a, cmplx b) attr_const;
float ccrossf(cmplxf a, cmplxf b) attr_const;
cmplx csort(cmplx z) attr_const;
cmplxf csortf(cmplxf z) attr_const;
double psin(double) attr_const;
double pcos(double) attr_const;
float psinf(float) attr_const;
float pcosf(float) attr_const;
int sign(double) attr_const;
double swing(double x, double s) attr_const;
double sawtooth(double x) attr_const;
double triangle(double x) attr_const;
uint32_t topow2_u32(uint32_t x) attr_const;
uint64_t topow2_u64(uint64_t x) attr_const;
float smooth(float x) attr_const;
double circle_angle(double index, double max_elements) attr_const;
cmplx circle_dir(double index, double max_elements) attr_const;
cmplx circle_dir_ofs(double index, double max_elements, double ofs) attr_const;
uint64_t upow10(uint n) attr_const;
uint digitcnt(uint64_t x) attr_const;
uint64_t uceildiv64(uint64_t x, uint64_t y) attr_const;
int popcnt32(uint32_t) attr_const;
int popcnt64(uint64_t) attr_const;
// Compute (a*b)/c with 128-bit intermediate precision.
// If the final result would not fit into 64 bits, the return value is undefined.
uint64_t umuldiv64(uint64_t x, uint64_t multiplier, uint64_t divisor);
#define ASSUME_FINITE(x) ({ \
auto _temp = (x); \
assert(isfinite(_temp)) ; \
_temp; \
})
INLINE double cabs2(cmplx c) {
return re(c) * re(c) + im(c) * im(c);
}
INLINE float cabs2f(cmplxf c) {
return re(c) * re(c) + im(c) * im(c);
}
INLINE double cdot(cmplx c0, cmplx c1) {
return re(c0) * re(c1) + im(c0) * im(c1);
}
INLINE float cdotf(cmplxf c0, cmplxf c1) {
return re(c0) * re(c1) + im(c0) * im(c1);
}
INLINE cmplx cmul_finite(cmplx a, cmplx b) {
double ra = ASSUME_FINITE(re(a));
double ia = ASSUME_FINITE(im(a));
double rb = ASSUME_FINITE(re(b));
double ib = ASSUME_FINITE(im(b));
return CMPLX(ra * rb - ia * ib, ra * ib + ia * rb);
}
INLINE cmplxf cmulf_finite(cmplxf a, cmplxf b) {
float ra = ASSUME_FINITE(re(a));
float ia = ASSUME_FINITE(im(a));
float rb = ASSUME_FINITE(re(b));
float ib = ASSUME_FINITE(im(b));
return CMPLXF(ra * rb - ia * ib, ra * ib + ia * rb);
}
INLINE cmplx cdiv_finite(cmplx a, cmplx b) {
double ra = ASSUME_FINITE(re(a));
double ia = ASSUME_FINITE(im(a));
double rb = ASSUME_FINITE(re(b));
double ib = ASSUME_FINITE(im(b));
double denom = rb * rb + ib * ib;
return CMPLX((ra*rb + ia*ib) / denom, (ia*rb - ra*ib) / denom);
}
INLINE cmplxf cdivf_finite(cmplxf a, cmplxf b) {
float ra = ASSUME_FINITE(re(a));
float ia = ASSUME_FINITE(im(a));
float rb = ASSUME_FINITE(re(b));
float ib = ASSUME_FINITE(im(b));
float denom = rb * rb + ib * ib;
return CMPLXF((ra*rb + ia*ib) / denom, (ia*rb - ra*ib) / denom);
}
#define topow2(x) (_Generic((x), \
uint32_t: topow2_u32, \
uint64_t: topow2_u64, \
default: topow2_u64 \
)(x))
#include <cglm/types.h>
typedef float vec2_noalign[2];
typedef int ivec2_noalign[2];
typedef float vec3_noalign[3];
typedef int ivec3_noalign[3];
typedef float vec4_noalign[4];
typedef int ivec4_noalign[4];
typedef vec3_noalign mat3_noalign[3];
typedef vec4_noalign mat4_noalign[4];