import { describe, it, expect } from 'vitest';
import { bilinearInterp } from '../bilinear-interp';
import { linearInterp1D, logInterp1D } from '../log-interp';

describe('Interpolação Bilinear (sec. 3.2)', () => {
  it('Ponto exato: f(2, 2) = 5', () => {
    const grid = {
      xs: [1, 2, 3],
      ys: [1, 2, 3],
      values: [
        [1, 2, 3],
        [4, 5, 6],
        [7, 8, 9],
      ],
    };
    expect(bilinearInterp(grid, 2, 2)).toBe(5);
  });

  it('Ponto intermediário: f(1.5, 1.5) ≈ 4.0', () => {
    const grid = {
      xs: [1, 2],
      ys: [1, 2],
      values: [
        [0, 4],
        [4, 8],
      ],
    };
    // Interpolação: (1/4)·(0+4+4+8) = 4
    expect(bilinearInterp(grid, 1.5, 1.5)).toBeCloseTo(4.0, 1);
  });

  it('Clamp em valores fora do intervalo', () => {
    const grid = {
      xs: [0, 10],
      ys: [0, 10],
      values: [
        [0, 5],
        [5, 10],
      ],
    };
    // Valor exato na extremidade
    expect(bilinearInterp(grid, 10, 10)).toBe(10);
    expect(bilinearInterp(grid, 0, 0)).toBe(0);
    // Extrapolação linear além do intervalo
    expect(bilinearInterp(grid, 20, 20)).toBe(20);
  });
});

describe('Interpolação 1D', () => {
  it('linearInterp1D: f(1.5) entre 0 e 2 → 1.0', () => {
    expect(linearInterp1D([0, 2], [0, 2], 1.5)).toBeCloseTo(1.5, 5);
  });

  it('logInterp1D: log-mean entre 1 e 100 → ≈ 10', () => {
    const r = logInterp1D([1, 100], [0, 1], 10);
    expect(r).toBeCloseTo(0.5, 5);
  });
});