*** ./liboctave/ChangeLog.orig 2004-01-30 15:24:31.000000000 +0100 --- ./liboctave/ChangeLog 2004-01-30 15:25:30.000000000 +0100 *************** *** 1,3 **** --- 1,14 ---- + 2004-01-30 David Bateman + + * oct-fftw.cc: Add support for FFTW 3.x. Include the ability to + use the real to complex transform for fft's of real matrices + * oct-fftw.h: Decls updated for the above + + * dMatrix.cc: fft's use real to complex transforms. 1D fft of a + matrix done as single call rather than loop. Update for FFTW 3.x + * CMatrix.cc: 1D fft of a matrix done as single call rather than + loop. Update for FFTW 3.x + 2004-01-22 John W. Eaton * Array.cc (Array::assign2, Array::assignN): *** ./liboctave/dMatrix.cc.orig 2004-01-28 15:17:03.000000000 +0100 --- ./liboctave/dMatrix.cc 2004-01-30 11:04:11.000000000 +0100 *************** *** 52,58 **** #include "oct-cmplx.h" #include "quit.h" ! #ifdef HAVE_FFTW #include "oct-fftw.h" #endif --- 52,58 ---- #include "oct-cmplx.h" #include "quit.h" ! #if defined (HAVE_FFTW) || defined (HAVE_FFTW3) #include "oct-fftw.h" #endif *************** *** 766,772 **** } } ! #ifdef HAVE_FFTW ComplexMatrix Matrix::fourier (void) const --- 766,772 ---- } } ! #if defined (HAVE_FFTW) || defined (HAVE_FFTW3) ComplexMatrix Matrix::fourier (void) const *************** *** 789,804 **** nsamples = nc; } ! ComplexMatrix tmp (*this); ! Complex *in (tmp.fortran_vec ()); Complex *out (retval.fortran_vec ()); for (size_t i = 0; i < nsamples; i++) { OCTAVE_QUIT; octave_fftw::fft (&in[npts * i], &out[npts * i], npts); } return retval; } --- 789,809 ---- nsamples = nc; } ! const double *in (fortran_vec ()); Complex *out (retval.fortran_vec ()); + // XXX FIXME XXX octave_fftw::fft (in, out, npts, nsamples); + // should be faster for FFTW 2.1.x as well but isn't !!! + #ifdef HAVE_FFTW3 + octave_fftw::fft (in, out, npts, nsamples); + #else for (size_t i = 0; i < nsamples; i++) { OCTAVE_QUIT; octave_fftw::fft (&in[npts * i], &out[npts * i], npts); } + #endif return retval; } *************** *** 828,839 **** --- 833,850 ---- Complex *in (tmp.fortran_vec ()); Complex *out (retval.fortran_vec ()); + // XXX FIXME XXX octave_fftw::ifft (in, out, npts, nsamples); + // should be faster for FFTW 2.1.x as well but isn't !!! + #ifdef HAVE_FFTW3 + octave_fftw::ifft (in, out, npts, nsamples); + #else for (size_t i = 0; i < nsamples; i++) { OCTAVE_QUIT; octave_fftw::ifft (&in[npts * i], &out[npts * i], npts); } + #endif return retval; } *************** *** 844,853 **** int nr = rows (); int nc = cols (); ! ComplexMatrix retval (*this); // Note the order of passing the rows and columns to account for // column-major storage. ! octave_fftw::fft2d (retval.fortran_vec (), nc, nr); return retval; } --- 855,865 ---- int nr = rows (); int nc = cols (); ! const double *in = fortran_vec (); ! ComplexMatrix retval (rows (), cols ()); // Note the order of passing the rows and columns to account for // column-major storage. ! octave_fftw::fft2d (in, retval.fortran_vec (), nc, nr); return retval; } *** ./liboctave/CMatrix.cc.orig 2004-01-28 15:17:09.000000000 +0100 --- ./liboctave/CMatrix.cc 2004-01-30 14:22:53.000000000 +0100 *************** *** 56,62 **** #include "mx-inlines.cc" #include "oct-cmplx.h" ! #ifdef HAVE_FFTW #include "oct-fftw.h" #endif --- 56,62 ---- #include "mx-inlines.cc" #include "oct-cmplx.h" ! #if defined (HAVE_FFTW) || defined (HAVE_FFTW3) #include "oct-fftw.h" #endif *************** *** 1102,1108 **** return retval; } ! #ifdef HAVE_FFTW ComplexMatrix ComplexMatrix::fourier (void) const --- 1102,1108 ---- return retval; } ! #if defined (HAVE_FFTW) || defined (HAVE_FFTW3) ComplexMatrix ComplexMatrix::fourier (void) const *************** *** 1128,1139 **** --- 1128,1145 ---- const Complex *in (data ()); Complex *out (retval.fortran_vec ()); + // XXX FIXME XXX octave_fftw::fft (in, out, npts, nsamples); + // should be faster for FFTW 2.1.x as well but isn't !!! + #ifdef HAVE_FFTW3 + octave_fftw::fft (in, out, npts, nsamples); + #else for (size_t i = 0; i < nsamples; i++) { OCTAVE_QUIT; octave_fftw::fft (&in[npts * i], &out[npts * i], npts); } + #endif return retval; } *************** *** 1162,1173 **** --- 1168,1185 ---- const Complex *in (data ()); Complex *out (retval.fortran_vec ()); + // XXX FIXME XXX octave_fftw::ifft (in, out, npts, nsamples); + // should be faster for FFTW 2.1.x as well but isn't !!! + #ifdef HAVE_FFTW3 + octave_fftw::ifft (in, out, npts, nsamples); + #else for (size_t i = 0; i < nsamples; i++) { OCTAVE_QUIT; octave_fftw::ifft (&in[npts * i], &out[npts * i], npts); } + #endif return retval; } *** ./liboctave/oct-fftw.h.orig 2004-01-28 15:17:17.000000000 +0100 --- ./liboctave/oct-fftw.h 2004-01-30 10:29:25.000000000 +0100 *************** *** 23,32 **** #include ! #if defined (HAVE_DFFTW_H) ! #include #else ! #include #endif #include "oct-cmplx.h" --- 23,38 ---- #include ! #if defined (HAVE_FFTW3) ! # include #else ! # if defined (HAVE_DFFTW_H) ! # include ! # include ! # else ! # include ! # include ! # endif #endif #include "oct-cmplx.h" *************** *** 35,42 **** octave_fftw { public: ! static int fft (const Complex*, Complex *, size_t); ! static int ifft (const Complex*, Complex *, size_t); static int fft2d (Complex*, size_t, size_t); static int ifft2d (Complex*, size_t, size_t); --- 41,54 ---- octave_fftw { public: ! static int fft (const double *in, Complex *out, size_t npts, ! size_t nsamples = 1); ! static int fft (const Complex *in, Complex *out, size_t npts, ! size_t nsamples = 1); ! static int ifft (const Complex *in, Complex *out, size_t npts, ! size_t nsamples = 1); ! ! static int fft2d (const double*, Complex*, size_t, size_t); static int fft2d (Complex*, size_t, size_t); static int ifft2d (Complex*, size_t, size_t); *** ./liboctave/oct-fftw.cc.orig 2004-01-28 15:17:22.000000000 +0100 --- ./liboctave/oct-fftw.cc 2004-01-30 15:30:19.000000000 +0100 *************** *** 22,33 **** #include #endif ! #ifdef HAVE_FFTW #include "oct-fftw.h" #include "lo-error.h" - // Helper class to create and cache fftw plans for both 1d and 2d. This // implementation uses FFTW_ESTIMATE to create the plans, which in theory // is suboptimal, but provides quite reasonable performance. Future --- 22,32 ---- #include #endif ! #if defined (HAVE_FFTW) || defined (HAVE_FFTW3) #include "oct-fftw.h" #include "lo-error.h" // Helper class to create and cache fftw plans for both 1d and 2d. This // implementation uses FFTW_ESTIMATE to create the plans, which in theory // is suboptimal, but provides quite reasonable performance. Future *************** *** 35,40 **** --- 34,195 ---- // to manipulate fftw wisdom so that users may choose the appropriate // planner. + // Also note that if FFTW_ESTIMATE is not used the planner in FFTW3 + // destroys the input and output arrays. So with the form of the + // current code we definitely want FFTW_ESTIMATE!! + + // XXX FIXME XXX If we can ensure 16 byte alignment in Array ( *data) + // the FFTW3 can use SIMD instructions for further acceleration. + + #ifdef HAVE_FFTW3 + + #define plan_flags (FFTW_ESTIMATE) + + static inline void convert_packcomplex_1d (Complex *out, size_t nr, + size_t nc) + { + // Fill in the missing data + for (size_t i = 0; i < nr; i++) + for (size_t j = nc/2+1; j < nc; j++) + out[j + i*nc] = conj(out[nc - j + i*nc]); + } + + static inline void convert_packcomplex_2d (Complex *out, size_t nr, + size_t nc) + { + Complex *ptr1, *ptr2; + + // Create space for the missing elements + for (size_t i = 0; i < nr; i++) + { + ptr1 = out + i * (nc/2 + 1) + nr*((nc-1)/2); + ptr2 = out + i * nc; + for (size_t j = 0; j < nc/2+1; j++) + *ptr2++ = *ptr1++; + } + + // Fill in the missing data + for (size_t i = 1; i < nr; i++) + for (size_t j = nc/2+1; j < nc; j++) + out[j + i*nc] = conj(out[nc - j + (nr-i)*nc]); + for (size_t j = nc/2+1; j < nc; j++) + out[j] = conj(out[nc - j]); + } + + int + octave_fftw::fft (const double *in, Complex *out, size_t npts, size_t nsamples) + { + fftw_plan plan + = fftw_plan_many_dft_r2c (1, reinterpret_cast (&npts), nsamples, + (const_cast (in)), NULL, 1, npts, + reinterpret_cast (out), NULL, 1, npts, plan_flags); + + fftw_execute (plan); + + fftw_destroy_plan (plan); + + // Need to create other half of the transform + convert_packcomplex_1d (out, nsamples, npts); + + return 0; + } + + int + octave_fftw::fft (const Complex *in, Complex *out, size_t npts, + size_t nsamples) + { + fftw_plan plan = fftw_plan_many_dft (1, reinterpret_cast (&npts), + nsamples, + reinterpret_cast (const_cast (in)), + NULL, 1, npts, + reinterpret_cast (out), NULL, 1, npts, + FFTW_FORWARD, plan_flags); + + fftw_execute (plan); + + fftw_destroy_plan (plan); + + return 0; + } + + int + octave_fftw::ifft (const Complex *in, Complex *out, size_t npts, + size_t nsamples) + { + fftw_plan plan = fftw_plan_many_dft (1, reinterpret_cast (&npts), + nsamples, + reinterpret_cast (const_cast (in)), + NULL, 1, npts, + reinterpret_cast (out), NULL, 1, npts, + FFTW_BACKWARD, plan_flags); + + fftw_execute (plan); + + fftw_destroy_plan (plan); + + const Complex scale = npts; + for (size_t i = 0; i < npts*nsamples; i++) + out[i] /= scale; + + return 0; + } + + int + octave_fftw::fft2d (const double *in, Complex *out, size_t nr, size_t nc) + { + // Fool with the position of the start of the matrix, so that creating + // other half of the matrix won't cause cache problems + fftw_plan plan = fftw_plan_dft_r2c_2d (nr, nc, (const_cast(in)), + reinterpret_cast (out + nr*((nc-1)/2)), plan_flags); + + fftw_execute (plan); + + fftw_destroy_plan (plan); + + // Need to create other half of the transform + convert_packcomplex_2d (out, nr, nc); + + return 0; + } + + int + octave_fftw::fft2d (Complex *inout, size_t nr, size_t nc) + { + fftw_plan plan + = fftw_plan_dft_2d (nr, nc, + reinterpret_cast (const_cast (inout)), + reinterpret_cast (inout), FFTW_FORWARD, plan_flags); + + fftw_execute (plan); + + fftw_destroy_plan (plan); + + return 0; + } + + int + octave_fftw::ifft2d (Complex *inout, size_t nr, size_t nc) + { + fftw_plan plan + = fftw_plan_dft_2d (nr, nc, + reinterpret_cast (const_cast (inout)), + reinterpret_cast (inout), FFTW_BACKWARD, + plan_flags); + + fftw_execute (plan); + + fftw_destroy_plan (plan); + + const size_t npts = nr * nc; + const Complex scale = npts; + for (size_t i = 0; i < npts; i++) + inout[i] /= scale; + + return 0; + } + + #else // HAVE_FFTW3 + class octave_fftw_planner { *************** *** 42,48 **** octave_fftw_planner (); fftw_plan create_plan (fftw_direction, size_t); ! fftwnd_plan create_plan2d (fftw_direction, size_t, size_t); private: int plan_flags; --- 197,206 ---- octave_fftw_planner (); fftw_plan create_plan (fftw_direction, size_t); ! fftwnd_plan create_plan2d (fftw_direction, size_t, size_t, Complex); ! ! rfftw_plan create_rplan (fftw_direction, size_t); ! rfftwnd_plan create_rplan2d (fftw_direction, size_t, size_t); private: int plan_flags; *************** *** 50,57 **** --- 208,221 ---- fftw_plan plan[2]; fftwnd_plan plan2d[2]; + rfftw_plan rplan[2]; + rfftwnd_plan rplan2d[2]; + size_t n[2]; size_t n2d[2][2]; + + size_t rn[2]; + size_t rn2d[2][2]; }; octave_fftw_planner::octave_fftw_planner () *************** *** 63,68 **** --- 227,239 ---- n[0] = n[1] = 0; n2d[0][0] = n2d[0][1] = n2d[1][0] = n2d[1][1] = 0; + + rplan[0] = rplan[1] = 0; + rplan2d[0] = rplan2d[1] = 0; + + rn[0] = rn[1] = 0; + rn2d[0][0] = rn2d[0][1] = rn2d[1][0] = rn2d[1][1] = 0; + } fftw_plan *************** *** 92,106 **** return *cur_plan_p; } fftwnd_plan ! octave_fftw_planner::create_plan2d (fftw_direction dir, ! size_t nrows, size_t ncols) { size_t which = (dir == FFTW_FORWARD) ? 0 : 1; fftwnd_plan *cur_plan_p = &plan2d[which]; bool create_new_plan = false; ! if (plan2d[which] == 0 || n2d[which][0] != nrows || n2d[which][1] != ncols) { create_new_plan = true; --- 263,305 ---- return *cur_plan_p; } + rfftw_plan + octave_fftw_planner::create_rplan (fftw_direction dir, size_t npts) + { + size_t which = (dir == FFTW_FORWARD) ? 0 : 1; + rfftw_plan *cur_plan_p = &rplan[which]; + bool create_new_plan = false; + + if (rplan[which] == 0 || rn[which] != npts) + { + create_new_plan = true; + rn[which] = npts; + } + + if (create_new_plan) + { + if (*cur_plan_p) + rfftw_destroy_plan (*cur_plan_p); + + *cur_plan_p = rfftw_create_plan (npts, dir, plan_flags); + + if (*cur_plan_p == 0) + (*current_liboctave_error_handler) ("Error creating fftw plan"); + } + + return *cur_plan_p; + } + fftwnd_plan ! octave_fftw_planner::create_plan2d (fftw_direction dir, size_t nrows, ! size_t ncols) { size_t which = (dir == FFTW_FORWARD) ? 0 : 1; fftwnd_plan *cur_plan_p = &plan2d[which]; bool create_new_plan = false; ! if (plan2d[which] == 0 || n2d[which][0] != nrows || ! n2d[which][1] != ncols) { create_new_plan = true; *************** *** 115,121 **** --- 314,351 ---- *cur_plan_p = fftw2d_create_plan (nrows, ncols, dir, plan_flags | FFTW_IN_PLACE); + + if (*cur_plan_p == 0) + (*current_liboctave_error_handler) ("Error creating 2d fftw plan"); + } + return *cur_plan_p; + } + + rfftwnd_plan + octave_fftw_planner::create_rplan2d (fftw_direction dir, size_t nrows, + size_t ncols) + { + size_t which = (dir == FFTW_FORWARD) ? 0 : 1; + fftwnd_plan *cur_plan_p = &rplan2d[which]; + bool create_new_plan = false; + + if (rplan2d[which] == 0 || rn2d[which][0] != nrows || + rn2d[which][1] != ncols) + { + create_new_plan = true; + + rn2d[which][0] = nrows; + rn2d[which][1] = ncols; + } + + if (create_new_plan) + { + if (*cur_plan_p) + rfftwnd_destroy_plan (*cur_plan_p); + + *cur_plan_p = rfftw2d_create_plan (nrows, ncols, dir, plan_flags); + if (*cur_plan_p == 0) (*current_liboctave_error_handler) ("Error creating 2d fftw plan"); } *************** *** 125,158 **** static octave_fftw_planner fftw_planner; int ! octave_fftw::fft (const Complex *in, Complex *out, size_t npts) { ! fftw_one (fftw_planner.create_plan (FFTW_FORWARD, npts), ! reinterpret_cast (const_cast (in)), ! reinterpret_cast (out)); return 0; } int ! octave_fftw::ifft (const Complex *in, Complex *out, size_t npts) { ! fftw_one (fftw_planner.create_plan (FFTW_BACKWARD, npts), ! reinterpret_cast (const_cast (in)), ! reinterpret_cast (out)); const Complex scale = npts; ! for (size_t i = 0; i < npts; i++) out[i] /= scale; return 0; } int octave_fftw::fft2d (Complex *inout, size_t nr, size_t nc) { ! fftwnd_one (fftw_planner.create_plan2d (FFTW_FORWARD, nr, nc), reinterpret_cast (inout), 0); --- 355,481 ---- static octave_fftw_planner fftw_planner; + static inline void convert_halfcomplex (Complex *in, size_t npts, + size_t nsamples) + { + // This is likely to thrash about in the cache !!! + double *ptr1, *ptr2; + + for (size_t k = 0; k < nsamples; k++) + { + // First move the imaginary parts + ptr1 = (double *)in + 3; + ptr2 = (double *)in + 2 * (npts-1); + for (size_t i = 0; i < (npts-1)/2; i++) + { + *ptr1 = *ptr2; + *(ptr2+1) = - *ptr2; + ptr1 += 2; + ptr2 -= 2; + } + + // Now move the real parts + ptr1 = (double *)in + 2; + ptr2 = (double *)in + 2 * (npts-1); + for (size_t i = 0; i < npts/2; i++) + { + *ptr2 = *ptr1; + ptr1 += 2; + ptr2 -= 2; + } + + // Fix-up complex parts at zero and n/2+1 if n is even + ptr1 = (double *)in; + *(ptr1 + 1) = 0.; + if (!(npts & 1)) + *(ptr1 + npts + 1) = 0.; + + // Advance to the next data + in += npts; + } + } + + static inline void convert_packcomplex (Complex *out, size_t nr, size_t nc) + { + Complex *ptr1, *ptr2; + + // Create space for the missing elements + for (size_t i = 0; i < nr; i++) + { + ptr1 = out + i * (nc/2 + 1) + nr*((nc-1)/2); + ptr2 = out + i * nc; + for (size_t j = 0; j < nc/2+1; j++) + *ptr2++ = *ptr1++; + } + + // Fill in the missing data + for (size_t i = 1; i < nr; i++) + for (size_t j = nc/2+1; j < nc; j++) + out[j + i*nc] = conj(out[nc - j + (nr-i)*nc]); + for (size_t j = nc/2+1; j < nc; j++) + out[j] = conj(out[nc - j]); + } + + int + octave_fftw::fft (const double *in, Complex *out, size_t npts, size_t nsamples) + { + // Fool with the stride to make the conversion to complex easier + rfftw (fftw_planner.create_rplan (FFTW_FORWARD, npts, nsamples, in, out), + nsamples, reinterpret_cast (const_cast (in)), + 1, npts, reinterpret_cast (out), 2, 2*npts); + + // Need to create other half of the transform + convert_halfcomplex (out, npts, nsamples); + + return 0; + } + int ! octave_fftw::fft (const Complex *in, Complex *out, size_t npts, ! size_t nsamples) { ! fftw (fftw_planner.create_plan (FFTW_FORWARD, npts, nsamples, in, out), ! nsamples, reinterpret_cast (const_cast (in)), ! 1, npts, reinterpret_cast (out), 1, npts); return 0; } int ! octave_fftw::ifft (const Complex *in, Complex *out, size_t npts, ! size_t nsamples) { ! fftw (fftw_planner.create_plan (FFTW_BACKWARD, npts, nsamples, in, out), ! nsamples, reinterpret_cast (const_cast (in)), ! 1, npts, reinterpret_cast (out), 1, npts); const Complex scale = npts; ! for (size_t i = 0; i < npts*nsamples; i++) out[i] /= scale; return 0; } int + octave_fftw::fft2d (const double *in, Complex *out, size_t nr, size_t nc) + { + // Fool with the position of the start of the matrix, so that creating + // other half of the matrix won't cause cache problems + rfftwnd_one_real_to_complex (fftw_planner.create_rplan2d (FFTW_FORWARD, + nr, nc, in, out), + reinterpret_cast (const_cast(in)), + reinterpret_cast (out + nr*((nc-1)/2))); + + // Need to create other half of the transform + convert_packcomplex (out, nr, nc); + + return 0; + } + + int octave_fftw::fft2d (Complex *inout, size_t nr, size_t nc) { ! fftwnd_one (fftw_planner.create_plan2d (FFTW_FORWARD, nr, nc, in, out), reinterpret_cast (inout), 0); *************** *** 162,168 **** int octave_fftw::ifft2d (Complex *inout, size_t nr, size_t nc) { ! fftwnd_one (fftw_planner.create_plan2d (FFTW_BACKWARD, nr, nc), reinterpret_cast (inout), 0); --- 485,491 ---- int octave_fftw::ifft2d (Complex *inout, size_t nr, size_t nc) { ! fftwnd_one (fftw_planner.create_plan2d (FFTW_BACKWARD, nr, nc, in, out), reinterpret_cast (inout), 0); *************** *** 174,180 **** return 0; } ! #endif /* ;;; Local Variables: *** --- 497,504 ---- return 0; } ! #endif // HAVE_FFTW3 ! #endif // HAVE_FFTW or HAVE_FFTW3 /* ;;; Local Variables: *** *** ./configure.in.orig 2004-01-28 15:16:49.000000000 +0100 --- ./configure.in 2004-01-29 21:30:25.000000000 +0100 *************** *** 407,425 **** with_fftw=$withval, with_fftw=yes) if test "$with_fftw" = "yes"; then ! have_fftw_header=no ! AC_CHECK_HEADERS(dfftw.h fftw.h, [have_fftw_header=yes; break]) ! if test "$have_fftw_header" = yes; then ! AC_CHECK_LIB(dfftw, fftw_create_plan, FFTW_LIBS="-ldfftw", ! [AC_CHECK_LIB(fftw, fftw_create_plan, FFTW_LIBS="-lfftw", with_fftw=no)]) ! else ! with_fftw=no fi fi ! if test "$with_fftw" = yes; then FFT_DIR='' ! AC_DEFINE(HAVE_FFTW, 1, [Define if the FFTW library is available.]) fi WITH_MPI=true --- 407,442 ---- with_fftw=$withval, with_fftw=yes) if test "$with_fftw" = "yes"; then ! have_fftw3_header=no ! with_fftw3=no ! AC_CHECK_HEADER(fftw3.h, [have_fftw3_header=yes; break]) ! if test "$have_fftw3_header" = yes; then ! AC_CHECK_LIB(fftw3, fftw_plan_dft_1d, [FFTW_LIBS="-lfftw3"; with_fftw3=yes]) ! fi ! if test "$with_fftw3" = no; then ! have_fftw_header=no ! have_rfftw_header=no ! AC_CHECK_HEADERS(dfftw.h fftw.h, [have_fftw_header=yes; break]) ! AC_CHECK_HEADERS(drfftw.h rfftw.h, [have_rfftw_header=yes; break]) ! if test "$have_fftw_header" = yes && test "$have_rfftw_header" = yes; then ! AC_CHECK_LIB(dfftw, fftw_create_plan, FFTW_LIBS="-ldfftw", ! [AC_CHECK_LIB(fftw, fftw_create_plan, FFTW_LIBS="-lfftw", with_fftw=no)]) ! AC_CHECK_LIB(drfftw, rfftw_create_plan, FFTW_LIBS="$FFTW_LIBS -ldrfftw", ! [AC_CHECK_LIB(rfftw, rfftw_create_plan, FFTW_LIBS="$FFTW_LIBS -lrfftw", with_fftw=no, $FFTW_LIBS)], $FFTW_LIBS) ! else ! with_fftw=no ! fi fi fi ! if test "$with_fftw" = yes || test "$with_fftw3" = yes; then FFT_DIR='' ! if test "$with_fftw3" = yes; then ! AC_DEFINE(HAVE_FFTW3, 1, [Define if the FFTW3 library is used.]) ! else ! AC_DEFINE(HAVE_FFTW, 1, [Define if the FFTW library is used.]) ! warn_fftw="Old version of FFTW found. This will affect performance!!" ! fi fi WITH_MPI=true *************** *** 1608,1613 **** --- 1625,1635 ---- warn_msg_printed=true fi + if test -n "$warn_fftw"; then + AC_MSG_WARN($warn_fftw) + warn_msg_printed=true + fi + if $warn_msg_printed; then AC_MSG_RESULT([]) fi *** ./ChangeLog.orig 2004-01-30 15:25:15.000000000 +0100 --- ./ChangeLog 2004-01-30 15:26:32.000000000 +0100 *************** *** 1,3 **** --- 1,8 ---- + 2004-01-30 David Bateman + + * configure.in: Test for the presence of FFTW 3.x and use it in + preference to FFTW 2.x. Define HAVE_FFTW3 + 2004-01-22 John W. Eaton * octMakefile.in (maintainer-clean, distclean):