80 lines
3.1 KiB
C
80 lines
3.1 KiB
C
#include "set_plot.h"
|
|
#include <math.h>
|
|
|
|
static double clamp(double v, double lo, double hi) { return fmin(hi, fmax(lo, v)); }
|
|
static int finite_values(const double *v, size_t n) {
|
|
size_t i;
|
|
for (i = 0; i < n; ++i) if (!isfinite(v[i])) return 0;
|
|
return 1;
|
|
}
|
|
|
|
uint32_t set_plot_abi_version(void) { return 1U; }
|
|
|
|
size_t set_plot_eval(uint32_t op, const double *v, size_t n, double *out, size_t cap) {
|
|
static const size_t sizes[] = {10, 3, 4, 4, 6, 2, 3, 2, 4};
|
|
double span, fraction;
|
|
if (op > SET_PLOT_LIMITS || !v || !out || n != sizes[op] ||
|
|
cap < (op == SET_PLOT_TRANSFORM || op == SET_PLOT_LIMITS ? 4U : 1U)) return 0;
|
|
if (op == SET_PLOT_TRANSFORM) {
|
|
double w, h, fx, fy;
|
|
if (!finite_values(v, 4) || v[2] < 1.0/128 || v[2] > 1 ||
|
|
v[3] < 1.0/128 || v[3] > 1 || v[0] < 0 || v[1] < 0 ||
|
|
v[0] + v[2] > 1.000000000001 || v[1] + v[3] > 1.000000000001) return 0;
|
|
out[0] = v[0]; out[1] = v[1]; out[2] = v[2]; out[3] = v[3];
|
|
if (!finite_values(v + 4, 6) || v[4] <= 0 || v[5] <= 0) return 4;
|
|
w = clamp(v[2] / v[4], 1.0/128, 1);
|
|
h = clamp(v[3] / v[5], 1.0/128, 1);
|
|
fx = clamp(v[8], 0, 1); fy = clamp(v[9], 0, 1);
|
|
out[0] = clamp(v[0] + (v[2] - w) * fx - v[6] * w, 0, 1 - w);
|
|
out[1] = clamp(v[1] + (v[3] - h) * fy - v[7] * h, 0, 1 - h);
|
|
out[2] = w; out[3] = h;
|
|
return 4;
|
|
}
|
|
if (!finite_values(v, n)) return 0;
|
|
switch (op) {
|
|
case SET_PLOT_AXIS:
|
|
if (v[2] < 0) return 0;
|
|
out[0] = fmax(fabs(v[0]), fabs(v[1])) <= v[2] ? 0 :
|
|
(fabs(v[1]) > fabs(v[0]) ? 2 : 1);
|
|
break;
|
|
case SET_PLOT_FRACTION:
|
|
case SET_PLOT_VALUE:
|
|
span = v[2] - v[1];
|
|
if (!isfinite(span) || span <= 0 || (v[3] != 0 && v[3] != 1)) return 0;
|
|
if (op == SET_PLOT_FRACTION) {
|
|
fraction = (v[0] - v[1]) / span;
|
|
out[0] = v[3] ? 1 - fraction : fraction;
|
|
} else {
|
|
fraction = v[3] ? 1 - v[0] : v[0];
|
|
out[0] = v[1] + fraction * span;
|
|
}
|
|
break;
|
|
case SET_PLOT_DRAG:
|
|
span = v[4] - v[3];
|
|
if (!isfinite(span) || span <= 0 || v[2] <= 0 || (v[5] != 0 && v[5] != 1)) return 0;
|
|
out[0] = clamp(v[0] + (v[5] ? -1 : 1) * (v[1] / v[2]) * span, v[3], v[4]);
|
|
break;
|
|
case SET_PLOT_TICK_STEP: {
|
|
double raw, magnitude, scaled;
|
|
if (v[0] <= 0 || v[1] <= 0) return 0;
|
|
raw = v[0] / fmax(2, floor(v[1] / 100));
|
|
magnitude = pow(10, floor(log10(raw)));
|
|
if (magnitude <= 0 || !isfinite(magnitude)) return 0;
|
|
scaled = raw / magnitude;
|
|
out[0] = (scaled <= 1 ? 1 : scaled <= 2 ? 2 : scaled <= 5 ? 5 : 10) * magnitude;
|
|
break;
|
|
}
|
|
case SET_PLOT_DELTA: out[0] = (v[1] - v[0]) * v[2]; break;
|
|
case SET_PLOT_DB_DELTA:
|
|
if (v[0] == 0 || v[1] == 0) return 0;
|
|
out[0] = 20 * log10(fabs(v[1] / v[0]));
|
|
break;
|
|
case SET_PLOT_LIMITS:
|
|
if (v[0] >= v[1] || v[2] >= v[3]) return 0;
|
|
out[0] = v[0]; out[1] = v[1]; out[2] = v[2]; out[3] = v[3];
|
|
return 4;
|
|
default: return 0;
|
|
}
|
|
return isfinite(out[0]) ? 1 : 0;
|
|
}
|