#include "zmult.h"

#define reg register double /* XXX: long double */
#define alpha48 zmult_alpha48
#define twom48 zmult_twom48

/* u -> 2^3b u; b between 0 and 1023 */
void zmult_32fft_twist(double u[32],int b,double tmp[32])
{
  int i;
  int k;
  reg t0, t1, t2, t3, t4, t5, t6, t7;
  k = b >> 4;
  b &= 15;
  if (k < 32) {
    for (i = 32 - k;i < 32;++i) tmp[i] = u[i];
    for (i = 31 - k;i >= 0;--i) u[i + k] = u[i];
    for (i = 32 - k;i < 32;++i) u[i + k - 32] = -tmp[i];
  }
  else {
    k -= 32;
    for (i = 32 - k;i < 32;++i) tmp[i] = u[i];
    for (i = 31 - k;i >= 0;--i) u[i + k] = -u[i];
    for (i = 32 - k;i < 32;++i) u[i + k - 32] = tmp[i];
  }
  t4 = 0;
  for (i = 0;i < 32;++i) {
    t0 = u[i];
    t0 *= zmult_two3[b];
    t1 = alpha48;
    t1 += t0;
    t1 -= alpha48;
    t0 -= t1;
    t1 *= twom48;
    t0 += t4;
    u[i] = t0;
    t4 = t1;
  }
  u[0] -= t4;
}

void zmult_32fft_512_carry(double u[16384],double tmp[32])
{
  int i;
  i = 512;
  do {
    zmult_32fft_twist(u,0,tmp);
    u += 32;
  } while (--i);
}

void zmult_32fft_512_scale(double u[16384],double tmp[32])
{
  int i;
  i = 512;
  do {
    zmult_32fft_twist(u,1021,tmp);
    u += 32;
  } while (--i);
}
