65 lines
1.9 KiB
C
65 lines
1.9 KiB
C
#ifndef __ACCEL_SYNCHRONOUS_H_
|
|
#define __ACCEL_SYNCHRONOUS_H_
|
|
|
|
#include "../fixedptc.h"
|
|
|
|
struct synchronous_curve_args {
|
|
fpt gamma;
|
|
fpt smooth;
|
|
fpt motivity;
|
|
fpt sync_speed;
|
|
};
|
|
|
|
/**
|
|
* Sensitivity Function for `Synchronous` Acceleration
|
|
*/
|
|
static inline fpt __synchronous_sens_fun(fpt input_speed,
|
|
struct synchronous_curve_args args) {
|
|
fpt log_motivity = fpt_ln(args.motivity);
|
|
fpt gamma_const = fpt_div(args.gamma, log_motivity);
|
|
fpt log_syncspeed = fpt_ln(args.sync_speed);
|
|
fpt syncspeed = args.sync_speed;
|
|
fpt sharpness = args.smooth == 0 ? fpt_rconst(16.0)
|
|
: fpt_div(fpt_rconst(0.5), args.smooth);
|
|
int use_linear_clamp = sharpness >= fpt_rconst(16.0);
|
|
fpt sharpness_recip = fpt_div(FIXEDPT_ONE, sharpness);
|
|
fpt minimum_sens = fpt_div(FIXEDPT_ONE, args.motivity);
|
|
fpt maximum_sens = args.motivity;
|
|
|
|
// if sharpness >= 16, use linear clamp for activation function.
|
|
// linear clamp means: fpt_clamp(input_speed, -1, 1).
|
|
if (use_linear_clamp) {
|
|
fpt log_space = fpt_mul(gamma_const, (fpt_ln(input_speed) - log_syncspeed));
|
|
|
|
if (log_space < -FIXEDPT_ONE) {
|
|
return minimum_sens;
|
|
}
|
|
|
|
if (log_space > FIXEDPT_ONE) {
|
|
return maximum_sens;
|
|
}
|
|
|
|
return fpt_exp(fpt_mul(log_space, log_motivity));
|
|
}
|
|
|
|
if (input_speed == syncspeed) {
|
|
return FIXEDPT_ONE;
|
|
}
|
|
|
|
fpt log_x = fpt_ln(input_speed);
|
|
fpt log_diff = log_x - log_syncspeed;
|
|
|
|
if (log_diff > 0) {
|
|
fpt log_space = fpt_mul(gamma_const, log_diff);
|
|
fpt exponent =
|
|
fpt_pow(fpt_tanh(fpt_pow(log_space, sharpness)), sharpness_recip);
|
|
return fpt_exp(fpt_mul(exponent, log_motivity));
|
|
} else {
|
|
fpt log_space = fpt_mul(-gamma_const, log_diff);
|
|
fpt exponent =
|
|
-fpt_pow(fpt_tanh(fpt_pow(log_space, sharpness)), sharpness_recip);
|
|
return fpt_exp(fpt_mul(exponent, log_motivity));
|
|
}
|
|
}
|
|
#endif
|