Esempio n. 1
0
void
zn_array_mulmid_fft_precomp1_execute
                    (ulong* res, const ulong* op2, ulong x,
                     const zn_array_mulmid_fft_precomp1_t precomp)
{
   const pmfvec_struct* vec1 = precomp->vec1;
   size_t n1 = precomp->n1;
   size_t n2 = precomp->n2;
   ulong m1 = precomp->m1;
   ulong m2 = precomp->m2;

   pmfvec_t vec2;
   pmfvec_init (vec2, vec1->lgK, vec1->skip, vec1->lgM, vec1->mod);

   // split and compute FFT of second input (with requested scaling factor)
   fft_split (vec2, op2, n2, 0, x, 0);
   pmfvec_fft (vec2, m1, m2, 0);
   
   // pointwise multiply against precomputed transposed IFFT of first input
   pmfvec_mul (vec2, vec1, vec2, m1, 0);

   // transposed FFT
   ulong m3 = m1 - m2 + 1;
   pmfvec_tpfft (vec2, m1, m3, 0);
   
   // reverse output and combine
   pmfvec_reverse (vec2, m3);
   fft_combine (res, n1 - n2 + 1, vec2, m3, 1);
   pmfvec_reverse (vec2, m3);

   pmfvec_clear (vec2);
}
Esempio n. 2
0
int main(int argc, char **argv) {
    // init args, format :  fft -f file_name num_entries
    //                      fft samples cycles [phase] <- sin, phase in
    //                          increments of pi
    //                      fft -c samples cycles [phase] <- cos
    //                      fft -s samples cycles [phase] <- sqr
    Cnum *input;
    if (argc > 2) {
        int samples = 0;
        if (argv[1][0] == '-') {
            if (!argv[1][1]) goto usage;
            if (argv[1][1] == 'f') {
                if (argc == 4) {
                    sscanf(argv[3], "%d", &samples);
                    input = (Cnum *) malloc(sizeof(Cnum)*samples);
                    input = read_file_in(argv[2]);
                } else goto usage;
            } else {
                double cycles = 0;
                sscanf(argv[2], "%d", &samples);
                sscanf(argv[3], "%lf", &cycles);
                double phase = 0;
                input = (Cnum *) malloc(sizeof(Cnum)*samples);
                if (argc == 5) sscanf(argv[4], "%lf", &phase);
                if (argv[1][1] == 'c') cos_wave(samples, cycles, phase*M_PI, input);
                if (argv[1][1] == 's') sqr_wave(samples, cycles, phase*M_PI, input);
                else goto usage;
            }
        } else {
            if (argc != 3 && argc != 4) goto usage;
            double cycles = 0;
            sscanf(argv[1], "%d", &samples);
            sscanf(argv[2], "%lf", &cycles);
            input = (Cnum *) malloc(sizeof(Cnum)*samples);
            double phase = 0;
            if (argc == 4) sscanf(argv[3], "%lf", &phase);
            sin_wave(samples, cycles, phase*M_PI, input);
        }
        Cnum *output = (Cnum *) malloc(sizeof(Cnum)*samples);
        /*Cnum *dout = (Cnum *) malloc(sizeof(Cnum)*samples);*/

        Cnum *even = (Cnum *) malloc(sizeof(Cnum)*samples/2);
        Cnum *odd  = (Cnum *) malloc(sizeof(Cnum)*samples/2);
        for (int i = 0; i < samples/2; i++) {
            even[i] = input[2*i];
            odd[i]  = input[2*i+1];
        }
        // output = fft(samples, input);
        output = fft_combine(samples, fft(samples/2, even), fft(samples/2, odd));
        Cnum *x;
        printf("Test example for two nodes:\n");
        for (int i = 0; i < samples; i++) {
            /*double y = magn(&output[i])/samples;*/
            x = &output[i];
            printf("%f + %f i\n", x->real, x->imag);
        }
        printf("\n");
        Cnum *even_even = (Cnum *) malloc(sizeof(Cnum)*samples/4);
        Cnum *even_odd  = (Cnum *) malloc(sizeof(Cnum)*samples/4);
        for (int i = 0; i < samples/4; i++) {
            even_even[i] = even[2*i];
            even_odd[i]  = even[2*i+1];
        }
        Cnum *odd_even = (Cnum *) malloc(sizeof(Cnum)*samples/4);
        Cnum *odd_odd  = (Cnum *) malloc(sizeof(Cnum)*samples/4);
        for (int i = 0; i < samples/4; i++) {
            odd_even[i] = odd[2*i];
            odd_odd[i]  = odd[2*i+1];
        }
        printf("Test example for four nodes:\n");
        output = fft_combine(samples, fft_combine(samples/2, fft(samples/4, even_even), fft(samples/4, even_odd)), fft_combine(samples/2, fft(samples/4, odd_even), fft(samples/4, odd_odd)));
        for (int i = 0; i < samples; i++) {
            /*double y = magn(&output[i])/samples;*/
            x = &output[i];
            printf("%f + %f i\n", x->real, x->imag);
        }
        return 0;
    }


    usage:
        free (input);
        puts ("Usage : fft -[cs] samples cycles [phase]");
        puts ("        fft -f file_name samples");
        exit (1);
}
Esempio n. 3
0
void zn_array_mul_fft (ulong* res,
                       const ulong* op1, size_t n1,
                       const ulong* op2, size_t n2,
                       ulong x, const zn_mod_t mod)
{
   ZNP_ASSERT (mod->m & 1);
   ZNP_ASSERT (n2 >= 1);
   ZNP_ASSERT (n1 >= n2);

   unsigned lgK, lgM;
   
   // number of pmf_t coefficients for each input poly
   ulong m1, m2;

   // figure out how big the transform needs to be
   mul_fft_params (&lgK, &lgM, &m1, &m2, n1, n2);
   
   // number of pmf_t coefficients for output poly
   ulong m3 = m1 + m2 - 1;

   ulong M = 1UL << lgM;
   ulong K = 1UL << lgK;
   ptrdiff_t skip = M + 1;
   
   pmfvec_t vec1, vec2;
   
   int sqr = (op1 == op2  &&  n1 == n2);

   if (!sqr)
   {
      // multiplying two distinct inputs

      // split inputs into pmf_t's and perform FFTs
      pmfvec_init (vec1, lgK, skip, lgM, mod);
      fft_split (vec1, op1, n1, 0, 1, 0);
      pmfvec_fft (vec1, m3, m1, 0);

      // note: we apply the fudge factor here, because the second input is
      // shorter than both the first input and the output :-)
      pmfvec_init (vec2, lgK, skip, lgM, mod);
      fft_split (vec2, op2, n2, 0, x, 0);
      pmfvec_fft (vec2, m3, m2, 0);

      // pointwise multiplication
      pmfvec_mul (vec1, vec1, vec2, m3, 1);

      pmfvec_clear (vec2);
   }
   else
   {
      // squaring a single input
   
      // split input into pmf_t's and perform FFTs
      pmfvec_init (vec1, lgK, skip, lgM, mod);
      fft_split (vec1, op1, n1, 0, 1, 0);
      pmfvec_fft (vec1, m3, m1, 0);

      // pointwise multiplication
      pmfvec_mul (vec1, vec1, vec1, m3, 1);
   }

   // inverse FFT, and write output
   pmfvec_ifft (vec1, m3, 0, m3, 0);
   size_t n3 = n1 + n2 - 1;
   fft_combine (res, n3, vec1, m3, 0);

   pmfvec_clear (vec1);
   
   // if we're squaring, then we haven't applied the fudge factor yet,
   // so do it now
   if (sqr)
      zn_array_scalar_mul_or_copy (res, res, n3, x, mod);
}
Esempio n. 4
0
void
zn_array_invert_extend_fft (ulong* res, const ulong* approx, const ulong* op,
                            size_t n1, size_t n2, const zn_mod_t mod)
{
   ZNP_ASSERT (n2 >= 1);
   ZNP_ASSERT (n1 >= n2);
   ZNP_ASSERT (mod->m & 1);

   // The algorithm here is the same as in zn_array_invert_extend(), except
   // that we work with the FFTs directly. This allows us to save one FFT,
   // since we use the FFT of g in both the middle product step and the
   // product step.

   // Determine FFT parameters for computing h = middle product of
   // f[1, n1 + n2) and g[0, n1). (These parameters will also work for the
   // subsequent product g * h.)
   unsigned lgK, lgM; 
   ulong m1, m2, m3, p;

   mulmid_fft_params (&lgK, &lgM, &m3, &m1, &p, n1 + n2 - 1, n1);
   m2 = m3 - m1 + 1;

   // We now have
   //     m1 = ceil(n1 / (M/2))
   //        = (n1 + p - 1) / (M/2).
   // Therefore
   //     m3 = ceil((n1 + n2 - 1 + p) / (M/2))
   //        = ceil(n2 / (M/2)) + (n1 + p - 1) / (M/2)
   // and
   //     m2 = ceil(n2 / (M/2)) + 1.
   
   ulong M = 1UL << lgM;
   ulong K = 1UL << lgK;
   ptrdiff_t skip = M + 1;

   pmfvec_t vec1, vec2;
   pmfvec_init (vec1, lgK, skip, lgM, mod);
   pmfvec_init (vec2, lgK, skip, lgM, mod);

   // Find scaling factor that needs to be applied to both of the products
   // below; takes into account the fudge from the pointwise multiplies, and
   // the division by 2^lgK coming from the FFTs.
   ulong x = pmfvec_mul_fudge (lgM, 0, mod);
   x = zn_mod_mul (x, zn_mod_pow2 (-lgK, mod), mod);

   // Split g[0, n1) into m1 coefficients, apply scaling factor, and compute
   // m3 fourier coefficients, written to vec2.
   fft_split (vec2, approx, n1, 0, x, 0);
   pmfvec_fft (vec2, m3, m1, 0);

   // Split f[1, n1 + n2) into m3 coefficients (in reversed order, with
   // appropriate zero-padding), and compute transposed IFFT of length m3,
   // written to vec1.
   pmfvec_reverse (vec1, m3);
   fft_split (vec1, op + 1, n1 + n2 - 1, p, 1, 0);
   pmfvec_reverse (vec1, m3);
   pmfvec_tpifft (vec1, m3, 0, m3, 0);

   // Pointwise multiply the above FFT and transposed IFFT, into vec1.
   pmfvec_mul (vec1, vec1, vec2, m3, 0);
   
   // Transposed FFT vec1, obtaining m2 coefficients, then reverse and combine.
   pmfvec_tpfft (vec1, m3, m2, 0);
   pmfvec_reverse (vec1, m2);
   fft_combine (res, n2, vec1, m2, 1);
   pmfvec_reverse (vec1, m2);
   
   // At this stage we have obtained the polynomial h in res[0, n2).
   // Now we must compute h * g.
   
   // Split h[0, n2) into m2 - 1 coefficients, and compute m3 - 1 fourier
   // coefficients in vec1. For the splitting step, we set the bias to M,
   // which effectively negates everything, so we're really computing the FFT
   // of -h.
   fft_split (vec1, res, n2, 0, 1, M);
   pmfvec_fft (vec1, m3 - 1, m2 - 1, 0);

   // Pointwise multiply that FFT with the first FFT of g into vec2.
   pmfvec_mul (vec2, vec2, vec1, m3 - 1, 1);
   pmfvec_clear (vec1);

   // IFFT and combine, to obtain the product -h * g. We only need the low n2
   // terms of the product (we throw away the high n1 - 1 terms).
   pmfvec_ifft (vec2, m3 - 1, 0, m3 - 1, 0);
   fft_combine (res, n2, vec2, m3 - 1, 0);
   pmfvec_clear (vec2);
}