aboutsummaryrefslogtreecommitdiff
path: root/shared/common/clc.c
diff options
context:
space:
mode:
Diffstat (limited to 'shared/common/clc.c')
-rw-r--r--shared/common/clc.c84
1 files changed, 84 insertions, 0 deletions
diff --git a/shared/common/clc.c b/shared/common/clc.c
new file mode 100644
index 0000000..b4d1208
--- /dev/null
+++ b/shared/common/clc.c
@@ -0,0 +1,84 @@
+/* Copyright (c) 2004 krzYszcz and others.
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
+
+#include <math.h>
+
+/* Problem: find a function f : p -> q (where p is user's curve control
+ parameter, q is log factor) such that the curves will bend in
+ a semi-linear way over the p's range of 0..1. The curve function is
+ then g(x, p) = (exp(f(p) * x) - 1) / (exp(f(p)) - 1), where x is
+ curve's domain. If, for example, the points g(0.5, p) are to make
+ a semi-linear pattern, then the solution is a function f that minimizes
+ the integral of the error function e(p) = sqr(((1-p)/2)-g(.5, p))
+ over 0..1. Until someone does this analytically, we are left with
+ a lame formula, which has been tweaked and tested in gnuplot:
+ f(p) = h(p) / (1 - h(p)), where h(p) = (((p + 1e-20) * 1.2) ** .41) * .91.
+ The file curve.gp, in the sickle's source directory, may come handy,
+ in case there is anyone, who fancy tweaking it even further.
+
+ To implement this, start from these equations:
+ nhops = npoints - 1
+ bb * mm ^ nhops = bb + 1
+ (bb ^ 2) * (mm ^ nhops) = ((exp(ff/2) - 1) / (exp(ff) - 1)) ^ 2
+
+ and calculate:
+ hh = pow(((p + c1) * c2), c3) * c4
+ ff = hh / (1 - hh)
+ eff = exp(ff) - 1
+ gh = (exp(ff * .5) - 1) / eff
+ bb = gh * (gh / (1 - (gh + gh)))
+ mm = ((exp(ff * (1/nhops)) - 1) / (eff * bb)) + 1
+
+ The loop is:
+ for (vv = bb, i = 0; i <= nhops; vv *= mm, i++)
+ result = (vv - bb) * (y1 - y0) + y0
+ where y0, y1 are start and destination values
+
+ This formula generates curves with < .000004% deviation from the straight
+ line for p = 0 at half-domain, range 1. There are no nans for -1 <= p <= 1.
+*/
+
+#define CLCCURVE_C1 1e-20
+#define CLCCURVE_C2 1.2
+#define CLCCURVE_C3 0.41
+#define CLCCURVE_C4 0.91
+
+void clccurve_coefs(int nhops, double crv, double *bbp, double *mmp)
+{
+ if (nhops > 0)
+ {
+ double hh, ff, eff, gh;
+ if (crv < 0)
+ {
+ if (crv < -1.)
+ crv = -1.;
+ hh = pow(((CLCCURVE_C1 - crv) * CLCCURVE_C2), CLCCURVE_C3)
+ * CLCCURVE_C4;
+ ff = hh / (1. - hh);
+ eff = exp(ff) - 1.;
+ gh = (exp(ff * .5) - 1.) / eff;
+ *bbp = gh * (gh / (1. - (gh + gh)));
+ *mmp = 1. / (((exp(ff * (1. / (double)nhops)) - 1.) /
+ (eff * *bbp)) + 1.);
+ *bbp += 1.;
+ }
+ else
+ {
+ if (crv > 1.)
+ crv = 1.;
+ hh = pow(((crv + CLCCURVE_C1) * CLCCURVE_C2), CLCCURVE_C3)
+ * CLCCURVE_C4;
+ ff = hh / (1. - hh);
+ eff = exp(ff) - 1.;
+ gh = (exp(ff * .5) - 1.) / eff;
+ *bbp = gh * (gh / (1. - (gh + gh)));
+ *mmp = ((exp(ff * (1. / (double)nhops)) - 1.) /
+ (eff * *bbp)) + 1.;
+ }
+ }
+ else if (crv < 0)
+ *bbp = 2., *mmp = 1.;
+ else
+ *bbp = *mmp = 1.;
+}