summaryrefslogtreecommitdiff
path: root/common/accel-power.hpp
diff options
context:
space:
mode:
authora1xd <[email protected]>2021-09-24 02:04:43 -0400
committerGitHub <[email protected]>2021-09-24 02:04:43 -0400
commit2896b8a09ce42e965705c58593b8738adc454f7f (patch)
tree71e4d0cff60b5a1ad11427d78e1f8c7b775e5690 /common/accel-power.hpp
parentMerge pull request #107 from a1xd/1.5.0-fix (diff)
parentmake note clearer (diff)
downloadrawaccel-1.6.0.tar.xz
rawaccel-1.6.0.zip
Merge pull request #108 from a1xd/1.6r2HEADv1.6.0masterdark-mode
v1.6
Diffstat (limited to 'common/accel-power.hpp')
-rw-r--r--common/accel-power.hpp161
1 files changed, 149 insertions, 12 deletions
diff --git a/common/accel-power.hpp b/common/accel-power.hpp
index c8faabb..8e3f417 100644
--- a/common/accel-power.hpp
+++ b/common/accel-power.hpp
@@ -2,25 +2,162 @@
#include "rawaccel-base.hpp"
-#include <math.h>
+#include <float.h>
namespace rawaccel {
- /// <summary> Struct to hold power (non-additive) acceleration implementation. </summary>
- struct power {
- double pre_scale;
- double exponent;
- double post_scale;
+ struct power_base {
+ vec2d offset;
+ double scale;
+ double constant;
+
+ power_base(const accel_args& args)
+ {
+ auto n = args.exponent_power;
+
+ if (args.cap_mode != cap_mode::io) {
+ scale = args.scale;
+ }
+ else if (args.gain) {
+ scale = scale_from_gain_point(args.cap.x, args.cap.y, n);
+ }
+ else {
+ /*
+ * special case for legacy + io cap mode
+ *
+ * offset is ignored because of the circular dependency:
+ * scale -> constant -> offset
+ */
+ offset = {};
+ constant = 0;
+ scale = scale_from_sens_point(args.cap.x, args.cap.y, n, constant);
+ return;
+ }
+
+ offset.x = gain_inverse(args.output_offset, n, scale);
+ offset.y = args.output_offset;
+ constant = offset.x * offset.y * n / (n + 1);
+ }
+
+ double base_fn(double x, const accel_args& args) const
+ {
+ if (x <= offset.x) {
+ return offset.y;
+ }
+ else {
+ return pow(scale * x, args.exponent_power) + constant / x;
+ }
+ }
+
+ static double gain(double input, double power, double scale)
+ {
+ return (power + 1) * pow(input * scale, power);
+ }
+
+ static double gain_inverse(double gain, double power, double scale)
+ {
+ return pow(gain / (power + 1), 1 / power) / scale;
+ }
+
+ static double scale_from_gain_point(double input, double gain, double power)
+ {
+ return pow(gain / (power + 1), 1 / power) / input;
+ }
+
+ static double scale_from_sens_point(double input, double sens, double power, double C)
+ {
+ return pow(sens - C / input, 1 / power) / input;
+ }
+ };
+
+ template <bool Gain> struct power;
+
+ template <>
+ struct power<LEGACY> : power_base {
+ double cap = DBL_MAX;
+
+ power(const accel_args& args) :
+ power_base(args)
+ {
+
+ switch (args.cap_mode){
+ case cap_mode::io:
+ cap = args.cap.y;
+ break;
+ case cap_mode::in:
+ if (args.cap.x > 0) cap = base_fn(args.cap.x, args);
+ break;
+ case cap_mode::out:
+ default:
+ if (args.cap.y > 0) cap = args.cap.y;
+ break;
+ }
+ }
+
+ double operator()(double speed, const accel_args& args) const
+ {
+ return minsd(base_fn(speed, args), cap);
+ }
+
+ };
+
+ template <>
+ struct power<GAIN> : power_base {
+ vec2d cap = { DBL_MAX, DBL_MAX };
+ double constant_b;
power(const accel_args& args) :
- pre_scale(args.scale),
- exponent(args.exponent),
- post_scale(args.weight) {}
+ power_base(args)
+ {
+ switch (args.cap_mode) {
+ case cap_mode::io:
+ cap = args.cap;
+ break;
+ case cap_mode::in:
+ if (args.cap.x > 0) {
+
+ if (args.cap.x <= offset.x) {
+ cap.x = 0;
+ cap.y = offset.y;
+ constant_b = 0;
+ return;
+ }
+
+ cap.x = args.cap.x;
+ cap.y = gain(
+ args.cap.x,
+ args.exponent_power,
+ scale);
+ }
+ break;
+ case cap_mode::out:
+ default:
+ if (args.cap.y > 0) {
+ cap.x = gain_inverse(
+ args.cap.y,
+ args.exponent_power,
+ scale);
+ cap.y = args.cap.y;
+ }
+ break;
+ }
+
+ constant_b = integration_constant(cap.x, cap.y, base_fn(cap.x, args));
+ }
+
+ double operator()(double speed, const accel_args& args) const
+ {
+ if (speed < cap.x) {
+ return base_fn(speed, args);
+ }
+ else {
+ return cap.y + constant_b / speed;
+ }
+ }
- double operator()(double speed) const
+ static double integration_constant(double input, double gain, double output)
{
- // f(x) = (mx)^k
- return post_scale * pow(speed * pre_scale, exponent);
+ return (output - gain) * input;
}
};