/* -*- mode:c++; coding: koi8-r -*- */

/* $Id: BinomialVariation.cpp,v 1.1 2003/04/14 19:35:28 cher Exp $ */
/* Copyright (C) 2003 Alexander Chernov <cher@unicorn.cmc.msu.ru> */

/*
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.

 See the `COPYING' file for the full terms and conditions.
*/

#include "BinomialVariation.hpp"
#include "../double/cephes.h"

BinomialVariation::BinomialVariation(Random *_rnd, int _n, double _p)
  throw (BadArgsError)
{
  if (!_rnd) throw BadArgsError();
  if (_n <= 0) throw BadArgsError();
  if (_p < 0 || _p > 1) throw BadArgsError();

  rnd = _rnd;
  n = _n;
  p = _p;
  v = new double[n + 2];
  v[0] = 0.0;
  v[n + 1] = 1.0;
  for (int i = 1; i <= n; i++)
    v[i] = cephes_bdtr(i - 1, n, p);
}

BinomialVariation::~BinomialVariation()
  throw ()
{
  delete[] v;
}

int
BinomialVariation::get()
  throw ()
{
  double x;
  int k;

  if (p == 0) return 0;
  if (p == 1) return n;
  x = rnd->uniform();
  // dumb! better use dichotomy!
  for (k = 0; k <= n; k++) {
    if (v[k + 1] > x) return k;
  }
  return n;
}

/*
 * Local variables:
 *  compile-command: "make -C .."
 *  c++-font-lock-extra-types: ("[A-Z]\\sw*[a-z]\\sw*")
 * End:
 */
