import { EPS, HALF_PI, PI } from "./api.js";
const mix = (a, b, t) => a + (b - a) * t;
const mixBilinear = (a, b, c, d, u, v) => {
  const iu = 1 - u;
  const iv = 1 - v;
  return a * iu * iv + b * u * iv + c * iu * v + d * u * v;
};
const mixQuadratic = (a, b, c, t) => {
  const s = 1 - t;
  return a * s * s + b * 2 * s * t + c * t * t;
};
const mixCubic = (a, b, c, d, t) => {
  const t2 = t * t;
  const s = 1 - t;
  const s2 = s * s;
  return a * s2 * s + b * 3 * s2 * t + c * 3 * t2 * s + d * t2 * t;
};
const mixHermite = (a, b, c, d, t) => {
  const y1 = 0.5 * (c - a);
  const y2 = 1.5 * (b - c) + 0.5 * (d - a);
  return ((y2 * t + a - b + y1 - y2) * t + y1) * t + b;
};
const mixCubicHermite = (a, ta, b, tb, t) => {
  const s = t - 1;
  const t2 = t * t;
  const s2 = s * s;
  const h00 = (1 + 2 * t) * s2;
  const h10 = t * s2;
  const h01 = t2 * (3 - 2 * t);
  const h11 = t2 * s;
  return h00 * a + h10 * ta + h01 * b + h11 * tb;
};
const mixCubicHermiteFromPoints = (a, b, c, d, t) => {
  d *= 0.5;
  const aa = -0.5 * a + 1.5 * b - 1.5 * c + d;
  const bb = a - 2.5 * b + 2 * c - d;
  const cc = -0.5 * a + 0.5 * c;
  const dd = b;
  const t2 = t * t;
  return t * t2 * aa + t2 * bb + t * cc + dd;
};
const mixBicubic = (s00, s01, s02, s03, s10, s11, s12, s13, s20, s21, s22, s23, s30, s31, s32, s33, u, v) => mixCubicHermiteFromPoints(
  mixCubicHermiteFromPoints(s00, s01, s02, s03, u),
  mixCubicHermiteFromPoints(s10, s11, s12, s13, u),
  mixCubicHermiteFromPoints(s20, s21, s22, s23, u),
  mixCubicHermiteFromPoints(s30, s31, s32, s33, u),
  v
);
const tangentCardinal = (prev, next, scale = 0.5, ta = 0, tc = 2) => scale * ((next - prev) / (tc - ta));
const tangentDiff3 = (prev, curr, next, ta = 0, tb = 1, tc = 2) => 0.5 * ((next - curr) / (tc - tb) + (curr - prev) / (tb - ta));
const tween = (f, from, to) => (t) => mix(from, to, f(t));
const circular = (t) => {
  t = 1 - t;
  return Math.sqrt(1 - t * t);
};
const invCircular = (t) => 1 - circular(1 - t);
const lens = (pos, strength, t) => {
  const impl = strength > 0 ? invCircular : circular;
  const tp = 1 - pos;
  const tl = t <= pos ? impl(t / pos) * pos : 1 - impl((1 - t) / tp) * tp;
  return mix(t, tl, Math.abs(strength));
};
const cosine = (t) => 1 - (Math.cos(t * PI) * 0.5 + 0.5);
const decimated = (n, t) => Math.floor(t * n) / n;
const bounce = (k, amp, t) => {
  const tk = t * k;
  return 1 - amp * Math.sin(tk) / tk * Math.cos(t * HALF_PI);
};
const ease = (ease2, t) => Math.pow(t, ease2);
const impulse = (k, t) => {
  const h = k * t;
  return h * Math.exp(1 - h);
};
const gain = (k, t) => t < 0.5 ? 0.5 * Math.pow(2 * t, k) : 1 - 0.5 * Math.pow(2 - 2 * t, k);
const parabola = (k, t) => Math.pow(4 * t * (1 - t), k);
const cubicPulse = (w, c, t) => {
  t = Math.abs(t - c);
  return t > w ? 0 : (t /= w, 1 - t * t * (3 - 2 * t));
};
const sinc = (t) => t !== 0 ? Math.sin(t) / t : 1;
const sincNormalized = (k, t) => sinc(PI * k * t);
const lanczos = (a, t) => t !== 0 ? -a < t && t < a ? sinc(PI * t) * sinc(PI * t / a) : 0 : 1;
const sigmoid = (bias, k, t) => t != bias ? 1 / (1 + Math.exp(-k * (t - bias))) : 0.5;
const sigmoid01 = (k, t) => sigmoid(0.5, k, t);
const sigmoid11 = (k, t) => sigmoid(0, k, t);
const schlick = (a, b, t) => t <= b ? b * t / (t + a * (b - t) + EPS) : (1 - b) * (t - 1) / (1 - t - a * (b - t) + EPS) + 1;
const expFactor = (a, b, num) => (b / a) ** (1 / num);
const gaussian = (bias, sigma, t) => Math.exp(-((t - bias) ** 2) / (2 * sigma * sigma));
export {
  bounce,
  circular,
  cosine,
  cubicPulse,
  decimated,
  ease,
  expFactor,
  gain,
  gaussian,
  impulse,
  invCircular,
  lanczos,
  lens,
  mix,
  mixBicubic,
  mixBilinear,
  mixCubic,
  mixCubicHermite,
  mixCubicHermiteFromPoints,
  mixHermite,
  mixQuadratic,
  parabola,
  schlick,
  sigmoid,
  sigmoid01,
  sigmoid11,
  sinc,
  sincNormalized,
  tangentCardinal,
  tangentDiff3,
  tween
};
