#include "halton.h"
#include <cassert>

using namespace std;

// compute \phi_p^\pi(i)
double phi(int p, permutation &pi, int i) {
  double r = 0., pl = 1./p;
  while(i) {
    r += (double)pi[i%p]*pl;
    pl /= p;
    i /= p;
  }
  return r;
}

halton::halton(int dim, int *p) : dim(dim), p(p) {
  assert(dim > 0);
  for(int i = 0; i < dim; i++) {
    assert(p[i] > 2); // otherwise there is only one permutation : no optimisations are possible
    pi.emplace_back(p[i]);
  }
}

permutation& halton::get_pi(int i) {
  assert(0 <= i && i < dim);
  return pi[i];
}

void halton::set_pis(vector<permutation> &pis) {
  assert((int)pis.size() == dim);
  for(int i = 0; i < dim; i++)
    assert(pis[i].get_size() == p[i]);
  pi = pis;
}

void halton::compute(int i, double* res) {
  for(int d = 0; d < dim; d++) {
    res[d] = phi(p[d], pi[d], i);
  }
}

int halton::get_p(int i) {
  assert(0 <= i && i < dim);
  return p[i];
}
