From 2954f96f0c421f3d1acd143ff670f0282d276845 Mon Sep 17 00:00:00 2001 From: div0 Date: Sat, 7 Nov 2009 19:42:13 +0000 Subject: [PATCH] add a crude version of to QC git-svn-id: svn://svn.icculus.org/nexuiz/trunk@8227 f962a42d-fe04-0410-a3ab-8c8b0445ebaa --- data/qcsrc/client/View.qc | 3 +- data/qcsrc/client/progs.src | 3 + data/qcsrc/common/gamecommand.qc | 4 + data/qcsrc/common/mathlib.qc | 296 +++++++++++++++++++++++ data/qcsrc/common/mathlib.qh | 99 ++++++++ data/qcsrc/common/util.qh | 2 +- data/qcsrc/menu/item/listbox.c | 16 +- data/qcsrc/menu/nexuiz/slider_decibels.c | 47 +--- data/qcsrc/menu/progs.src | 3 + data/qcsrc/server/cl_physics.qc | 8 +- data/qcsrc/server/movelib.qc | 8 +- data/qcsrc/server/progs.src | 3 + 12 files changed, 428 insertions(+), 64 deletions(-) create mode 100644 data/qcsrc/common/mathlib.qc create mode 100644 data/qcsrc/common/mathlib.qh diff --git a/data/qcsrc/client/View.qc b/data/qcsrc/client/View.qc index dd404d634..2c6b34042 100644 --- a/data/qcsrc/client/View.qc +++ b/data/qcsrc/client/View.qc @@ -922,8 +922,7 @@ void CSQC_WAKIZASHI_HUD() // 0--1 floats. 1 = 100%, 0.6 = 50%. float health, shield, energy, rockets; - float i; - vector p, pp; + vector p; p = drawgetimagesize(SPIDER_CROSS); p_x *= cvar_or("cl_vehicle_spiderbot_cross_size", 1); diff --git a/data/qcsrc/client/progs.src b/data/qcsrc/client/progs.src index 159744123..e7be8c8ff 100644 --- a/data/qcsrc/client/progs.src +++ b/data/qcsrc/client/progs.src @@ -6,6 +6,7 @@ Defs.qc csqc_constants.qc ../common/constants.qh csqc_builtins.qc +../common/mathlib.qh ../common/util.qh ../common/items.qh @@ -54,3 +55,5 @@ bgmscript.qc ../common/gamecommand.qc ../common/mapinfo.qc ../common/items.qc + +../common/mathlib.qc diff --git a/data/qcsrc/common/gamecommand.qc b/data/qcsrc/common/gamecommand.qc index de2858332..d5874b0fc 100644 --- a/data/qcsrc/common/gamecommand.qc +++ b/data/qcsrc/common/gamecommand.qc @@ -767,6 +767,10 @@ float GameCommand_Generic(string command) rpn_setf(0); } } + } else if(rpncmd == "log") { + rpn_setf(log(rpn_getf())); + } else if(rpncmd == "exp") { + rpn_setf(exp(rpn_getf())); } else if(rpncmd == "localtime") { rpn_set(strftime(TRUE, rpn_get())); } else if(rpncmd == "gmtime") { diff --git a/data/qcsrc/common/mathlib.qc b/data/qcsrc/common/mathlib.qc new file mode 100644 index 000000000..6643b0682 --- /dev/null +++ b/data/qcsrc/common/mathlib.qc @@ -0,0 +1,296 @@ +int fpclassify(float x) +{ + if(isnan(x)) + return FP_NAN; + if(isinf(x)) + return FP_INFINITE; + if(x == 0) + return FP_ZERO; + return FP_NORMAL; +} +int isfinite(float x) +{ + return !(isnan(x) || isinf(x)); +} +int isinf(float x) +{ + return (x != 0) && (x + x == x); +} +int isnan(float x) +{ + return isunordered(x, x); +} +int isnormal(float x) +{ + return isfinite(x); +} +int signbit(float x) +{ + return (x < 0); +} + +float acosh(float x) +{ + return log(x + sqrt(x*x - 1)); +} +float asinh(float x) +{ + return log(x + sqrt(x*x + 1)); +} +float atanh(float x) +{ + return 0.5 * log((1+x) / (1-x)); +} +float cosh(float x) +{ + return 0.5 * (exp(x) + exp(-x)); +} +float sinh(float x) +{ + return 0.5 * (exp(x) - exp(-x)); +} +float tanh(float x) +{ + return sinh(x) / cosh(x); +} + +float exp(float x) +{ + return pow(M_E, x); +} +float exp2(float x) +{ + return pow(2, x); +} +float expm1(float x) +{ + return exp(x) - 1; +} + +vector frexp(float x) +{ + vector v; + v_z = 0; + v_y = ilogb(x); + v_x = x / exp2(v_y); + return v; +} +int ilogb(float x) +{ + return floor(log2(x)); +} +float ldexp(float x, int e) +{ + return x * pow(2, e); +} +float log(float x) +{ + // TODO improve speed + float i; + float r, r0; + if(x <= 0) + return nan("log"); + if(!isfinite(x)) + return x; + if(x >= 8) + return -log(1 / x); // faster + if(x < 0.0009765625) + return 2 * log(sqrt(x)); // faster + r = 1; + r0 = 0; + for(i = 1; fabs(r - r0) >= 0.0000001; ++i) + { + // Newton iteration on exp(r) = x: + // r <- r - (exp(r) - x) / (exp(r)) + // r <- r - 1 + x / exp(r) + r0 = r; + r = r0 - 1 + x / exp(r0); + } + print(ftos(i), "\n"); + return r; +} +float log10(float x) +{ + return log(x) * M_LOG10E; +} +float log1p(float x) +{ + return log(x + 1); +} +float log2(float x) +{ + return log(x) * M_LOG2E; +} +float logb(float x) +{ + return floor(log2(x)); +} +vector modf(float f) +{ + return '1 0 0' * (f - trunc(f)) + '0 1 0' * trunc(f); +} + +float scalbn(float x, int n) +{ + return x * pow(2, n); +} + +float cbrt(float x) +{ + return pow(x, 1.0/3.0); +} +float hypot(float x, float y) +{ + return sqrt(x*x + y*y); +} +//float pow(float x, float y); +//float sqrt(float x, float y); + +float erf(float x) +{ + // approximation taken from wikipedia + float y; + y = x*x; + return copysign(sqrt(1 - exp(-y * (1.273239544735163 + 0.14001228868667 * y) / (1 + 0.14001228868667 * y))), x); +} +float erfc(float x) +{ + return 1.0 - erf(x); +} +vector lgamma(float x) +{ + // TODO improve accuracy + if(x < 1 && x == floor(x)) + return nan("gamma") * '1 1 1'; + if(x < 0.1) + { + vector v; + v = lgamma(1.0 - x); + // reflection formula: + // gamma(1-z) * gamma(z) = pi / sin(pi*z) + // lgamma(1-z) + lgamma(z) = log(pi) - log(sin(pi*z)) + // sign of gamma(1-z) = sign of gamma(z) * sign of sin(pi*z) + v_z = sin(M_PI * x); + v_x = log(M_PI) - log(fabs(v_z)) - v_x; + if(v_z < 0) + v_y = -v_y; + v_z = 0; + return v; + } + if(x < 1.1) + return lgamma(x + 1) - log(x) * '1 0 0'; + x -= 1; + return (0.5 * log(2 * M_PI * x) + x * (log(x) - 1)) * '1 0 0' + '0 1 0'; +} +float tgamma(float x) +{ + vector v; + v = lgamma(x); + return exp(v_x) * v_y; +} + +//float ceil(float x); +//float floor(float x); +float nearbyint(float x) +{ + return rint(x); +} +//float rint(float x); +//float round(float x); +float trunc(float x) +{ + return (x>=0) ? floor(x) : ceil(x); +} + +float fmod(float x, float y) +{ + return x - y * trunc(x / y); +} +float remainder(float x, float y) +{ + return x - y * rint(x / y); +} +vector remquo(float x, float y) +{ + vector v; + v_z = 0; + v_y = rint(x / y); + v_x = x - y * v_y; + return v; +} + +float copysign(float x, float y) +{ + return fabs(x) * ((y>0) ? 1 : -1); +} +float nan(string tag) +{ + return sqrt(-1); +} +float nextafter(float x, float y) +{ + // TODO very crude + if(x == y) + return nan("nextafter"); + if(x > y) + return -nextafter(-x, -y); + // now we know that x < y + // so we need the next number > x + float d, a, b; + d = max(fabs(x), 0.00000000000000000000001); + a = x + d; + do + { + d *= 0.5; + b = a; + a = x + d; + } + while(a != x); + return b; +} +float nexttoward(float x, float y) +{ + return nextafter(x, y); +} + +float fdim(float x, float y) +{ + return max(x-y, 0); +} +float fmax(float x, float y) +{ + return max(x, y); +} +float fmin(float x, float y) +{ + return min(x, y); +} +float fma(float x, float y, float z) +{ + return x * y + z; +} + +int isgreater(float x, float y) +{ + return x > y; +} +int isgreaterequal(float x, float y) +{ + return x >= y; +} +int isless(float x, float y) +{ + return x < y; +} +int islessequal(float x, float y) +{ + return x <= y; +} +int islessgreater(float x, float y) +{ + return x < y || x > y; +} +int isunordered(float x, float y) +{ + return !(x < y || x == y || x > y); +} diff --git a/data/qcsrc/common/mathlib.qh b/data/qcsrc/common/mathlib.qh new file mode 100644 index 000000000..9193d27f5 --- /dev/null +++ b/data/qcsrc/common/mathlib.qh @@ -0,0 +1,99 @@ +// + +#define int float + +#define FP_NAN 0 +#define FP_INFINITE 1 +#define FP_ZERO 2 +#define FP_SUBNORMAL 3 +#define FP_NORMAL 4 +int fpclassify(float x); +int isfinite(float x); +int isinf(float x); +int isnan(float x); +int isnormal(float x); +int signbit(float x); + +//float acos(float x); +//float asin(float x); +//float atan(float x); +//float atan2(float y, float x); +//float cos(float x); +//float sin(float x); +//float tan(float x); + +float acosh(float x); +float asinh(float x); +float atanh(float x); +float cosh(float x); +float sinh(float x); +float tanh(float x); + +float exp(float x); +float exp2(float x); +float expm1(float x); + +vector frexp(float x); // returns mantissa as _x, exponent as _y +int ilogb(float x); +float ldexp(float x, int e); +float log(float x); +float log10(float x); +float log1p(float x); +float log2(float x); +float logb(float x); +vector modf(float f); // fraction as _x, integer as _y + +float scalbn(float x, int n); + +float cbrt(float x); +//float fabs(float x); +float hypot(float x, float y); +//float pow(float x, float y); +//float sqrt(float x, float y); + +float erf(float x); +float erfc(float x); +vector lgamma(float x); // value in _x, sign in _y +float tgamma(float x); + +//float ceil(float x); +//float floor(float x); +float nearbyint(float x); +//float rint(float x); +//float round(float x); +float trunc(float x); + +float fmod(float x, float y); +float remainder(float x, float y); +vector remquo(float x, float y); + +float copysign(float x, float y); +float nan(string tag); +float nextafter(float x, float y); +float nexttoward(float x, float y); + +float fdim(float x, float y); +float fmax(float x, float y); +float fmin(float x, float y); +float fma(float x, float y, float z); + +int isgreater(float x, float y); +int isgreaterequal(float x, float y); +int isless(float x, float y); +int islessequal(float x, float y); +int islessgreater(float x, float y); +int isunordered(float x, float y); + +#define M_E 2.7182818284590452354 /* e */ +#define M_LOG2E 1.4426950408889634074 /* log_2 e */ +#define M_LOG10E 0.43429448190325182765 /* log_10 e */ +#define M_LN2 0.69314718055994530942 /* log_e 2 */ +#define M_LN10 2.30258509299404568402 /* log_e 10 */ +#define M_PI 3.14159265358979323846 /* pi */ +#define M_PI_2 1.57079632679489661923 /* pi/2 */ +#define M_PI_4 0.78539816339744830962 /* pi/4 */ +#define M_1_PI 0.31830988618379067154 /* 1/pi */ +#define M_2_PI 0.63661977236758134308 /* 2/pi */ +#define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */ +#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ +#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ diff --git a/data/qcsrc/common/util.qh b/data/qcsrc/common/util.qh index 72bb4a11b..e31865240 100644 --- a/data/qcsrc/common/util.qh +++ b/data/qcsrc/common/util.qh @@ -196,7 +196,7 @@ void WriteInt24_t(float dest, float val); #endif // the NULL function -const var void func_null(void); +const var void func_null(void); FTEQCC_YOU_SUCK_THIS_IS_NOT_UNREFERENCED(func_null) const var string string_null; float float2range11(float f); float float2range01(float f); diff --git a/data/qcsrc/menu/item/listbox.c b/data/qcsrc/menu/item/listbox.c index 98af5e138..a04934820 100644 --- a/data/qcsrc/menu/item/listbox.c +++ b/data/qcsrc/menu/item/listbox.c @@ -223,16 +223,16 @@ void updateControlTopBottomListBox(entity me) me.controlTop = max(0, me.scrollPos / (me.nItems * me.itemHeight)); me.controlBottom = min((me.scrollPos + 1) / (me.nItems * me.itemHeight), 1); - float fmin; - fmin = 1 * me.controlWidth / me.size_y * me.size_x; + float minfactor; + minfactor = 1 * me.controlWidth / me.size_y * me.size_x; f = me.controlBottom - me.controlTop; - if(f < fmin) // FIXME good default? + if(f < minfactor) // FIXME good default? { - // f * X + 1 * (1-X) = fmin - // (f - 1) * X + 1 = fmin - // (f - 1) * X = fmin - 1 - // X = (fmin - 1) / (f - 1) - f = (fmin - 1) / (f - 1); + // f * X + 1 * (1-X) = minfactor + // (f - 1) * X + 1 = minfactor + // (f - 1) * X = minfactor - 1 + // X = (minfactor - 1) / (f - 1) + f = (minfactor - 1) / (f - 1); me.controlTop = me.controlTop * f + 0 * (1 - f); me.controlBottom = me.controlBottom * f + 1 * (1 - f); } diff --git a/data/qcsrc/menu/nexuiz/slider_decibels.c b/data/qcsrc/menu/nexuiz/slider_decibels.c index aa63393f0..18c1f711d 100644 --- a/data/qcsrc/menu/nexuiz/slider_decibels.c +++ b/data/qcsrc/menu/nexuiz/slider_decibels.c @@ -9,49 +9,6 @@ entity makeNexuizDecibelsSlider(float, float, float, string); #ifdef IMPLEMENTATION -float exp(float x) -{ - return pow(2.718281828459045, x); - - /* wtf did I do here? - float i; - float t, s; - - s = 1; - t = 1; - for(i = 1; i < 100; ++i) - { - t *= x; - t /= i; - s += t; - } - - return s; - */ -} - -float ln(float x) -{ - float i; - float r, r0; - - r = 1; - r0 = 0; - for(i = 1; fabs(r - r0) >= 0.05; ++i) - { - // Newton iteration on exp(r) = x: - // r <- r - (exp(r) - x) / (exp(r)) - // r <- r - 1 + x / exp(r) - r0 = r; - r = r0 - 1 + x / exp(r0); - } - dprint("ln: ", ftos(i), " iterations\n"); - - return r; -} - -#define LOG10 2.302585093 - entity makeNexuizDecibelsSlider(float theValueMin, float theValueMax, float theValueStep, string theCvar) { entity me; @@ -72,7 +29,7 @@ void loadCvarsNexuizDecibelsSlider(entity me) else if(v < 0.0005) me.value = -1000000; else - me.value = 0.1 * floor(0.5 + 10.0 * ln(cvar(me.cvarName)) * 10 / LOG10); + me.value = 0.1 * floor(0.5 + 10.0 * log10(cvar(me.cvarName)) * 10); } void saveCvarsNexuizDecibelsSlider(entity me) { @@ -84,7 +41,7 @@ void saveCvarsNexuizDecibelsSlider(entity me) if(me.value < -33) cvar_set(me.cvarName, "0"); else - cvar_set(me.cvarName, ftos(exp(me.value / 10 * LOG10))); + cvar_set(me.cvarName, ftos(pow(10, me.value / 10))); } string valueToTextNexuizDecibelsSlider(entity me, float v) diff --git a/data/qcsrc/menu/progs.src b/data/qcsrc/menu/progs.src index 1261c2183..d90c354aa 100644 --- a/data/qcsrc/menu/progs.src +++ b/data/qcsrc/menu/progs.src @@ -4,6 +4,7 @@ config.qh ../common/util-pre.qh msys.qh mbuiltin.qh +../common/mathlib.qh ../common/util.qh oo/base.h @@ -38,3 +39,5 @@ nexuiz/util.qc ../common/campaign_setup.qc ../common/mapinfo.qc ../common/items.qc + +../common/mathlib.qc diff --git a/data/qcsrc/server/cl_physics.qc b/data/qcsrc/server/cl_physics.qc index e7ae19dd2..963d6abd9 100644 --- a/data/qcsrc/server/cl_physics.qc +++ b/data/qcsrc/server/cl_physics.qc @@ -436,13 +436,13 @@ void PM_Accelerate(vector wishdir, float wishspeed, float wishspeed0, float acce if(sidefric < 0 && (vel_perpend*vel_perpend)) { - float f, fmin; + float f, fminimum; f = (1 + frametime * wishspeed * sidefric); - fmin = (savespeed - vel_straight*vel_straight) / (vel_perpend*vel_perpend); - if(fmin <= 0) + fminimum = (savespeed - vel_straight*vel_straight) / (vel_perpend*vel_perpend); + if(fminimum <= 0) vel_perpend = vel_perpend * f; else - vel_perpend = vel_perpend * min(1, max(fmin, f)); + vel_perpend = vel_perpend * min(1, max(fminimum, f)); } else vel_perpend = vel_perpend * (1 - frametime * wishspeed * sidefric); diff --git a/data/qcsrc/server/movelib.qc b/data/qcsrc/server/movelib.qc index e2a6b65ac..dd3f43f9f 100644 --- a/data/qcsrc/server/movelib.qc +++ b/data/qcsrc/server/movelib.qc @@ -4,13 +4,13 @@ Simulate drag self.velocity = movelib_dragvec(self.velocity,0.02,0.5); **/ -vector movelib_dragvec(float drag, float exp) +vector movelib_dragvec(float drag, float exp_) { float lspeed,ldrag; lspeed = vlen(self.velocity); ldrag = lspeed * drag; - ldrag = ldrag * (drag * exp); + ldrag = ldrag * (drag * exp_); ldrag = 1 - (ldrag / lspeed); return self.velocity * ldrag; @@ -20,12 +20,12 @@ vector movelib_dragvec(float drag, float exp) Simulate drag self.velocity *= movelib_dragflt(somespeed,0.01,0.7); **/ -float movelib_dragflt(float fspeed,float drag,float exp) +float movelib_dragflt(float fspeed,float drag,float exp_) { float ldrag; ldrag = fspeed * drag; - ldrag = ldrag * ldrag * exp; + ldrag = ldrag * ldrag * exp_; ldrag = 1 - (ldrag / fspeed); return ldrag; diff --git a/data/qcsrc/server/progs.src b/data/qcsrc/server/progs.src index a2d745fab..3c636a907 100644 --- a/data/qcsrc/server/progs.src +++ b/data/qcsrc/server/progs.src @@ -6,6 +6,7 @@ pre-builtins.qh builtins.qh extensions.qh post-builtins.qh +../common/mathlib.qh constants.qh ../common/constants.qh ../common/util.qh @@ -167,3 +168,5 @@ monsters/ai.qc monsters/m_monsters.qc monsters/monster_zombie.qc csqcprojectile.qc + +../common/mathlib.qc -- 2.39.2