#if 0
/*─────────────────────────────────────────────────────────────────╗
│ To the extent possible under law, Justine Tunney has waived      │
│ all copyright and related or neighboring rights to this file,    │
│ as it is written in the following disclaimers:                   │
│   • http://unlicense.org/                                        │
│   • http://creativecommons.org/publicdomain/zero/1.0/            │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/calls/calls.h"
#include "libc/macros.internal.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/sig.h"
#include "libc/testlib/ezbench.h"

/**
 * @fileoverview Fast Division Using Multiplication Tutorial
 *
 * Expected program output:
 *
 *     23 / 3 = 7
 *     0x5555555555555556 1 1
 *     division   l: 16𝑐  5𝑛𝑠
 *     fast div   l:  5𝑐  2𝑛𝑠
 *     precomps   l: 70𝑐 23𝑛𝑠
 */

struct Divisor {
  uint64_t m;
  uint8_t s;
  uint8_t t;
};

struct Divisor GetDivisor(uint64_t d) {
  int b;
  uint128_t x;
  if (!d) raise(SIGFPE);
  b = __builtin_clzll(d) ^ 63;
  x = -d & (((1ull << b) - 1) | (1ull << b));
  return (struct Divisor){(x << 64) / d + 1, MIN(1, b + 1), MAX(0, b)};
}

uint64_t Divide(uint64_t x, struct Divisor d) {
  uint128_t t;
  uint64_t l, h;
  t = d.m;
  t *= x;
  l = t;
  h = t >> 64;
  l = (x - h) >> d.s;
  return (h + l) >> d.t;
}

int main(int argc, char *argv[]) {
  printf("23 / 3 = %ld\n", Divide(23, GetDivisor(3)));
  volatile struct Divisor v = GetDivisor(3);
  volatile uint64_t x = 23, y = 3, z;
  EZBENCH2("division", donothing, z = x / y);
  EZBENCH2("fast div", donothing, z = Divide(x, v));
  EZBENCH2("precomp ", donothing, v = GetDivisor(y));
  return 0;
}