Blame gst-libs/gst/fft/kiss_fft_f64.c

Packit 971217
/*
Packit 971217
Copyright (c) 2003-2004, Mark Borgerding
Packit 971217
Packit 971217
All rights reserved.
Packit 971217
Packit 971217
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Packit 971217
Packit 971217
    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Packit 971217
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Packit 971217
    * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
Packit 971217
Packit 971217
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 971217
*/
Packit 971217
#ifdef HAVE_CONFIG_H
Packit 971217
#include "config.h"
Packit 971217
#endif
Packit 971217
Packit 971217
#include "_kiss_fft_guts_f64.h"
Packit 971217
/* The guts header contains all the multiplication and addition macros that are defined for
Packit 971217
 fixed or floating point complex numbers.  It also delares the kf_ internal functions.
Packit 971217
 */
Packit 971217
Packit 971217
static kiss_fft_f64_cpx *scratchbuf = NULL;
Packit 971217
static size_t nscratchbuf = 0;
Packit 971217
static kiss_fft_f64_cpx *tmpbuf = NULL;
Packit 971217
static size_t ntmpbuf = 0;
Packit 971217
Packit 971217
#define CHECKBUF(buf,nbuf,n) \
Packit 971217
    do { \
Packit 971217
        if ( nbuf < (size_t)(n) ) {\
Packit 971217
            free(buf); \
Packit 971217
            buf = (kiss_fft_f64_cpx*)KISS_FFT_F64_MALLOC(sizeof(kiss_fft_f64_cpx)*(n)); \
Packit 971217
            nbuf = (size_t)(n); \
Packit 971217
        } \
Packit 971217
   }while(0)
Packit 971217
Packit 971217
Packit 971217
static void
Packit 971217
kf_bfly2 (kiss_fft_f64_cpx * Fout,
Packit 971217
    const size_t fstride, const kiss_fft_f64_cfg st, int m)
Packit 971217
{
Packit 971217
  kiss_fft_f64_cpx *Fout2;
Packit 971217
  kiss_fft_f64_cpx *tw1 = st->twiddles;
Packit 971217
  kiss_fft_f64_cpx t;
Packit 971217
Packit 971217
  Fout2 = Fout + m;
Packit 971217
  do {
Packit 971217
    C_FIXDIV (*Fout, 2);
Packit 971217
    C_FIXDIV (*Fout2, 2);
Packit 971217
Packit 971217
    C_MUL (t, *Fout2, *tw1);
Packit 971217
    tw1 += fstride;
Packit 971217
    C_SUB (*Fout2, *Fout, t);
Packit 971217
    C_ADDTO (*Fout, t);
Packit 971217
    ++Fout2;
Packit 971217
    ++Fout;
Packit 971217
  } while (--m);
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
kf_bfly4 (kiss_fft_f64_cpx * Fout,
Packit 971217
    const size_t fstride, const kiss_fft_f64_cfg st, const size_t m)
Packit 971217
{
Packit 971217
  kiss_fft_f64_cpx *tw1, *tw2, *tw3;
Packit 971217
  kiss_fft_f64_cpx scratch[6];
Packit 971217
  size_t k = m;
Packit 971217
  const size_t m2 = 2 * m;
Packit 971217
  const size_t m3 = 3 * m;
Packit 971217
Packit 971217
  tw3 = tw2 = tw1 = st->twiddles;
Packit 971217
Packit 971217
  do {
Packit 971217
    C_FIXDIV (*Fout, 4);
Packit 971217
    C_FIXDIV (Fout[m], 4);
Packit 971217
    C_FIXDIV (Fout[m2], 4);
Packit 971217
    C_FIXDIV (Fout[m3], 4);
Packit 971217
Packit 971217
    C_MUL (scratch[0], Fout[m], *tw1);
Packit 971217
    C_MUL (scratch[1], Fout[m2], *tw2);
Packit 971217
    C_MUL (scratch[2], Fout[m3], *tw3);
Packit 971217
Packit 971217
    C_SUB (scratch[5], *Fout, scratch[1]);
Packit 971217
    C_ADDTO (*Fout, scratch[1]);
Packit 971217
    C_ADD (scratch[3], scratch[0], scratch[2]);
Packit 971217
    C_SUB (scratch[4], scratch[0], scratch[2]);
Packit 971217
    C_SUB (Fout[m2], *Fout, scratch[3]);
Packit 971217
    tw1 += fstride;
Packit 971217
    tw2 += fstride * 2;
Packit 971217
    tw3 += fstride * 3;
Packit 971217
    C_ADDTO (*Fout, scratch[3]);
Packit 971217
Packit 971217
    if (st->inverse) {
Packit 971217
      Fout[m].r = scratch[5].r - scratch[4].i;
Packit 971217
      Fout[m].i = scratch[5].i + scratch[4].r;
Packit 971217
      Fout[m3].r = scratch[5].r + scratch[4].i;
Packit 971217
      Fout[m3].i = scratch[5].i - scratch[4].r;
Packit 971217
    } else {
Packit 971217
      Fout[m].r = scratch[5].r + scratch[4].i;
Packit 971217
      Fout[m].i = scratch[5].i - scratch[4].r;
Packit 971217
      Fout[m3].r = scratch[5].r - scratch[4].i;
Packit 971217
      Fout[m3].i = scratch[5].i + scratch[4].r;
Packit 971217
    }
Packit 971217
    ++Fout;
Packit 971217
  } while (--k);
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
kf_bfly3 (kiss_fft_f64_cpx * Fout,
Packit 971217
    const size_t fstride, const kiss_fft_f64_cfg st, size_t m)
Packit 971217
{
Packit 971217
  size_t k = m;
Packit 971217
  const size_t m2 = 2 * m;
Packit 971217
  kiss_fft_f64_cpx *tw1, *tw2;
Packit 971217
  kiss_fft_f64_cpx scratch[5];
Packit 971217
  kiss_fft_f64_cpx epi3;
Packit 971217
Packit 971217
  epi3 = st->twiddles[fstride * m];
Packit 971217
Packit 971217
  tw1 = tw2 = st->twiddles;
Packit 971217
Packit 971217
  do {
Packit 971217
    C_FIXDIV (*Fout, 3);
Packit 971217
    C_FIXDIV (Fout[m], 3);
Packit 971217
    C_FIXDIV (Fout[m2], 3);
Packit 971217
Packit 971217
    C_MUL (scratch[1], Fout[m], *tw1);
Packit 971217
    C_MUL (scratch[2], Fout[m2], *tw2);
Packit 971217
Packit 971217
    C_ADD (scratch[3], scratch[1], scratch[2]);
Packit 971217
    C_SUB (scratch[0], scratch[1], scratch[2]);
Packit 971217
    tw1 += fstride;
Packit 971217
    tw2 += fstride * 2;
Packit 971217
Packit 971217
    Fout[m].r = Fout->r - HALF_OF (scratch[3].r);
Packit 971217
    Fout[m].i = Fout->i - HALF_OF (scratch[3].i);
Packit 971217
Packit 971217
    C_MULBYSCALAR (scratch[0], epi3.i);
Packit 971217
Packit 971217
    C_ADDTO (*Fout, scratch[3]);
Packit 971217
Packit 971217
    Fout[m2].r = Fout[m].r + scratch[0].i;
Packit 971217
    Fout[m2].i = Fout[m].i - scratch[0].r;
Packit 971217
Packit 971217
    Fout[m].r -= scratch[0].i;
Packit 971217
    Fout[m].i += scratch[0].r;
Packit 971217
Packit 971217
    ++Fout;
Packit 971217
  } while (--k);
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
kf_bfly5 (kiss_fft_f64_cpx * Fout,
Packit 971217
    const size_t fstride, const kiss_fft_f64_cfg st, int m)
Packit 971217
{
Packit 971217
  kiss_fft_f64_cpx *Fout0, *Fout1, *Fout2, *Fout3, *Fout4;
Packit 971217
  int u;
Packit 971217
  kiss_fft_f64_cpx scratch[13];
Packit 971217
  kiss_fft_f64_cpx *twiddles = st->twiddles;
Packit 971217
  kiss_fft_f64_cpx *tw;
Packit 971217
  kiss_fft_f64_cpx ya, yb;
Packit 971217
Packit 971217
  ya = twiddles[fstride * m];
Packit 971217
  yb = twiddles[fstride * 2 * m];
Packit 971217
Packit 971217
  Fout0 = Fout;
Packit 971217
  Fout1 = Fout0 + m;
Packit 971217
  Fout2 = Fout0 + 2 * m;
Packit 971217
  Fout3 = Fout0 + 3 * m;
Packit 971217
  Fout4 = Fout0 + 4 * m;
Packit 971217
Packit 971217
  tw = st->twiddles;
Packit 971217
  for (u = 0; u < m; ++u) {
Packit 971217
    C_FIXDIV (*Fout0, 5);
Packit 971217
    C_FIXDIV (*Fout1, 5);
Packit 971217
    C_FIXDIV (*Fout2, 5);
Packit 971217
    C_FIXDIV (*Fout3, 5);
Packit 971217
    C_FIXDIV (*Fout4, 5);
Packit 971217
    scratch[0] = *Fout0;
Packit 971217
Packit 971217
    C_MUL (scratch[1], *Fout1, tw[u * fstride]);
Packit 971217
    C_MUL (scratch[2], *Fout2, tw[2 * u * fstride]);
Packit 971217
    C_MUL (scratch[3], *Fout3, tw[3 * u * fstride]);
Packit 971217
    C_MUL (scratch[4], *Fout4, tw[4 * u * fstride]);
Packit 971217
Packit 971217
    C_ADD (scratch[7], scratch[1], scratch[4]);
Packit 971217
    C_SUB (scratch[10], scratch[1], scratch[4]);
Packit 971217
    C_ADD (scratch[8], scratch[2], scratch[3]);
Packit 971217
    C_SUB (scratch[9], scratch[2], scratch[3]);
Packit 971217
Packit 971217
    Fout0->r += scratch[7].r + scratch[8].r;
Packit 971217
    Fout0->i += scratch[7].i + scratch[8].i;
Packit 971217
Packit 971217
    scratch[5].r =
Packit 971217
        scratch[0].r + S_MUL (scratch[7].r, ya.r) + S_MUL (scratch[8].r, yb.r);
Packit 971217
    scratch[5].i =
Packit 971217
        scratch[0].i + S_MUL (scratch[7].i, ya.r) + S_MUL (scratch[8].i, yb.r);
Packit 971217
Packit 971217
    scratch[6].r = S_MUL (scratch[10].i, ya.i) + S_MUL (scratch[9].i, yb.i);
Packit 971217
    scratch[6].i = -S_MUL (scratch[10].r, ya.i) - S_MUL (scratch[9].r, yb.i);
Packit 971217
Packit 971217
    C_SUB (*Fout1, scratch[5], scratch[6]);
Packit 971217
    C_ADD (*Fout4, scratch[5], scratch[6]);
Packit 971217
Packit 971217
    scratch[11].r =
Packit 971217
        scratch[0].r + S_MUL (scratch[7].r, yb.r) + S_MUL (scratch[8].r, ya.r);
Packit 971217
    scratch[11].i =
Packit 971217
        scratch[0].i + S_MUL (scratch[7].i, yb.r) + S_MUL (scratch[8].i, ya.r);
Packit 971217
    scratch[12].r = -S_MUL (scratch[10].i, yb.i) + S_MUL (scratch[9].i, ya.i);
Packit 971217
    scratch[12].i = S_MUL (scratch[10].r, yb.i) - S_MUL (scratch[9].r, ya.i);
Packit 971217
Packit 971217
    C_ADD (*Fout2, scratch[11], scratch[12]);
Packit 971217
    C_SUB (*Fout3, scratch[11], scratch[12]);
Packit 971217
Packit 971217
    ++Fout0;
Packit 971217
    ++Fout1;
Packit 971217
    ++Fout2;
Packit 971217
    ++Fout3;
Packit 971217
    ++Fout4;
Packit 971217
  }
Packit 971217
}
Packit 971217
Packit 971217
/* perform the butterfly for one stage of a mixed radix FFT */
Packit 971217
static void
Packit 971217
kf_bfly_generic (kiss_fft_f64_cpx * Fout,
Packit 971217
    const size_t fstride, const kiss_fft_f64_cfg st, int m, int p)
Packit 971217
{
Packit 971217
  int u, k, q1, q;
Packit 971217
  kiss_fft_f64_cpx *twiddles = st->twiddles;
Packit 971217
  kiss_fft_f64_cpx t;
Packit 971217
  int Norig = st->nfft;
Packit 971217
Packit 971217
  CHECKBUF (scratchbuf, nscratchbuf, p);
Packit 971217
Packit 971217
  for (u = 0; u < m; ++u) {
Packit 971217
    k = u;
Packit 971217
    for (q1 = 0; q1 < p; ++q1) {
Packit 971217
      scratchbuf[q1] = Fout[k];
Packit 971217
      C_FIXDIV (scratchbuf[q1], p);
Packit 971217
      k += m;
Packit 971217
    }
Packit 971217
Packit 971217
    k = u;
Packit 971217
    for (q1 = 0; q1 < p; ++q1) {
Packit 971217
      int twidx = 0;
Packit 971217
Packit 971217
      Fout[k] = scratchbuf[0];
Packit 971217
      for (q = 1; q < p; ++q) {
Packit 971217
        twidx += fstride * k;
Packit 971217
        if (twidx >= Norig)
Packit 971217
          twidx -= Norig;
Packit 971217
        C_MUL (t, scratchbuf[q], twiddles[twidx]);
Packit 971217
        C_ADDTO (Fout[k], t);
Packit 971217
      }
Packit 971217
      k += m;
Packit 971217
    }
Packit 971217
  }
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
kf_work (kiss_fft_f64_cpx * Fout,
Packit 971217
    const kiss_fft_f64_cpx * f,
Packit 971217
    const size_t fstride,
Packit 971217
    int in_stride, int *factors, const kiss_fft_f64_cfg st)
Packit 971217
{
Packit 971217
  kiss_fft_f64_cpx *Fout_beg = Fout;
Packit 971217
  const int p = *factors++;     /* the radix  */
Packit 971217
  const int m = *factors++;     /* stage's fft length/p */
Packit 971217
  const kiss_fft_f64_cpx *Fout_end = Fout + p * m;
Packit 971217
Packit 971217
#ifdef _OPENMP
Packit 971217
  // use openmp extensions at the 
Packit 971217
  // top-level (not recursive)
Packit 971217
  if (fstride == 1) {
Packit 971217
    int k;
Packit 971217
Packit 971217
    // execute the p different work units in different threads
Packit 971217
#       pragma omp parallel for
Packit 971217
    for (k = 0; k < p; ++k)
Packit 971217
      kf_work (Fout + k * m, f + fstride * in_stride * k, fstride * p,
Packit 971217
          in_stride, factors, st);
Packit 971217
    // all threads have joined by this point
Packit 971217
Packit 971217
    switch (p) {
Packit 971217
      case 2:
Packit 971217
        kf_bfly2 (Fout, fstride, st, m);
Packit 971217
        break;
Packit 971217
      case 3:
Packit 971217
        kf_bfly3 (Fout, fstride, st, m);
Packit 971217
        break;
Packit 971217
      case 4:
Packit 971217
        kf_bfly4 (Fout, fstride, st, m);
Packit 971217
        break;
Packit 971217
      case 5:
Packit 971217
        kf_bfly5 (Fout, fstride, st, m);
Packit 971217
        break;
Packit 971217
      default:
Packit 971217
        kf_bfly_generic (Fout, fstride, st, m, p);
Packit 971217
        break;
Packit 971217
    }
Packit 971217
    return;
Packit 971217
  }
Packit 971217
#endif
Packit 971217
Packit 971217
  if (m == 1) {
Packit 971217
    do {
Packit 971217
      *Fout = *f;
Packit 971217
      f += fstride * in_stride;
Packit 971217
    } while (++Fout != Fout_end);
Packit 971217
  } else {
Packit 971217
    do {
Packit 971217
      // recursive call:
Packit 971217
      // DFT of size m*p performed by doing
Packit 971217
      // p instances of smaller DFTs of size m, 
Packit 971217
      // each one takes a decimated version of the input
Packit 971217
      kf_work (Fout, f, fstride * p, in_stride, factors, st);
Packit 971217
      f += fstride * in_stride;
Packit 971217
    } while ((Fout += m) != Fout_end);
Packit 971217
  }
Packit 971217
Packit 971217
  Fout = Fout_beg;
Packit 971217
Packit 971217
  // recombine the p smaller DFTs 
Packit 971217
  switch (p) {
Packit 971217
    case 2:
Packit 971217
      kf_bfly2 (Fout, fstride, st, m);
Packit 971217
      break;
Packit 971217
    case 3:
Packit 971217
      kf_bfly3 (Fout, fstride, st, m);
Packit 971217
      break;
Packit 971217
    case 4:
Packit 971217
      kf_bfly4 (Fout, fstride, st, m);
Packit 971217
      break;
Packit 971217
    case 5:
Packit 971217
      kf_bfly5 (Fout, fstride, st, m);
Packit 971217
      break;
Packit 971217
    default:
Packit 971217
      kf_bfly_generic (Fout, fstride, st, m, p);
Packit 971217
      break;
Packit 971217
  }
Packit 971217
}
Packit 971217
Packit 971217
/*  facbuf is populated by p1,m1,p2,m2, ...
Packit 971217
    where 
Packit 971217
    p[i] * m[i] = m[i-1]
Packit 971217
    m0 = n                  */
Packit 971217
static void
Packit 971217
kf_factor (int n, int *facbuf)
Packit 971217
{
Packit 971217
  int p = 4;
Packit 971217
  double floor_sqrt;
Packit 971217
Packit 971217
  floor_sqrt = floor (sqrt ((double) n));
Packit 971217
Packit 971217
  /*factor out powers of 4, powers of 2, then any remaining primes */
Packit 971217
  do {
Packit 971217
    while (n % p) {
Packit 971217
      switch (p) {
Packit 971217
        case 4:
Packit 971217
          p = 2;
Packit 971217
          break;
Packit 971217
        case 2:
Packit 971217
          p = 3;
Packit 971217
          break;
Packit 971217
        default:
Packit 971217
          p += 2;
Packit 971217
          break;
Packit 971217
      }
Packit 971217
      if (p > floor_sqrt)
Packit 971217
        p = n;                  /* no more factors, skip to end */
Packit 971217
    }
Packit 971217
    n /= p;
Packit 971217
    *facbuf++ = p;
Packit 971217
    *facbuf++ = n;
Packit 971217
  } while (n > 1);
Packit 971217
}
Packit 971217
Packit 971217
/*
Packit 971217
 *
Packit 971217
 * User-callable function to allocate all necessary storage space for the fft.
Packit 971217
 *
Packit 971217
 * The return value is a contiguous block of memory, allocated with malloc.  As such,
Packit 971217
 * It can be freed with free(), rather than a kiss_fft-specific function.
Packit 971217
 * */
Packit 971217
kiss_fft_f64_cfg
Packit 971217
kiss_fft_f64_alloc (int nfft, int inverse_fft, void *mem, size_t * lenmem)
Packit 971217
{
Packit 971217
  kiss_fft_f64_cfg st = NULL;
Packit 971217
  const double pi =
Packit 971217
      3.141592653589793238462643383279502884197169399375105820974944;
Packit 971217
  size_t memneeded = sizeof (struct kiss_fft_f64_state)
Packit 971217
      + sizeof (kiss_fft_f64_cpx) * (nfft - 1); /* twiddle factors */
Packit 971217
Packit 971217
  if (lenmem == NULL) {
Packit 971217
    st = (kiss_fft_f64_cfg) KISS_FFT_F64_MALLOC (memneeded);
Packit 971217
  } else {
Packit 971217
    if (mem != NULL && *lenmem >= memneeded)
Packit 971217
      st = (kiss_fft_f64_cfg) mem;
Packit 971217
    *lenmem = memneeded;
Packit 971217
  }
Packit 971217
  if (st) {
Packit 971217
    int i;
Packit 971217
Packit 971217
    st->nfft = nfft;
Packit 971217
    st->inverse = inverse_fft;
Packit 971217
Packit 971217
    for (i = 0; i < nfft; ++i) {
Packit 971217
      double phase = -2 * pi * i / nfft;
Packit 971217
Packit 971217
      if (st->inverse)
Packit 971217
        phase *= -1;
Packit 971217
      kf_cexp (st->twiddles + i, phase);
Packit 971217
    }
Packit 971217
Packit 971217
    kf_factor (nfft, st->factors);
Packit 971217
  }
Packit 971217
  return st;
Packit 971217
}
Packit 971217
Packit 971217
Packit 971217
Packit 971217
Packit 971217
void
Packit 971217
kiss_fft_f64_stride (kiss_fft_f64_cfg st, const kiss_fft_f64_cpx * fin,
Packit 971217
    kiss_fft_f64_cpx * fout, int in_stride)
Packit 971217
{
Packit 971217
  if (fin == fout) {
Packit 971217
    CHECKBUF (tmpbuf, ntmpbuf, st->nfft);
Packit 971217
    kf_work (tmpbuf, fin, 1, in_stride, st->factors, st);
Packit 971217
    memcpy (fout, tmpbuf, sizeof (kiss_fft_f64_cpx) * st->nfft);
Packit 971217
  } else {
Packit 971217
    kf_work (fout, fin, 1, in_stride, st->factors, st);
Packit 971217
  }
Packit 971217
}
Packit 971217
Packit 971217
void
Packit 971217
kiss_fft_f64 (kiss_fft_f64_cfg cfg, const kiss_fft_f64_cpx * fin,
Packit 971217
    kiss_fft_f64_cpx * fout)
Packit 971217
{
Packit 971217
  kiss_fft_f64_stride (cfg, fin, fout, 1);
Packit 971217
}
Packit 971217
Packit 971217
Packit 971217
/* not really necessary to call, but if someone is doing in-place ffts, they may want to free the 
Packit 971217
   buffers from CHECKBUF
Packit 971217
 */
Packit 971217
void
Packit 971217
kiss_fft_f64_cleanup (void)
Packit 971217
{
Packit 971217
  free (scratchbuf);
Packit 971217
  scratchbuf = NULL;
Packit 971217
  nscratchbuf = 0;
Packit 971217
  free (tmpbuf);
Packit 971217
  tmpbuf = NULL;
Packit 971217
  ntmpbuf = 0;
Packit 971217
}
Packit 971217
Packit 971217
int
Packit 971217
kiss_fft_f64_next_fast_size (int n)
Packit 971217
{
Packit 971217
  while (1) {
Packit 971217
    int m = n;
Packit 971217
Packit 971217
    while ((m % 2) == 0)
Packit 971217
      m /= 2;
Packit 971217
    while ((m % 3) == 0)
Packit 971217
      m /= 3;
Packit 971217
    while ((m % 5) == 0)
Packit 971217
      m /= 5;
Packit 971217
    if (m <= 1)
Packit 971217
      break;                    /* n is completely factorable by twos, threes, and fives */
Packit 971217
    n++;
Packit 971217
  }
Packit 971217
  return n;
Packit 971217
}