-- Create 2 random numeric values whose product has
--
--  1. n random decimal digits, followed by
--  2. '5' followed by z '0' decimal digits, followed by
--  3. m more random decimal digits
--  4. a decimal weight w
CREATE OR REPLACE FUNCTION mul_var_rscale_test_vals(IN n int,
                                                    IN z int,
                                                    IN m int,
                                                    IN w int,
                                                    OUT x numeric,
                                                    OUT y numeric)
AS
$$
DECLARE
  len int;
  res_str text;
  res numeric;
  xlen int;
  ylen int;
  rw int;
  xweight int;
  yweight int;
BEGIN
  len := n + z + m + 1;
  res_str := random(('1e'||(n-1))::numeric, ('1e'||n)::numeric-1)::text
          || '5' || repeat('0', z)
          || random(('1e'||(m-1))::numeric, ('1e'||m)::numeric-1)::text
          || repeat('0', len);
  res := res_str::numeric;

  xlen := len + random(-m/2, m/2);
  ylen := 2*len - xlen;
  x := random(('1e'||(xlen-1))::numeric, ('1e'||xlen)::numeric-1);
  y := trunc(ceil(res / x));

  rw := greatest(20, abs(w));
  xweight := w/2 + random(-rw, rw);
  x := x * ('1e'||(xweight-xlen))::numeric;

  yweight := w - xweight + 1;
  y := y * ('1e'||(yweight-ylen))::numeric;
END
$$
LANGUAGE plpgsql;

SELECT setseed(0);
CREATE TEMP TABLE results AS
  WITH t1(n, z, m, w) AS (
    SELECT random(1,20), 5, random(1,8), random(-20,0)
    FROM generate_series(1,1000000)
  ), t2 AS (
    SELECT t1.*, x, y, x*y AS prod
    FROM t1, LATERAL mul_var_rscale_test_vals(n, z, m, w)
  )
  SELECT n, z, m, w, x, y,
         round(prod, n-w-1) AS expected,
         numeric_mul_rscale(x, y, n-w-1-scale(prod)) FROM t2;

CREATE TEMP TABLE diffs AS
  SELECT * FROM results WHERE numeric_mul_rscale != expected;

SELECT count(*) FROM diffs;

SELECT DISTINCT expected - numeric_mul_rscale FROM diffs;

\copy diffs to diffs.dump
