Merge release-4-6 into master
authorRoland Schulz <roland@utk.edu>
Sun, 3 Jun 2012 15:45:26 +0000 (11:45 -0400)
committerRoland Schulz <roland@utk.edu>
Sun, 3 Jun 2012 15:45:26 +0000 (11:45 -0400)
Conflicts:
src/mdlib/CMakeLists.txt
          change applied to src/gromacs/mdlib/CMakeLists.txt
src/tools/gmx_tune_pme.c
  trivial conflict

Moved:
src/mdlib/fftpack.c & src/mdlib/fftpack.h to src/external/fftpack

Fixed paths in COPYING-OTHER and added boost and gtest/gmock.

Moved the copyright header and list of modifications from fftpack.c into
new README file. Reduces modifications to original file.

Fixed header location in src/gromacs/mdlib/gmx_fft_fftpack.c.

Added macros.h to g_tune_pme (fixing missing min/max)

Change-Id: I9324b1695412e21d16bdcb4d2dc316c53356da5f

23 files changed:
1  2 
CMakeLists.txt
COPYING-OTHER
src/external/fftpack/README
src/external/fftpack/fftpack.c
src/external/fftpack/fftpack.h
src/gromacs/gmxlib/shift_util.c
src/gromacs/gmxlib/thread_mpi/numa_malloc.c
src/gromacs/gmxlib/tpxio.c
src/gromacs/gmxlib/vmdio.c
src/gromacs/gmxlib/vmdio.h
src/gromacs/legacyheaders/domdec.h
src/gromacs/legacyheaders/domdec_network.h
src/gromacs/legacyheaders/mdrun.h
src/gromacs/legacyheaders/types/commrec.h
src/gromacs/legacyheaders/vec.h
src/gromacs/mdlib/CMakeLists.txt
src/gromacs/mdlib/gmx_fft_fftpack.c
src/gromacs/mdlib/gmx_fft_fftw3.c
src/programs/mdrun/md.c
src/tools/gmx_anaeig.c
src/tools/gmx_density.c
src/tools/gmx_editconf.c
src/tools/gmx_tune_pme.c

diff --cc CMakeLists.txt
Simple merge
diff --cc COPYING-OTHER
index 0000000000000000000000000000000000000000,073db8715a3a4657977f9abe98b4df19bd70be59..32686cf8387e943cacba7c6acc27ae32d6f5c2ce
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,83 +1,139 @@@
 -   Files: include/molfile_plugin.h
 -          include/vmddlopen.h
 -          include/vmdplugin.h
 -          src/gmxlib/vmddlopen.c
 -          src/gmxlib/vmdio.c
+ GROMACS is free software, distributed under the GNU General Public License. 
+ See COPING for details. It however includes optional code covered by several 
+ different licences as described below.
+ 1. Trajectory file reading using VMD plugins 
 -   Files: src/mdlib/fftpack.c
++   Files: src/external/vmd_molfile/*
++        src/gromacs/gmxlib/vmdio.c
+                 (C) Copyright 1995-2009 The Board of Trustees of the
+                             University of Illinois
+                              All Rights Reserved
+ Developed by:           Theoretical and Computational Biophysics Group
+                         University of Illinois at Urbana-Champaign
+                         http://www.ks.uiuc.edu/
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
+ this software and associated documentation files (the Software), to deal with
+ the Software without restriction, including without limitation the rights to
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is furnished to
+ do so, subject to the following conditions:
+ Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+ Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the documentation
+ and/or other materials provided with the distribution.
+ Neither the names of Theoretical and Computational Biophysics Group,
+ University of Illinois at Urbana-Champaign, nor the names of its contributors
+ may be used to endorse or promote products derived from this Software without
+ specific prior written permission.
+ THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ OTHER DEALINGS WITH THE SOFTWARE.
+ 2. Internal FFT
++   Files: src/external/fftpack/fftpack.c
+ Copyright (c) 2005-2011, NumPy Developers.
+ All rights reserved.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+     * Redistributions of source code must retain the above copyright
+        notice, this list of conditions and the following disclaimer.
+     * 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.
+     * Neither the name of the NumPy Developers nor the names of any
+        contributors may be used to endorse or promote products derived
+        from this software without specific prior written permission.
+ 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.
+ fftpack.c : A set of FFT routines in C.
+ Algorithmically based on Fortran-77 FFTPACK by Paul N. Swarztrauber (Version 4, 1985).
++
++3. Subset of Boost C++ library
++   Files: src/external/boost/boost/*
++
++Boost Software License - Version 1.0 - August 17th, 2003
++
++Permission is hereby granted, free of charge, to any person or organization
++obtaining a copy of the software and accompanying documentation covered by
++this license (the "Software") to use, reproduce, display, distribute,
++execute, and transmit the Software, and to prepare derivative works of the
++Software, and to permit third-parties to whom the Software is furnished to
++do so, all subject to the following:
++
++The copyright notices in the Software and this entire statement, including
++the above license grant, this restriction and the following disclaimer,
++must be included in all copies of the Software, in whole or in part, and
++all derivative works of the Software, unless such copies or derivative
++works are solely in the form of machine-executable object code generated by
++a source language processor.
++
++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
++SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
++FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
++ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++DEALINGS IN THE SOFTWARE.
++
++4. Google Test and Google Mock
++   Files: src/external/gmock-1.6.0/*
++
++Copyright 2008, Google Inc.
++All rights reserved.
++
++Redistribution and use in source and binary forms, with or without
++modification, are permitted provided that the following conditions are
++met:
++
++    * Redistributions of source code must retain the above copyright
++notice, this list of conditions and the following disclaimer.
++    * 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.
++    * Neither the name of Google Inc. nor the names of its
++contributors may be used to endorse or promote products derived from
++this software without specific prior written permission.
++
++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.
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..a5ab8df89f39b01e438ca2fe36240b88c571f524
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,75 @@@
++ *                This source code is part of
++ * 
++ *                 G   R   O   M   A   C   S
++ * 
++ *          GROningen MAchine for Chemical Simulations
++ * 
++ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
++ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
++ * Copyright (c) 2001-2012, The GROMACS development team,
++ * check out http://www.gromacs.org for more information.
++ 
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2
++ * of the License, or (at your option) any later version.
++ * 
++ * If you want to redistribute modifications, please consider that
++ * scientific software is very special. Version control is crucial -
++ * bugs must be traceable. We will be happy to consider code for
++ * inclusion in the official distribution, but derived work must not
++ * be called official GROMACS. Details are found in the README & COPYING
++ * files - if they are missing, get the official version at www.gromacs.org.
++ * 
++ * To help us fund GROMACS development, we humbly ask that you cite
++ * the papers on the package - you can find them in the top README file.
++ * 
++ * For more info, check our website at http://www.gromacs.org
++ * 
++ * And Hey:
++ * Groningen Machine for Chemical Simulation
++
++************************************************************
++
++fftpack.c is copy of fftpack from Numpy with very minor modifications:
++  - usage of fftpack.h (replacement for Treal define)
++  - [cr]fft[ifb]1 non-static
++  - Added Copyright headers
++  - Added fftpack_ prefix
++
++fftpack.h is GROMACS specific
++
++Original version is from Numpy 1.6
++
++************************************************************
++
++Copyright (c) 2005-2011, NumPy Developers.
++All rights reserved.
++
++Redistribution and use in source and binary forms, with or without
++modification, are permitted provided that the following conditions are
++met:
++
++    * Redistributions of source code must retain the above copyright
++       notice, this list of conditions and the following disclaimer.
++
++    * 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.
++
++    * Neither the name of the NumPy Developers nor the names of any
++       contributors may be used to endorse or promote products derived
++       from this software without specific prior written permission.
++
++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.
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..c913888bd190492c946ff278505c6831ae609e72
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,1495 @@@
++/*
++fftpack.c : A set of FFT routines in C.
++Algorithmically based on Fortran-77 FFTPACK by Paul N. Swarztrauber (Version 4, 1985).
++
++*/
++
++/* isign is +1 for backward and -1 for forward transforms */
++
++#include <math.h>
++#include <stdio.h>
++
++#include "fftpack.h"
++
++#define ref(u,a) u[a]
++
++#define MAXFAC 13    /* maximum number of factors in factorization of n */
++#define NSPECIAL 4   /* number of factors for which we have special-case routines */
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++
++/* ----------------------------------------------------------------------
++   passf2, passf3, passf4, passf5, passf. Complex FFT passes fwd and bwd.
++---------------------------------------------------------------------- */
++
++static void passf2(int ido, int l1, const Treal cc[], Treal ch[], const Treal wa1[], int isign)
++  /* isign==+1 for backward transform */
++  {
++    int i, k, ah, ac;
++    Treal ti2, tr2;
++    if (ido <= 2) {
++      for (k=0; k<l1; k++) {
++        ah = k*ido;
++        ac = 2*k*ido;
++        ch[ah]              = ref(cc,ac) + ref(cc,ac + ido);
++        ch[ah + ido*l1]     = ref(cc,ac) - ref(cc,ac + ido);
++        ch[ah+1]            = ref(cc,ac+1) + ref(cc,ac + ido + 1);
++        ch[ah + ido*l1 + 1] = ref(cc,ac+1) - ref(cc,ac + ido + 1);
++      }
++    } else {
++      for (k=0; k<l1; k++) {
++        for (i=0; i<ido-1; i+=2) {
++          ah = i + k*ido;
++          ac = i + 2*k*ido;
++          ch[ah]   = ref(cc,ac) + ref(cc,ac + ido);
++          tr2      = ref(cc,ac) - ref(cc,ac + ido);
++          ch[ah+1] = ref(cc,ac+1) + ref(cc,ac + 1 + ido);
++          ti2      = ref(cc,ac+1) - ref(cc,ac + 1 + ido);
++          ch[ah+l1*ido+1] = wa1[i]*ti2 + isign*wa1[i+1]*tr2;
++          ch[ah+l1*ido]   = wa1[i]*tr2 - isign*wa1[i+1]*ti2;
++        }
++      }
++    }
++  } /* passf2 */
++
++
++static void passf3(int ido, int l1, const Treal cc[], Treal ch[],
++      const Treal wa1[], const Treal wa2[], int isign)
++  /* isign==+1 for backward transform */
++  {
++    static const Treal taur = -0.5;
++    static const Treal taui = 0.866025403784439;
++    int i, k, ac, ah;
++    Treal ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2;
++    if (ido == 2) {
++      for (k=1; k<=l1; k++) {
++        ac = (3*k - 2)*ido;
++        tr2 = ref(cc,ac) + ref(cc,ac + ido);
++        cr2 = ref(cc,ac - ido) + taur*tr2;
++        ah = (k - 1)*ido;
++        ch[ah] = ref(cc,ac - ido) + tr2;
++
++        ti2 = ref(cc,ac + 1) + ref(cc,ac + ido + 1);
++        ci2 = ref(cc,ac - ido + 1) + taur*ti2;
++        ch[ah + 1] = ref(cc,ac - ido + 1) + ti2;
++
++        cr3 = isign*taui*(ref(cc,ac) - ref(cc,ac + ido));
++        ci3 = isign*taui*(ref(cc,ac + 1) - ref(cc,ac + ido + 1));
++        ch[ah + l1*ido] = cr2 - ci3;
++        ch[ah + 2*l1*ido] = cr2 + ci3;
++        ch[ah + l1*ido + 1] = ci2 + cr3;
++        ch[ah + 2*l1*ido + 1] = ci2 - cr3;
++      }
++    } else {
++      for (k=1; k<=l1; k++) {
++        for (i=0; i<ido-1; i+=2) {
++          ac = i + (3*k - 2)*ido;
++          tr2 = ref(cc,ac) + ref(cc,ac + ido);
++          cr2 = ref(cc,ac - ido) + taur*tr2;
++          ah = i + (k-1)*ido;
++          ch[ah] = ref(cc,ac - ido) + tr2;
++          ti2 = ref(cc,ac + 1) + ref(cc,ac + ido + 1);
++          ci2 = ref(cc,ac - ido + 1) + taur*ti2;
++          ch[ah + 1] = ref(cc,ac - ido + 1) + ti2;
++          cr3 = isign*taui*(ref(cc,ac) - ref(cc,ac + ido));
++          ci3 = isign*taui*(ref(cc,ac + 1) - ref(cc,ac + ido + 1));
++          dr2 = cr2 - ci3;
++          dr3 = cr2 + ci3;
++          di2 = ci2 + cr3;
++          di3 = ci2 - cr3;
++          ch[ah + l1*ido + 1] = wa1[i]*di2 + isign*wa1[i+1]*dr2;
++          ch[ah + l1*ido] = wa1[i]*dr2 - isign*wa1[i+1]*di2;
++          ch[ah + 2*l1*ido + 1] = wa2[i]*di3 + isign*wa2[i+1]*dr3;
++          ch[ah + 2*l1*ido] = wa2[i]*dr3 - isign*wa2[i+1]*di3;
++        }
++      }
++    }
++  } /* passf3 */
++
++
++static void passf4(int ido, int l1, const Treal cc[], Treal ch[],
++      const Treal wa1[], const Treal wa2[], const Treal wa3[], int isign)
++  /* isign == -1 for forward transform and +1 for backward transform */
++  {
++    int i, k, ac, ah;
++    Treal ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4;
++    if (ido == 2) {
++      for (k=0; k<l1; k++) {
++        ac = 4*k*ido + 1;
++        ti1 = ref(cc,ac) - ref(cc,ac + 2*ido);
++        ti2 = ref(cc,ac) + ref(cc,ac + 2*ido);
++        tr4 = ref(cc,ac + 3*ido) - ref(cc,ac + ido);
++        ti3 = ref(cc,ac + ido) + ref(cc,ac + 3*ido);
++        tr1 = ref(cc,ac - 1) - ref(cc,ac + 2*ido - 1);
++        tr2 = ref(cc,ac - 1) + ref(cc,ac + 2*ido - 1);
++        ti4 = ref(cc,ac + ido - 1) - ref(cc,ac + 3*ido - 1);
++        tr3 = ref(cc,ac + ido - 1) + ref(cc,ac + 3*ido - 1);
++        ah = k*ido;
++        ch[ah] = tr2 + tr3;
++        ch[ah + 2*l1*ido] = tr2 - tr3;
++        ch[ah + 1] = ti2 + ti3;
++        ch[ah + 2*l1*ido + 1] = ti2 - ti3;
++        ch[ah + l1*ido] = tr1 + isign*tr4;
++        ch[ah + 3*l1*ido] = tr1 - isign*tr4;
++        ch[ah + l1*ido + 1] = ti1 + isign*ti4;
++        ch[ah + 3*l1*ido + 1] = ti1 - isign*ti4;
++      }
++    } else {
++      for (k=0; k<l1; k++) {
++        for (i=0; i<ido-1; i+=2) {
++          ac = i + 1 + 4*k*ido;
++          ti1 = ref(cc,ac) - ref(cc,ac + 2*ido);
++          ti2 = ref(cc,ac) + ref(cc,ac + 2*ido);
++          ti3 = ref(cc,ac + ido) + ref(cc,ac + 3*ido);
++          tr4 = ref(cc,ac + 3*ido) - ref(cc,ac + ido);
++          tr1 = ref(cc,ac - 1) - ref(cc,ac + 2*ido - 1);
++          tr2 = ref(cc,ac - 1) + ref(cc,ac + 2*ido - 1);
++          ti4 = ref(cc,ac + ido - 1) - ref(cc,ac + 3*ido - 1);
++          tr3 = ref(cc,ac + ido - 1) + ref(cc,ac + 3*ido - 1);
++          ah = i + k*ido;
++          ch[ah] = tr2 + tr3;
++          cr3 = tr2 - tr3;
++          ch[ah + 1] = ti2 + ti3;
++          ci3 = ti2 - ti3;
++          cr2 = tr1 + isign*tr4;
++          cr4 = tr1 - isign*tr4;
++          ci2 = ti1 + isign*ti4;
++          ci4 = ti1 - isign*ti4;
++          ch[ah + l1*ido] = wa1[i]*cr2 - isign*wa1[i + 1]*ci2;
++          ch[ah + l1*ido + 1] = wa1[i]*ci2 + isign*wa1[i + 1]*cr2;
++          ch[ah + 2*l1*ido] = wa2[i]*cr3 - isign*wa2[i + 1]*ci3;
++          ch[ah + 2*l1*ido + 1] = wa2[i]*ci3 + isign*wa2[i + 1]*cr3;
++          ch[ah + 3*l1*ido] = wa3[i]*cr4 -isign*wa3[i + 1]*ci4;
++          ch[ah + 3*l1*ido + 1] = wa3[i]*ci4 + isign*wa3[i + 1]*cr4;
++        }
++      }
++    }
++  } /* passf4 */
++
++
++static void passf5(int ido, int l1, const Treal cc[], Treal ch[],
++      const Treal wa1[], const Treal wa2[], const Treal wa3[], const Treal wa4[], int isign)
++  /* isign == -1 for forward transform and +1 for backward transform */
++  {
++    static const Treal tr11 = 0.309016994374947;
++    static const Treal ti11 = 0.951056516295154;
++    static const Treal tr12 = -0.809016994374947;
++    static const Treal ti12 = 0.587785252292473;
++    int i, k, ac, ah;
++    Treal ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, ti2, ti3,
++        ti4, ti5, dr3, dr4, dr5, dr2, tr2, tr3, tr4, tr5;
++    if (ido == 2) {
++      for (k = 1; k <= l1; ++k) {
++        ac = (5*k - 4)*ido + 1;
++        ti5 = ref(cc,ac) - ref(cc,ac + 3*ido);
++        ti2 = ref(cc,ac) + ref(cc,ac + 3*ido);
++        ti4 = ref(cc,ac + ido) - ref(cc,ac + 2*ido);
++        ti3 = ref(cc,ac + ido) + ref(cc,ac + 2*ido);
++        tr5 = ref(cc,ac - 1) - ref(cc,ac + 3*ido - 1);
++        tr2 = ref(cc,ac - 1) + ref(cc,ac + 3*ido - 1);
++        tr4 = ref(cc,ac + ido - 1) - ref(cc,ac + 2*ido - 1);
++        tr3 = ref(cc,ac + ido - 1) + ref(cc,ac + 2*ido - 1);
++        ah = (k - 1)*ido;
++        ch[ah] = ref(cc,ac - ido - 1) + tr2 + tr3;
++        ch[ah + 1] = ref(cc,ac - ido) + ti2 + ti3;
++        cr2 = ref(cc,ac - ido - 1) + tr11*tr2 + tr12*tr3;
++        ci2 = ref(cc,ac - ido) + tr11*ti2 + tr12*ti3;
++        cr3 = ref(cc,ac - ido - 1) + tr12*tr2 + tr11*tr3;
++        ci3 = ref(cc,ac - ido) + tr12*ti2 + tr11*ti3;
++        cr5 = isign*(ti11*tr5 + ti12*tr4);
++        ci5 = isign*(ti11*ti5 + ti12*ti4);
++        cr4 = isign*(ti12*tr5 - ti11*tr4);
++        ci4 = isign*(ti12*ti5 - ti11*ti4);
++        ch[ah + l1*ido] = cr2 - ci5;
++        ch[ah + 4*l1*ido] = cr2 + ci5;
++        ch[ah + l1*ido + 1] = ci2 + cr5;
++        ch[ah + 2*l1*ido + 1] = ci3 + cr4;
++        ch[ah + 2*l1*ido] = cr3 - ci4;
++        ch[ah + 3*l1*ido] = cr3 + ci4;
++        ch[ah + 3*l1*ido + 1] = ci3 - cr4;
++        ch[ah + 4*l1*ido + 1] = ci2 - cr5;
++      }
++    } else {
++      for (k=1; k<=l1; k++) {
++        for (i=0; i<ido-1; i+=2) {
++          ac = i + 1 + (k*5 - 4)*ido;
++          ti5 = ref(cc,ac) - ref(cc,ac + 3*ido);
++          ti2 = ref(cc,ac) + ref(cc,ac + 3*ido);
++          ti4 = ref(cc,ac + ido) - ref(cc,ac + 2*ido);
++          ti3 = ref(cc,ac + ido) + ref(cc,ac + 2*ido);
++          tr5 = ref(cc,ac - 1) - ref(cc,ac + 3*ido - 1);
++          tr2 = ref(cc,ac - 1) + ref(cc,ac + 3*ido - 1);
++          tr4 = ref(cc,ac + ido - 1) - ref(cc,ac + 2*ido - 1);
++          tr3 = ref(cc,ac + ido - 1) + ref(cc,ac + 2*ido - 1);
++          ah = i + (k - 1)*ido;
++          ch[ah] = ref(cc,ac - ido - 1) + tr2 + tr3;
++          ch[ah + 1] = ref(cc,ac - ido) + ti2 + ti3;
++          cr2 = ref(cc,ac - ido - 1) + tr11*tr2 + tr12*tr3;
++
++          ci2 = ref(cc,ac - ido) + tr11*ti2 + tr12*ti3;
++          cr3 = ref(cc,ac - ido - 1) + tr12*tr2 + tr11*tr3;
++
++          ci3 = ref(cc,ac - ido) + tr12*ti2 + tr11*ti3;
++          cr5 = isign*(ti11*tr5 + ti12*tr4);
++          ci5 = isign*(ti11*ti5 + ti12*ti4);
++          cr4 = isign*(ti12*tr5 - ti11*tr4);
++          ci4 = isign*(ti12*ti5 - ti11*ti4);
++          dr3 = cr3 - ci4;
++          dr4 = cr3 + ci4;
++          di3 = ci3 + cr4;
++          di4 = ci3 - cr4;
++          dr5 = cr2 + ci5;
++          dr2 = cr2 - ci5;
++          di5 = ci2 - cr5;
++          di2 = ci2 + cr5;
++          ch[ah + l1*ido] = wa1[i]*dr2 - isign*wa1[i+1]*di2;
++          ch[ah + l1*ido + 1] = wa1[i]*di2 + isign*wa1[i+1]*dr2;
++          ch[ah + 2*l1*ido] = wa2[i]*dr3 - isign*wa2[i+1]*di3;
++          ch[ah + 2*l1*ido + 1] = wa2[i]*di3 + isign*wa2[i+1]*dr3;
++          ch[ah + 3*l1*ido] = wa3[i]*dr4 - isign*wa3[i+1]*di4;
++          ch[ah + 3*l1*ido + 1] = wa3[i]*di4 + isign*wa3[i+1]*dr4;
++          ch[ah + 4*l1*ido] = wa4[i]*dr5 - isign*wa4[i+1]*di5;
++          ch[ah + 4*l1*ido + 1] = wa4[i]*di5 + isign*wa4[i+1]*dr5;
++        }
++      }
++    }
++  } /* passf5 */
++
++
++static void passf(int *nac, int ido, int ip, int l1, int idl1,
++      Treal cc[], Treal ch[],
++      const Treal wa[], int isign)
++  /* isign is -1 for forward transform and +1 for backward transform */
++  {
++    int idij, idlj, idot, ipph, i, j, k, l, jc, lc, ik, idj, idl, inc,idp;
++    Treal wai, war;
++
++    idot = ido / 2;
++    /* nt = ip*idl1;*/
++    ipph = (ip + 1) / 2;
++    idp = ip*ido;
++    if (ido >= l1) {
++      for (j=1; j<ipph; j++) {
++        jc = ip - j;
++        for (k=0; k<l1; k++) {
++          for (i=0; i<ido; i++) {
++            ch[i + (k + j*l1)*ido] =
++                ref(cc,i + (j + k*ip)*ido) + ref(cc,i + (jc + k*ip)*ido);
++            ch[i + (k + jc*l1)*ido] =
++                ref(cc,i + (j + k*ip)*ido) - ref(cc,i + (jc + k*ip)*ido);
++          }
++        }
++      }
++      for (k=0; k<l1; k++)
++        for (i=0; i<ido; i++)
++          ch[i + k*ido] = ref(cc,i + k*ip*ido);
++    } else {
++      for (j=1; j<ipph; j++) {
++        jc = ip - j;
++        for (i=0; i<ido; i++) {
++          for (k=0; k<l1; k++) {
++            ch[i + (k + j*l1)*ido] = ref(cc,i + (j + k*ip)*ido) + ref(cc,i + (jc + k*
++                ip)*ido);
++            ch[i + (k + jc*l1)*ido] = ref(cc,i + (j + k*ip)*ido) - ref(cc,i + (jc + k*
++                ip)*ido);
++          }
++        }
++      }
++      for (i=0; i<ido; i++)
++        for (k=0; k<l1; k++)
++          ch[i + k*ido] = ref(cc,i + k*ip*ido);
++    }
++
++    idl = 2 - ido;
++    inc = 0;
++    for (l=1; l<ipph; l++) {
++      lc = ip - l;
++      idl += ido;
++      for (ik=0; ik<idl1; ik++) {
++        cc[ik + l*idl1] = ch[ik] + wa[idl - 2]*ch[ik + idl1];
++        cc[ik + lc*idl1] = isign*wa[idl-1]*ch[ik + (ip-1)*idl1];
++      }
++      idlj = idl;
++      inc += ido;
++      for (j=2; j<ipph; j++) {
++        jc = ip - j;
++        idlj += inc;
++        if (idlj > idp) idlj -= idp;
++        war = wa[idlj - 2];
++        wai = wa[idlj-1];
++        for (ik=0; ik<idl1; ik++) {
++          cc[ik + l*idl1] += war*ch[ik + j*idl1];
++          cc[ik + lc*idl1] += isign*wai*ch[ik + jc*idl1];
++        }
++      }
++    }
++    for (j=1; j<ipph; j++)
++      for (ik=0; ik<idl1; ik++)
++        ch[ik] += ch[ik + j*idl1];
++    for (j=1; j<ipph; j++) {
++      jc = ip - j;
++      for (ik=1; ik<idl1; ik+=2) {
++        ch[ik - 1 + j*idl1] = cc[ik - 1 + j*idl1] - cc[ik + jc*idl1];
++        ch[ik - 1 + jc*idl1] = cc[ik - 1 + j*idl1] + cc[ik + jc*idl1];
++        ch[ik + j*idl1] = cc[ik + j*idl1] + cc[ik - 1 + jc*idl1];
++        ch[ik + jc*idl1] = cc[ik + j*idl1] - cc[ik - 1 + jc*idl1];
++      }
++    }
++    *nac = 1;
++    if (ido == 2) return;
++    *nac = 0;
++    for (ik=0; ik<idl1; ik++)
++      cc[ik] = ch[ik];
++    for (j=1; j<ip; j++) {
++      for (k=0; k<l1; k++) {
++        cc[(k + j*l1)*ido + 0] = ch[(k + j*l1)*ido + 0];
++        cc[(k + j*l1)*ido + 1] = ch[(k + j*l1)*ido + 1];
++      }
++    }
++    if (idot <= l1) {
++      idij = 0;
++      for (j=1; j<ip; j++) {
++        idij += 2;
++        for (i=3; i<ido; i+=2) {
++          idij += 2;
++          for (k=0; k<l1; k++) {
++            cc[i - 1 + (k + j*l1)*ido] =
++                wa[idij - 2]*ch[i - 1 + (k + j*l1)*ido] -
++                isign*wa[idij-1]*ch[i + (k + j*l1)*ido];
++            cc[i + (k + j*l1)*ido] =
++                wa[idij - 2]*ch[i + (k + j*l1)*ido] +
++                isign*wa[idij-1]*ch[i - 1 + (k + j*l1)*ido];
++          }
++        }
++      }
++    } else {
++      idj = 2 - ido;
++      for (j=1; j<ip; j++) {
++        idj += ido;
++        for (k = 0; k < l1; k++) {
++          idij = idj;
++          for (i=3; i<ido; i+=2) {
++            idij += 2;
++            cc[i - 1 + (k + j*l1)*ido] =
++                wa[idij - 2]*ch[i - 1 + (k + j*l1)*ido] -
++                isign*wa[idij-1]*ch[i + (k + j*l1)*ido];
++            cc[i + (k + j*l1)*ido] =
++                wa[idij - 2]*ch[i + (k + j*l1)*ido] +
++                isign*wa[idij-1]*ch[i - 1 + (k + j*l1)*ido];
++          }
++        }
++      }
++    }
++  } /* passf */
++
++
++  /* ----------------------------------------------------------------------
++radf2,radb2, radf3,radb3, radf4,radb4, radf5,radb5, radfg,radbg.
++Treal FFT passes fwd and bwd.
++---------------------------------------------------------------------- */
++
++static void radf2(int ido, int l1, const Treal cc[], Treal ch[], const Treal wa1[])
++  {
++    int i, k, ic;
++    Treal ti2, tr2;
++    for (k=0; k<l1; k++) {
++      ch[2*k*ido] =
++          ref(cc,k*ido) + ref(cc,(k + l1)*ido);
++      ch[(2*k+1)*ido + ido-1] =
++          ref(cc,k*ido) - ref(cc,(k + l1)*ido);
++    }
++    if (ido < 2) return;
++    if (ido != 2) {
++      for (k=0; k<l1; k++) {
++        for (i=2; i<ido; i+=2) {
++          ic = ido - i;
++          tr2 = wa1[i - 2]*ref(cc, i-1 + (k + l1)*ido) + wa1[i - 1]*ref(cc, i + (k + l1)*ido);
++          ti2 = wa1[i - 2]*ref(cc, i + (k + l1)*ido) - wa1[i - 1]*ref(cc, i-1 + (k + l1)*ido);
++          ch[i + 2*k*ido] = ref(cc,i + k*ido) + ti2;
++          ch[ic + (2*k+1)*ido] = ti2 - ref(cc,i + k*ido);
++          ch[i - 1 + 2*k*ido] = ref(cc,i - 1 + k*ido) + tr2;
++          ch[ic - 1 + (2*k+1)*ido] = ref(cc,i - 1 + k*ido) - tr2;
++        }
++      }
++      if (ido % 2 == 1) return;
++    }
++    for (k=0; k<l1; k++) {
++      ch[(2*k+1)*ido] = -ref(cc,ido-1 + (k + l1)*ido);
++      ch[ido-1 + 2*k*ido] = ref(cc,ido-1 + k*ido);
++    }
++  } /* radf2 */
++
++
++static void radb2(int ido, int l1, const Treal cc[], Treal ch[], const Treal wa1[])
++  {
++    int i, k, ic;
++    Treal ti2, tr2;
++    for (k=0; k<l1; k++) {
++      ch[k*ido] =
++          ref(cc,2*k*ido) + ref(cc,ido-1 + (2*k+1)*ido);
++      ch[(k + l1)*ido] =
++          ref(cc,2*k*ido) - ref(cc,ido-1 + (2*k+1)*ido);
++    }
++    if (ido < 2) return;
++    if (ido != 2) {
++      for (k = 0; k < l1; ++k) {
++        for (i = 2; i < ido; i += 2) {
++          ic = ido - i;
++          ch[i-1 + k*ido] =
++              ref(cc,i-1 + 2*k*ido) + ref(cc,ic-1 + (2*k+1)*ido);
++          tr2 = ref(cc,i-1 + 2*k*ido) - ref(cc,ic-1 + (2*k+1)*ido);
++          ch[i + k*ido] =
++              ref(cc,i + 2*k*ido) - ref(cc,ic + (2*k+1)*ido);
++          ti2 = ref(cc,i + (2*k)*ido) + ref(cc,ic + (2*k+1)*ido);
++          ch[i-1 + (k + l1)*ido] =
++              wa1[i - 2]*tr2 - wa1[i - 1]*ti2;
++          ch[i + (k + l1)*ido] =
++              wa1[i - 2]*ti2 + wa1[i - 1]*tr2;
++        }
++      }
++      if (ido % 2 == 1) return;
++    }
++    for (k = 0; k < l1; k++) {
++      ch[ido-1 + k*ido] = 2*ref(cc,ido-1 + 2*k*ido);
++      ch[ido-1 + (k + l1)*ido] = -2*ref(cc,(2*k+1)*ido);
++    }
++  } /* radb2 */
++
++
++static void radf3(int ido, int l1, const Treal cc[], Treal ch[],
++      const Treal wa1[], const Treal wa2[])
++  {
++    static const Treal taur = -0.5;
++    static const Treal taui = 0.866025403784439;
++    int i, k, ic;
++    Treal ci2, di2, di3, cr2, dr2, dr3, ti2, ti3, tr2, tr3;
++    for (k=0; k<l1; k++) {
++      cr2 = ref(cc,(k + l1)*ido) + ref(cc,(k + 2*l1)*ido);
++      ch[3*k*ido] = ref(cc,k*ido) + cr2;
++      ch[(3*k+2)*ido] = taui*(ref(cc,(k + l1*2)*ido) - ref(cc,(k + l1)*ido));
++      ch[ido-1 + (3*k + 1)*ido] = ref(cc,k*ido) + taur*cr2;
++    }
++    if (ido == 1) return;
++    for (k=0; k<l1; k++) {
++      for (i=2; i<ido; i+=2) {
++        ic = ido - i;
++        dr2 = wa1[i - 2]*ref(cc,i - 1 + (k + l1)*ido) +
++            wa1[i - 1]*ref(cc,i + (k + l1)*ido);
++        di2 = wa1[i - 2]*ref(cc,i + (k + l1)*ido) - wa1[i - 1]*ref(cc,i - 1 + (k + l1)*ido);
++        dr3 = wa2[i - 2]*ref(cc,i - 1 + (k + l1*2)*ido) + wa2[i - 1]*ref(cc,i + (k + l1*2)*ido);
++        di3 = wa2[i - 2]*ref(cc,i + (k + l1*2)*ido) - wa2[i - 1]*ref(cc,i - 1 + (k + l1*2)*ido);
++        cr2 = dr2 + dr3;
++        ci2 = di2 + di3;
++        ch[i - 1 + 3*k*ido] = ref(cc,i - 1 + k*ido) + cr2;
++        ch[i + 3*k*ido] = ref(cc,i + k*ido) + ci2;
++        tr2 = ref(cc,i - 1 + k*ido) + taur*cr2;
++        ti2 = ref(cc,i + k*ido) + taur*ci2;
++        tr3 = taui*(di2 - di3);
++        ti3 = taui*(dr3 - dr2);
++        ch[i - 1 + (3*k + 2)*ido] = tr2 + tr3;
++        ch[ic - 1 + (3*k + 1)*ido] = tr2 - tr3;
++        ch[i + (3*k + 2)*ido] = ti2 + ti3;
++        ch[ic + (3*k + 1)*ido] = ti3 - ti2;
++      }
++    }
++  } /* radf3 */
++
++
++static void radb3(int ido, int l1, const Treal cc[], Treal ch[],
++      const Treal wa1[], const Treal wa2[])
++  {
++    static const Treal taur = -0.5;
++    static const Treal taui = 0.866025403784439;
++    int i, k, ic;
++    Treal ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2;
++    for (k=0; k<l1; k++) {
++      tr2 = 2*ref(cc,ido-1 + (3*k + 1)*ido);
++      cr2 = ref(cc,3*k*ido) + taur*tr2;
++      ch[k*ido] = ref(cc,3*k*ido) + tr2;
++      ci3 = 2*taui*ref(cc,(3*k + 2)*ido);
++      ch[(k + l1)*ido] = cr2 - ci3;
++      ch[(k + 2*l1)*ido] = cr2 + ci3;
++    }
++    if (ido == 1) return;
++    for (k=0; k<l1; k++) {
++      for (i=2; i<ido; i+=2) {
++        ic = ido - i;
++        tr2 = ref(cc,i - 1 + (3*k + 2)*ido) + ref(cc,ic - 1 + (3*k + 1)*ido);
++        cr2 = ref(cc,i - 1 + 3*k*ido) + taur*tr2;
++        ch[i - 1 + k*ido] = ref(cc,i - 1 + 3*k*ido) + tr2;
++        ti2 = ref(cc,i + (3*k + 2)*ido) - ref(cc,ic + (3*k + 1)*ido);
++        ci2 = ref(cc,i + 3*k*ido) + taur*ti2;
++        ch[i + k*ido] = ref(cc,i + 3*k*ido) + ti2;
++        cr3 = taui*(ref(cc,i - 1 + (3*k + 2)*ido) - ref(cc,ic - 1 + (3*k + 1)*ido));
++        ci3 = taui*(ref(cc,i + (3*k + 2)*ido) + ref(cc,ic + (3*k + 1)*ido));
++        dr2 = cr2 - ci3;
++        dr3 = cr2 + ci3;
++        di2 = ci2 + cr3;
++        di3 = ci2 - cr3;
++        ch[i - 1 + (k + l1)*ido] = wa1[i - 2]*dr2 - wa1[i - 1]*di2;
++        ch[i + (k + l1)*ido] = wa1[i - 2]*di2 + wa1[i - 1]*dr2;
++        ch[i - 1 + (k + 2*l1)*ido] = wa2[i - 2]*dr3 - wa2[i - 1]*di3;
++        ch[i + (k + 2*l1)*ido] = wa2[i - 2]*di3 + wa2[i - 1]*dr3;
++      }
++    }
++  } /* radb3 */
++
++
++static void radf4(int ido, int l1, const Treal cc[], Treal ch[],
++      const Treal wa1[], const Treal wa2[], const Treal wa3[])
++  {
++    static const Treal hsqt2 = 0.7071067811865475;
++    int i, k, ic;
++    Treal ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4;
++    for (k=0; k<l1; k++) {
++      tr1 = ref(cc,(k + l1)*ido) + ref(cc,(k + 3*l1)*ido);
++      tr2 = ref(cc,k*ido) + ref(cc,(k + 2*l1)*ido);
++      ch[4*k*ido] = tr1 + tr2;
++      ch[ido-1 + (4*k + 3)*ido] = tr2 - tr1;
++      ch[ido-1 + (4*k + 1)*ido] = ref(cc,k*ido) - ref(cc,(k + 2*l1)*ido);
++      ch[(4*k + 2)*ido] = ref(cc,(k + 3*l1)*ido) - ref(cc,(k + l1)*ido);
++    }
++    if (ido < 2) return;
++    if (ido != 2) {
++      for (k=0; k<l1; k++) {
++        for (i=2; i<ido; i += 2) {
++          ic = ido - i;
++          cr2 = wa1[i - 2]*ref(cc,i - 1 + (k + l1)*ido) + wa1[i - 1]*ref(cc,i + (k + l1)*ido);
++          ci2 = wa1[i - 2]*ref(cc,i + (k + l1)*ido) - wa1[i - 1]*ref(cc,i - 1 + (k + l1)*ido);
++          cr3 = wa2[i - 2]*ref(cc,i - 1 + (k + 2*l1)*ido) + wa2[i - 1]*ref(cc,i + (k + 2*l1)*
++              ido);
++          ci3 = wa2[i - 2]*ref(cc,i + (k + 2*l1)*ido) - wa2[i - 1]*ref(cc,i - 1 + (k + 2*l1)*
++              ido);
++          cr4 = wa3[i - 2]*ref(cc,i - 1 + (k + 3*l1)*ido) + wa3[i - 1]*ref(cc,i + (k + 3*l1)*
++              ido);
++          ci4 = wa3[i - 2]*ref(cc,i + (k + 3*l1)*ido) - wa3[i - 1]*ref(cc,i - 1 + (k + 3*l1)*
++              ido);
++          tr1 = cr2 + cr4;
++          tr4 = cr4 - cr2;
++          ti1 = ci2 + ci4;
++          ti4 = ci2 - ci4;
++          ti2 = ref(cc,i + k*ido) + ci3;
++          ti3 = ref(cc,i + k*ido) - ci3;
++          tr2 = ref(cc,i - 1 + k*ido) + cr3;
++          tr3 = ref(cc,i - 1 + k*ido) - cr3;
++          ch[i - 1 + 4*k*ido] = tr1 + tr2;
++          ch[ic - 1 + (4*k + 3)*ido] = tr2 - tr1;
++          ch[i + 4*k*ido] = ti1 + ti2;
++          ch[ic + (4*k + 3)*ido] = ti1 - ti2;
++          ch[i - 1 + (4*k + 2)*ido] = ti4 + tr3;
++          ch[ic - 1 + (4*k + 1)*ido] = tr3 - ti4;
++          ch[i + (4*k + 2)*ido] = tr4 + ti3;
++          ch[ic + (4*k + 1)*ido] = tr4 - ti3;
++        }
++      }
++      if (ido % 2 == 1) return;
++    }
++    for (k=0; k<l1; k++) {
++      ti1 = -hsqt2*(ref(cc,ido-1 + (k + l1)*ido) + ref(cc,ido-1 + (k + 3*l1)*ido));
++      tr1 = hsqt2*(ref(cc,ido-1 + (k + l1)*ido) - ref(cc,ido-1 + (k + 3*l1)*ido));
++      ch[ido-1 + 4*k*ido] = tr1 + ref(cc,ido-1 + k*ido);
++      ch[ido-1 + (4*k + 2)*ido] = ref(cc,ido-1 + k*ido) - tr1;
++      ch[(4*k + 1)*ido] = ti1 - ref(cc,ido-1 + (k + 2*l1)*ido);
++      ch[(4*k + 3)*ido] = ti1 + ref(cc,ido-1 + (k + 2*l1)*ido);
++    }
++  } /* radf4 */
++
++
++static void radb4(int ido, int l1, const Treal cc[], Treal ch[],
++      const Treal wa1[], const Treal wa2[], const Treal wa3[])
++  {
++    static const Treal sqrt2 = 1.414213562373095;
++    int i, k, ic;
++    Treal ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4;
++    for (k = 0; k < l1; k++) {
++      tr1 = ref(cc,4*k*ido) - ref(cc,ido-1 + (4*k + 3)*ido);
++      tr2 = ref(cc,4*k*ido) + ref(cc,ido-1 + (4*k + 3)*ido);
++      tr3 = ref(cc,ido-1 + (4*k + 1)*ido) + ref(cc,ido-1 + (4*k + 1)*ido);
++      tr4 = ref(cc,(4*k + 2)*ido) + ref(cc,(4*k + 2)*ido);
++      ch[k*ido] = tr2 + tr3;
++      ch[(k + l1)*ido] = tr1 - tr4;
++      ch[(k + 2*l1)*ido] = tr2 - tr3;
++      ch[(k + 3*l1)*ido] = tr1 + tr4;
++    }
++    if (ido < 2) return;
++    if (ido != 2) {
++      for (k = 0; k < l1; ++k) {
++        for (i = 2; i < ido; i += 2) {
++          ic = ido - i;
++          ti1 = ref(cc,i + 4*k*ido) + ref(cc,ic + (4*k + 3)*ido);
++          ti2 = ref(cc,i + 4*k*ido) - ref(cc,ic + (4*k + 3)*ido);
++          ti3 = ref(cc,i + (4*k + 2)*ido) - ref(cc,ic + (4*k + 1)*ido);
++          tr4 = ref(cc,i + (4*k + 2)*ido) + ref(cc,ic + (4*k + 1)*ido);
++          tr1 = ref(cc,i - 1 + 4*k*ido) - ref(cc,ic - 1 + (4*k + 3)*ido);
++          tr2 = ref(cc,i - 1 + 4*k*ido) + ref(cc,ic - 1 + (4*k + 3)*ido);
++          ti4 = ref(cc,i - 1 + (4*k + 2)*ido) - ref(cc,ic - 1 + (4*k + 1)*ido);
++          tr3 = ref(cc,i - 1 + (4*k + 2)*ido) + ref(cc,ic - 1 + (4*k + 1)*ido);
++          ch[i - 1 + k*ido] = tr2 + tr3;
++          cr3 = tr2 - tr3;
++          ch[i + k*ido] = ti2 + ti3;
++          ci3 = ti2 - ti3;
++          cr2 = tr1 - tr4;
++          cr4 = tr1 + tr4;
++          ci2 = ti1 + ti4;
++          ci4 = ti1 - ti4;
++          ch[i - 1 + (k + l1)*ido] = wa1[i - 2]*cr2 - wa1[i - 1]*ci2;
++          ch[i + (k + l1)*ido] = wa1[i - 2]*ci2 + wa1[i - 1]*cr2;
++          ch[i - 1 + (k + 2*l1)*ido] = wa2[i - 2]*cr3 - wa2[i - 1]*ci3;
++          ch[i + (k + 2*l1)*ido] = wa2[i - 2]*ci3 + wa2[i - 1]*cr3;
++          ch[i - 1 + (k + 3*l1)*ido] = wa3[i - 2]*cr4 - wa3[i - 1]*ci4;
++          ch[i + (k + 3*l1)*ido] = wa3[i - 2]*ci4 + wa3[i - 1]*cr4;
++        }
++      }
++      if (ido % 2 == 1) return;
++    }
++    for (k = 0; k < l1; k++) {
++      ti1 = ref(cc,(4*k + 1)*ido) + ref(cc,(4*k + 3)*ido);
++      ti2 = ref(cc,(4*k + 3)*ido) - ref(cc,(4*k + 1)*ido);
++      tr1 = ref(cc,ido-1 + 4*k*ido) - ref(cc,ido-1 + (4*k + 2)*ido);
++      tr2 = ref(cc,ido-1 + 4*k*ido) + ref(cc,ido-1 + (4*k + 2)*ido);
++      ch[ido-1 + k*ido] = tr2 + tr2;
++      ch[ido-1 + (k + l1)*ido] = sqrt2*(tr1 - ti1);
++      ch[ido-1 + (k + 2*l1)*ido] = ti2 + ti2;
++      ch[ido-1 + (k + 3*l1)*ido] = -sqrt2*(tr1 + ti1);
++    }
++  } /* radb4 */
++
++
++static void radf5(int ido, int l1, const Treal cc[], Treal ch[],
++      const Treal wa1[], const Treal wa2[], const Treal wa3[], const Treal wa4[])
++  {
++    static const Treal tr11 = 0.309016994374947;
++    static const Treal ti11 = 0.951056516295154;
++    static const Treal tr12 = -0.809016994374947;
++    static const Treal ti12 = 0.587785252292473;
++    int i, k, ic;
++    Treal ci2, di2, ci4, ci5, di3, di4, di5, ci3, cr2, cr3, dr2, dr3, dr4, dr5,
++        cr5, cr4, ti2, ti3, ti5, ti4, tr2, tr3, tr4, tr5;
++    for (k = 0; k < l1; k++) {
++      cr2 = ref(cc,(k + 4*l1)*ido) + ref(cc,(k + l1)*ido);
++      ci5 = ref(cc,(k + 4*l1)*ido) - ref(cc,(k + l1)*ido);
++      cr3 = ref(cc,(k + 3*l1)*ido) + ref(cc,(k + 2*l1)*ido);
++      ci4 = ref(cc,(k + 3*l1)*ido) - ref(cc,(k + 2*l1)*ido);
++      ch[5*k*ido] = ref(cc,k*ido) + cr2 + cr3;
++      ch[ido-1 + (5*k + 1)*ido] = ref(cc,k*ido) + tr11*cr2 + tr12*cr3;
++      ch[(5*k + 2)*ido] = ti11*ci5 + ti12*ci4;
++      ch[ido-1 + (5*k + 3)*ido] = ref(cc,k*ido) + tr12*cr2 + tr11*cr3;
++      ch[(5*k + 4)*ido] = ti12*ci5 - ti11*ci4;
++    }
++    if (ido == 1) return;
++    for (k = 0; k < l1; ++k) {
++      for (i = 2; i < ido; i += 2) {
++        ic = ido - i;
++        dr2 = wa1[i - 2]*ref(cc,i - 1 + (k + l1)*ido) + wa1[i - 1]*ref(cc,i + (k + l1)*ido);
++        di2 = wa1[i - 2]*ref(cc,i + (k + l1)*ido) - wa1[i - 1]*ref(cc,i - 1 + (k + l1)*ido);
++        dr3 = wa2[i - 2]*ref(cc,i - 1 + (k + 2*l1)*ido) + wa2[i - 1]*ref(cc,i + (k + 2*l1)*ido);
++        di3 = wa2[i - 2]*ref(cc,i + (k + 2*l1)*ido) - wa2[i - 1]*ref(cc,i - 1 + (k + 2*l1)*ido);
++        dr4 = wa3[i - 2]*ref(cc,i - 1 + (k + 3*l1)*ido) + wa3[i - 1]*ref(cc,i + (k + 3*l1)*ido);
++        di4 = wa3[i - 2]*ref(cc,i + (k + 3*l1)*ido) - wa3[i - 1]*ref(cc,i - 1 + (k + 3*l1)*ido);
++        dr5 = wa4[i - 2]*ref(cc,i - 1 + (k + 4*l1)*ido) + wa4[i - 1]*ref(cc,i + (k + 4*l1)*ido);
++        di5 = wa4[i - 2]*ref(cc,i + (k + 4*l1)*ido) - wa4[i - 1]*ref(cc,i - 1 + (k + 4*l1)*ido);
++        cr2 = dr2 + dr5;
++        ci5 = dr5 - dr2;
++        cr5 = di2 - di5;
++        ci2 = di2 + di5;
++        cr3 = dr3 + dr4;
++        ci4 = dr4 - dr3;
++        cr4 = di3 - di4;
++        ci3 = di3 + di4;
++        ch[i - 1 + 5*k*ido] = ref(cc,i - 1 + k*ido) + cr2 + cr3;
++        ch[i + 5*k*ido] = ref(cc,i + k*ido) + ci2 + ci3;
++        tr2 = ref(cc,i - 1 + k*ido) + tr11*cr2 + tr12*cr3;
++        ti2 = ref(cc,i + k*ido) + tr11*ci2 + tr12*ci3;
++        tr3 = ref(cc,i - 1 + k*ido) + tr12*cr2 + tr11*cr3;
++        ti3 = ref(cc,i + k*ido) + tr12*ci2 + tr11*ci3;
++        tr5 = ti11*cr5 + ti12*cr4;
++        ti5 = ti11*ci5 + ti12*ci4;
++        tr4 = ti12*cr5 - ti11*cr4;
++        ti4 = ti12*ci5 - ti11*ci4;
++        ch[i - 1 + (5*k + 2)*ido] = tr2 + tr5;
++        ch[ic - 1 + (5*k + 1)*ido] = tr2 - tr5;
++        ch[i + (5*k + 2)*ido] = ti2 + ti5;
++        ch[ic + (5*k + 1)*ido] = ti5 - ti2;
++        ch[i - 1 + (5*k + 4)*ido] = tr3 + tr4;
++        ch[ic - 1 + (5*k + 3)*ido] = tr3 - tr4;
++        ch[i + (5*k + 4)*ido] = ti3 + ti4;
++        ch[ic + (5*k + 3)*ido] = ti4 - ti3;
++      }
++    }
++  } /* radf5 */
++
++
++static void radb5(int ido, int l1, const Treal cc[], Treal ch[],
++      const Treal wa1[], const Treal wa2[], const Treal wa3[], const Treal wa4[])
++  {
++    static const Treal tr11 = 0.309016994374947;
++    static const Treal ti11 = 0.951056516295154;
++    static const Treal tr12 = -0.809016994374947;
++    static const Treal ti12 = 0.587785252292473;
++    int i, k, ic;
++    Treal ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, ti2, ti3,
++        ti4, ti5, dr3, dr4, dr5, dr2, tr2, tr3, tr4, tr5;
++    for (k = 0; k < l1; k++) {
++      ti5 = 2*ref(cc,(5*k + 2)*ido);
++      ti4 = 2*ref(cc,(5*k + 4)*ido);
++      tr2 = 2*ref(cc,ido-1 + (5*k + 1)*ido);
++      tr3 = 2*ref(cc,ido-1 + (5*k + 3)*ido);
++      ch[k*ido] = ref(cc,5*k*ido) + tr2 + tr3;
++      cr2 = ref(cc,5*k*ido) + tr11*tr2 + tr12*tr3;
++      cr3 = ref(cc,5*k*ido) + tr12*tr2 + tr11*tr3;
++      ci5 = ti11*ti5 + ti12*ti4;
++      ci4 = ti12*ti5 - ti11*ti4;
++      ch[(k + l1)*ido] = cr2 - ci5;
++      ch[(k + 2*l1)*ido] = cr3 - ci4;
++      ch[(k + 3*l1)*ido] = cr3 + ci4;
++      ch[(k + 4*l1)*ido] = cr2 + ci5;
++    }
++    if (ido == 1) return;
++    for (k = 0; k < l1; ++k) {
++      for (i = 2; i < ido; i += 2) {
++        ic = ido - i;
++        ti5 = ref(cc,i + (5*k + 2)*ido) + ref(cc,ic + (5*k + 1)*ido);
++        ti2 = ref(cc,i + (5*k + 2)*ido) - ref(cc,ic + (5*k + 1)*ido);
++        ti4 = ref(cc,i + (5*k + 4)*ido) + ref(cc,ic + (5*k + 3)*ido);
++        ti3 = ref(cc,i + (5*k + 4)*ido) - ref(cc,ic + (5*k + 3)*ido);
++        tr5 = ref(cc,i - 1 + (5*k + 2)*ido) - ref(cc,ic - 1 + (5*k + 1)*ido);
++        tr2 = ref(cc,i - 1 + (5*k + 2)*ido) + ref(cc,ic - 1 + (5*k + 1)*ido);
++        tr4 = ref(cc,i - 1 + (5*k + 4)*ido) - ref(cc,ic - 1 + (5*k + 3)*ido);
++        tr3 = ref(cc,i - 1 + (5*k + 4)*ido) + ref(cc,ic - 1 + (5*k + 3)*ido);
++        ch[i - 1 + k*ido] = ref(cc,i - 1 + 5*k*ido) + tr2 + tr3;
++        ch[i + k*ido] = ref(cc,i + 5*k*ido) + ti2 + ti3;
++        cr2 = ref(cc,i - 1 + 5*k*ido) + tr11*tr2 + tr12*tr3;
++
++        ci2 = ref(cc,i + 5*k*ido) + tr11*ti2 + tr12*ti3;
++        cr3 = ref(cc,i - 1 + 5*k*ido) + tr12*tr2 + tr11*tr3;
++
++        ci3 = ref(cc,i + 5*k*ido) + tr12*ti2 + tr11*ti3;
++        cr5 = ti11*tr5 + ti12*tr4;
++        ci5 = ti11*ti5 + ti12*ti4;
++        cr4 = ti12*tr5 - ti11*tr4;
++        ci4 = ti12*ti5 - ti11*ti4;
++        dr3 = cr3 - ci4;
++        dr4 = cr3 + ci4;
++        di3 = ci3 + cr4;
++        di4 = ci3 - cr4;
++        dr5 = cr2 + ci5;
++        dr2 = cr2 - ci5;
++        di5 = ci2 - cr5;
++        di2 = ci2 + cr5;
++        ch[i - 1 + (k + l1)*ido] = wa1[i - 2]*dr2 - wa1[i - 1]*di2;
++        ch[i + (k + l1)*ido] = wa1[i - 2]*di2 + wa1[i - 1]*dr2;
++        ch[i - 1 + (k + 2*l1)*ido] = wa2[i - 2]*dr3 - wa2[i - 1]*di3;
++        ch[i + (k + 2*l1)*ido] = wa2[i - 2]*di3 + wa2[i - 1]*dr3;
++        ch[i - 1 + (k + 3*l1)*ido] = wa3[i - 2]*dr4 - wa3[i - 1]*di4;
++        ch[i + (k + 3*l1)*ido] = wa3[i - 2]*di4 + wa3[i - 1]*dr4;
++        ch[i - 1 + (k + 4*l1)*ido] = wa4[i - 2]*dr5 - wa4[i - 1]*di5;
++        ch[i + (k + 4*l1)*ido] = wa4[i - 2]*di5 + wa4[i - 1]*dr5;
++      }
++    }
++  } /* radb5 */
++
++
++static void radfg(int ido, int ip, int l1, int idl1,
++      Treal cc[], Treal ch[], const Treal wa[])
++  {
++    static const Treal twopi = 6.28318530717959;
++    int idij, ipph, i, j, k, l, j2, ic, jc, lc, ik, is, nbd;
++    Treal dc2, ai1, ai2, ar1, ar2, ds2, dcp, arg, dsp, ar1h, ar2h;
++    arg = twopi / ip;
++    dcp = cos(arg);
++    dsp = sin(arg);
++    ipph = (ip + 1) / 2;
++    nbd = (ido - 1) / 2;
++    if (ido != 1) {
++      for (ik=0; ik<idl1; ik++) ch[ik] = cc[ik];
++      for (j=1; j<ip; j++)
++        for (k=0; k<l1; k++)
++          ch[(k + j*l1)*ido] = cc[(k + j*l1)*ido];
++      if (nbd <= l1) {
++        is = -ido;
++        for (j=1; j<ip; j++) {
++          is += ido;
++          idij = is-1;
++          for (i=2; i<ido; i+=2) {
++            idij += 2;
++            for (k=0; k<l1; k++) {
++              ch[i - 1 + (k + j*l1)*ido] =
++                  wa[idij - 1]*cc[i - 1 + (k + j*l1)*ido] + wa[idij]*cc[i + (k + j*l1)*ido];
++              ch[i + (k + j*l1)*ido] =
++                  wa[idij - 1]*cc[i + (k + j*l1)*ido] - wa[idij]*cc[i - 1 + (k + j*l1)*ido];
++            }
++          }
++        }
++      } else {
++        is = -ido;
++        for (j=1; j<ip; j++) {
++          is += ido;
++          for (k=0; k<l1; k++) {
++            idij = is-1;
++            for (i=2; i<ido; i+=2) {
++              idij += 2;
++              ch[i - 1 + (k + j*l1)*ido] =
++                  wa[idij - 1]*cc[i - 1 + (k + j*l1)*ido] + wa[idij]*cc[i + (k + j*l1)*ido];
++              ch[i + (k + j*l1)*ido] =
++                  wa[idij - 1]*cc[i + (k + j*l1)*ido] - wa[idij]*cc[i - 1 + (k + j*l1)*ido];
++            }
++          }
++        }
++      }
++      if (nbd >= l1) {
++        for (j=1; j<ipph; j++) {
++          jc = ip - j;
++          for (k=0; k<l1; k++) {
++            for (i=2; i<ido; i+=2) {
++              cc[i - 1 + (k + j*l1)*ido] = ch[i - 1 + (k + j*l1)*ido] + ch[i - 1 + (k + jc*l1)*ido];
++              cc[i - 1 + (k + jc*l1)*ido] = ch[i + (k + j*l1)*ido] - ch[i + (k + jc*l1)*ido];
++              cc[i + (k + j*l1)*ido] = ch[i + (k + j*l1)*ido] + ch[i + (k + jc*l1)*ido];
++              cc[i + (k + jc*l1)*ido] = ch[i - 1 + (k + jc*l1)*ido] - ch[i - 1 + (k + j*l1)*ido];
++            }
++          }
++        }
++      } else {
++        for (j=1; j<ipph; j++) {
++          jc = ip - j;
++          for (i=2; i<ido; i+=2) {
++            for (k=0; k<l1; k++) {
++              cc[i - 1 + (k + j*l1)*ido] =
++                  ch[i - 1 + (k + j*l1)*ido] + ch[i - 1 + (k + jc*l1)*ido];
++              cc[i - 1 + (k + jc*l1)*ido] = ch[i + (k + j*l1)*ido] - ch[i + (k + jc*l1)*ido];
++              cc[i + (k + j*l1)*ido] = ch[i + (k + j*l1)*ido] + ch[i + (k + jc*l1)*ido];
++              cc[i + (k + jc*l1)*ido] = ch[i - 1 + (k + jc*l1)*ido] - ch[i - 1 + (k + j*l1)*ido];
++            }
++          }
++        }
++      }
++    } else {  /* now ido == 1 */
++      for (ik=0; ik<idl1; ik++) cc[ik] = ch[ik];
++    }
++    for (j=1; j<ipph; j++) {
++      jc = ip - j;
++      for (k=0; k<l1; k++) {
++        cc[(k + j*l1)*ido] = ch[(k + j*l1)*ido] + ch[(k + jc*l1)*ido];
++        cc[(k + jc*l1)*ido] = ch[(k + jc*l1)*ido] - ch[(k + j*l1)*ido];
++      }
++    }
++
++    ar1 = 1;
++    ai1 = 0;
++    for (l=1; l<ipph; l++) {
++      lc = ip - l;
++      ar1h = dcp*ar1 - dsp*ai1;
++      ai1 = dcp*ai1 + dsp*ar1;
++      ar1 = ar1h;
++      for (ik=0; ik<idl1; ik++) {
++        ch[ik + l*idl1] = cc[ik] + ar1*cc[ik + idl1];
++        ch[ik + lc*idl1] = ai1*cc[ik + (ip-1)*idl1];
++      }
++      dc2 = ar1;
++      ds2 = ai1;
++      ar2 = ar1;
++      ai2 = ai1;
++      for (j=2; j<ipph; j++) {
++        jc = ip - j;
++        ar2h = dc2*ar2 - ds2*ai2;
++        ai2 = dc2*ai2 + ds2*ar2;
++        ar2 = ar2h;
++        for (ik=0; ik<idl1; ik++) {
++          ch[ik + l*idl1] += ar2*cc[ik + j*idl1];
++          ch[ik + lc*idl1] += ai2*cc[ik + jc*idl1];
++        }
++      }
++    }
++    for (j=1; j<ipph; j++)
++      for (ik=0; ik<idl1; ik++)
++        ch[ik] += cc[ik + j*idl1];
++
++    if (ido >= l1) {
++      for (k=0; k<l1; k++) {
++        for (i=0; i<ido; i++) {
++          ref(cc,i + k*ip*ido) = ch[i + k*ido];
++        }
++      }
++    } else {
++      for (i=0; i<ido; i++) {
++        for (k=0; k<l1; k++) {
++          ref(cc,i + k*ip*ido) = ch[i + k*ido];
++        }
++      }
++    }
++    for (j=1; j<ipph; j++) {
++      jc = ip - j;
++      j2 = 2*j;
++      for (k=0; k<l1; k++) {
++        ref(cc,ido-1 + (j2 - 1 + k*ip)*ido) =
++            ch[(k + j*l1)*ido];
++        ref(cc,(j2 + k*ip)*ido) =
++            ch[(k + jc*l1)*ido];
++      }
++    }
++    if (ido == 1) return;
++    if (nbd >= l1) {
++      for (j=1; j<ipph; j++) {
++        jc = ip - j;
++        j2 = 2*j;
++        for (k=0; k<l1; k++) {
++          for (i=2; i<ido; i+=2) {
++            ic = ido - i;
++            ref(cc,i - 1 + (j2 + k*ip)*ido) = ch[i - 1 + (k + j*l1)*ido] + ch[i - 1 + (k + jc*l1)*ido];
++            ref(cc,ic - 1 + (j2 - 1 + k*ip)*ido) = ch[i - 1 + (k + j*l1)*ido] - ch[i - 1 + (k + jc*l1)*ido];
++            ref(cc,i + (j2 + k*ip)*ido) = ch[i + (k + j*l1)*ido] + ch[i + (k + jc*l1)*ido];
++            ref(cc,ic + (j2 - 1 + k*ip)*ido) = ch[i + (k + jc*l1)*ido] - ch[i + (k + j*l1)*ido];
++          }
++        }
++      }
++    } else {
++      for (j=1; j<ipph; j++) {
++        jc = ip - j;
++        j2 = 2*j;
++        for (i=2; i<ido; i+=2) {
++          ic = ido - i;
++          for (k=0; k<l1; k++) {
++            ref(cc,i - 1 + (j2 + k*ip)*ido) = ch[i - 1 + (k + j*l1)*ido] + ch[i - 1 + (k + jc*l1)*ido];
++            ref(cc,ic - 1 + (j2 - 1 + k*ip)*ido) = ch[i - 1 + (k + j*l1)*ido] - ch[i - 1 + (k + jc*l1)*ido];
++            ref(cc,i + (j2 + k*ip)*ido) = ch[i + (k + j*l1)*ido] + ch[i + (k + jc*l1)*ido];
++            ref(cc,ic + (j2 - 1 + k*ip)*ido) = ch[i + (k + jc*l1)*ido] - ch[i + (k + j*l1)*ido];
++          }
++        }
++      }
++    }
++  } /* radfg */
++
++
++static void radbg(int ido, int ip, int l1, int idl1,
++      Treal cc[], Treal ch[], const Treal wa[])
++  {
++    static const Treal twopi = 6.28318530717959;
++    int idij, ipph, i, j, k, l, j2, ic, jc, lc, ik, is;
++    Treal dc2, ai1, ai2, ar1, ar2, ds2;
++    int nbd;
++    Treal dcp, arg, dsp, ar1h, ar2h;
++    arg = twopi / ip;
++    dcp = cos(arg);
++    dsp = sin(arg);
++    nbd = (ido - 1) / 2;
++    ipph = (ip + 1) / 2;
++    if (ido >= l1) {
++      for (k=0; k<l1; k++) {
++        for (i=0; i<ido; i++) {
++          ch[i + k*ido] = ref(cc,i + k*ip*ido);
++        }
++      }
++    } else {
++      for (i=0; i<ido; i++) {
++        for (k=0; k<l1; k++) {
++          ch[i + k*ido] = ref(cc,i + k*ip*ido);
++        }
++      }
++    }
++    for (j=1; j<ipph; j++) {
++      jc = ip - j;
++      j2 = 2*j;
++      for (k=0; k<l1; k++) {
++        ch[(k + j*l1)*ido] = ref(cc,ido-1 + (j2 - 1 + k*ip)*ido) + ref(cc,ido-1 + (j2 - 1 + k*ip)*
++            ido);
++        ch[(k + jc*l1)*ido] = ref(cc,(j2 + k*ip)*ido) + ref(cc,(j2 + k*ip)*ido);
++      }
++    }
++
++    if (ido != 1) {
++      if (nbd >= l1) {
++        for (j=1; j<ipph; j++) {
++          jc = ip - j;
++          for (k=0; k<l1; k++) {
++            for (i=2; i<ido; i+=2) {
++              ic = ido - i;
++              ch[i - 1 + (k + j*l1)*ido] = ref(cc,i - 1 + (2*j + k*ip)*ido) + ref(cc,
++                  ic - 1 + (2*j - 1 + k*ip)*ido);
++              ch[i - 1 + (k + jc*l1)*ido] = ref(cc,i - 1 + (2*j + k*ip)*ido) -
++                  ref(cc,ic - 1 + (2*j - 1 + k*ip)*ido);
++              ch[i + (k + j*l1)*ido] = ref(cc,i + (2*j + k*ip)*ido) - ref(cc,ic
++                  + (2*j - 1 + k*ip)*ido);
++              ch[i + (k + jc*l1)*ido] = ref(cc,i + (2*j + k*ip)*ido) + ref(cc,ic
++                  + (2*j - 1 + k*ip)*ido);
++            }
++          }
++        }
++      } else {
++        for (j=1; j<ipph; j++) {
++          jc = ip - j;
++          for (i=2; i<ido; i+=2) {
++            ic = ido - i;
++            for (k=0; k<l1; k++) {
++              ch[i - 1 + (k + j*l1)*ido] = ref(cc,i - 1 + (2*j + k*ip)*ido) + ref(cc,
++                  ic - 1 + (2*j - 1 + k*ip)*ido);
++              ch[i - 1 + (k + jc*l1)*ido] = ref(cc,i - 1 + (2*j + k*ip)*ido) -
++                  ref(cc,ic - 1 + (2*j - 1 + k*ip)*ido);
++              ch[i + (k + j*l1)*ido] = ref(cc,i + (2*j + k*ip)*ido) - ref(cc,ic
++                  + (2*j - 1 + k*ip)*ido);
++              ch[i + (k + jc*l1)*ido] = ref(cc,i + (2*j + k*ip)*ido) + ref(cc,ic
++                  + (2*j - 1 + k*ip)*ido);
++            }
++          }
++        }
++      }
++    }
++
++    ar1 = 1;
++    ai1 = 0;
++    for (l=1; l<ipph; l++) {
++      lc = ip - l;
++      ar1h = dcp*ar1 - dsp*ai1;
++      ai1 = dcp*ai1 + dsp*ar1;
++      ar1 = ar1h;
++      for (ik=0; ik<idl1; ik++) {
++        cc[ik + l*idl1] = ch[ik] + ar1*ch[ik + idl1];
++        cc[ik + lc*idl1] = ai1*ch[ik + (ip-1)*idl1];
++      }
++      dc2 = ar1;
++      ds2 = ai1;
++      ar2 = ar1;
++      ai2 = ai1;
++      for (j=2; j<ipph; j++) {
++        jc = ip - j;
++        ar2h = dc2*ar2 - ds2*ai2;
++        ai2 = dc2*ai2 + ds2*ar2;
++        ar2 = ar2h;
++        for (ik=0; ik<idl1; ik++) {
++          cc[ik + l*idl1] += ar2*ch[ik + j*idl1];
++          cc[ik + lc*idl1] += ai2*ch[ik + jc*idl1];
++        }
++      }
++    }
++    for (j=1; j<ipph; j++) {
++      for (ik=0; ik<idl1; ik++) {
++        ch[ik] += ch[ik + j*idl1];
++      }
++    }
++    for (j=1; j<ipph; j++) {
++      jc = ip - j;
++      for (k=0; k<l1; k++) {
++        ch[(k + j*l1)*ido] = cc[(k + j*l1)*ido] - cc[(k + jc*l1)*ido];
++        ch[(k + jc*l1)*ido] = cc[(k + j*l1)*ido] + cc[(k + jc*l1)*ido];
++      }
++    }
++
++    if (ido == 1) return;
++    if (nbd >= l1) {
++      for (j=1; j<ipph; j++) {
++        jc = ip - j;
++        for (k=0; k<l1; k++) {
++          for (i=2; i<ido; i+=2) {
++            ch[i - 1 + (k + j*l1)*ido] = cc[i - 1 + (k + j*l1)*ido] - cc[i + (k + jc*l1)*ido];
++            ch[i - 1 + (k + jc*l1)*ido] = cc[i - 1 + (k + j*l1)*ido] + cc[i + (k + jc*l1)*ido];
++            ch[i + (k + j*l1)*ido] = cc[i + (k + j*l1)*ido] + cc[i - 1 + (k + jc*l1)*ido];
++            ch[i + (k + jc*l1)*ido] = cc[i + (k + j*l1)*ido] - cc[i - 1 + (k + jc*l1)*ido];
++          }
++        }
++      }
++    } else {
++      for (j=1; j<ipph; j++) {
++        jc = ip - j;
++        for (i=2; i<ido; i+=2) {
++          for (k=0; k<l1; k++) {
++            ch[i - 1 + (k + j*l1)*ido] = cc[i - 1 + (k + j*l1)*ido] - cc[i + (k + jc*l1)*ido];
++            ch[i - 1 + (k + jc*l1)*ido] = cc[i - 1 + (k + j *l1)*ido] + cc[i + (k + jc*l1)*ido];
++            ch[i + (k + j*l1)*ido] = cc[i + (k + j*l1)*ido] + cc[i - 1 + (k + jc*l1)*ido];
++            ch[i + (k + jc*l1)*ido] = cc[i + (k + j*l1)*ido] - cc[i - 1 + (k + jc*l1)*ido];
++          }
++        }
++      }
++    }
++    for (ik=0; ik<idl1; ik++) cc[ik] = ch[ik];
++    for (j=1; j<ip; j++)
++      for (k=0; k<l1; k++)
++        cc[(k + j*l1)*ido] = ch[(k + j*l1)*ido];
++    if (nbd <= l1) {
++      is = -ido;
++      for (j=1; j<ip; j++) {
++        is += ido;
++        idij = is-1;
++        for (i=2; i<ido; i+=2) {
++          idij += 2;
++          for (k=0; k<l1; k++) {
++            cc[i - 1 + (k + j*l1)*ido] = wa[idij - 1]*ch[i - 1 + (k + j*l1)*ido] - wa[idij]*
++                ch[i + (k + j*l1)*ido];
++            cc[i + (k + j*l1)*ido] = wa[idij - 1]*ch[i + (k + j*l1)*ido] + wa[idij]*ch[i - 1 + (k + j*l1)*ido];
++          }
++        }
++      }
++    } else {
++      is = -ido;
++      for (j=1; j<ip; j++) {
++        is += ido;
++        for (k=0; k<l1; k++) {
++          idij = is - 1;
++          for (i=2; i<ido; i+=2) {
++            idij += 2;
++            cc[i - 1 + (k + j*l1)*ido] = wa[idij-1]*ch[i - 1 + (k + j*l1)*ido] - wa[idij]*
++                ch[i + (k + j*l1)*ido];
++            cc[i + (k + j*l1)*ido] = wa[idij-1]*ch[i + (k + j*l1)*ido] + wa[idij]*ch[i - 1 + (k + j*l1)*ido];
++          }
++        }
++      }
++    }
++  } /* radbg */
++
++  /* ----------------------------------------------------------------------
++cfftf1, cfftf, cfftb, cffti1, cffti. Complex FFTs.
++---------------------------------------------------------------------- */
++
++void fftpack_cfftf1(int n, Treal c[], Treal ch[], const Treal wa[], const int ifac[MAXFAC+2], int isign)
++  {
++    int idot, i;
++    int k1, l1, l2;
++    int na, nf, ip, iw, ix2, ix3, ix4, nac, ido, idl1;
++    Treal *cinput, *coutput;
++    nf = ifac[1];
++    na = 0;
++    l1 = 1;
++    iw = 0;
++    for (k1=2; k1<=nf+1; k1++) {
++      ip = ifac[k1];
++      l2 = ip*l1;
++      ido = n / l2;
++      idot = ido + ido;
++      idl1 = idot*l1;
++      if (na) {
++        cinput = ch;
++        coutput = c;
++      } else {
++        cinput = c;
++        coutput = ch;
++      }
++      switch (ip) {
++      case 4:
++        ix2 = iw + idot;
++        ix3 = ix2 + idot;
++        passf4(idot, l1, cinput, coutput, &wa[iw], &wa[ix2], &wa[ix3], isign);
++        na = !na;
++        break;
++      case 2:
++        passf2(idot, l1, cinput, coutput, &wa[iw], isign);
++        na = !na;
++        break;
++      case 3:
++        ix2 = iw + idot;
++        passf3(idot, l1, cinput, coutput, &wa[iw], &wa[ix2], isign);
++        na = !na;
++        break;
++      case 5:
++        ix2 = iw + idot;
++        ix3 = ix2 + idot;
++        ix4 = ix3 + idot;
++        passf5(idot, l1, cinput, coutput, &wa[iw], &wa[ix2], &wa[ix3], &wa[ix4], isign);
++        na = !na;
++        break;
++      default:
++        passf(&nac, idot, ip, l1, idl1, cinput, coutput, &wa[iw], isign);
++        if (nac != 0) na = !na;
++      }
++      l1 = l2;
++      iw += (ip - 1)*idot;
++    }
++    if (na == 0) return;
++    for (i=0; i<2*n; i++) c[i] = ch[i];
++  } /* cfftf1 */
++
++
++void fftpack_cfftf(int n, Treal c[], Treal wsave[])
++  {
++    int iw1, iw2;
++    if (n == 1) return;
++    iw1 = 2*n;
++    iw2 = iw1 + 2*n;
++    fftpack_cfftf1(n, c, wsave, wsave+iw1, (int*)(wsave+iw2), -1);
++  } /* cfftf */
++
++
++void fftpack_cfftb(int n, Treal c[], Treal wsave[])
++  {
++    int iw1, iw2;
++    if (n == 1) return;
++    iw1 = 2*n;
++    iw2 = iw1 + 2*n;
++    fftpack_cfftf1(n, c, wsave, wsave+iw1, (int*)(wsave+iw2), +1);
++  } /* cfftb */
++
++
++static void factorize(int n, int ifac[MAXFAC+2], const int ntryh[NSPECIAL])
++  /* Factorize n in factors in ntryh and rest. On exit,
++ifac[0] contains n and ifac[1] contains number of factors,
++the factors start from ifac[2]. */
++  {
++    int ntry=3, i, j=0, ib, nf=0, nl=n, nq, nr;
++startloop:
++    if (j < NSPECIAL)
++      ntry = ntryh[j];
++    else
++      ntry+= 2;
++    j++;
++    do {
++      nq = nl / ntry;
++      nr = nl - ntry*nq;
++      if (nr != 0) goto startloop;
++      nf++;
++      ifac[nf + 1] = ntry;
++      nl = nq;
++      if (ntry == 2 && nf != 1) {
++        for (i=2; i<=nf; i++) {
++          ib = nf - i + 2;
++          ifac[ib + 1] = ifac[ib];
++        }
++        ifac[2] = 2;
++      }
++    } while (nl != 1);
++    ifac[0] = n;
++    ifac[1] = nf;
++  }
++
++
++void fftpack_cffti1(int n, Treal wa[], int ifac[MAXFAC+2])
++  {
++    static const Treal twopi = 6.28318530717959;
++    Treal arg, argh, argld, fi;
++    int idot, i, j;
++    int i1, k1, l1, l2;
++    int ld, ii, nf, ip;
++    int ido, ipm;
++
++    static const int ntryh[NSPECIAL] = {
++      3,4,2,5    }; /* Do not change the order of these. */
++
++    factorize(n,ifac,ntryh);
++    nf = ifac[1];
++    argh = twopi/(Treal)n;
++    i = 1;
++    l1 = 1;
++    for (k1=1; k1<=nf; k1++) {
++      ip = ifac[k1+1];
++      ld = 0;
++      l2 = l1*ip;
++      ido = n / l2;
++      idot = ido + ido + 2;
++      ipm = ip - 1;
++      for (j=1; j<=ipm; j++) {
++        i1 = i;
++        wa[i-1] = 1;
++        wa[i] = 0;
++        ld += l1;
++        fi = 0;
++        argld = ld*argh;
++        for (ii=4; ii<=idot; ii+=2) {
++          i+= 2;
++          fi+= 1;
++          arg = fi*argld;
++          wa[i-1] = cos(arg);
++          wa[i] = sin(arg);
++        }
++        if (ip > 5) {
++          wa[i1-1] = wa[i-1];
++          wa[i1] = wa[i];
++        }
++      }
++      l1 = l2;
++    }
++  } /* cffti1 */
++
++
++void fftpack_cffti(int n, Treal wsave[])
++ {
++    int iw1, iw2;
++    if (n == 1) return;
++    iw1 = 2*n;
++    iw2 = iw1 + 2*n;
++    fftpack_cffti1(n, wsave+iw1, (int*)(wsave+iw2));
++  } /* cffti */
++
++  /* ----------------------------------------------------------------------
++rfftf1, rfftb1, rfftf, rfftb, rffti1, rffti. Treal FFTs.
++---------------------------------------------------------------------- */
++
++void fftpack_rfftf1(int n, Treal c[], Treal ch[], const Treal wa[], const int ifac[MAXFAC+2])
++  {
++    int i;
++    int k1, l1, l2, na, kh, nf, ip, iw, ix2, ix3, ix4, ido, idl1;
++    Treal *cinput, *coutput;
++    nf = ifac[1];
++    na = 1;
++    l2 = n;
++    iw = n-1;
++    for (k1 = 1; k1 <= nf; ++k1) {
++      kh = nf - k1;
++      ip = ifac[kh + 2];
++      l1 = l2 / ip;
++      ido = n / l2;
++      idl1 = ido*l1;
++      iw -= (ip - 1)*ido;
++      na = !na;
++      if (na) {
++        cinput = ch;
++        coutput = c;
++      } else {
++        cinput = c;
++        coutput = ch;
++      }
++      switch (ip) {
++      case 4:
++        ix2 = iw + ido;
++        ix3 = ix2 + ido;
++        radf4(ido, l1, cinput, coutput, &wa[iw], &wa[ix2], &wa[ix3]);
++        break;
++      case 2:
++        radf2(ido, l1, cinput, coutput, &wa[iw]);
++        break;
++      case 3:
++        ix2 = iw + ido;
++        radf3(ido, l1, cinput, coutput, &wa[iw], &wa[ix2]);
++        break;
++      case 5:
++        ix2 = iw + ido;
++        ix3 = ix2 + ido;
++        ix4 = ix3 + ido;
++        radf5(ido, l1, cinput, coutput, &wa[iw], &wa[ix2], &wa[ix3], &wa[ix4]);
++        break;
++      default:
++        if (ido == 1)
++          na = !na;
++        if (na == 0) {
++          radfg(ido, ip, l1, idl1, c, ch, &wa[iw]);
++          na = 1;
++        } else {
++          radfg(ido, ip, l1, idl1, ch, c, &wa[iw]);
++          na = 0;
++        }
++      }
++      l2 = l1;
++    }
++    if (na == 1) return;
++    for (i = 0; i < n; i++) c[i] = ch[i];
++  } /* rfftf1 */
++
++
++void fftpack_rfftb1(int n, Treal c[], Treal ch[], const Treal wa[], const int ifac[MAXFAC+2])
++  {
++    int i;
++    int k1, l1, l2, na, nf, ip, iw, ix2, ix3, ix4, ido, idl1;
++    Treal *cinput, *coutput;
++    nf = ifac[1];
++    na = 0;
++    l1 = 1;
++    iw = 0;
++    for (k1=1; k1<=nf; k1++) {
++      ip = ifac[k1 + 1];
++      l2 = ip*l1;
++      ido = n / l2;
++      idl1 = ido*l1;
++      if (na) {
++        cinput = ch;
++        coutput = c;
++      } else {
++        cinput = c;
++        coutput = ch;
++      }
++      switch (ip) {
++      case 4:
++        ix2 = iw + ido;
++        ix3 = ix2 + ido;
++        radb4(ido, l1, cinput, coutput, &wa[iw], &wa[ix2], &wa[ix3]);
++        na = !na;
++        break;
++      case 2:
++        radb2(ido, l1, cinput, coutput, &wa[iw]);
++        na = !na;
++        break;
++      case 3:
++        ix2 = iw + ido;
++        radb3(ido, l1, cinput, coutput, &wa[iw], &wa[ix2]);
++        na = !na;
++        break;
++      case 5:
++        ix2 = iw + ido;
++        ix3 = ix2 + ido;
++        ix4 = ix3 + ido;
++        radb5(ido, l1, cinput, coutput, &wa[iw], &wa[ix2], &wa[ix3], &wa[ix4]);
++        na = !na;
++        break;
++      default:
++        radbg(ido, ip, l1, idl1, cinput, coutput, &wa[iw]);
++        if (ido == 1) na = !na;
++      }
++      l1 = l2;
++      iw += (ip - 1)*ido;
++    }
++    if (na == 0) return;
++    for (i=0; i<n; i++) c[i] = ch[i];
++  } /* rfftb1 */
++
++
++void fftpack_rfftf(int n, Treal r[], Treal wsave[])
++  {
++    if (n == 1) return;
++    fftpack_rfftf1(n, r, wsave, wsave+n, (int*)(wsave+2*n));
++  } /* rfftf */
++
++
++void fftpack_rfftb(int n, Treal r[], Treal wsave[])
++  {
++    if (n == 1) return;
++    fftpack_rfftb1(n, r, wsave, wsave+n, (int*)(wsave+2*n));
++  } /* rfftb */
++
++
++void fftpack_rffti1(int n, Treal wa[], int ifac[MAXFAC+2])
++  {
++    static const Treal twopi = 6.28318530717959;
++    Treal arg, argh, argld, fi;
++    int i, j;
++    int k1, l1, l2;
++    int ld, ii, nf, ip, is;
++    int ido, ipm, nfm1;
++    static const int ntryh[NSPECIAL] = {
++      4,2,3,5    }; /* Do not change the order of these. */
++    factorize(n,ifac,ntryh);
++    nf = ifac[1];
++    argh = twopi / n;
++    is = 0;
++    nfm1 = nf - 1;
++    l1 = 1;
++    if (nfm1 == 0) return;
++    for (k1 = 1; k1 <= nfm1; k1++) {
++      ip = ifac[k1 + 1];
++      ld = 0;
++      l2 = l1*ip;
++      ido = n / l2;
++      ipm = ip - 1;
++      for (j = 1; j <= ipm; ++j) {
++        ld += l1;
++        i = is;
++        argld = (Treal) ld*argh;
++        fi = 0;
++        for (ii = 3; ii <= ido; ii += 2) {
++          i += 2;
++          fi += 1;
++          arg = fi*argld;
++          wa[i - 2] = cos(arg);
++          wa[i - 1] = sin(arg);
++        }
++        is += ido;
++      }
++      l1 = l2;
++    }
++  } /* rffti1 */
++
++
++void fftpack_rffti(int n, Treal wsave[])
++  {
++    if (n == 1) return;
++    fftpack_rffti1(n, wsave+n, (int*)(wsave+2*n));
++  } /* rffti */
++
++#ifdef __cplusplus
++}
++#endif
index 0000000000000000000000000000000000000000,bb9b86d014e8d3a8025aef12a717a66ddcdd3f0e..bb9b86d014e8d3a8025aef12a717a66ddcdd3f0e
mode 000000,100644..100644
--- /dev/null
Simple merge
Simple merge
index 52121fdaa8f92229102da2315818b228c3016207,0000000000000000000000000000000000000000..df4cfe6d5632dbc81440654235fc6b02920fd3dd
mode 100644,000000..100644
--- /dev/null
@@@ -1,414 -1,0 +1,414 @@@
- int load_vmd_library(const char *fn, t_gmxvmdplugin *vmdplugin)
 +/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
 + *
 + * 
 + * This file is part of Gromacs        Copyright (c) 1991-2008
 + * David van der Spoel, Erik Lindahl, Berk Hess, University of Groningen.
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * To help us fund GROMACS development, we humbly ask that you cite
 + * the research papers on the package. Check out http://www.gromacs.org
 + * 
 + * And Hey:
 + * Gnomes, ROck Monsters And Chili Sauce
 + */
 +#ifdef HAVE_CONFIG_H
 +#include <config.h>
 +#endif
 +#include "gromacs/utility/gmx_header_config.h"
 +
 +
 +
 +/* Derived from PluginMgr.C and catdcd.c */
 +
 +/* PluginMgr.C: Copyright: */
 +/***************************************************************************
 + *cr
 + *cr            (C) Copyright 1995-2009 The Board of Trustees of the
 + *cr                        University of Illinois
 + *cr                         All Rights Reserved
 + *cr
 +Developed by:           Theoretical and Computational Biophysics Group
 +                        University of Illinois at Urbana-Champaign
 +                        http://www.ks.uiuc.edu/
 +
 +Permission is hereby granted, free of charge, to any person obtaining a copy of
 +this software and associated documentation files (the Software), to deal with
 +the Software without restriction, including without limitation the rights to
 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 +of the Software, and to permit persons to whom the Software is furnished to
 +do so, subject to the following conditions:
 +
 +Redistributions of source code must retain the above copyright notice,
 +this list of conditions and the following disclaimers.
 +
 +Redistributions in binary form must reproduce the above copyright notice,
 +this list of conditions and the following disclaimers in the documentation
 +and/or other materials provided with the distribution.
 +
 +Neither the names of Theoretical and Computational Biophysics Group,
 +University of Illinois at Urbana-Champaign, nor the names of its contributors
 +may be used to endorse or promote products derived from this Software without
 +specific prior written permission.
 +
 +THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 +THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 +OTHER DEALINGS WITH THE SOFTWARE.
 + ***************************************************************************/
 +
 +/* catdcd.c: Copyright: */
 +/*****************************************************************************/
 +/*                                                                           */
 +/* (C) Copyright 2001-2005 Justin Gullingsrud and the University of Illinois.*/
 +/*                                                                           */
 +/*****************************************************************************/
 +
 +#include <stdlib.h>
 +#include <stdio.h>
 +#include <string.h>
 +#include <assert.h>
 +
 +/* 
 + * Plugin header files; get plugin source from www.ks.uiuc.edu/Research/vmd"
 + */
 +#include "external/vmd_molfile/molfile_plugin.h"
 +#include "external/vmd_molfile/vmddlopen.h"
 +#ifndef GMX_NATIVE_WINDOWS
 +#include <glob.h>
 +#else
 +#include <windows.h>
 +#include <shlobj.h>
 +#endif
 +#include "smalloc.h"
 +#include "futil.h"
 +#include "vmdio.h"
 +
 +
 +#include "types/simple.h"
 +#include "vec.h"
 +#include "gmxfio.h"
 +
 +
 +typedef int (*initfunc)(void);
 +typedef int (*regfunc)(void *, vmdplugin_register_cb);
 +typedef int (*finifunc)(void);
 +
 +
 +
 +static int register_cb(void *v, vmdplugin_t *p) {
 +    const char *key = p->name;
 +    t_gmxvmdplugin *vmdplugin = (t_gmxvmdplugin*)v;
 +
 +    if (strcmp(key,vmdplugin->filetype)==0)
 +    {
 +        vmdplugin->api = (molfile_plugin_t *)p;
 +    }
 +    return VMDPLUGIN_SUCCESS;
 +}
 +
 +static int load_sharedlibrary_plugins(const char *fullpath,t_gmxvmdplugin* vmdplugin) {
 +    /* Open the dll; try to execute the init function. */
 +    void *handle, *ifunc, *registerfunc; 
 +    handle = vmddlopen(fullpath);
 +    if (!handle) {
 +        if (debug) fprintf(debug, "\nUnable to open dynamic library %s.\n%s\n",  fullpath, vmddlerror());  /*only to debug because of stdc++ erros */
 +        return 0;
 +    }
 +
 +    ifunc = vmddlsym(handle, "vmdplugin_init");
 +    if (ifunc && ((initfunc)(ifunc))()) {
 +        printf("\nvmdplugin_init() for %s returned an error; plugin(s) not loaded.\n", fullpath);
 +        vmddlclose(handle);
 +        return 0;
 +    }
 +
 +    registerfunc = vmddlsym(handle, "vmdplugin_register");
 +    if (!registerfunc) {
 +        printf("\nDidn't find the register function in %s; plugin(s) not loaded.\n", fullpath);
 +        vmddlclose(handle);
 +        return 0;
 +    } else {
 +        /* Load plugins from the library.*/
 +        ((regfunc)registerfunc)(vmdplugin, register_cb);
 +    } 
 +    
 +    /* in case this library does not support the filetype, close it */
 +    if (vmdplugin->api == NULL)
 +    {
 +        vmddlclose(handle);
 +    }
 +
 +    return 1;
 +}
 +
 +/*return: 1: success, 0: last frame, -1: error*/
 +gmx_bool read_next_vmd_frame(int status,t_trxframe *fr)
 +{
 +    int rc,i;
 +    rvec vec, angle;
 +    molfile_timestep_t ts;
 +
 +
 +    fr->bV = fr->vmdplugin->bV;
 +        
 +#ifdef GMX_DOUBLE
 +    snew(ts.coords, fr->natoms*3);
 +    if (fr->bV)
 +    {
 +        snew(ts.velocities, fr->natoms*3);
 +    }
 +#else
 +    ts.coords = (float*)fr->x;
 +    if (fr->bV)
 +    {
 +        ts.velocities = (float*)fr->v;
 +    }
 +#endif
 +
 +    rc = fr->vmdplugin->api->read_next_timestep(fr->vmdplugin->handle, fr->natoms, &ts);
 +
 +    if (rc < -1) {
 +        fprintf(stderr, "\nError reading input file (error code %d)\n", rc);
 +    }
 +    if (rc < 0)
 +    {
 +        fr->vmdplugin->api->close_file_read(fr->vmdplugin->handle);
 +        return 0;
 +    }
 +
 +#ifdef GMX_DOUBLE
 +    for (i=0;i<fr->natoms;i++)
 +    {
 +        fr->x[i][0] = .1*ts.coords[i*3];
 +        fr->x[i][1] = .1*ts.coords[i*3+1];
 +        fr->x[i][2] = .1*ts.coords[i*3+2];
 +        if (fr->bV)
 +        {
 +            fr->v[i][0] = .1*ts.velocities[i*3];
 +            fr->v[i][1] = .1*ts.velocities[i*3+1];
 +            fr->v[i][2] = .1*ts.velocities[i*3+2];
 +        }
 +    }
 +    sfree(ts.coords);
 +    if (fr->bV)
 +    {
 +        sfree(ts.velocities);
 +    }
 +#else
 +    for (i=0;i<fr->natoms;i++)
 +    {
 +        svmul(.1,fr->x[i],fr->x[i]);
 +        if (fr->bV)
 +        {
 +            svmul(.1,fr->v[i],fr->v[i]);
 +        }
 +    }
 +#endif
 +
 +    fr->bX = 1;
 +    fr->bBox = 1;
 +    vec[0] = .1*ts.A; vec[1] = .1*ts.B; vec[2] = .1*ts.C;
 +    angle[0] = ts.alpha; angle[1] = ts.beta; angle[2] = ts.gamma; 
 +    matrix_convert(fr->box,vec,angle);
 +    if (fr->vmdplugin->api->abiversion>10)
 +    {
 +        fr->bTime = TRUE;
 +        fr->time = ts.physical_time;
 +    }
 +    else
 +    {
 +        fr->bTime = FALSE;
 +    }
 +
 +
 +    return 1;
 +}
 +
++static int load_vmd_library(const char *fn, t_gmxvmdplugin *vmdplugin)
 +{
 +    char pathname[GMX_PATH_MAX],filename[GMX_PATH_MAX];
 +    const char *pathenv;
 +    const char *err;
 +    int i;
 +    int ret=0;
 +    char pathenv_buffer[GMX_PATH_MAX];
 +#ifndef GMX_NATIVE_WINDOWS
 +    glob_t globbuf;
 +    const char *defpath_suffix = "/plugins/*/molfile";
 +    const char *defpathenv = GMX_VMD_PLUGIN_PATH;
 +#else
 +    WIN32_FIND_DATA ffd;
 +    HANDLE hFind = INVALID_HANDLE_VALUE;
 +    char progfolder[GMX_PATH_MAX];
 +    char defpathenv[GMX_PATH_MAX];
 +    const char *defpath_suffix = "\\plugins\\WIN32\\molfile";
 +    SHGetFolderPath(NULL,CSIDL_PROGRAM_FILES,NULL,SHGFP_TYPE_CURRENT,progfolder);
 +    sprintf(defpathenv,"%s\\University of Illinois\\VMD\\plugins\\WIN32\\molfile",progfolder);
 +#endif
 +
 +    vmdplugin->api = NULL;
 +    vmdplugin->filetype = strrchr(fn,'.');
 +    if (!vmdplugin->filetype)
 +    {
 +        return 0;
 +    }
 +    vmdplugin->filetype++;
 +
 +    /* First look for an explicit path given at run time for the
 +     * plugins, then an implicit run-time path, and finally for one
 +     * given at configure time. This last might be hard-coded to the
 +     * default for VMD installs. */
 +    pathenv = getenv("VMD_PLUGIN_PATH");
 +    if (pathenv==NULL) 
 +    {
 +        pathenv = getenv("VMDDIR");
 +        if (NULL == pathenv)
 +        {
 +            printf("\nNeither VMD_PLUGIN_PATH or VMDDIR set. ");
 +            printf("Using default location:\n%s\n",defpathenv);
 +            pathenv=defpathenv;
 +        }
 +        else
 +        {
 +            printf("\nVMD_PLUGIN_PATH no set, but VMDDIR is set. ");
 +#ifdef _MSC_VER
 +            _snprintf_s(pathenv_buffer, sizeof(pathenv_buffer), _TRUNCATE, "%s%s", pathenv, defpath_suffix);
 +#else
 +            snprintf(pathenv_buffer, sizeof(pathenv_buffer), "%s%s", pathenv, defpath_suffix);
 +#endif
 +            printf("Using semi-default location:\n%s\n",pathenv_buffer);
 +            pathenv = pathenv_buffer;
 +        }
 +    }
 +    strncpy(pathname,pathenv,sizeof(pathname));
 +#ifndef GMX_NATIVE_WINDOWS
 +    strcat(pathname,"/*.so");
 +    glob(pathname, 0, NULL, &globbuf);
 +    if (globbuf.gl_pathc == 0)
 +    {
 +        printf("\nNo VMD Plugins found\n"
 +            "Set the environment variable VMD_PLUGIN_PATH to the molfile folder within the\n"
 +            "VMD installation.\n"
 +            "The architecture (e.g. 32bit versus 64bit) of Gromacs and VMD has to match.\n");
 +        return 0;
 +    }
 +    for (i=0; i<globbuf.gl_pathc && vmdplugin->api == NULL; i++)
 +    {
 +        /* FIXME: Undefined which plugin is chosen if more than one plugin
 +           can read a certain file ending. Requires some additional command
 +           line option or enviroment variable to specify which plugin should
 +           be picked.
 +        */
 +        ret|=load_sharedlibrary_plugins(globbuf.gl_pathv[i],vmdplugin);
 +    }
 +    globfree(&globbuf);
 +#else
 +    strcat(pathname,"\\*.so");
 +    hFind = FindFirstFile(pathname, &ffd);
 +    if (INVALID_HANDLE_VALUE == hFind) 
 +    {
 +        printf("\nNo VMD Plugins found\n");
 +        return 0;
 +    } 
 +    do
 +    {
 +        sprintf(filename,"%s\\%s",pathenv,ffd.cFileName);
 +        ret|=load_sharedlibrary_plugins(filename,vmdplugin);
 +    }
 +    while (FindNextFile(hFind, &ffd )  != 0 && vmdplugin->api == NULL );
 +    FindClose(hFind);
 +#endif
 +
 +    if (!ret)
 +    {
 +        printf("\nCould not open any VMD library.\n");
 +        err = vmddlerror();
 +        if (!err) 
 +        {
 +            printf("Compiled with dlopen?\n");
 +        }
 +        else
 +        {
 +            printf("Last error:\n%s\n",err);
 +        }
 +        return 0;
 +    }
 +
 +    if (vmdplugin->api == NULL)
 +    {
 +        printf("\nNo plugin for %s found\n",vmdplugin->filetype);
 +        return 0;
 +    }
 +
 +    if (vmdplugin->api->abiversion < 10)
 +    {
 +        printf("\nPlugin and/or VMD is too old. At least VMD 1.8.6 is required.\n");
 +        return 0;
 +    }
 +
 +    printf("\nUsing VMD plugin: %s (%s)\n",vmdplugin->api->name,vmdplugin->api->prettyname);
 +
 +    return 1;
 +
 +}
 +
 +int read_first_vmd_frame(int *status,const char *fn,t_trxframe *fr,int flags)
 +{
 +    molfile_timestep_metadata_t *metadata=NULL;
 +    
 +    snew(fr->vmdplugin,1);
 +    if (!load_vmd_library(fn,fr->vmdplugin))
 +    {
 +        return 0;
 +    }
 +
 +    fr->vmdplugin->handle = fr->vmdplugin->api->open_file_read(fn, fr->vmdplugin->filetype, &fr->natoms);
 +
 +    if (!fr->vmdplugin->handle) {
 +        fprintf(stderr, "\nError: could not open file '%s' for reading.\n",
 +                fn);
 +        return 0;
 +    }
 +
 +    if (fr->natoms == MOLFILE_NUMATOMS_UNKNOWN) {
 +        fprintf(stderr, "\nFormat of file %s does not record number of atoms.\n", fn);
 +        return 0;
 +    } else if (fr->natoms == MOLFILE_NUMATOMS_NONE) {
 +        fprintf(stderr, "\nNo atoms found by VMD plugin in file %s.\n", fn );
 +        return 0;
 +    } else if (fr->natoms < 1) { /*should not be reached*/
 +        fprintf(stderr, "\nUnknown number of atoms %d for VMD plugin opening file %s.\n",
 +                fr->natoms, fn );
 +        return 0;
 +    }
 +    
 +    snew(fr->x,fr->natoms);
 +
 +    fr->vmdplugin->bV = 0;
 +    if (fr->vmdplugin->api->abiversion > 10 && fr->vmdplugin->api->read_timestep_metadata)
 +    {
 +        fr->vmdplugin->api->read_timestep_metadata(fr->vmdplugin->handle, metadata);
 +        assert(metadata);
 +        fr->vmdplugin->bV = metadata->has_velocities;
 +        if (fr->vmdplugin->bV)
 +        {
 +            snew(fr->v,fr->natoms);
 +        }
 +    }
 +    else
 +    {
 +        fprintf(stderr,
 +                "\nThis trajectory is being read with a VMD plug-in from before VMD"
 +                "\nversion 1.8, or from a trajectory that lacks time step metadata."
 +                "\nEither way, GROMACS cannot tell whether the trajectory has velocities.\n");
 +    }
 +    return 1;
 +
 +}
index dbd18f9c341cb62e12f674ce25dd7ebbc08db470,0000000000000000000000000000000000000000..f4150b847f5de41fc51c450b906065de02d15f45
mode 100644,000000..100644
--- /dev/null
@@@ -1,45 -1,0 +1,44 @@@
- int load_vmd_library(const char *fn, t_gmxvmdplugin *vmdplugin);
 +/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
 + *
 + * 
 + * This file is part of Gromacs        Copyright (c) 1991-2008
 + * David van der Spoel, Erik Lindahl, Berk Hess, University of Groningen.
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * To help us fund GROMACS development, we humbly ask that you cite
 + * the research papers on the package. Check out http://www.gromacs.org
 + * 
 + * And Hey:
 + * Gnomes, ROck Monsters And Chili Sauce
 + */
 +
 +#ifndef VMDIO_H_
 +#define VMDIO_H_
 +
 +#include "external/vmd_molfile/molfile_plugin.h"
 +#include "types/trx.h"
 +
 +#ifdef __cplusplus
 +extern "C" {
 +#endif
 +
 +struct gmxvmdplugin
 +{
 +    molfile_plugin_t *api;
 +    const char* filetype;
 +    void* handle;
 +    gmx_bool bV;
 +};
 +    
 +int read_first_vmd_frame(int  *status,const char *fn, struct trxframe *fr,int flags);
 +gmx_bool read_next_vmd_frame(int status,struct trxframe *fr);
 +
 +#ifdef __cplusplus
 +}
 +#endif
 +
 +#endif /* VMDIO_H_ */
Simple merge
Simple merge
index 79a761955eb3d50388f1c4f1cf352a655d573de1,0000000000000000000000000000000000000000..dc25bce58b2f95cff04d8e795d2f920040f22a79
mode 100644,000000..100644
--- /dev/null
@@@ -1,871 -1,0 +1,893 @@@
-   return (real)sqrt(a[XX]*a[XX]+a[YY]*a[YY]+a[ZZ]*a[ZZ]);
 +/*
 + * 
 + *                This source code is part of
 + * 
 + *                 G   R   O   M   A   C   S
 + * 
 + *          GROningen MAchine for Chemical Simulations
 + * 
 + *                        VERSION 3.2.0
 + * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
 + * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
 + * Copyright (c) 2001-2004, The GROMACS development team,
 + * check out http://www.gromacs.org for more information.
 +
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + * 
 + * If you want to redistribute modifications, please consider that
 + * scientific software is very special. Version control is crucial -
 + * bugs must be traceable. We will be happy to consider code for
 + * inclusion in the official distribution, but derived work must not
 + * be called official GROMACS. Details are found in the README & COPYING
 + * files - if they are missing, get the official version at www.gromacs.org.
 + * 
 + * To help us fund GROMACS development, we humbly ask that you cite
 + * the papers on the package - you can find them in the top README file.
 + * 
 + * For more info, check our website at http://www.gromacs.org
 + * 
 + * And Hey:
 + * Gromacs Runs On Most of All Computer Systems
 + */
 +#ifndef _vec_h
 +#define _vec_h
 +
 +/*
 +  collection of in-line ready operations:
 +  
 +  lookup-table optimized scalar operations:
 +  real gmx_invsqrt(real x)
 +  void vecinvsqrt(real in[],real out[],int n)
 +  void vecrecip(real in[],real out[],int n)
 +  real sqr(real x)
 +  double dsqr(double x)
 +  
 +  vector operations:
 +  void rvec_add(const rvec a,const rvec b,rvec c)  c = a + b
 +  void dvec_add(const dvec a,const dvec b,dvec c)  c = a + b
 +  void ivec_add(const ivec a,const ivec b,ivec c)  c = a + b
 +  void rvec_inc(rvec a,const rvec b)               a += b
 +  void dvec_inc(dvec a,const dvec b)               a += b
 +  void ivec_inc(ivec a,const ivec b)               a += b
 +  void rvec_sub(const rvec a,const rvec b,rvec c)  c = a - b
 +  void dvec_sub(const dvec a,const dvec b,dvec c)  c = a - b
 +  void rvec_dec(rvec a,rvec b)                     a -= b
 +  void copy_rvec(const rvec a,rvec b)              b = a (reals)
 +  void copy_dvec(const dvec a,dvec b)              b = a (reals)
 +  void copy_ivec(const ivec a,ivec b)              b = a (integers)
 +  void ivec_sub(const ivec a,const ivec b,ivec c)  c = a - b
 +  void svmul(real a,rvec v1,rvec v2)               v2 = a * v1
 +  void dsvmul(double a,dvec v1,dvec v2)            v2 = a * v1
 +  void clear_rvec(rvec a)                          a = 0
 +  void clear_dvec(dvec a)                          a = 0
 +  void clear_ivec(rvec a)                          a = 0
 +  void clear_rvecs(int n,rvec v[])
 +  real iprod(rvec a,rvec b)                        = a . b (inner product)
 +  double diprod(dvec a,dvec b)                     = a . b (inner product)
 +  real iiprod(ivec a,ivec b)                       = a . b (integers)
 +  real norm2(rvec a)                               = | a |^2 ( = x*y*z )
 +  double dnorm2(dvec a)                            = | a |^2 ( = x*y*z )
 +  real norm(rvec a)                                = | a |
 +  double dnorm(dvec a)                             = | a |
 +  void cprod(rvec a,rvec b,rvec c)                 c = a x b (cross product)
 +  void dprod(rvec a,rvec b,rvec c)                 c = a x b (cross product)
 +  void dprod(rvec a,rvec b,rvec c)                 c = a * b (direct product)
 +  real cos_angle(rvec a,rvec b)
 +  real cos_angle_no_table(rvec a,rvec b)
 +  real distance2(rvec v1, rvec v2)                 = | v2 - v1 |^2
 +  void unitv(rvec src,rvec dest)                   dest = src / |src|
 +  void unitv_no_table(rvec src,rvec dest)          dest = src / |src|
 +  
 +  matrix (3x3) operations:
 +    ! indicates that dest should not be the same as a, b or src
 +    the _ur0 varieties work on matrices that have only zeros
 +    in the upper right part, such as box matrices, these varieties
 +    could produce less rounding errors, not due to the operations themselves,
 +    but because the compiler can easier recombine the operations
 +  void copy_mat(matrix a,matrix b)                 b = a
 +  void clear_mat(matrix a)                       a = 0
 +  void mmul(matrix a,matrix b,matrix dest)    !  dest = a . b
 +  void mmul_ur0(matrix a,matrix b,matrix dest)     dest = a . b
 +  void transpose(matrix src,matrix dest)      !  dest = src*
 +  void tmmul(matrix a,matrix b,matrix dest)   !  dest = a* . b
 +  void mtmul(matrix a,matrix b,matrix dest)   !  dest = a . b*
 +  real det(matrix a)                             = det(a)
 +  void m_add(matrix a,matrix b,matrix dest)      dest = a + b
 +  void m_sub(matrix a,matrix b,matrix dest)      dest = a - b
 +  void msmul(matrix m1,real r1,matrix dest)      dest = r1 * m1
 +  void m_inv_ur0(matrix src,matrix dest)           dest = src^-1
 +  void m_inv(matrix src,matrix dest)          !  dest = src^-1
 +  void mvmul(matrix a,rvec src,rvec dest)     !  dest = a . src
 +  void mvmul_ur0(matrix a,rvec src,rvec dest)      dest = a . src
 +  void tmvmul_ur0(matrix a,rvec src,rvec dest)     dest = a* . src
 +  real trace(matrix m)                             = trace(m)
 +*/
 +
 +#include "types/simple.h"
 +#include "maths.h"
 +#include "typedefs.h"
 +#include "sysstuff.h"
 +#include "gmx_fatal.h"
 +#include "physics.h"
 +
 +#ifdef __cplusplus
 +extern "C" {
 +#elif 0
 +} /* avoid screwing up indentation */
 +#endif
 +
 +
 +#define EXP_LSB         0x00800000
 +#define EXP_MASK        0x7f800000
 +#define EXP_SHIFT       23
 +#define FRACT_MASK      0x007fffff
 +#define FRACT_SIZE      11              /* significant part of fraction */
 +#define FRACT_SHIFT     (EXP_SHIFT-FRACT_SIZE)
 +#define EXP_ADDR(val)   (((val)&EXP_MASK)>>EXP_SHIFT)
 +#define FRACT_ADDR(val) (((val)&(FRACT_MASK|EXP_LSB))>>FRACT_SHIFT)
 +
 +#define PR_VEC(a)       a[XX],a[YY],a[ZZ]
 +
 +#ifdef GMX_SOFTWARE_INVSQRT
 +extern const unsigned int *  gmx_invsqrt_exptab;
 +extern const unsigned int *  gmx_invsqrt_fracttab;
 +#endif
 +
 +
 +typedef union 
 +{
 +  unsigned int bval;
 +  float fval;
 +} t_convert;
 +
 +
 +#ifdef GMX_SOFTWARE_INVSQRT
 +static real gmx_invsqrt(real x)
 +{
 +  const real  half=0.5;
 +  const real  three=3.0;
 +  t_convert   result,bit_pattern;
 +  unsigned int exp,fract;
 +  real        lu;
 +  real        y;
 +#ifdef GMX_DOUBLE
 +  real        y2;
 +#endif
 + 
 +  bit_pattern.fval=x;
 +  exp   = EXP_ADDR(bit_pattern.bval);
 +  fract = FRACT_ADDR(bit_pattern.bval);
 +  result.bval=gmx_invsqrt_exptab[exp] | gmx_invsqrt_fracttab[fract];
 +  lu    = result.fval;
 +  
 +  y=(half*lu*(three-((x*lu)*lu)));
 +#ifdef GMX_DOUBLE
 +  y2=(half*y*(three-((x*y)*y)));
 +  
 +  return y2;                    /* 10 Flops */
 +#else
 +  return y;                     /* 5  Flops */
 +#endif
 +}
 +#define INVSQRT_DONE 
 +#endif /* gmx_invsqrt */
 +
 +#ifdef GMX_POWERPC_SQRT
 +static real gmx_invsqrt(real x)
 +{
 +  const real  half=0.5;
 +  const real  three=3.0;
 +  t_convert   result,bit_pattern;
 +  unsigned int exp,fract;
 +  real        lu;
 +  real        y;
 +#ifdef GMX_DOUBLE
 +  real        y2;
 +#endif
 +
 +  lu = __frsqrte((double)x);
 +
 +  y=(half*lu*(three-((x*lu)*lu)));
 +
 +#if (GMX_POWERPC_SQRT==2)
 +  /* Extra iteration required */
 +  y=(half*y*(three-((x*y)*y)));
 +#endif
 +
 +#ifdef GMX_DOUBLE
 +  y2=(half*y*(three-((x*y)*y)));
 +
 +  return y2;                    /* 10 Flops */
 +#else
 +  return y;                     /* 5  Flops */
 +#endif
 +}
 +#define INVSQRT_DONE
 +#endif /* powerpc_invsqrt */
 +
 +
 +#ifndef INVSQRT_DONE
 +#define gmx_invsqrt(x) (1.0f/sqrt(x))
 +#endif
 +
 +
 +
 +
 +
 +static real sqr(real x)
 +{
 +  return (x*x);
 +}
 +
 +static gmx_inline double dsqr(double x)
 +{
 +  return (x*x);
 +}
 +
 +/* Maclaurin series for sinh(x)/x, useful for NH chains and MTTK pressure control 
 +   Here, we compute it to 10th order, which might be overkill, 8th is probably enough, 
 +   but it's not very much more expensive. */
 +
 +static gmx_inline real series_sinhx(real x) 
 +{
 +  real x2 = x*x;
 +  return (1 + (x2/6.0)*(1 + (x2/20.0)*(1 + (x2/42.0)*(1 + (x2/72.0)*(1 + (x2/110.0))))));
 +}
 +
 +void vecinvsqrt(real in[],real out[],int n);
 +/* Perform out[i]=1.0/sqrt(in[i]) for n elements */
 +
 +
 +void vecrecip(real in[],real out[],int n);
 +/* Perform out[i]=1.0/(in[i]) for n elements */
 +
 +/* Note: If you need a fast version of vecinvsqrt 
 + * and/or vecrecip, call detectcpu() and run the SSE/3DNow/SSE2/Altivec
 + * versions if your hardware supports it.
 + *
 + * To use those routines, your memory HAS TO BE CACHE-ALIGNED.
 + * Use snew_aligned(ptr,size,32) to allocate and sfree_aligned to free.
 + */
 +
 +
 +static gmx_inline void rvec_add(const rvec a,const rvec b,rvec c)
 +{
 +  real x,y,z;
 +  
 +  x=a[XX]+b[XX];
 +  y=a[YY]+b[YY];
 +  z=a[ZZ]+b[ZZ];
 +  
 +  c[XX]=x;
 +  c[YY]=y;
 +  c[ZZ]=z;
 +}
 +
 +static gmx_inline void dvec_add(const dvec a,const dvec b,dvec c)
 +{
 +  double x,y,z;
 +  
 +  x=a[XX]+b[XX];
 +  y=a[YY]+b[YY];
 +  z=a[ZZ]+b[ZZ];
 +  
 +  c[XX]=x;
 +  c[YY]=y;
 +  c[ZZ]=z;
 +}
 +
 +static gmx_inline void ivec_add(const ivec a,const ivec b,ivec c)
 +{
 +  int x,y,z;
 +  
 +  x=a[XX]+b[XX];
 +  y=a[YY]+b[YY];
 +  z=a[ZZ]+b[ZZ];
 +  
 +  c[XX]=x;
 +  c[YY]=y;
 +  c[ZZ]=z;
 +}
 +
 +static gmx_inline void rvec_inc(rvec a,const rvec b)
 +{
 +  real x,y,z;
 +  
 +  x=a[XX]+b[XX];
 +  y=a[YY]+b[YY];
 +  z=a[ZZ]+b[ZZ];
 +  
 +  a[XX]=x;
 +  a[YY]=y;
 +  a[ZZ]=z;
 +}
 +
 +static gmx_inline void dvec_inc(dvec a,const dvec b)
 +{
 +  double x,y,z;
 +
 +  x=a[XX]+b[XX];
 +  y=a[YY]+b[YY];
 +  z=a[ZZ]+b[ZZ];
 +
 +  a[XX]=x;
 +  a[YY]=y;
 +  a[ZZ]=z;
 +}
 +
 +static gmx_inline void rvec_sub(const rvec a,const rvec b,rvec c)
 +{
 +  real x,y,z;
 +  
 +  x=a[XX]-b[XX];
 +  y=a[YY]-b[YY];
 +  z=a[ZZ]-b[ZZ];
 +  
 +  c[XX]=x;
 +  c[YY]=y;
 +  c[ZZ]=z;
 +}
 +
 +static gmx_inline void dvec_sub(const dvec a,const dvec b,dvec c)
 +{
 +  double x,y,z;
 +  
 +  x=a[XX]-b[XX];
 +  y=a[YY]-b[YY];
 +  z=a[ZZ]-b[ZZ];
 +  
 +  c[XX]=x;
 +  c[YY]=y;
 +  c[ZZ]=z;
 +}
 +
 +static gmx_inline void rvec_dec(rvec a,const rvec b)
 +{
 +  real x,y,z;
 +  
 +  x=a[XX]-b[XX];
 +  y=a[YY]-b[YY];
 +  z=a[ZZ]-b[ZZ];
 +  
 +  a[XX]=x;
 +  a[YY]=y;
 +  a[ZZ]=z;
 +}
 +
 +static gmx_inline void copy_rvec(const rvec a,rvec b)
 +{
 +  b[XX]=a[XX];
 +  b[YY]=a[YY];
 +  b[ZZ]=a[ZZ];
 +}
 +
 +static gmx_inline void copy_rvecn(rvec *a,rvec *b,int startn, int endn)
 +{
 +  int i;
 +  for (i=startn;i<endn;i++) {
 +    b[i][XX]=a[i][XX];
 +    b[i][YY]=a[i][YY];
 +    b[i][ZZ]=a[i][ZZ];
 +  }
 +}
 +
 +static gmx_inline void copy_dvec(const dvec a,dvec b)
 +{
 +  b[XX]=a[XX];
 +  b[YY]=a[YY];
 +  b[ZZ]=a[ZZ];
 +}
 +
 +static gmx_inline void copy_ivec(const ivec a,ivec b)
 +{
 +  b[XX]=a[XX];
 +  b[YY]=a[YY];
 +  b[ZZ]=a[ZZ];
 +}
 +
 +static gmx_inline void ivec_sub(const ivec a,const ivec b,ivec c)
 +{
 +  int x,y,z;
 +  
 +  x=a[XX]-b[XX];
 +  y=a[YY]-b[YY];
 +  z=a[ZZ]-b[ZZ];
 +  
 +  c[XX]=x;
 +  c[YY]=y;
 +  c[ZZ]=z;
 +}
 +
 +static gmx_inline void copy_mat(matrix a,matrix b)
 +{
 +  copy_rvec(a[XX],b[XX]);
 +  copy_rvec(a[YY],b[YY]);
 +  copy_rvec(a[ZZ],b[ZZ]);
 +}
 +
 +static gmx_inline void svmul(real a,const rvec v1,rvec v2)
 +{
 +  v2[XX]=a*v1[XX];
 +  v2[YY]=a*v1[YY];
 +  v2[ZZ]=a*v1[ZZ];
 +}
 +
 +static gmx_inline void dsvmul(double a,const dvec v1,dvec v2)
 +{
 +  v2[XX]=a*v1[XX];
 +  v2[YY]=a*v1[YY];
 +  v2[ZZ]=a*v1[ZZ];
 +}
 +
 +static gmx_inline real distance2(const rvec v1,const rvec v2)
 +{
 +  return sqr(v2[XX]-v1[XX]) + sqr(v2[YY]-v1[YY]) + sqr(v2[ZZ]-v1[ZZ]);
 +}
 +
 +static gmx_inline void clear_rvec(rvec a)
 +{
 +  /* The ibm compiler has problems with inlining this 
 +   * when we use a const real variable
 +   */
 +  a[XX]=0.0;
 +  a[YY]=0.0;
 +  a[ZZ]=0.0;
 +}
 +
 +static gmx_inline void clear_dvec(dvec a)
 +{
 +  /* The ibm compiler has problems with inlining this 
 +   * when we use a const real variable
 +   */
 +  a[XX]=0.0;
 +  a[YY]=0.0;
 +  a[ZZ]=0.0;
 +}
 +
 +static gmx_inline void clear_ivec(ivec a)
 +{
 +  a[XX]=0;
 +  a[YY]=0;
 +  a[ZZ]=0;
 +}
 +
 +static gmx_inline void clear_rvecs(int n,rvec v[])
 +{
 +/*  memset(v[0],0,DIM*n*sizeof(v[0][0])); */
 +  int i;
 +    
 +  for(i=0; (i<n); i++) 
 +    clear_rvec(v[i]);
 +}
 +
 +static gmx_inline void clear_mat(matrix a)
 +{
 +/*  memset(a[0],0,DIM*DIM*sizeof(a[0][0])); */
 +  
 +  const real nul=0.0;
 +  
 +  a[XX][XX]=a[XX][YY]=a[XX][ZZ]=nul;
 +  a[YY][XX]=a[YY][YY]=a[YY][ZZ]=nul;
 +  a[ZZ][XX]=a[ZZ][YY]=a[ZZ][ZZ]=nul;
 +}
 +
 +static gmx_inline real iprod(const rvec a,const rvec b)
 +{
 +  return (a[XX]*b[XX]+a[YY]*b[YY]+a[ZZ]*b[ZZ]);
 +}
 +
 +static gmx_inline double diprod(const dvec a,const dvec b)
 +{
 +  return (a[XX]*b[XX]+a[YY]*b[YY]+a[ZZ]*b[ZZ]);
 +}
 +
 +static gmx_inline int iiprod(const ivec a,const ivec b)
 +{
 +  return (a[XX]*b[XX]+a[YY]*b[YY]+a[ZZ]*b[ZZ]);
 +}
 +
 +static gmx_inline real norm2(const rvec a)
 +{
 +  return a[XX]*a[XX]+a[YY]*a[YY]+a[ZZ]*a[ZZ];
 +}
 +
 +static gmx_inline double dnorm2(const dvec a)
 +{
 +  return a[XX]*a[XX]+a[YY]*a[YY]+a[ZZ]*a[ZZ];
 +}
 +
++/* WARNING:
++ * As dnorm() uses sqrt() (which is slow) _only_ use it if you are sure you
++ * don't need 1/dnorm(), otherwise use dnorm2()*dinvnorm(). */
++static gmx_inline double dnorm(const dvec a)
++{
++  return sqrt(diprod(a, a));
++}
++
++/* WARNING:
++ * As norm() uses sqrtf() (which is slow) _only_ use it if you are sure you
++ * don't need 1/norm(), otherwise use norm2()*invnorm(). */
 +static gmx_inline real norm(const rvec a)
 +{
- static gmx_inline double dnorm(const dvec a)
++  /* This is ugly, but we deliberately do not define gmx_sqrt() and handle the
++   * float/double case here instead to avoid gmx_sqrt() being accidentally used. */
++#ifdef GMX_DOUBLE
++  return dnorm(a);
++#else
++  return sqrtf(iprod(a, a));
++#endif
 +}
 +
-   return sqrt(a[XX]*a[XX]+a[YY]*a[YY]+a[ZZ]*a[ZZ]);
++static gmx_inline real invnorm(const rvec a)
++{
++    return gmx_invsqrt(norm2(a));
++}
++
++static gmx_inline real dinvnorm(const dvec a)
 +{
++    return gmx_invsqrt(dnorm2(a));
 +}
 +
 +/* WARNING:
 + * Do _not_ use these routines to calculate the angle between two vectors
 + * as acos(cos_angle(u,v)). While it might seem obvious, the acos function
 + * is very flat close to -1 and 1, which will lead to accuracy-loss.
 + * Instead, use the new gmx_angle() function directly.
 + */
 +static gmx_inline real 
 +cos_angle(const rvec a,const rvec b)
 +{
 +  /* 
 +   *                  ax*bx + ay*by + az*bz
 +   * cos-vec (a,b) =  ---------------------
 +   *                      ||a|| * ||b||
 +   */
 +  real   cosval;
 +  int    m;
 +  double aa,bb,ip,ipa,ipb,ipab; /* For accuracy these must be double! */
 +  
 +  ip=ipa=ipb=0.0;
 +  for(m=0; (m<DIM); m++) {            /* 18           */
 +    aa   = a[m];
 +    bb   = b[m];
 +    ip  += aa*bb;
 +    ipa += aa*aa;
 +    ipb += bb*bb;
 +  }
 +  ipab = ipa*ipb;
 +  if (ipab > 0)
 +    cosval = ip*gmx_invsqrt(ipab);            /*  7           */
 +  else 
 +    cosval = 1;
 +                                      /* 25 TOTAL     */
 +  if (cosval > 1.0) 
 +    return  1.0; 
 +  if (cosval <-1.0) 
 +    return -1.0;
 +  
 +  return cosval;
 +}
 +
 +/* WARNING:
 + * Do _not_ use these routines to calculate the angle between two vectors
 + * as acos(cos_angle(u,v)). While it might seem obvious, the acos function
 + * is very flat close to -1 and 1, which will lead to accuracy-loss.
 + * Instead, use the new gmx_angle() function directly.
 + */
 +static gmx_inline real 
 +cos_angle_no_table(const rvec a,const rvec b)
 +{
 +  /* This version does not need the invsqrt lookup table */
 +  real   cosval;
 +  int    m;
 +  double aa,bb,ip,ipa,ipb; /* For accuracy these must be double! */
 +  
 +  ip=ipa=ipb=0.0;
 +  for(m=0; (m<DIM); m++) {            /* 18           */
 +    aa   = a[m];
 +    bb   = b[m];
 +    ip  += aa*bb;
 +    ipa += aa*aa;
 +    ipb += bb*bb;
 +  }
 +  cosval=ip/sqrt(ipa*ipb);            /* 12           */
 +                                      /* 30 TOTAL     */
 +  if (cosval > 1.0) 
 +    return  1.0; 
 +  if (cosval <-1.0) 
 +    return -1.0;
 +  
 +  return cosval;
 +}
 +
 +
 +static gmx_inline void cprod(const rvec a,const rvec b,rvec c)
 +{
 +  c[XX]=a[YY]*b[ZZ]-a[ZZ]*b[YY];
 +  c[YY]=a[ZZ]*b[XX]-a[XX]*b[ZZ];
 +  c[ZZ]=a[XX]*b[YY]-a[YY]*b[XX];
 +}
 +
 +static gmx_inline void dcprod(const dvec a,const dvec b,dvec c)
 +{
 +  c[XX]=a[YY]*b[ZZ]-a[ZZ]*b[YY];
 +  c[YY]=a[ZZ]*b[XX]-a[XX]*b[ZZ];
 +  c[ZZ]=a[XX]*b[YY]-a[YY]*b[XX];
 +}
 +
 +/* This routine calculates the angle between a & b without any loss of accuracy close to 0/PI.
 + * If you only need cos(theta), use the cos_angle() routines to save a few cycles.
 + * This routine is faster than it might appear, since atan2 is accelerated on many CPUs (e.g. x86).
 + */
 +static gmx_inline real 
 +gmx_angle(const rvec a, const rvec b)
 +{
 +    rvec w;
 +    real wlen,s;
 +    
 +    cprod(a,b,w);
 +    
 +    wlen  = norm(w);
 +    s     = iprod(a,b);
 +    
 +    return atan2(wlen,s);
 +}
 +
 +static gmx_inline void mmul_ur0(matrix a,matrix b,matrix dest)
 +{
 +  dest[XX][XX]=a[XX][XX]*b[XX][XX];
 +  dest[XX][YY]=0.0;
 +  dest[XX][ZZ]=0.0;
 +  dest[YY][XX]=a[YY][XX]*b[XX][XX]+a[YY][YY]*b[YY][XX];
 +  dest[YY][YY]=                    a[YY][YY]*b[YY][YY];
 +  dest[YY][ZZ]=0.0;
 +  dest[ZZ][XX]=a[ZZ][XX]*b[XX][XX]+a[ZZ][YY]*b[YY][XX]+a[ZZ][ZZ]*b[ZZ][XX];
 +  dest[ZZ][YY]=                    a[ZZ][YY]*b[YY][YY]+a[ZZ][ZZ]*b[ZZ][YY];
 +  dest[ZZ][ZZ]=                                        a[ZZ][ZZ]*b[ZZ][ZZ];
 +}
 +
 +static gmx_inline void mmul(matrix a,matrix b,matrix dest)
 +{
 +  dest[XX][XX]=a[XX][XX]*b[XX][XX]+a[XX][YY]*b[YY][XX]+a[XX][ZZ]*b[ZZ][XX];
 +  dest[YY][XX]=a[YY][XX]*b[XX][XX]+a[YY][YY]*b[YY][XX]+a[YY][ZZ]*b[ZZ][XX];
 +  dest[ZZ][XX]=a[ZZ][XX]*b[XX][XX]+a[ZZ][YY]*b[YY][XX]+a[ZZ][ZZ]*b[ZZ][XX];
 +  dest[XX][YY]=a[XX][XX]*b[XX][YY]+a[XX][YY]*b[YY][YY]+a[XX][ZZ]*b[ZZ][YY];
 +  dest[YY][YY]=a[YY][XX]*b[XX][YY]+a[YY][YY]*b[YY][YY]+a[YY][ZZ]*b[ZZ][YY];
 +  dest[ZZ][YY]=a[ZZ][XX]*b[XX][YY]+a[ZZ][YY]*b[YY][YY]+a[ZZ][ZZ]*b[ZZ][YY];
 +  dest[XX][ZZ]=a[XX][XX]*b[XX][ZZ]+a[XX][YY]*b[YY][ZZ]+a[XX][ZZ]*b[ZZ][ZZ];
 +  dest[YY][ZZ]=a[YY][XX]*b[XX][ZZ]+a[YY][YY]*b[YY][ZZ]+a[YY][ZZ]*b[ZZ][ZZ];
 +  dest[ZZ][ZZ]=a[ZZ][XX]*b[XX][ZZ]+a[ZZ][YY]*b[YY][ZZ]+a[ZZ][ZZ]*b[ZZ][ZZ];
 +}
 +
 +static gmx_inline void transpose(matrix src,matrix dest)
 +{
 +  dest[XX][XX]=src[XX][XX];
 +  dest[YY][XX]=src[XX][YY];
 +  dest[ZZ][XX]=src[XX][ZZ];
 +  dest[XX][YY]=src[YY][XX];
 +  dest[YY][YY]=src[YY][YY];
 +  dest[ZZ][YY]=src[YY][ZZ];
 +  dest[XX][ZZ]=src[ZZ][XX];
 +  dest[YY][ZZ]=src[ZZ][YY];
 +  dest[ZZ][ZZ]=src[ZZ][ZZ];
 +}
 +
 +static gmx_inline void tmmul(matrix a,matrix b,matrix dest)
 +{
 +  /* Computes dest=mmul(transpose(a),b,dest) - used in do_pr_pcoupl */
 +  dest[XX][XX]=a[XX][XX]*b[XX][XX]+a[YY][XX]*b[YY][XX]+a[ZZ][XX]*b[ZZ][XX];
 +  dest[XX][YY]=a[XX][XX]*b[XX][YY]+a[YY][XX]*b[YY][YY]+a[ZZ][XX]*b[ZZ][YY];
 +  dest[XX][ZZ]=a[XX][XX]*b[XX][ZZ]+a[YY][XX]*b[YY][ZZ]+a[ZZ][XX]*b[ZZ][ZZ];
 +  dest[YY][XX]=a[XX][YY]*b[XX][XX]+a[YY][YY]*b[YY][XX]+a[ZZ][YY]*b[ZZ][XX];
 +  dest[YY][YY]=a[XX][YY]*b[XX][YY]+a[YY][YY]*b[YY][YY]+a[ZZ][YY]*b[ZZ][YY];
 +  dest[YY][ZZ]=a[XX][YY]*b[XX][ZZ]+a[YY][YY]*b[YY][ZZ]+a[ZZ][YY]*b[ZZ][ZZ];
 +  dest[ZZ][XX]=a[XX][ZZ]*b[XX][XX]+a[YY][ZZ]*b[YY][XX]+a[ZZ][ZZ]*b[ZZ][XX];
 +  dest[ZZ][YY]=a[XX][ZZ]*b[XX][YY]+a[YY][ZZ]*b[YY][YY]+a[ZZ][ZZ]*b[ZZ][YY];
 +  dest[ZZ][ZZ]=a[XX][ZZ]*b[XX][ZZ]+a[YY][ZZ]*b[YY][ZZ]+a[ZZ][ZZ]*b[ZZ][ZZ];
 +}
 +
 +static gmx_inline void mtmul(matrix a,matrix b,matrix dest)
 +{
 +  /* Computes dest=mmul(a,transpose(b),dest) - used in do_pr_pcoupl */
 +  dest[XX][XX]=a[XX][XX]*b[XX][XX]+a[XX][YY]*b[XX][YY]+a[XX][ZZ]*b[XX][ZZ];
 +  dest[XX][YY]=a[XX][XX]*b[YY][XX]+a[XX][YY]*b[YY][YY]+a[XX][ZZ]*b[YY][ZZ];
 +  dest[XX][ZZ]=a[XX][XX]*b[ZZ][XX]+a[XX][YY]*b[ZZ][YY]+a[XX][ZZ]*b[ZZ][ZZ];
 +  dest[YY][XX]=a[YY][XX]*b[XX][XX]+a[YY][YY]*b[XX][YY]+a[YY][ZZ]*b[XX][ZZ];
 +  dest[YY][YY]=a[YY][XX]*b[YY][XX]+a[YY][YY]*b[YY][YY]+a[YY][ZZ]*b[YY][ZZ];
 +  dest[YY][ZZ]=a[YY][XX]*b[ZZ][XX]+a[YY][YY]*b[ZZ][YY]+a[YY][ZZ]*b[ZZ][ZZ];
 +  dest[ZZ][XX]=a[ZZ][XX]*b[XX][XX]+a[ZZ][YY]*b[XX][YY]+a[ZZ][ZZ]*b[XX][ZZ];
 +  dest[ZZ][YY]=a[ZZ][XX]*b[YY][XX]+a[ZZ][YY]*b[YY][YY]+a[ZZ][ZZ]*b[YY][ZZ];
 +  dest[ZZ][ZZ]=a[ZZ][XX]*b[ZZ][XX]+a[ZZ][YY]*b[ZZ][YY]+a[ZZ][ZZ]*b[ZZ][ZZ];
 +}
 +
 +static gmx_inline real det(matrix a)
 +{
 +  return ( a[XX][XX]*(a[YY][YY]*a[ZZ][ZZ]-a[ZZ][YY]*a[YY][ZZ])
 +        -a[YY][XX]*(a[XX][YY]*a[ZZ][ZZ]-a[ZZ][YY]*a[XX][ZZ])
 +        +a[ZZ][XX]*(a[XX][YY]*a[YY][ZZ]-a[YY][YY]*a[XX][ZZ]));
 +}
 +
 +static gmx_inline void m_add(matrix a,matrix b,matrix dest)
 +{
 +  dest[XX][XX]=a[XX][XX]+b[XX][XX];
 +  dest[XX][YY]=a[XX][YY]+b[XX][YY];
 +  dest[XX][ZZ]=a[XX][ZZ]+b[XX][ZZ];
 +  dest[YY][XX]=a[YY][XX]+b[YY][XX];
 +  dest[YY][YY]=a[YY][YY]+b[YY][YY];
 +  dest[YY][ZZ]=a[YY][ZZ]+b[YY][ZZ];
 +  dest[ZZ][XX]=a[ZZ][XX]+b[ZZ][XX];
 +  dest[ZZ][YY]=a[ZZ][YY]+b[ZZ][YY];
 +  dest[ZZ][ZZ]=a[ZZ][ZZ]+b[ZZ][ZZ];
 +}
 +
 +static gmx_inline void m_sub(matrix a,matrix b,matrix dest)
 +{
 +  dest[XX][XX]=a[XX][XX]-b[XX][XX];
 +  dest[XX][YY]=a[XX][YY]-b[XX][YY];
 +  dest[XX][ZZ]=a[XX][ZZ]-b[XX][ZZ];
 +  dest[YY][XX]=a[YY][XX]-b[YY][XX];
 +  dest[YY][YY]=a[YY][YY]-b[YY][YY];
 +  dest[YY][ZZ]=a[YY][ZZ]-b[YY][ZZ];
 +  dest[ZZ][XX]=a[ZZ][XX]-b[ZZ][XX];
 +  dest[ZZ][YY]=a[ZZ][YY]-b[ZZ][YY];
 +  dest[ZZ][ZZ]=a[ZZ][ZZ]-b[ZZ][ZZ];
 +}
 +
 +static gmx_inline void msmul(matrix m1,real r1,matrix dest)
 +{
 +  dest[XX][XX]=r1*m1[XX][XX];
 +  dest[XX][YY]=r1*m1[XX][YY];
 +  dest[XX][ZZ]=r1*m1[XX][ZZ];
 +  dest[YY][XX]=r1*m1[YY][XX];
 +  dest[YY][YY]=r1*m1[YY][YY];
 +  dest[YY][ZZ]=r1*m1[YY][ZZ];
 +  dest[ZZ][XX]=r1*m1[ZZ][XX];
 +  dest[ZZ][YY]=r1*m1[ZZ][YY];
 +  dest[ZZ][ZZ]=r1*m1[ZZ][ZZ];
 +}
 +
 +static gmx_inline void m_inv_ur0(matrix src,matrix dest)
 +{
 +  double tmp = src[XX][XX]*src[YY][YY]*src[ZZ][ZZ];
 +  if (fabs(tmp) <= 100*GMX_REAL_MIN)
 +    gmx_fatal(FARGS,"Can not invert matrix, determinant is zero");
 +
 +  dest[XX][XX] = 1/src[XX][XX];
 +  dest[YY][YY] = 1/src[YY][YY];
 +  dest[ZZ][ZZ] = 1/src[ZZ][ZZ];
 +  dest[ZZ][XX] = (src[YY][XX]*src[ZZ][YY]*dest[YY][YY]
 +                - src[ZZ][XX])*dest[XX][XX]*dest[ZZ][ZZ];
 +  dest[YY][XX] = -src[YY][XX]*dest[XX][XX]*dest[YY][YY];
 +  dest[ZZ][YY] = -src[ZZ][YY]*dest[YY][YY]*dest[ZZ][ZZ];
 +  dest[XX][YY] = 0.0;
 +  dest[XX][ZZ] = 0.0;
 +  dest[YY][ZZ] = 0.0;
 +}
 +
 +static gmx_inline void m_inv(matrix src,matrix dest)
 +{
 +  const real smallreal = (real)1.0e-24;
 +  const real largereal = (real)1.0e24;
 +  real  deter,c,fc;
 +
 +  deter = det(src);
 +  c     = (real)1.0/deter;
 +  fc    = (real)fabs(c);
 +  
 +  if ((fc <= smallreal) || (fc >= largereal)) 
 +    gmx_fatal(FARGS,"Can not invert matrix, determinant = %e",deter);
 +
 +  dest[XX][XX]= c*(src[YY][YY]*src[ZZ][ZZ]-src[ZZ][YY]*src[YY][ZZ]);
 +  dest[XX][YY]=-c*(src[XX][YY]*src[ZZ][ZZ]-src[ZZ][YY]*src[XX][ZZ]);
 +  dest[XX][ZZ]= c*(src[XX][YY]*src[YY][ZZ]-src[YY][YY]*src[XX][ZZ]);
 +  dest[YY][XX]=-c*(src[YY][XX]*src[ZZ][ZZ]-src[ZZ][XX]*src[YY][ZZ]);
 +  dest[YY][YY]= c*(src[XX][XX]*src[ZZ][ZZ]-src[ZZ][XX]*src[XX][ZZ]);
 +  dest[YY][ZZ]=-c*(src[XX][XX]*src[YY][ZZ]-src[YY][XX]*src[XX][ZZ]);
 +  dest[ZZ][XX]= c*(src[YY][XX]*src[ZZ][YY]-src[ZZ][XX]*src[YY][YY]);
 +  dest[ZZ][YY]=-c*(src[XX][XX]*src[ZZ][YY]-src[ZZ][XX]*src[XX][YY]);
 +  dest[ZZ][ZZ]= c*(src[XX][XX]*src[YY][YY]-src[YY][XX]*src[XX][YY]);
 +}
 +
 +static gmx_inline void mvmul(matrix a,const rvec src,rvec dest)
 +{
 +  dest[XX]=a[XX][XX]*src[XX]+a[XX][YY]*src[YY]+a[XX][ZZ]*src[ZZ];
 +  dest[YY]=a[YY][XX]*src[XX]+a[YY][YY]*src[YY]+a[YY][ZZ]*src[ZZ];
 +  dest[ZZ]=a[ZZ][XX]*src[XX]+a[ZZ][YY]*src[YY]+a[ZZ][ZZ]*src[ZZ];
 +}
 +
 +static gmx_inline void mvmul_ur0(matrix a,const rvec src,rvec dest)
 +{
 +  dest[ZZ]=a[ZZ][XX]*src[XX]+a[ZZ][YY]*src[YY]+a[ZZ][ZZ]*src[ZZ];
 +  dest[YY]=a[YY][XX]*src[XX]+a[YY][YY]*src[YY];
 +  dest[XX]=a[XX][XX]*src[XX];
 +}
 +
 +static gmx_inline void tmvmul_ur0(matrix a,const rvec src,rvec dest)
 +{
 +  dest[XX]=a[XX][XX]*src[XX]+a[YY][XX]*src[YY]+a[ZZ][XX]*src[ZZ];
 +  dest[YY]=                  a[YY][YY]*src[YY]+a[ZZ][YY]*src[ZZ];
 +  dest[ZZ]=                                    a[ZZ][ZZ]*src[ZZ];
 +}
 +
 +static gmx_inline void unitv(const rvec src,rvec dest)
 +{
 +  real linv;
 +  
 +  linv=gmx_invsqrt(norm2(src));
 +  dest[XX]=linv*src[XX];
 +  dest[YY]=linv*src[YY];
 +  dest[ZZ]=linv*src[ZZ];
 +}
 +
 +static gmx_inline void unitv_no_table(const rvec src,rvec dest)
 +{
 +  real linv;
 +  
 +  linv=1.0/sqrt(norm2(src));
 +  dest[XX]=linv*src[XX];
 +  dest[YY]=linv*src[YY];
 +  dest[ZZ]=linv*src[ZZ];
 +}
 +
 +static void calc_lll(rvec box,rvec lll)
 +{
 +  lll[XX] = 2.0*M_PI/box[XX];
 +  lll[YY] = 2.0*M_PI/box[YY];
 +  lll[ZZ] = 2.0*M_PI/box[ZZ];
 +}
 +
 +static gmx_inline real trace(matrix m)
 +{
 +  return (m[XX][XX]+m[YY][YY]+m[ZZ][ZZ]);
 +}
 +
 +static gmx_inline real _divide_err(real a,real b,const char *file,int line)
 +{
 +    if (fabs(b) <= GMX_REAL_MIN) 
 +        gmx_fatal(FARGS,"Dividing by zero, file %s, line %d",file,line);
 +    return a/b;
 +}
 +
 +static gmx_inline int _mod(int a,int b,char *file,int line)
 +{
 +  if(b==0)
 +    gmx_fatal(FARGS,"Modulo zero, file %s, line %d",file,line);
 +  return a % b;
 +}
 +
 +/* Operations on multidimensional rvecs, used e.g. in edsam.c */
 +static void m_rveccopy(int dim, rvec *a, rvec *b)
 +{
 +    /* b = a */
 +    int i;
 +
 +    for (i=0; i<dim; i++)
 +        copy_rvec(a[i],b[i]);
 +} 
 +
 +/*computer matrix vectors from base vectors and angles */
 +static void matrix_convert(matrix box, rvec vec, rvec angle)
 +{
 +    svmul(DEG2RAD,angle,angle);
 +    box[XX][XX] = vec[XX];
 +    box[YY][XX] = vec[YY]*cos(angle[ZZ]);
 +    box[YY][YY] = vec[YY]*sin(angle[ZZ]);
 +    box[ZZ][XX] = vec[ZZ]*cos(angle[YY]);
 +    box[ZZ][YY] = vec[ZZ]
 +                         *(cos(angle[XX])-cos(angle[YY])*cos(angle[ZZ]))/sin(angle[ZZ]);
 +    box[ZZ][ZZ] = sqrt(sqr(vec[ZZ])
 +                       -box[ZZ][XX]*box[ZZ][XX]-box[ZZ][YY]*box[ZZ][YY]);
 +}
 +
 +#define divide_err(a,b) _divide_err((a),(b),__FILE__,__LINE__)
 +#define mod(a,b)    _mod((a),(b),__FILE__,__LINE__)
 +
 +#ifdef __cplusplus
 +}
 +#endif
 +
 +
 +#endif        /* _vec_h */
index 150cd535464b3e68906485ad22fe2f387fd690cd,0000000000000000000000000000000000000000..4871f08f8e2cef93d43815cbec13fb1b379e748f
mode 100644,000000..100644
--- /dev/null
@@@ -1,2 -1,0 +1,5 @@@
 +file(GLOB MDLIB_SOURCES *.c)
++if(GMX_FFT_FFTPACK)
++list(APPEND MDLIB_SOURCES ${CMAKE_SOURCE_DIR}/src/external/fftpack/fftpack.c)
++endif()
 +set(MDLIB_SOURCES ${MDLIB_SOURCES} PARENT_SCOPE)
index a834e0c7d24ed2210cfd34dbd4922c984c90b4cf,0000000000000000000000000000000000000000..1091d2c63bce6f7489a1b9f3322a057fd26154b9
mode 100644,000000..100644
--- /dev/null
@@@ -1,2688 -1,0 +1,925 @@@
 +/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*- 
 + *
 + *
 + * Gromacs 4.0                         Copyright (c) 1991-2003
 + * David van der Spoel, Erik Lindahl, University of Groningen.
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * To help us fund GROMACS development, we humbly ask that you cite
 + * the research papers on the package. Check out http://www.gromacs.org
 + * 
 + * And Hey:
 + * Gnomes, ROck Monsters And Chili Sauce
 + */
 +#ifdef HAVE_CONFIG_H
 +#include <config.h>
 +#endif
 +
 +#ifdef GMX_FFT_FFTPACK
 +
 +#include <math.h>
 +#include <stdlib.h>
 +#include <string.h>
 +#include <errno.h>
 +
 +
 +#include "gmx_fft.h"
 +#include "gmx_fatal.h"
- static void 
- fftpack_passf2(int         ido, 
-                int         l1, 
-                real  cc[],
-                real  ch[],
-                real  wa1[],
-                int         isign)
- {
-     int i, k, ah, ac;
-     real ti2, tr2;
-     
-     if (ido <= 2)
-     {
-         for (k=0; k<l1; k++) 
-         {
-             ah = k*ido;
-             ac = 2*k*ido;
-             ch[ah]              = cc[ac]   + cc[ac + ido];
-             ch[ah + ido*l1]     = cc[ac]   - cc[ac + ido];
-             ch[ah+1]            = cc[ac+1] + cc[ac + ido + 1];
-             ch[ah + ido*l1 + 1] = cc[ac+1] - cc[ac + ido + 1];
-         }
-     } 
-     else
-     {
-         for (k=0; k<l1; k++) 
-         {
-             for (i=0; i<ido-1; i+=2) 
-             {
-                 ah              = i + k*ido;
-                 ac              = i + 2*k*ido;
-                 ch[ah]          = cc[ac] + cc[ac + ido];
-                 tr2             = cc[ac] - cc[ac + ido];
-                 ch[ah+1]        = cc[ac+1] + cc[ac + 1 + ido];
-                 ti2             = cc[ac+1] - cc[ac + 1 + ido];
-                 ch[ah+l1*ido+1] = wa1[i]*ti2 + isign*wa1[i+1]*tr2;
-                 ch[ah+l1*ido]   = wa1[i]*tr2 - isign*wa1[i+1]*ti2;
-             }
-         }
-     }
- } 
- static void 
- fftpack_passf3(int         ido,
-                int         l1, 
-                real  cc[],
-                real  ch[],
-                real  wa1[], 
-                real  wa2[],
-                int         isign)
- {
-     const real taur = -0.5;
-     const real taui = 0.866025403784439;
-     
-     int i, k, ac, ah;
-     real ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2;
-     
-     if (ido == 2) 
-     {
-         for (k=1; k<=l1; k++) 
-         {
-             ac = (3*k - 2)*ido;
-             tr2 = cc[ac] + cc[ac + ido];
-             cr2 = cc[ac - ido] + taur*tr2;
-             ah = (k - 1)*ido;
-             ch[ah] = cc[ac - ido] + tr2;
-             
-             ti2 = cc[ac + 1] + cc[ac + ido + 1];
-             ci2 = cc[ac - ido + 1] + taur*ti2;
-             ch[ah + 1] = cc[ac - ido + 1] + ti2;
-             
-             cr3 = isign*taui*(cc[ac] - cc[ac + ido]);
-             ci3 = isign*taui*(cc[ac + 1] - cc[ac + ido + 1]);
-             ch[ah + l1*ido] = cr2 - ci3;
-             ch[ah + 2*l1*ido] = cr2 + ci3;
-             ch[ah + l1*ido + 1] = ci2 + cr3;
-             ch[ah + 2*l1*ido + 1] = ci2 - cr3;
-         }
-     } 
-     else
-     {
-         for (k=1; k<=l1; k++) 
-         {
-             for (i=0; i<ido-1; i+=2)
-             {
-                 ac = i + (3*k - 2)*ido;
-                 tr2 = cc[ac] + cc[ac + ido];
-                 cr2 = cc[ac - ido] + taur*tr2;
-                 ah = i + (k-1)*ido;
-                 ch[ah] = cc[ac - ido] + tr2;
-                 ti2 = cc[ac + 1] + cc[ac + ido + 1];
-                 ci2 = cc[ac - ido + 1] + taur*ti2;
-                 ch[ah + 1] = cc[ac - ido + 1] + ti2;
-                 cr3 = isign*taui*(cc[ac] - cc[ac + ido]);
-                 ci3 = isign*taui*(cc[ac + 1] - cc[ac + ido + 1]);
-                 dr2 = cr2 - ci3;
-                 dr3 = cr2 + ci3;
-                 di2 = ci2 + cr3;
-                 di3 = ci2 - cr3;
-                 ch[ah + l1*ido + 1] = wa1[i]*di2 + isign*wa1[i+1]*dr2;
-                 ch[ah + l1*ido] = wa1[i]*dr2 - isign*wa1[i+1]*di2;
-                 ch[ah + 2*l1*ido + 1] = wa2[i]*di3 + isign*wa2[i+1]*dr3;
-                 ch[ah + 2*l1*ido] = wa2[i]*dr3 - isign*wa2[i+1]*di3;
-             }
-         }
-     }
- } 
- static void 
- fftpack_passf4(int          ido, 
-                int          l1,
-                real   cc[], 
-                real   ch[],
-                real   wa1[],
-                real   wa2[], 
-                real   wa3[],
-                int          isign)
- {
-     int i, k, ac, ah;
-     real ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4;
-     
-     if (ido == 2) 
-     {
-         for (k=0; k<l1; k++)
-         {
-             ac = 4*k*ido + 1;
-             ti1 = cc[ac] - cc[ac + 2*ido];
-             ti2 = cc[ac] + cc[ac + 2*ido];
-             tr4 = cc[ac + 3*ido] - cc[ac + ido];
-             ti3 = cc[ac + ido] + cc[ac + 3*ido];
-             tr1 = cc[ac - 1] - cc[ac + 2*ido - 1];
-             tr2 = cc[ac - 1] + cc[ac + 2*ido - 1];
-             ti4 = cc[ac + ido - 1] - cc[ac + 3*ido - 1];
-             tr3 = cc[ac + ido - 1] + cc[ac + 3*ido - 1];
-             ah = k*ido;
-             ch[ah] = tr2 + tr3;
-             ch[ah + 2*l1*ido] = tr2 - tr3;
-             ch[ah + 1] = ti2 + ti3;
-             ch[ah + 2*l1*ido + 1] = ti2 - ti3;
-             ch[ah + l1*ido] = tr1 + isign*tr4;
-             ch[ah + 3*l1*ido] = tr1 - isign*tr4;
-             ch[ah + l1*ido + 1] = ti1 + isign*ti4;
-             ch[ah + 3*l1*ido + 1] = ti1 - isign*ti4;
-         }
-     } 
-     else
-     {
-         for (k=0; k<l1; k++)
-         {
-             for (i=0; i<ido-1; i+=2)
-             {
-                 ac = i + 1 + 4*k*ido;
-                 ti1 = cc[ac] - cc[ac + 2*ido];
-                 ti2 = cc[ac] + cc[ac + 2*ido];
-                 ti3 = cc[ac + ido] + cc[ac + 3*ido];
-                 tr4 = cc[ac + 3*ido] - cc[ac + ido];
-                 tr1 = cc[ac - 1] - cc[ac + 2*ido - 1];
-                 tr2 = cc[ac - 1] + cc[ac + 2*ido - 1];
-                 ti4 = cc[ac + ido - 1] - cc[ac + 3*ido - 1];
-                 tr3 = cc[ac + ido - 1] + cc[ac + 3*ido - 1];
-                 ah = i + k*ido;
-                 ch[ah] = tr2 + tr3;
-                 cr3 = tr2 - tr3;
-                 ch[ah + 1] = ti2 + ti3;
-                 ci3 = ti2 - ti3;
-                 cr2 = tr1 + isign*tr4;
-                 cr4 = tr1 - isign*tr4;
-                 ci2 = ti1 + isign*ti4;
-                 ci4 = ti1 - isign*ti4;
-                 ch[ah + l1*ido] = wa1[i]*cr2 - isign*wa1[i + 1]*ci2;
-                 ch[ah + l1*ido + 1] = wa1[i]*ci2 + isign*wa1[i + 1]*cr2;
-                 ch[ah + 2*l1*ido] = wa2[i]*cr3 - isign*wa2[i + 1]*ci3;
-                 ch[ah + 2*l1*ido + 1] = wa2[i]*ci3 + isign*wa2[i + 1]*cr3;
-                 ch[ah + 3*l1*ido] = wa3[i]*cr4 -isign*wa3[i + 1]*ci4;
-                 ch[ah + 3*l1*ido + 1] = wa3[i]*ci4 + isign*wa3[i + 1]*cr4;
-             }
-         }
-     }
- } 
- static void 
- fftpack_passf5(int          ido,
-                int          l1, 
-                real   cc[],
-                real   ch[],
-                real   wa1[], 
-                real   wa2[],
-                real   wa3[], 
-                real   wa4[],
-                int          isign)
- {
-     const real tr11 = 0.309016994374947;
-     const real ti11 = 0.951056516295154;
-     const real tr12 = -0.809016994374947;
-     const real ti12 = 0.587785252292473;
-     
-     int i, k, ac, ah;
-     real ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, ti2, ti3,
-         ti4, ti5, dr3, dr4, dr5, dr2, tr2, tr3, tr4, tr5;
-     
-     if (ido == 2) 
-     {
-         for (k = 1; k <= l1; ++k) 
-         {
-             ac = (5*k - 4)*ido + 1;
-             ti5 = cc[ac] - cc[ac + 3*ido];
-             ti2 = cc[ac] + cc[ac + 3*ido];
-             ti4 = cc[ac + ido] - cc[ac + 2*ido];
-             ti3 = cc[ac + ido] + cc[ac + 2*ido];
-             tr5 = cc[ac - 1] - cc[ac + 3*ido - 1];
-             tr2 = cc[ac - 1] + cc[ac + 3*ido - 1];
-             tr4 = cc[ac + ido - 1] - cc[ac + 2*ido - 1];
-             tr3 = cc[ac + ido - 1] + cc[ac + 2*ido - 1];
-             ah = (k - 1)*ido;
-             ch[ah] = cc[ac - ido - 1] + tr2 + tr3;
-             ch[ah + 1] = cc[ac - ido] + ti2 + ti3;
-             cr2 = cc[ac - ido - 1] + tr11*tr2 + tr12*tr3;
-             ci2 = cc[ac - ido] + tr11*ti2 + tr12*ti3;
-             cr3 = cc[ac - ido - 1] + tr12*tr2 + tr11*tr3;
-             ci3 = cc[ac - ido] + tr12*ti2 + tr11*ti3;
-             cr5 = isign*(ti11*tr5 + ti12*tr4);
-             ci5 = isign*(ti11*ti5 + ti12*ti4);
-             cr4 = isign*(ti12*tr5 - ti11*tr4);
-             ci4 = isign*(ti12*ti5 - ti11*ti4);
-             ch[ah + l1*ido] = cr2 - ci5;
-             ch[ah + 4*l1*ido] = cr2 + ci5;
-             ch[ah + l1*ido + 1] = ci2 + cr5;
-             ch[ah + 2*l1*ido + 1] = ci3 + cr4;
-             ch[ah + 2*l1*ido] = cr3 - ci4;
-             ch[ah + 3*l1*ido] = cr3 + ci4;
-             ch[ah + 3*l1*ido + 1] = ci3 - cr4;
-             ch[ah + 4*l1*ido + 1] = ci2 - cr5;
-         }
-     } 
-     else
-     {
-         for (k=1; k<=l1; k++) 
-         {
-             for (i=0; i<ido-1; i+=2) 
-             {
-                 ac = i + 1 + (k*5 - 4)*ido;
-                 ti5 = cc[ac] - cc[ac + 3*ido];
-                 ti2 = cc[ac] + cc[ac + 3*ido];
-                 ti4 = cc[ac + ido] - cc[ac + 2*ido];
-                 ti3 = cc[ac + ido] + cc[ac + 2*ido];
-                 tr5 = cc[ac - 1] - cc[ac + 3*ido - 1];
-                 tr2 = cc[ac - 1] + cc[ac + 3*ido - 1];
-                 tr4 = cc[ac + ido - 1] - cc[ac + 2*ido - 1];
-                 tr3 = cc[ac + ido - 1] + cc[ac + 2*ido - 1];
-                 ah = i + (k - 1)*ido;
-                 ch[ah] = cc[ac - ido - 1] + tr2 + tr3;
-                 ch[ah + 1] = cc[ac - ido] + ti2 + ti3;
-                 cr2 = cc[ac - ido - 1] + tr11*tr2 + tr12*tr3;
-                 ci2 = cc[ac - ido] + tr11*ti2 + tr12*ti3;
-                 cr3 = cc[ac - ido - 1] + tr12*tr2 + tr11*tr3;
-                 ci3 = cc[ac - ido] + tr12*ti2 + tr11*ti3;
-                 cr5 = isign*(ti11*tr5 + ti12*tr4);
-                 ci5 = isign*(ti11*ti5 + ti12*ti4);
-                 cr4 = isign*(ti12*tr5 - ti11*tr4);
-                 ci4 = isign*(ti12*ti5 - ti11*ti4);
-                 dr3 = cr3 - ci4;
-                 dr4 = cr3 + ci4;
-                 di3 = ci3 + cr4;
-                 di4 = ci3 - cr4;
-                 dr5 = cr2 + ci5;
-                 dr2 = cr2 - ci5;
-                 di5 = ci2 - cr5;
-                 di2 = ci2 + cr5;
-                 ch[ah + l1*ido] = wa1[i]*dr2 - isign*wa1[i+1]*di2;
-                 ch[ah + l1*ido + 1] = wa1[i]*di2 + isign*wa1[i+1]*dr2;
-                 ch[ah + 2*l1*ido] = wa2[i]*dr3 - isign*wa2[i+1]*di3;
-                 ch[ah + 2*l1*ido + 1] = wa2[i]*di3 + isign*wa2[i+1]*dr3;
-                 ch[ah + 3*l1*ido] = wa3[i]*dr4 - isign*wa3[i+1]*di4;
-                 ch[ah + 3*l1*ido + 1] = wa3[i]*di4 + isign*wa3[i+1]*dr4;
-                 ch[ah + 4*l1*ido] = wa4[i]*dr5 - isign*wa4[i+1]*di5;
-                 ch[ah + 4*l1*ido + 1] = wa4[i]*di5 + isign*wa4[i+1]*dr5;
-             }
-         }
-     }
- } 
- static void 
- fftpack_passf(int *        nac, 
-               int          ido,
-               int          ip, 
-               int          l1,
-               int          idl1,
-               real   cc[],
-               real   ch[],
-               real   wa[],
-               int          isign)
- {
-     int idij, idlj, idot, ipph, i, j, k, l, jc, lc, ik, nt, idj, idl, inc,idp;
-     real wai, war;
-     
-     idot = ido / 2;
-     nt = ip*idl1;
-     ipph = (ip + 1) / 2;
-     idp = ip*ido;
-     if (ido >= l1) 
-     {
-         for (j=1; j<ipph; j++)
-         {
-             jc = ip - j;
-             for (k=0; k<l1; k++) 
-             {
-                 for (i=0; i<ido; i++) 
-                 {
-                     ch[i + (k + j*l1)*ido]  = cc[i + (j + k*ip)*ido] + cc[i + (jc + k*ip)*ido];
-                     ch[i + (k + jc*l1)*ido] = cc[i + (j + k*ip)*ido] - cc[i + (jc + k*ip)*ido];
-                 }
-             }
-         }
-         for (k=0; k<l1; k++)
-             for (i=0; i<ido; i++)
-                 ch[i + k*ido] = cc[i + k*ip*ido];
-     } 
-     else
-     {
-         for (j=1; j<ipph; j++) 
-         {
-             jc = ip - j;
-             for (i=0; i<ido; i++) 
-             {
-                 for (k=0; k<l1; k++) 
-                 {
-                     ch[i + (k + j*l1)*ido] =  cc[i + (j + k*ip)*ido] + cc[i + (jc + k*ip)*ido];
-                     ch[i + (k + jc*l1)*ido] = cc[i + (j + k*ip)*ido] - cc[i + (jc + k*ip)*ido];
-                 }
-             }
-         }
-         for (i=0; i<ido; i++)
-             for (k=0; k<l1; k++)
-                 ch[i + k*ido] = cc[i + k*ip*ido];
-     }
-     
-     idl = 2 - ido;
-     inc = 0;
-     for (l=1; l<ipph; l++) 
-     {
-         lc = ip - l;
-         idl += ido;
-         for (ik=0; ik<idl1; ik++)
-         {
-             cc[ik + l*idl1] = ch[ik] + wa[idl - 2]*ch[ik + idl1];
-             cc[ik + lc*idl1] = isign*wa[idl-1]*ch[ik + (ip-1)*idl1];
-         }
-         idlj = idl;
-         inc += ido;
-         for (j=2; j<ipph; j++)
-         {
-             jc = ip - j;
-             idlj += inc;
-             if (idlj > idp) idlj -= idp;
-             war = wa[idlj - 2];
-             wai = wa[idlj-1];
-             for (ik=0; ik<idl1; ik++)
-             {
-                 cc[ik + l*idl1] += war*ch[ik + j*idl1];
-                 cc[ik + lc*idl1] += isign*wai*ch[ik + jc*idl1];
-             }
-         }
-     }
-     for (j=1; j<ipph; j++)
-         for (ik=0; ik<idl1; ik++)
-             ch[ik] += ch[ik + j*idl1];
-     for (j=1; j<ipph; j++) 
-     {
-         jc = ip - j;
-         for (ik=1; ik<idl1; ik+=2) 
-         {
-             ch[ik - 1 + j*idl1] = cc[ik - 1 + j*idl1] - cc[ik + jc*idl1];
-             ch[ik - 1 + jc*idl1] = cc[ik - 1 + j*idl1] + cc[ik + jc*idl1];
-             ch[ik + j*idl1] = cc[ik + j*idl1] + cc[ik - 1 + jc*idl1];
-             ch[ik + jc*idl1] = cc[ik + j*idl1] - cc[ik - 1 + jc*idl1];
-         }
-     }
-     *nac = 1;
-     if (ido == 2) 
-         return;
-     *nac = 0;
-     for (ik=0; ik<idl1; ik++)
-     {
-         cc[ik] = ch[ik];
-     }
-     for (j=1; j<ip; j++)
-     {
-         for (k=0; k<l1; k++) 
-         {
-             cc[(k + j*l1)*ido + 0] = ch[(k + j*l1)*ido + 0];
-             cc[(k + j*l1)*ido + 1] = ch[(k + j*l1)*ido + 1];
-         }
-     }
-     if (idot <= l1) 
-     {
-         idij = 0;
-         for (j=1; j<ip; j++)
-         {
-             idij += 2;
-             for (i=3; i<ido; i+=2) 
-             {
-                 idij += 2;
-                 for (k=0; k<l1; k++)
-                 {
-                     cc[i - 1 + (k + j*l1)*ido] =
-                     wa[idij - 2]*ch[i - 1 + (k + j*l1)*ido] -
-                     isign*wa[idij-1]*ch[i + (k + j*l1)*ido];
-                     cc[i + (k + j*l1)*ido] =
-                         wa[idij - 2]*ch[i + (k + j*l1)*ido] +
-                         isign*wa[idij-1]*ch[i - 1 + (k + j*l1)*ido];
-                 }
-             }
-         }
-     }
-     else
-     {
-         idj = 2 - ido;
-         for (j=1; j<ip; j++) 
-         {
-             idj += ido;
-             for (k = 0; k < l1; k++) 
-             {
-                 idij = idj;
-                 for (i=3; i<ido; i+=2)
-                 {
-                     idij += 2;
-                     cc[i - 1 + (k + j*l1)*ido] =
-                         wa[idij - 2]*ch[i - 1 + (k + j*l1)*ido] -
-                         isign*wa[idij-1]*ch[i + (k + j*l1)*ido];
-                     cc[i + (k + j*l1)*ido] =
-                         wa[idij - 2]*ch[i + (k + j*l1)*ido] +
-                         isign*wa[idij-1]*ch[i - 1 + (k + j*l1)*ido];
-                 }
-             }
-         }
-     }
- } 
- static void 
- fftpack_radf2(int          ido,
-               int          l1, 
-               real   cc[], 
-               real   ch[], 
-               real   wa1[])
- {
-     int i, k, ic;
-     real ti2, tr2;
-     for (k=0; k<l1; k++) 
-     {
-         ch[2*k*ido] = cc[k*ido] + cc[(k + l1)*ido];
-         ch[(2*k+1)*ido + ido-1] = cc[k*ido] - cc[(k + l1)*ido];
-     }
-     if (ido < 2) 
-         return;
-     if (ido != 2) 
-     {
-         for (k=0; k<l1; k++) 
-         {
-             for (i=2; i<ido; i+=2) 
-             {
-                 ic = ido - i;
-                 tr2 = wa1[i - 2]*cc[i-1 + (k + l1)*ido] + wa1[i - 1]*cc[i + (k + l1)*ido];
-                 ti2 = wa1[i - 2]*cc[i + (k + l1)*ido] - wa1[i - 1]*cc[i-1 + (k + l1)*ido];
-                 ch[i + 2*k*ido] = cc[i + k*ido] + ti2;
-                 ch[ic + (2*k+1)*ido] = ti2 - cc[i + k*ido];
-                 ch[i - 1 + 2*k*ido] = cc[i - 1 + k*ido] + tr2;
-                 ch[ic - 1 + (2*k+1)*ido] = cc[i - 1 + k*ido] - tr2;
-             }
-         }
-         if (ido % 2 == 1) 
-             return;
-     }
-     for (k=0; k<l1; k++)
-     {
-         ch[(2*k+1)*ido] = -cc[ido-1 + (k + l1)*ido];
-         ch[ido-1 + 2*k*ido] = cc[ido-1 + k*ido];
-     }
- }
- static void 
- fftpack_radb2(int          ido, 
-               int          l1, 
-               real   cc[],
-               real   ch[], 
-               real   wa1[])
- {
-     int i, k, ic;
-     real ti2, tr2;
-     for (k=0; k<l1; k++) 
-     {
-         ch[k*ido] = cc[2*k*ido] + cc[ido-1 + (2*k+1)*ido];
-         ch[(k + l1)*ido] = cc[2*k*ido] - cc[ido-1 + (2*k+1)*ido];
-     }
-     if (ido < 2) 
-         return;
-     if (ido != 2) 
-     {
-         for (k = 0; k < l1; ++k)
-         {
-             for (i = 2; i < ido; i += 2) 
-             {
-                 ic = ido - i;
-                 ch[i-1 + k*ido] = cc[i-1 + 2*k*ido] + cc[ic-1 + (2*k+1)*ido];
-                 tr2 = cc[i-1 + 2*k*ido] - cc[ic-1 + (2*k+1)*ido];
-                 ch[i + k*ido] = cc[i + 2*k*ido] - cc[ic + (2*k+1)*ido];
-                 ti2 = cc[i + (2*k)*ido] + cc[ic + (2*k+1)*ido];
-                 ch[i-1 + (k + l1)*ido] = wa1[i - 2]*tr2 - wa1[i - 1]*ti2;
-                 ch[i + (k + l1)*ido] = wa1[i - 2]*ti2 + wa1[i - 1]*tr2;
-             }
-         }
-         if (ido % 2 == 1) 
-             return;
-     }
-     for (k = 0; k < l1; k++) 
-     {
-         ch[ido-1 + k*ido] = 2*cc[ido-1 + 2*k*ido];
-         ch[ido-1 + (k + l1)*ido] = -2*cc[(2*k+1)*ido];
-     }
- } 
- static void 
- fftpack_radf3(int          ido, 
-               int          l1,
-               real   cc[], 
-               real   ch[],
-               real   wa1[], 
-               real   wa2[])
- {
-     const real taur = -0.5;
-     const real taui = 0.866025403784439;
-     int i, k, ic;
-     real ci2, di2, di3, cr2, dr2, dr3, ti2, ti3, tr2, tr3;
-     
-     for (k=0; k<l1; k++)
-     {
-         cr2 = cc[(k + l1)*ido] + cc[(k + 2*l1)*ido];
-         ch[3*k*ido] = cc[k*ido] + cr2;
-         ch[(3*k+2)*ido] = taui*(cc[(k + l1*2)*ido] - cc[(k + l1)*ido]);
-         ch[ido-1 + (3*k + 1)*ido] = cc[k*ido] + taur*cr2;
-     }
-     if (ido == 1) 
-         return;
-     for (k=0; k<l1; k++) 
-     {
-         for (i=2; i<ido; i+=2) 
-         {
-             ic = ido - i;
-             dr2 = wa1[i - 2]*cc[i - 1 + (k + l1)*ido] +wa1[i - 1]*cc[i + (k + l1)*ido];
-             di2 = wa1[i - 2]*cc[i + (k + l1)*ido] - wa1[i - 1]*cc[i - 1 + (k + l1)*ido];
-             dr3 = wa2[i - 2]*cc[i - 1 + (k + l1*2)*ido] + wa2[i - 1]*cc[i + (k + l1*2)*ido];
-             di3 = wa2[i - 2]*cc[i + (k + l1*2)*ido] - wa2[i - 1]*cc[i - 1 + (k + l1*2)*ido];
-             cr2 = dr2 + dr3;
-             ci2 = di2 + di3;
-             ch[i - 1 + 3*k*ido] = cc[i - 1 + k*ido] + cr2;
-             ch[i + 3*k*ido] = cc[i + k*ido] + ci2;
-             tr2 = cc[i - 1 + k*ido] + taur*cr2;
-             ti2 = cc[i + k*ido] + taur*ci2;
-             tr3 = taui*(di2 - di3);
-             ti3 = taui*(dr3 - dr2);
-             ch[i - 1 + (3*k + 2)*ido] = tr2 + tr3;
-             ch[ic - 1 + (3*k + 1)*ido] = tr2 - tr3;
-             ch[i + (3*k + 2)*ido] = ti2 + ti3;
-             ch[ic + (3*k + 1)*ido] = ti3 - ti2;
-         }
-     }
- } 
- static void 
- fftpack_radb3(int          ido, 
-               int          l1, 
-               real   cc[], 
-               real   ch[],
-               real   wa1[],
-               real   wa2[])
- {
-     const real taur = -0.5;
-     const real taui = 0.866025403784439;
-     int i, k, ic;
-     real ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2;
-     
-     for (k=0; k<l1; k++) 
-     {
-         tr2 = 2*cc[ido-1 + (3*k + 1)*ido];
-         cr2 = cc[3*k*ido] + taur*tr2;
-         ch[k*ido] = cc[3*k*ido] + tr2;
-         ci3 = 2*taui*cc[(3*k + 2)*ido];
-         ch[(k + l1)*ido] = cr2 - ci3;
-         ch[(k + 2*l1)*ido] = cr2 + ci3;
-     }
-     if (ido == 1) 
-         return;
-     
-     for (k=0; k<l1; k++)
-     {
-         for (i=2; i<ido; i+=2) 
-         {
-             ic = ido - i;
-             tr2 = cc[i - 1 + (3*k + 2)*ido] + cc[ic - 1 + (3*k + 1)*ido];
-             cr2 = cc[i - 1 + 3*k*ido] + taur*tr2;
-             ch[i - 1 + k*ido] = cc[i - 1 + 3*k*ido] + tr2;
-             ti2 = cc[i + (3*k + 2)*ido]- cc[ic + (3*k + 1)*ido];
-             ci2 = cc[i + 3*k*ido] + taur*ti2;
-             ch[i + k*ido] = cc[i + 3*k*ido] + ti2;
-             cr3 = taui*(cc[i - 1 + (3*k + 2)*ido] - cc[ic - 1 + (3*k + 1)*ido]);
-             ci3 = taui*(cc[i + (3*k + 2)*ido] + cc[ic + (3*k + 1)*ido]);
-             dr2 = cr2 - ci3;
-             dr3 = cr2 + ci3;
-             di2 = ci2 + cr3;
-             di3 = ci2 - cr3;
-             ch[i - 1 + (k + l1)*ido] = wa1[i - 2]*dr2 - wa1[i - 1]*di2;
-             ch[i + (k + l1)*ido] = wa1[i - 2]*di2 + wa1[i - 1]*dr2;
-             ch[i - 1 + (k + 2*l1)*ido] = wa2[i - 2]*dr3 - wa2[i - 1]*di3;
-             ch[i + (k + 2*l1)*ido] = wa2[i - 2]*di3 + wa2[i - 1]*dr3;
-         }
-     }
- } 
- static void 
- fftpack_radf4(int          ido, 
-               int          l1, 
-               real   cc[],
-               real   ch[],
-               real   wa1[],
-               real   wa2[],
-               real   wa3[])
- {
-     const real hsqt2 = 0.7071067811865475;
-     int i, k, ic;
-     real ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4;
-     
-     for (k=0; k<l1; k++) 
-     {
-         tr1 = cc[(k + l1)*ido] + cc[(k + 3*l1)*ido];
-         tr2 = cc[k*ido] + cc[(k + 2*l1)*ido];
-         ch[4*k*ido] = tr1 + tr2;
-         ch[ido-1 + (4*k + 3)*ido] = tr2 - tr1;
-         ch[ido-1 + (4*k + 1)*ido] = cc[k*ido] - cc[(k + 2*l1)*ido];
-         ch[(4*k + 2)*ido] = cc[(k + 3*l1)*ido] - cc[(k + l1)*ido];
-     }
-     if (ido < 2) 
-         return;
-     if (ido != 2)
-     {
-         for (k=0; k<l1; k++) 
-         {
-             for (i=2; i<ido; i += 2)
-             {
-                 ic = ido - i;
-                 cr2 = wa1[i - 2]*cc[i - 1 + (k + l1)*ido] + wa1[i - 1]*cc[i + (k + l1)*ido];
-                 ci2 = wa1[i - 2]*cc[i + (k + l1)*ido] - wa1[i - 1]*cc[i - 1 + (k + l1)*ido];
-                 cr3 = wa2[i - 2]*cc[i - 1 + (k + 2*l1)*ido] + wa2[i - 1]*cc[i + (k + 2*l1)*ido];
-                 ci3 = wa2[i - 2]*cc[i + (k + 2*l1)*ido] - wa2[i - 1]*cc[i - 1 + (k + 2*l1)*ido];
-                 cr4 = wa3[i - 2]*cc[i - 1 + (k + 3*l1)*ido] + wa3[i - 1]*cc[i + (k + 3*l1)*ido];
-                 ci4 = wa3[i - 2]*cc[i + (k + 3*l1)*ido] - wa3[i - 1]*cc[i - 1 + (k + 3*l1)*ido];
-                 tr1 = cr2 + cr4;
-                 tr4 = cr4 - cr2;
-                 ti1 = ci2 + ci4;
-                 ti4 = ci2 - ci4;
-                 ti2 = cc[i + k*ido] + ci3;
-                 ti3 = cc[i + k*ido] - ci3;
-                 tr2 = cc[i - 1 + k*ido] + cr3;
-                 tr3 = cc[i - 1 + k*ido] - cr3;
-                 ch[i - 1 + 4*k*ido] = tr1 + tr2;
-                 ch[ic - 1 + (4*k + 3)*ido] = tr2 - tr1;
-                 ch[i + 4*k*ido] = ti1 + ti2;
-                 ch[ic + (4*k + 3)*ido] = ti1 - ti2;
-                 ch[i - 1 + (4*k + 2)*ido] = ti4 + tr3;
-                 ch[ic - 1 + (4*k + 1)*ido] = tr3 - ti4;
-                 ch[i + (4*k + 2)*ido] = tr4 + ti3;
-                 ch[ic + (4*k + 1)*ido] = tr4 - ti3;
-             }
-         }
-         if (ido % 2 == 1) 
-             return;
-     }
-     for (k=0; k<l1; k++) 
-     {
-         ti1 = -hsqt2*(cc[ido-1 + (k + l1)*ido] + cc[ido-1 + (k + 3*l1)*ido]);
-         tr1 = hsqt2*(cc[ido-1 + (k + l1)*ido] - cc[ido-1 + (k + 3*l1)*ido]);
-         ch[ido-1 + 4*k*ido] = tr1 + cc[ido-1 + k*ido];
-         ch[ido-1 + (4*k + 2)*ido] = cc[ido-1 + k*ido] - tr1;
-         ch[(4*k + 1)*ido] = ti1 - cc[ido-1 + (k + 2*l1)*ido];
-         ch[(4*k + 3)*ido] = ti1 + cc[ido-1 + (k + 2*l1)*ido];
-     }
- } 
- static void
- fftpack_radb4(int          ido,
-               int          l1,
-               real   cc[], 
-               real   ch[],
-               real   wa1[], 
-               real   wa2[], 
-               real   wa3[])
- {
-     const real sqrt2 = 1.414213562373095;
-     int i, k, ic;
-     real ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4;
-     for (k = 0; k < l1; k++)
-     {
-         tr1 = cc[4*k*ido] - cc[ido-1 + (4*k + 3)*ido];
-         tr2 = cc[4*k*ido] + cc[ido-1 + (4*k + 3)*ido];
-         tr3 = cc[ido-1 + (4*k + 1)*ido] + cc[ido-1 + (4*k + 1)*ido];
-         tr4 = cc[(4*k + 2)*ido] + cc[(4*k + 2)*ido];
-         ch[k*ido] = tr2 + tr3;
-         ch[(k + l1)*ido] = tr1 - tr4;
-         ch[(k + 2*l1)*ido] = tr2 - tr3;
-         ch[(k + 3*l1)*ido] = tr1 + tr4;
-     }
-     if (ido < 2) 
-         return;
-     if (ido != 2) 
-     {
-         for (k = 0; k < l1; ++k)
-         {
-             for (i = 2; i < ido; i += 2)
-             {
-                 ic = ido - i;
-                 ti1 = cc[i + 4*k*ido] + cc[ic + (4*k + 3)*ido];
-                 ti2 = cc[i + 4*k*ido] - cc[ic + (4*k + 3)*ido];
-                 ti3 = cc[i + (4*k + 2)*ido] - cc[ic + (4*k + 1)*ido];
-                 tr4 = cc[i + (4*k + 2)*ido] + cc[ic + (4*k + 1)*ido];
-                 tr1 = cc[i - 1 + 4*k*ido] - cc[ic - 1 + (4*k + 3)*ido];
-                 tr2 = cc[i - 1 + 4*k*ido] + cc[ic - 1 + (4*k + 3)*ido];
-                 ti4 = cc[i - 1 + (4*k + 2)*ido] - cc[ic - 1 + (4*k + 1)*ido];
-                 tr3 = cc[i - 1 + (4*k + 2)*ido] + cc[ic - 1 + (4*k + 1)*ido];
-                 ch[i - 1 + k*ido] = tr2 + tr3;
-                 cr3 = tr2 - tr3;
-                 ch[i + k*ido] = ti2 + ti3;
-                 ci3 = ti2 - ti3;
-                 cr2 = tr1 - tr4;
-                 cr4 = tr1 + tr4;
-                 ci2 = ti1 + ti4;
-                 ci4 = ti1 - ti4;
-                 ch[i - 1 + (k + l1)*ido] = wa1[i - 2]*cr2 - wa1[i - 1]*ci2;
-                 ch[i + (k + l1)*ido] = wa1[i - 2]*ci2 + wa1[i - 1]*cr2;
-                 ch[i - 1 + (k + 2*l1)*ido] = wa2[i - 2]*cr3 - wa2[i - 1]*ci3;
-                 ch[i + (k + 2*l1)*ido] = wa2[i - 2]*ci3 + wa2[i - 1]*cr3;
-                 ch[i - 1 + (k + 3*l1)*ido] = wa3[i - 2]*cr4 - wa3[i - 1]*ci4;
-                 ch[i + (k + 3*l1)*ido] = wa3[i - 2]*ci4 + wa3[i - 1]*cr4;
-             }
-         }
-         if (ido % 2 == 1)
-             return;
-     }
-     for (k = 0; k < l1; k++) 
-     {
-         ti1 = cc[(4*k + 1)*ido] + cc[(4*k + 3)*ido];
-         ti2 = cc[(4*k + 3)*ido] - cc[(4*k + 1)*ido];
-         tr1 = cc[ido-1 + 4*k*ido] - cc[ido-1 + (4*k + 2)*ido];
-         tr2 = cc[ido-1 + 4*k*ido] + cc[ido-1 + (4*k + 2)*ido];
-         ch[ido-1 + k*ido] = tr2 + tr2;
-         ch[ido-1 + (k + l1)*ido] = sqrt2*(tr1 - ti1);
-         ch[ido-1 + (k + 2*l1)*ido] = ti2 + ti2;
-         ch[ido-1 + (k + 3*l1)*ido] = -sqrt2*(tr1 + ti1);
-     }
- }
- static void 
- fftpack_radf5(int          ido,
-               int          l1, 
-               real   cc[], 
-               real   ch[],
-               real   wa1[],
-               real   wa2[], 
-               real   wa3[], 
-               real   wa4[])
- {
-     const real tr11 = 0.309016994374947;
-     const real ti11 = 0.951056516295154;
-     const real tr12 = -0.809016994374947;
-     const real ti12 = 0.587785252292473;
-     int i, k, ic;
-     real ci2, di2, ci4, ci5, di3, di4, di5, ci3, cr2, cr3, dr2, dr3, dr4, dr5,
-         cr5, cr4, ti2, ti3, ti5, ti4, tr2, tr3, tr4, tr5;
-  
-     for (k = 0; k < l1; k++) 
-     {
-         cr2 = cc[(k + 4*l1)*ido] + cc[(k + l1)*ido];
-         ci5 = cc[(k + 4*l1)*ido] - cc[(k + l1)*ido];
-         cr3 = cc[(k + 3*l1)*ido] + cc[(k + 2*l1)*ido];
-         ci4 = cc[(k + 3*l1)*ido] - cc[(k + 2*l1)*ido];
-         ch[5*k*ido] = cc[k*ido] + cr2 + cr3;
-         ch[ido-1 + (5*k + 1)*ido] = cc[k*ido] + tr11*cr2 + tr12*cr3;
-         ch[(5*k + 2)*ido] = ti11*ci5 + ti12*ci4;
-         ch[ido-1 + (5*k + 3)*ido] = cc[k*ido] + tr12*cr2 + tr11*cr3;
-         ch[(5*k + 4)*ido] = ti12*ci5 - ti11*ci4;
-     }
-     if (ido == 1) 
-         return;
-     for (k = 0; k < l1; ++k) 
-     {
-         for (i = 2; i < ido; i += 2)
-         {
-             ic = ido - i;
-             dr2 = wa1[i - 2]*cc[i - 1 + (k + l1)*ido] + wa1[i - 1]*cc[i + (k + l1)*ido];
-             di2 = wa1[i - 2]*cc[i + (k + l1)*ido] - wa1[i - 1]*cc[i - 1 + (k + l1)*ido];
-             dr3 = wa2[i - 2]*cc[i - 1 + (k + 2*l1)*ido] + wa2[i - 1]*cc[i + (k + 2*l1)*ido];
-             di3 = wa2[i - 2]*cc[i + (k + 2*l1)*ido] - wa2[i - 1]*cc[i - 1 + (k + 2*l1)*ido];
-             dr4 = wa3[i - 2]*cc[i - 1 + (k + 3*l1)*ido] + wa3[i - 1]*cc[i + (k + 3*l1)*ido];
-             di4 = wa3[i - 2]*cc[i + (k + 3*l1)*ido] - wa3[i - 1]*cc[i - 1 + (k + 3*l1)*ido];
-             dr5 = wa4[i - 2]*cc[i - 1 + (k + 4*l1)*ido] + wa4[i - 1]*cc[i + (k + 4*l1)*ido];
-             di5 = wa4[i - 2]*cc[i + (k + 4*l1)*ido] - wa4[i - 1]*cc[i - 1 + (k + 4*l1)*ido];
-             cr2 = dr2 + dr5;
-             ci5 = dr5 - dr2;
-             cr5 = di2 - di5;
-             ci2 = di2 + di5;
-             cr3 = dr3 + dr4;
-             ci4 = dr4 - dr3;
-             cr4 = di3 - di4;
-             ci3 = di3 + di4;
-             ch[i - 1 + 5*k*ido] = cc[i - 1 + k*ido] + cr2 + cr3;
-             ch[i + 5*k*ido] = cc[i + k*ido] + ci2 + ci3;
-             tr2 = cc[i - 1 + k*ido] + tr11*cr2 + tr12*cr3;
-             ti2 = cc[i + k*ido] + tr11*ci2 + tr12*ci3;
-             tr3 = cc[i - 1 + k*ido] + tr12*cr2 + tr11*cr3;
-             ti3 = cc[i + k*ido] + tr12*ci2 + tr11*ci3;
-             tr5 = ti11*cr5 + ti12*cr4;
-             ti5 = ti11*ci5 + ti12*ci4;
-             tr4 = ti12*cr5 - ti11*cr4;
-             ti4 = ti12*ci5 - ti11*ci4;
-             ch[i - 1 + (5*k + 2)*ido] = tr2 + tr5;
-             ch[ic - 1 + (5*k + 1)*ido] = tr2 - tr5;
-             ch[i + (5*k + 2)*ido] = ti2 + ti5;
-             ch[ic + (5*k + 1)*ido] = ti5 - ti2;
-             ch[i - 1 + (5*k + 4)*ido] = tr3 + tr4;
-             ch[ic - 1 + (5*k + 3)*ido] = tr3 - tr4;
-             ch[i + (5*k + 4)*ido] = ti3 + ti4;
-             ch[ic + (5*k + 3)*ido] = ti4 - ti3;
-         }
-     }
- } 
- static void
- fftpack_radb5(int          ido,
-               int          l1, 
-               real   cc[], 
-               real   ch[],
-               real   wa1[],
-               real   wa2[], 
-               real   wa3[],
-               real   wa4[])
- {
-     const real tr11 = 0.309016994374947;
-     const real ti11 = 0.951056516295154;
-     const real tr12 = -0.809016994374947;
-     const real ti12 = 0.587785252292473;
-     
-     int i, k, ic;
-     real ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, ti2, ti3,
-         ti4, ti5, dr3, dr4, dr5, dr2, tr2, tr3, tr4, tr5;
-     
-     for (k = 0; k < l1; k++)
-     {
-         ti5 = 2*cc[(5*k + 2)*ido];
-         ti4 = 2*cc[(5*k + 4)*ido];
-         tr2 = 2*cc[ido-1 + (5*k + 1)*ido];
-         tr3 = 2*cc[ido-1 + (5*k + 3)*ido];
-         ch[k*ido] = cc[5*k*ido] + tr2 + tr3;
-         cr2 = cc[5*k*ido] + tr11*tr2 + tr12*tr3;
-         cr3 = cc[5*k*ido] + tr12*tr2 + tr11*tr3;
-         ci5 = ti11*ti5 + ti12*ti4;
-         ci4 = ti12*ti5 - ti11*ti4;
-         ch[(k + l1)*ido] = cr2 - ci5;
-         ch[(k + 2*l1)*ido] = cr3 - ci4;
-         ch[(k + 3*l1)*ido] = cr3 + ci4;
-         ch[(k + 4*l1)*ido] = cr2 + ci5;
-     }
-     if (ido == 1) return;
-     for (k = 0; k < l1; ++k)
-     {
-         for (i = 2; i < ido; i += 2)
-         {
-             ic = ido - i;
-             ti5 = cc[i + (5*k + 2)*ido] + cc[ic + (5*k + 1)*ido];
-             ti2 = cc[i + (5*k + 2)*ido] - cc[ic + (5*k + 1)*ido];
-             ti4 = cc[i + (5*k + 4)*ido] + cc[ic + (5*k + 3)*ido];
-             ti3 = cc[i + (5*k + 4)*ido] - cc[ic + (5*k + 3)*ido];
-             tr5 = cc[i - 1 + (5*k + 2)*ido] - cc[ic - 1 + (5*k + 1)*ido];
-             tr2 = cc[i - 1 + (5*k + 2)*ido] + cc[ic - 1 + (5*k + 1)*ido];
-             tr4 = cc[i - 1 + (5*k + 4)*ido] - cc[ic - 1 + (5*k + 3)*ido];
-             tr3 = cc[i - 1 + (5*k + 4)*ido] + cc[ic - 1 + (5*k + 3)*ido];
-             ch[i - 1 + k*ido] = cc[i - 1 + 5*k*ido] + tr2 + tr3;
-             ch[i + k*ido] = cc[i + 5*k*ido] + ti2 + ti3;
-             cr2 = cc[i - 1 + 5*k*ido] + tr11*tr2 + tr12*tr3;
-             ci2 = cc[i + 5*k*ido] + tr11*ti2 + tr12*ti3;
-             cr3 = cc[i - 1 + 5*k*ido] + tr12*tr2 + tr11*tr3;
-             ci3 = cc[i + 5*k*ido] + tr12*ti2 + tr11*ti3;
-             cr5 = ti11*tr5 + ti12*tr4;
-             ci5 = ti11*ti5 + ti12*ti4;
-             cr4 = ti12*tr5 - ti11*tr4;
-             ci4 = ti12*ti5 - ti11*ti4;
-             dr3 = cr3 - ci4;
-             dr4 = cr3 + ci4;
-             di3 = ci3 + cr4;
-             di4 = ci3 - cr4;
-             dr5 = cr2 + ci5;
-             dr2 = cr2 - ci5;
-             di5 = ci2 - cr5;
-             di2 = ci2 + cr5;
-             ch[i - 1 + (k + l1)*ido] = wa1[i - 2]*dr2 - wa1[i - 1]*di2;
-             ch[i + (k + l1)*ido] = wa1[i - 2]*di2 + wa1[i - 1]*dr2;
-             ch[i - 1 + (k + 2*l1)*ido] = wa2[i - 2]*dr3 - wa2[i - 1]*di3;
-             ch[i + (k + 2*l1)*ido] = wa2[i - 2]*di3 + wa2[i - 1]*dr3;
-             ch[i - 1 + (k + 3*l1)*ido] = wa3[i - 2]*dr4 - wa3[i - 1]*di4;
-             ch[i + (k + 3*l1)*ido] = wa3[i - 2]*di4 + wa3[i - 1]*dr4;
-             ch[i - 1 + (k + 4*l1)*ido] = wa4[i - 2]*dr5 - wa4[i - 1]*di5;
-             ch[i + (k + 4*l1)*ido] = wa4[i - 2]*di5 + wa4[i - 1]*dr5;
-         }
-     }
- } 
- static void 
- fftpack_radfg(int          ido, 
-               int          ip,
-               int          l1, 
-               int          idl1,
-               real   cc[], 
-               real   ch[],
-               real   wa[])
- {
-     const real twopi = 6.28318530717959;
-     int idij, ipph, i, j, k, l, j2, ic, jc, lc, ik, is, nbd;
-     real dc2, ai1, ai2, ar1, ar2, ds2, dcp, arg, dsp, ar1h, ar2h;
-     arg = twopi / ip;
-     dcp = cos(arg);
-     dsp = sin(arg);
-     ipph = (ip + 1) / 2;
-     nbd = (ido - 1) / 2;
-     if (ido != 1)
-     {
-         for (ik=0; ik<idl1; ik++) ch[ik] = cc[ik];
-         for (j=1; j<ip; j++)
-             for (k=0; k<l1; k++)
-                 ch[(k + j*l1)*ido] = cc[(k + j*l1)*ido];
-         if (nbd <= l1) 
-         {
-             is = -ido;
-             for (j=1; j<ip; j++) 
-             {
-                 is += ido;
-                 idij = is-1;
-                 for (i=2; i<ido; i+=2) 
-                 {
-                     idij += 2;
-                     for (k=0; k<l1; k++) 
-                     {
-                         ch[i - 1 + (k + j*l1)*ido] =
-                         wa[idij - 1]*cc[i - 1 + (k + j*l1)*ido] + wa[idij]*cc[i + (k + j*l1)*ido];
-                         ch[i + (k + j*l1)*ido] =
-                             wa[idij - 1]*cc[i + (k + j*l1)*ido] - wa[idij]*cc[i - 1 + (k + j*l1)*ido];
-                     }
-                 }
-             }
-         }
-         else 
-         {
-             is = -ido;
-             for (j=1; j<ip; j++)
-             {
-                 is += ido;
-                 for (k=0; k<l1; k++)
-                 {
-                     idij = is-1;
-                     for (i=2; i<ido; i+=2) 
-                     {
-                         idij += 2;
-                         ch[i - 1 + (k + j*l1)*ido] =
-                             wa[idij - 1]*cc[i - 1 + (k + j*l1)*ido] + wa[idij]*cc[i + (k + j*l1)*ido];
-                         ch[i + (k + j*l1)*ido] =
-                             wa[idij - 1]*cc[i + (k + j*l1)*ido] - wa[idij]*cc[i - 1 + (k + j*l1)*ido];
-                     }
-                 }
-             }
-         }
-         if (nbd >= l1) 
-         {
-             for (j=1; j<ipph; j++) 
-             {
-                 jc = ip - j;
-                 for (k=0; k<l1; k++)
-                 {
-                     for (i=2; i<ido; i+=2) 
-                     {
-                         cc[i - 1 + (k + j*l1)*ido] = ch[i - 1 + (k + j*l1)*ido] + ch[i - 1 + (k + jc*l1)*ido];
-                         cc[i - 1 + (k + jc*l1)*ido] = ch[i + (k + j*l1)*ido] - ch[i + (k + jc*l1)*ido];
-                         cc[i + (k + j*l1)*ido] = ch[i + (k + j*l1)*ido] + ch[i + (k + jc*l1)*ido];
-                         cc[i + (k + jc*l1)*ido] = ch[i - 1 + (k + jc*l1)*ido] - ch[i - 1 + (k + j*l1)*ido];
-                     }
-                 }
-             }
-         }
-         else 
-         {
-             for (j=1; j<ipph; j++) 
-             {
-                 jc = ip - j;
-                 for (i=2; i<ido; i+=2)
-                 {
-                     for (k=0; k<l1; k++)
-                     {
-                         cc[i - 1 + (k + j*l1)*ido] =
-                         ch[i - 1 + (k + j*l1)*ido] + ch[i - 1 + (k + jc*l1)*ido];
-                         cc[i - 1 + (k + jc*l1)*ido] = ch[i + (k + j*l1)*ido] - ch[i + (k + jc*l1)*ido];
-                         cc[i + (k + j*l1)*ido] = ch[i + (k + j*l1)*ido] + ch[i + (k + jc*l1)*ido];
-                         cc[i + (k + jc*l1)*ido] = ch[i - 1 + (k + jc*l1)*ido] - ch[i - 1 + (k + j*l1)*ido];
-                     }
-                 }
-             }
-         }
-     }
-     else
-     {
-         for (ik=0; ik<idl1; ik++) 
-             cc[ik] = ch[ik];
-     }
-     for (j=1; j<ipph; j++)
-     {
-         jc = ip - j;
-         for (k=0; k<l1; k++) 
-         {
-             cc[(k + j*l1)*ido] = ch[(k + j*l1)*ido] + ch[(k + jc*l1)*ido];
-             cc[(k + jc*l1)*ido] = ch[(k + jc*l1)*ido] - ch[(k + j*l1)*ido];
-         }
-     }
-     
-     ar1 = 1;
-     ai1 = 0;
-     for (l=1; l<ipph; l++) 
-     {
-         lc = ip - l;
-         ar1h = dcp*ar1 - dsp*ai1;
-         ai1 = dcp*ai1 + dsp*ar1;
-         ar1 = ar1h;
-         for (ik=0; ik<idl1; ik++) 
-         {
-             ch[ik + l*idl1] = cc[ik] + ar1*cc[ik + idl1];
-             ch[ik + lc*idl1] = ai1*cc[ik + (ip-1)*idl1];
-         }
-         dc2 = ar1;
-         ds2 = ai1;
-         ar2 = ar1;
-         ai2 = ai1;
-         for (j=2; j<ipph; j++)
-         {
-             jc = ip - j;
-             ar2h = dc2*ar2 - ds2*ai2;
-             ai2 = dc2*ai2 + ds2*ar2;
-             ar2 = ar2h;
-             for (ik=0; ik<idl1; ik++) 
-             {
-                 ch[ik + l*idl1] += ar2*cc[ik + j*idl1];
-                 ch[ik + lc*idl1] += ai2*cc[ik + jc*idl1];
-             }
-         }
-     }
-     for (j=1; j<ipph; j++)
-         for (ik=0; ik<idl1; ik++)
-             ch[ik] += cc[ik + j*idl1];
-     
-     if (ido >= l1) 
-     {
-         for (k=0; k<l1; k++) 
-         {
-             for (i=0; i<ido; i++) 
-             {
-                 cc[i + k*ip*ido] = ch[i + k*ido];
-             }
-         }
-     } 
-     else
-     {
-         for (i=0; i<ido; i++)
-         {
-             for (k=0; k<l1; k++)
-             {
-                 cc[i + k*ip*ido] = ch[i + k*ido];
-             }
-         }
-     }
-     for (j=1; j<ipph; j++)
-     {
-         jc = ip - j;
-         j2 = 2*j;
-         for (k=0; k<l1; k++)
-         {
-             cc[ido-1 + (j2 - 1 + k*ip)*ido] = ch[(k + j*l1)*ido];
-             cc[(j2 + k*ip)*ido] = ch[(k + jc*l1)*ido];
-         }
-     }
-     if (ido == 1) return;
-     if (nbd >= l1)
-     {
-         for (j=1; j<ipph; j++) 
-         {
-             jc = ip - j;
-             j2 = 2*j;
-             for (k=0; k<l1; k++)
-             {
-                 for (i=2; i<ido; i+=2)
-                 {
-                     ic = ido - i;
-                     cc[i - 1 + (j2 + k*ip)*ido] = ch[i - 1 + (k + j*l1)*ido] + ch[i - 1 + (k + jc*l1)*ido];
-                     cc[ic - 1 + (j2 - 1 + k*ip)*ido] = ch[i - 1 + (k + j*l1)*ido] - ch[i - 1 + (k + jc*l1)*ido];
-                     cc[i + (j2 + k*ip)*ido] = ch[i + (k + j*l1)*ido] + ch[i + (k + jc*l1)*ido];
-                     cc[ic + (j2 - 1 + k*ip)*ido] = ch[i + (k + jc*l1)*ido] - ch[i + (k + j*l1)*ido];
-                 }
-             }
-         }
-     }
-     else
-     {
-         for (j=1; j<ipph; j++)
-         {
-             jc = ip - j;
-             j2 = 2*j;
-             for (i=2; i<ido; i+=2) 
-             {
-                 ic = ido - i;
-                 for (k=0; k<l1; k++)
-                 {
-                     cc[i - 1 + (j2 + k*ip)*ido] = ch[i - 1 + (k + j*l1)*ido] + ch[i - 1 + (k + jc*l1)*ido];
-                     cc[ic - 1 + (j2 - 1 + k*ip)*ido] = ch[i - 1 + (k + j*l1)*ido] - ch[i - 1 + (k + jc*l1)*ido];
-                     cc[i + (j2 + k*ip)*ido] = ch[i + (k + j*l1)*ido] + ch[i + (k + jc*l1)*ido];
-                     cc[ic + (j2 - 1 + k*ip)*ido] = ch[i + (k + jc*l1)*ido] - ch[i + (k + j*l1)*ido];
-                 }
-             }
-         }
-     }
- } 
- static void 
- fftpack_radbg(int          ido,
-               int          ip, 
-               int          l1, 
-               int          idl1,
-               real   cc[],
-               real   ch[],
-               real   wa[])
- {
-     const real twopi = 6.28318530717959;
-     int idij, ipph, i, j, k, l, j2, ic, jc, lc, ik, is;
-     real dc2, ai1, ai2, ar1, ar2, ds2;
-     int nbd;
-     real dcp, arg, dsp, ar1h, ar2h;
-     arg = twopi / ip;
-     dcp = cos(arg);
-     dsp = sin(arg);
-     nbd = (ido - 1) / 2;
-     ipph = (ip + 1) / 2;
-     
-     if (ido >= l1) 
-     {
-         for (k=0; k<l1; k++) 
-         {
-             for (i=0; i<ido; i++)
-             {
-                 ch[i + k*ido] = cc[i + k*ip*ido];
-             }
-         }
-     }
-     else 
-     {
-         for (i=0; i<ido; i++) 
-         {
-             for (k=0; k<l1; k++)
-             {
-                 ch[i + k*ido] = cc[i + k*ip*ido];
-             }
-         }
-     }
-     for (j=1; j<ipph; j++)
-     {
-         jc = ip - j;
-         j2 = 2*j;
-         for (k=0; k<l1; k++) 
-         {
-             ch[(k + j*l1)*ido] = cc[ido-1 + (j2 - 1 + k*ip)*ido] + cc[ido-1 + (j2 - 1 + k*ip)*ido];
-             ch[(k + jc*l1)*ido] = cc[(j2 + k*ip)*ido] + cc[(j2 + k*ip)*ido];
-         }
-     }
-     
-     if (ido != 1) 
-     {
-         if (nbd >= l1)
-         {
-             for (j=1; j<ipph; j++) 
-             {
-                 jc = ip - j;
-                 for (k=0; k<l1; k++)
-                 {
-                     for (i=2; i<ido; i+=2) 
-                     {
-                         ic = ido - i;
-                         ch[i - 1 + (k + j*l1)*ido] = cc[i - 1 + (2*j + k*ip)*ido] +  cc[ic - 1 + (2*j - 1 + k*ip)*ido];
-                         ch[i - 1 + (k + jc*l1)*ido] = cc[i - 1 + (2*j + k*ip)*ido] - cc[ic - 1 + (2*j - 1 + k*ip)*ido];
-                         ch[i + (k + j*l1)*ido] = cc[i + (2*j + k*ip)*ido] - cc[ic + (2*j - 1 + k*ip)*ido];
-                         ch[i + (k + jc*l1)*ido] = cc[i + (2*j + k*ip)*ido] + cc[ic + (2*j - 1 + k*ip)*ido];
-                     }
-                 }
-             }
-         }
-         else 
-         {
-             for (j=1; j<ipph; j++) 
-             {
-                 jc = ip - j;
-                 for (i=2; i<ido; i+=2) 
-                 {
-                     ic = ido - i;
-                     for (k=0; k<l1; k++) 
-                     {
-                         ch[i - 1 + (k + j*l1)*ido] = cc[i - 1 + (2*j + k*ip)*ido] + cc[ic - 1 + (2*j - 1 + k*ip)*ido];
-                         ch[i - 1 + (k + jc*l1)*ido] = cc[i - 1 + (2*j + k*ip)*ido] - cc[ic - 1 + (2*j - 1 + k*ip)*ido];
-                         ch[i + (k + j*l1)*ido] = cc[i + (2*j + k*ip)*ido] - cc[ic + (2*j - 1 + k*ip)*ido];
-                         ch[i + (k + jc*l1)*ido] = cc[i + (2*j + k*ip)*ido] + cc[ic + (2*j - 1 + k*ip)*ido];
-                     }
-                 }
-             }
-         }
-     }
-     
-     ar1 = 1;
-     ai1 = 0;
-     for (l=1; l<ipph; l++)
-     {
-         lc = ip - l;
-         ar1h = dcp*ar1 - dsp*ai1;
-         ai1 = dcp*ai1 + dsp*ar1;
-         ar1 = ar1h;
-         for (ik=0; ik<idl1; ik++) 
-         {
-             cc[ik + l*idl1] = ch[ik] + ar1*ch[ik + idl1];
-             cc[ik + lc*idl1] = ai1*ch[ik + (ip-1)*idl1];
-         }
-         dc2 = ar1;
-         ds2 = ai1;
-         ar2 = ar1;
-         ai2 = ai1;
-         for (j=2; j<ipph; j++)
-         {
-             jc = ip - j;
-             ar2h = dc2*ar2 - ds2*ai2;
-             ai2 = dc2*ai2 + ds2*ar2;
-             ar2 = ar2h;
-             for (ik=0; ik<idl1; ik++) 
-             {
-                 cc[ik + l*idl1] += ar2*ch[ik + j*idl1];
-                 cc[ik + lc*idl1] += ai2*ch[ik + jc*idl1];
-             }
-         }
-     }
-     for (j=1; j<ipph; j++) 
-     {
-         for (ik=0; ik<idl1; ik++) 
-         {
-             ch[ik] += ch[ik + j*idl1];
-         }
-     }
-     for (j=1; j<ipph; j++) 
-     {
-         jc = ip - j;
-         for (k=0; k<l1; k++) 
-         {
-             ch[(k + j*l1)*ido] = cc[(k + j*l1)*ido] - cc[(k + jc*l1)*ido];
-             ch[(k + jc*l1)*ido] = cc[(k + j*l1)*ido] + cc[(k + jc*l1)*ido];
-         }
-     }
-     
-     if (ido == 1) return;
-     if (nbd >= l1) 
-     {
-         for (j=1; j<ipph; j++) 
-         {
-             jc = ip - j;
-             for (k=0; k<l1; k++) 
-             {
-                 for (i=2; i<ido; i+=2)
-                 {
-                     ch[i - 1 + (k + j*l1)*ido] = cc[i - 1 + (k + j*l1)*ido] - cc[i + (k + jc*l1)*ido];
-                     ch[i - 1 + (k + jc*l1)*ido] = cc[i - 1 + (k + j*l1)*ido] + cc[i + (k + jc*l1)*ido];
-                     ch[i + (k + j*l1)*ido] = cc[i + (k + j*l1)*ido] + cc[i - 1 + (k + jc*l1)*ido];
-                     ch[i + (k + jc*l1)*ido] = cc[i + (k + j*l1)*ido] - cc[i - 1 + (k + jc*l1)*ido];
-                 }
-             }
-         }
-     }
-     else
-     {
-         for (j=1; j<ipph; j++) 
-         {
-             jc = ip - j;
-             for (i=2; i<ido; i+=2)
-             {
-                 for (k=0; k<l1; k++)
-                 {
-                     ch[i - 1 + (k + j*l1)*ido] = cc[i - 1 + (k + j*l1)*ido] - cc[i + (k + jc*l1)*ido];
-                     ch[i - 1 + (k + jc*l1)*ido] = cc[i - 1 + (k + j *l1)*ido] + cc[i + (k + jc*l1)*ido];
-                     ch[i + (k + j*l1)*ido] = cc[i + (k + j*l1)*ido] + cc[i - 1 + (k + jc*l1)*ido];
-                     ch[i + (k + jc*l1)*ido] = cc[i + (k + j*l1)*ido] - cc[i - 1 + (k + jc*l1)*ido];
-                 }
-             }
-         }
-     }
-     for (ik=0; ik<idl1; ik++)
-     {
-         cc[ik] = ch[ik];
-     }
-     for (j=1; j<ip; j++)
-         for (k=0; k<l1; k++)
-             cc[(k + j*l1)*ido] = ch[(k + j*l1)*ido];
-     if (nbd <= l1) 
-     {
-         is = -ido;
-         for (j=1; j<ip; j++)
-         {
-             is += ido;
-             idij = is-1;
-             for (i=2; i<ido; i+=2)
-             {
-                 idij += 2;
-                 for (k=0; k<l1; k++) 
-                 {
-                     cc[i - 1 + (k + j*l1)*ido] = wa[idij - 1]*ch[i - 1 + (k + j*l1)*ido] - wa[idij]*ch[i + (k + j*l1)*ido];
-                     cc[i + (k + j*l1)*ido] = wa[idij - 1]*ch[i + (k + j*l1)*ido] + wa[idij]*ch[i - 1 + (k + j*l1)*ido];
-                 }
-             }
-         }
-     }
-     else
-     {
-         is = -ido;
-         for (j=1; j<ip; j++) 
-         {
-             is += ido;
-             for (k=0; k<l1; k++)
-             {
-                 idij = is;
-                 for (i=2; i<ido; i+=2)
-                 {
-                     idij += 2;
-                     cc[i - 1 + (k + j*l1)*ido] = wa[idij-1]*ch[i - 1 + (k + j*l1)*ido] - wa[idij]*ch[i + (k + j*l1)*ido];
-                     cc[i + (k + j*l1)*ido] = wa[idij-1]*ch[i + (k + j*l1)*ido] + wa[idij]*ch[i - 1 + (k + j*l1)*ido];
-                 }
-             }
-         }
-     }
- } 
- static void 
- fftpack_cfftf1(int          n,
-                real   c[],
-                real   ch[],
-                real   wa[],
-                int          ifac[15],
-                int          isign)
- {
-     int idot, i;
-     int k1, l1, l2;
-     int na, nf, ip, iw, ix2, ix3, ix4, nac, ido, idl1;
-     real *cinput, *coutput;
-     nf = ifac[1];
-     na = 0;
-     l1 = 1;
-     iw = 0;
-     
-     for (k1=2; k1<=nf+1; k1++) 
-     {
-         ip = ifac[k1];
-         l2 = ip*l1;
-         ido = n / l2;
-         idot = ido + ido;
-         idl1 = idot*l1;
-         if (na) 
-         {
-             cinput = ch;
-             coutput = c;
-         }
-         else 
-         {
-             cinput = c;
-             coutput = ch;
-         }
-         switch (ip) 
-         {
-             case 4:
-                 ix2 = iw + idot;
-                 ix3 = ix2 + idot;
-                 fftpack_passf4(idot, l1, cinput, coutput, &wa[iw], &wa[ix2], &wa[ix3], isign);
-                 na = !na;
-                 break;
-             case 2:
-                 fftpack_passf2(idot, l1, cinput, coutput, &wa[iw], isign);
-                 na = !na;
-                 break;
-             case 3:
-                 ix2 = iw + idot;
-                 fftpack_passf3(idot, l1, cinput, coutput, &wa[iw], &wa[ix2], isign);
-                 na = !na;
-                 break;
-             case 5:
-                 ix2 = iw + idot;
-                 ix3 = ix2 + idot;
-                 ix4 = ix3 + idot;
-                 fftpack_passf5(idot, l1, cinput, coutput, &wa[iw], &wa[ix2], &wa[ix3], &wa[ix4], isign);
-                 na = !na;
-                 break;
-             default:
-                 fftpack_passf(&nac, idot, ip, l1, idl1, cinput, coutput, &wa[iw], isign);
-                 if (nac != 0) na = !na;
-         }
-         l1 = l2;
-         iw += (ip - 1)*idot;
-     }
-     if (na == 0) 
-         return;
-     for (i=0; i<2*n; i++) 
-         c[i] = ch[i];
- }
- void
- fftpack_cfftf(int          n, 
-               real   c[], 
-               real   wsave[])
- {
-     int iw1, iw2;
-     
-     if (n == 1)
-         return;
-     iw1 = 2*n;
-     iw2 = iw1 + 2*n;
-     fftpack_cfftf1(n, c, wsave, wsave+iw1, (int*)(wsave+iw2), -1);
- } 
- void 
- fftpack_cfftb(int          n, 
-               real   c[], 
-               real   wsave[])
- {
-     int iw1, iw2;
-     
-     if (n == 1)
-         return;
-     iw1 = 2*n;
-     iw2 = iw1 + 2*n;
-     fftpack_cfftf1(n, c, wsave, wsave+iw1, (int*)(wsave+iw2), +1);
- } 
- static void 
- fftpack_factorize(int    n,
-                   int    ifac[15])
- {
-     static const int ntryh[4] = { 3,4,2,5 };
-     int ntry=3, i, j=0, ib, nf=0, nl=n, nq, nr;
- startloop:
-     if (j < 4)
-         ntry = ntryh[j];
-     else
-         ntry+= 2;
-     j++;
-     do 
-     {
-         nq = nl / ntry;
-         nr = nl - ntry*nq;
-         if (nr != 0) goto startloop;
-         nf++;
-         ifac[nf + 1] = ntry;
-         nl = nq;
-         if (ntry == 2 && nf != 1) 
-         {
-             for (i=2; i<=nf; i++) 
-             {
-                 ib = nf - i + 2;
-                 ifac[ib + 1] = ifac[ib];
-             }
-             ifac[2] = 2;
-         }
-     } 
-     while (nl != 1);
-     ifac[0] = n;
-     ifac[1] = nf;
- }
- static void
- fftpack_cffti1(int          n, 
-                real   wa[], 
-                int          ifac[15])
- {
-     const real twopi = 6.28318530717959;
-     real arg, argh, argld, fi;
-     int idot, i, j;
-     int i1, k1, l1, l2;
-     int ld, ii, nf, ip;
-     int ido, ipm;
-     fftpack_factorize(n,ifac);
-     nf = ifac[1];
-     argh = twopi/(real)n;
-     i = 1;
-     l1 = 1;
-     for (k1=1; k1<=nf; k1++) 
-     {
-         ip = ifac[k1+1];
-         ld = 0;
-         l2 = l1*ip;
-         ido = n / l2;
-         idot = ido + ido + 2;
-         ipm = ip - 1;
-         for (j=1; j<=ipm; j++)
-         {
-             i1 = i;
-             wa[i-1] = 1;
-             wa[i] = 0;
-             ld += l1;
-             fi = 0;
-             argld = ld*argh;
-             for (ii=4; ii<=idot; ii+=2) 
-             {
-                 i+= 2;
-                 fi+= 1;
-                 arg = fi*argld;
-                 wa[i-1] = cos(arg);
-                 wa[i] = sin(arg);
-             }
-             if (ip > 5) 
-             {
-                 wa[i1-1] = wa[i-1];
-                 wa[i1] = wa[i];
-             }
-         }
-         l1 = l2;
-     }
- } 
- static void 
- fftpack_rfftf1(int n, 
-                real   c[],
-                real   ch[], 
-                real   wa[], 
-                int          ifac[15])
- {
-     int i;
-     int k1, l1, l2, na, kh, nf, ip, iw, ix2, ix3, ix4, ido, idl1;
-     real *cinput, *coutput;
-     nf = ifac[1];
-     na = 1;
-     l2 = n;
-     iw = n-1;
-     for (k1 = 1; k1 <= nf; ++k1) 
-     {
-         kh = nf - k1;
-         ip = ifac[kh + 2];
-         l1 = l2 / ip;
-         ido = n / l2;
-         idl1 = ido*l1;
-         iw -= (ip - 1)*ido;
-         na = !na;
-         if (na) 
-         {
-             cinput = ch;
-             coutput = c;
-         }
-         else 
-         {
-             cinput = c;
-             coutput = ch;
-         }
-       switch (ip) 
-       {
-           case 4:
-               ix2 = iw + ido;
-               ix3 = ix2 + ido;
-               fftpack_radf4(ido, l1, cinput, coutput, &wa[iw], &wa[ix2], &wa[ix3]);
-               break;
-           case 2:
-               fftpack_radf2(ido, l1, cinput, coutput, &wa[iw]);
-               break;
-           case 3:
-               ix2 = iw + ido;
-               fftpack_radf3(ido, l1, cinput, coutput, &wa[iw], &wa[ix2]);
-               break;
-           case 5:
-               ix2 = iw + ido;
-               ix3 = ix2 + ido;
-               ix4 = ix3 + ido;
-               fftpack_radf5(ido, l1, cinput, coutput, &wa[iw], &wa[ix2], &wa[ix3], &wa[ix4]);
-               break;
-           default:
-               if (ido == 1)
-                   na = !na;
-               if (na == 0)
-               {
-                   fftpack_radfg(ido, ip, l1, idl1, c, ch, &wa[iw]);
-                   na = 1;
-               }
-                   else 
-                   {
-                       fftpack_radfg(ido, ip, l1, idl1, ch, c, &wa[iw]);
-                       na = 0;
-                   }
-       }
-         l2 = l1;
-     }
-     if (na == 1)
-         return;
-     for (i = 0; i < n; i++)
-         c[i] = ch[i];
- } 
- static void 
- fftpack_rfftb1(int          n, 
-                real   c[],
-                real   ch[], 
-                real   wa[], 
-                int          ifac[15])
- {
-     int i;
-     int k1, l1, l2, na, nf, ip, iw, ix2, ix3, ix4, ido, idl1;
-     real *cinput, *coutput;
-     nf = ifac[1];
-     na = 0;
-     l1 = 1;
-     iw = 0;
-     
-     for (k1=1; k1<=nf; k1++) 
-     {
-         ip = ifac[k1 + 1];
-         l2 = ip*l1;
-         ido = n / l2;
-         idl1 = ido*l1;
-         if (na) 
-         {
-             cinput = ch;
-             coutput = c;
-         }
-         else 
-         {
-             cinput = c;
-             coutput = ch;
-         }
-         switch (ip) 
-         {
-             case 4:
-                 ix2 = iw + ido;
-                 ix3 = ix2 + ido;
-                 fftpack_radb4(ido, l1, cinput, coutput, &wa[iw], &wa[ix2], &wa[ix3]);
-                 na = !na;
-                 break;
-             case 2:
-                 fftpack_radb2(ido, l1, cinput, coutput, &wa[iw]);
-                 na = !na;
-                 break;
-             case 3:
-                 ix2 = iw + ido;
-                 fftpack_radb3(ido, l1, cinput, coutput, &wa[iw], &wa[ix2]);
-                 na = !na;
-                 break;
-             case 5:
-                 ix2 = iw + ido;
-                 ix3 = ix2 + ido;
-                 ix4 = ix3 + ido;
-                 fftpack_radb5(ido, l1, cinput, coutput, &wa[iw], &wa[ix2], &wa[ix3], &wa[ix4]);
-                 na = !na;
-                 break;
-             default:
-                 fftpack_radbg(ido, ip, l1, idl1, cinput, coutput, &wa[iw]);
-                 if (ido == 1) na = !na;
-         }
-         l1 = l2;
-         iw += (ip - 1)*ido;
-     }
-     if (na == 0) 
-         return;
-     for (i=0; i<n; i++) 
-         c[i] = ch[i];
- } 
- static void
- fftpack_rffti1(int          n, 
-                real         wa[], 
-                int          ifac[15])
- {
-     const real twopi = 6.28318530717959;
-     real arg, argh, argld, fi;
-     int i, j;
-     int k1, l1, l2;
-     int ld, ii, nf, ip, is;
-     int ido, ipm, nfm1;
-     fftpack_factorize(n,ifac);
-     nf = ifac[1];
-     argh = twopi / n;
-     is = 0;
-     nfm1 = nf - 1;
-     l1 = 1;
-     if (nfm1 == 0) return;
-     for (k1 = 1; k1 <= nfm1; k1++) 
-     {
-         ip = ifac[k1 + 1];
-         ld = 0;
-         l2 = l1*ip;
-         ido = n / l2;
-         ipm = ip - 1;
-         for (j = 1; j <= ipm; ++j) 
-         {
-             ld += l1;
-             i = is;
-             argld = (real) ld*argh;
-             fi = 0;
-             for (ii = 3; ii <= ido; ii += 2) 
-             {
-                 i += 2;
-                 fi += 1;
-                 arg = fi*argld;
-                 wa[i - 2] = cos(arg);
-                 wa[i - 1] = sin(arg);
-             }
-             is += ido;
-         }
-         l1 = l2;
-     }
- } 
- /* End of fftpack - begin GROMACS code */
++#include "external/fftpack/fftpack.h"
 +
 +/** Contents of the FFTPACK fft datatype. 
 + *
 + *  FFTPACK only does 1d transforms, so we use a pointers to another fft for 
 + *  the transform in the next dimension.
 + * Thus, a 3d-structure contains a pointer to a 2d one, which in turns contains
 + * a pointer to a 1d. The 1d structure has next==NULL.
 + */
 +struct gmx_fft
 +{
 +    int            ndim;     /**< Dimensions, including our subdimensions.  */
 +    int            n;        /**< Number of points in this dimension.       */
 +    int            ifac[15]; /**< 15 bytes needed for cfft and rfft         */
 +    struct gmx_fft *next;    /**< Pointer to next dimension, or NULL.       */
 +    real *         work;     /**< 1st 4n reserved for cfft, 1st 2n for rfft */
 +};
 +
 +#include <math.h>
 +#include <stdio.h>
 +
 +
- #else
- int
- gmx_fft_fftpack_empty;
 +int
 +gmx_fft_init_1d(gmx_fft_t *        pfft,
 +                int                nx,
 +                int                flags)
 +{
 +    gmx_fft_t    fft;
 +   
 +    if(pfft==NULL)
 +    {
 +        gmx_fatal(FARGS,"Invalid FFT opaque type pointer.");
 +        return EINVAL;
 +    }
 +    *pfft = NULL;
 +    
 +    if( (fft = (struct gmx_fft *)malloc(sizeof(struct gmx_fft))) == NULL)
 +    {
 +        return ENOMEM;
 +    }    
 +        
 +    fft->next = NULL;
 +    fft->n    = nx;
 +    
 +    /* Need 4*n storage for 1D complex FFT */
 +    if( (fft->work = (real *)malloc(sizeof(real)*(4*nx))) == NULL) 
 +    {
 +        free(fft);
 +        return ENOMEM;
 +    }
 +
 +    if(fft->n>1)
 +        fftpack_cffti1(nx,fft->work,fft->ifac);
 +    
 +    *pfft = fft;
 +    return 0;
 +};
 +
 +
 +
 +int
 +gmx_fft_init_1d_real(gmx_fft_t *        pfft,
 +                     int                nx,
 +                     int                flags)
 +{
 +    gmx_fft_t    fft;
 +    
 +    if(pfft==NULL)
 +    {
 +        gmx_fatal(FARGS,"Invalid FFT opaque type pointer.");
 +        return EINVAL;
 +    }
 +    *pfft = NULL;
 +
 +    if( (fft = (struct gmx_fft *)malloc(sizeof(struct gmx_fft))) == NULL)
 +    {
 +        return ENOMEM;
 +    }    
 +
 +    fft->next = NULL;
 +    fft->n    = nx;
 +
 +    /* Need 2*n storage for 1D real FFT */
 +    if((fft->work = (real *)malloc(sizeof(real)*(2*nx)))==NULL) 
 +    {
 +        free(fft);
 +        return ENOMEM;
 +    }  
 +    
 +    if(fft->n>1)
 +        fftpack_rffti1(nx,fft->work,fft->ifac);
 +    
 +    *pfft = fft;
 +    return 0;
 +}
 +
 +
 +
 +int
 +gmx_fft_init_2d(gmx_fft_t *        pfft,
 +                int                nx,
 +                int                ny,
 +                int                flags)
 +{
 +    gmx_fft_t     fft;
 +    int           rc;
 +    
 +    if(pfft==NULL)
 +    {
 +        gmx_fatal(FARGS,"Invalid FFT opaque type pointer.");
 +        return EINVAL;
 +    }
 +    *pfft = NULL;
 +
 +    /* Create the X transform */
 +    if( (rc = gmx_fft_init_1d(&fft,nx,flags)) != 0)
 +    {
 +        return rc;
 +    }    
 +    
 +    /* Create Y transform as a link from X */
 +    if( (rc=gmx_fft_init_1d(&(fft->next),ny,flags)) != 0)
 +    {
 +        free(fft);
 +        return rc;
 +    }
 +    
 +    *pfft = fft;
 +    return 0;
 +};
 +
 +
 +int
 +gmx_fft_init_2d_real(gmx_fft_t *        pfft,
 +                     int                nx,
 +                     int                ny,
 +                     int                flags)
 +{
 +    gmx_fft_t     fft;
 +    int           nyc = (ny/2 + 1);
 +    int           rc;
 +    
 +    if(pfft==NULL)
 +    {
 +        gmx_fatal(FARGS,"Invalid FFT opaque type pointer.");
 +        return EINVAL;
 +    }
 +    *pfft = NULL;
 +    
 +    /* Create the X transform */
 +    if( (fft = (struct gmx_fft *)malloc(sizeof(struct gmx_fft))) == NULL)
 +    {
 +        return ENOMEM;
 +    }    
 +    
 +    fft->n    = nx;
 +    
 +    /* Need 4*nx storage for 1D complex FFT, and another
 +     * 2*nx*nyc elements for complex-to-real storage in our high-level routine.
 +     */
 +    if( (fft->work = (real *)malloc(sizeof(real)*(4*nx+2*nx*nyc))) == NULL) 
 +    {
 +        free(fft);
 +        return ENOMEM;
 +    }
 +    fftpack_cffti1(nx,fft->work,fft->ifac);
 +    
 +    /* Create real Y transform as a link from X */
 +    if( (rc=gmx_fft_init_1d_real(&(fft->next),ny,flags)) != 0)
 +    {
 +        free(fft);
 +        return rc;
 +    }
 +
 +    *pfft = fft;
 +    return 0;
 +}
 +
 +
 +int
 +gmx_fft_init_3d(gmx_fft_t *        pfft,
 +                int                nx,
 +                int                ny,
 +                int                nz,
 +                int                flags)
 +{
 +    gmx_fft_t     fft;
 +    int           rc;
 +    
 +    if(pfft==NULL)
 +    {
 +        gmx_fatal(FARGS,"Invalid FFT opaque type pointer.");
 +        return EINVAL;
 +    }
 +    *pfft = NULL;
 +
 +    /* Create the X transform */
 +
 +    if( (fft = (struct gmx_fft *)malloc(sizeof(struct gmx_fft))) == NULL)
 +    {
 +        return ENOMEM;
 +    }    
 +
 +    fft->n    = nx;
 +    
 +    /* Need 4*nx storage for 1D complex FFT, and another
 +     * 2*nz elements for gmx_fft_transpose_2d_nelem() storage.
 +     */
 +    if( (fft->work = (real *)malloc(sizeof(real)*(4*nx+2*nz))) == NULL) 
 +    {
 +        free(fft);
 +        return ENOMEM;
 +    }
 +    
 +    fftpack_cffti1(nx,fft->work,fft->ifac);
 +
 +    
 +    /* Create 2D Y/Z transforms as a link from X */
 +    if( (rc=gmx_fft_init_2d(&(fft->next),ny,nz,flags)) != 0)
 +    {
 +        free(fft);
 +        return rc;
 +    }
 +    
 +    *pfft = fft;
 +    return 0;
 +};
 +
 +
 +int
 +gmx_fft_init_3d_real(gmx_fft_t *        pfft,
 +                     int                nx,
 +                     int                ny,
 +                     int                nz,
 +                     int                flags)
 +{
 +    gmx_fft_t     fft;
 +    int           nzc = (nz/2 + 1);
 +    int           rc;
 +    
 +    if(pfft==NULL)
 +    {
 +        gmx_fatal(FARGS,"Invalid FFT opaque type pointer.");
 +        return EINVAL;
 +    }
 +    *pfft = NULL;
 +        
 +    /* Create the X transform */
 +    if( (fft = (struct gmx_fft *)malloc(sizeof(struct gmx_fft))) == NULL)
 +    {
 +        return ENOMEM;
 +    }    
 +    
 +    fft->n    = nx;
 +
 +    /* Need 4*nx storage for 1D complex FFT, another
 +     * 2*nx*ny*nzc elements to copy the entire 3D matrix when
 +     * doing out-of-place complex-to-real FFTs, and finally
 +     * 2*nzc elements for transpose work space.
 +     */
 +    if( (fft->work = (real *)malloc(sizeof(real)*(4*nx+2*nx*ny*nzc+2*nzc))) == NULL) 
 +    {
 +        free(fft);
 +        return ENOMEM;
 +    }
 +    fftpack_cffti1(nx,fft->work,fft->ifac);
 +    
 +    /* Create 2D real Y/Z transform as a link from X */
 +    if( (rc=gmx_fft_init_2d_real(&(fft->next),ny,nz,flags)) != 0)
 +    {
 +        free(fft);
 +        return rc;
 +    }
 +    
 +    *pfft = fft;
 +    return 0;
 +}
 +
 +
 +int 
 +gmx_fft_1d               (gmx_fft_t                  fft,
 +                          enum gmx_fft_direction     dir,
 +                          void *                     in_data,
 +                          void *                     out_data)
 +{
 +    int             i,n;
 +    real *    p1;
 +    real *    p2;
 +
 +    n=fft->n;
 +
 +    if(n==1)
 +    {
 +        p1 = (real *)in_data;
 +        p2 = (real *)out_data;        
 +        p2[0] = p1[0];
 +        p2[1] = p1[1];
 +    }
 +    
 +    /* FFTPACK only does in-place transforms, so emulate out-of-place
 +     * by copying data to the output array first.
 +     */
 +    if( in_data != out_data )
 +    {
 +        p1 = (real *)in_data;
 +        p2 = (real *)out_data;
 +        
 +        /* n complex = 2*n real elements */
 +        for(i=0;i<2*n;i++)
 +        {
 +            p2[i] = p1[i];
 +        }
 +    }
 +  
 +    /* Elements 0   .. 2*n-1 in work are used for ffac values,
 +     * Elements 2*n .. 4*n-1 are internal FFTPACK work space.
 +     */
 +    
 +    if(dir == GMX_FFT_FORWARD) 
 +    {
 +        fftpack_cfftf1(n,(real *)out_data,fft->work+2*n,fft->work,fft->ifac, -1);
 +    }
 +    else if(dir == GMX_FFT_BACKWARD)
 +    {
 +        fftpack_cfftf1(n,(real *)out_data,fft->work+2*n,fft->work,fft->ifac, 1); 
 +    }
 +    else
 +    {
 +        gmx_fatal(FARGS,"FFT plan mismatch - bad plan or direction.");
 +        return EINVAL;
 +    }    
 +
 +    return 0;
 +}
 +
 +
 +
 +int 
 +gmx_fft_1d_real          (gmx_fft_t                  fft,
 +                          enum gmx_fft_direction     dir,
 +                          void *                     in_data,
 +                          void *                     out_data)
 +{
 +    int           i,n;
 +    real *  p1;
 +    real *  p2;
 +
 +    n = fft->n;
 +    
 +    if(n==1)
 +    {
 +        p1 = (real *)in_data;
 +        p2 = (real *)out_data;        
 +        p2[0] = p1[0];
 +        if(dir == GMX_FFT_REAL_TO_COMPLEX)
 +            p2[1] = 0.0;
 +    }
 +    
 +    if(dir == GMX_FFT_REAL_TO_COMPLEX)
 +    {
 +        /* FFTPACK only does in-place transforms, so emulate out-of-place
 +         * by copying data to the output array first. This works fine, since
 +         * the complex array must be larger than the real.
 +         */
 +        if( in_data != out_data )
 +        {
 +            p1 = (real *)in_data;
 +            p2 = (real *)out_data;
 +            
 +            for(i=0;i<2*(n/2+1);i++)
 +            {
 +                p2[i] = p1[i];
 +            }
 +        }
 +
 +        /* Elements 0 ..   n-1 in work are used for ffac values,
 +         * Elements n .. 2*n-1 are internal FFTPACK work space.
 +         */
 +        fftpack_rfftf1(n,(real *)out_data,fft->work+n,fft->work,fft->ifac);
 +
 +        /*
 +         * FFTPACK has a slightly more compact storage than we, time to 
 +         * convert it: ove most of the array one step up to make room for 
 +         * zero imaginary parts. 
 +         */
 +        p2 = (real *)out_data;
 +        for(i=n-1;i>0;i--)
 +        {
 +            p2[i+1] = p2[i];
 +        }
 +        /* imaginary zero freq. */
 +        p2[1] = 0; 
 +        
 +        /* Is n even? */
 +        if( (n & 0x1) == 0 )
 +        {
 +            p2[n+1] = 0;
 +        }
 +        
 +    }
 +    else if(dir == GMX_FFT_COMPLEX_TO_REAL)
 +    {
 +        /* FFTPACK only does in-place transforms, and we cannot just copy
 +         * input to output first here since our real array is smaller than
 +         * the complex one. However, since the FFTPACK complex storage format 
 +         * is more compact than ours (2 reals) it will fit, so compact it
 +         * and copy on-the-fly to the output array.
 +         */
 +        p1 = (real *) in_data;
 +        p2 = (real *)out_data;
 +
 +        p2[0] = p1[0];
 +        for(i=1;i<n;i++)
 +        {
 +            p2[i] = p1[i+1];
 +        }
 +        fftpack_rfftb1(n,(real *)out_data,fft->work+n,fft->work,fft->ifac); 
 +    }  
 +    else
 +    {
 +        gmx_fatal(FARGS,"FFT plan mismatch - bad plan or direction.");
 +        return EINVAL;
 +    }    
 +    
 +    return 0;
 +}
 +
 +
 +int 
 +gmx_fft_2d               (gmx_fft_t                  fft,
 +                          enum gmx_fft_direction     dir,
 +                          void *                     in_data,
 +                          void *                     out_data)
 +{
 +    int                i,nx,ny;
 +    t_complex *    data;
 +    
 +    nx = fft->n;
 +    ny = fft->next->n;
 +    
 +    /* FFTPACK only does in-place transforms, so emulate out-of-place
 +     * by copying data to the output array first.
 +     * For 2D there is likely enough data to benefit from memcpy().
 +     */
 +    if( in_data != out_data )
 +    {
 +        memcpy(out_data,in_data,sizeof(t_complex)*nx*ny);
 +    }
 +
 +    /* Much easier to do pointer arithmetic when base has the correct type */
 +    data = (t_complex *)out_data;
 +
 +    /* y transforms */
 +    for(i=0;i<nx;i++)
 +    {
 +        gmx_fft_1d(fft->next,dir,data+i*ny,data+i*ny);
 +    }
 +    
 +    /* Transpose in-place to get data in place for x transform now */
 +    gmx_fft_transpose_2d(data,data,nx,ny);
 +    
 +    /* x transforms */
 +    for(i=0;i<ny;i++)
 +    {
 +        gmx_fft_1d(fft,dir,data+i*nx,data+i*nx);
 +    }
 +    
 +    /* Transpose in-place to get data back in original order */
 +    gmx_fft_transpose_2d(data,data,ny,nx);
 +    
 +    return 0;
 +}
 +
 +
 +
 +int 
 +gmx_fft_2d_real          (gmx_fft_t                  fft,
 +                          enum gmx_fft_direction     dir,
 +                          void *                     in_data,
 +                          void *                     out_data)
 +{
 +    int                i,j,nx,ny,nyc;
 +    t_complex *    data;
 +    real *       work;
 +    real *       p1;
 +    real *       p2;
 +    
 +    nx=fft->n;
 +    ny=fft->next->n;
 +    /* Number of complex elements in y direction */
 +    nyc=(ny/2+1);
 +    
 +    work = fft->work+4*nx;
 +        
 +    if(dir==GMX_FFT_REAL_TO_COMPLEX)
 +    {
 +        /* If we are doing an in-place transform the 2D array is already
 +         * properly padded by the user, and we are all set.
 +         *
 +         * For out-of-place there is no array padding, but FFTPACK only
 +         * does in-place FFTs internally, so we need to start by copying
 +         * data from the input to the padded (larger) output array.
 +         */
 +        if( in_data != out_data )
 +        {
 +            p1 = (real *)in_data;
 +            p2 = (real *)out_data;
 +            
 +            for(i=0;i<nx;i++)
 +            {
 +                for(j=0;j<ny;j++)
 +                {
 +                    p2[i*nyc*2+j] = p1[i*ny+j];
 +                }
 +            }
 +        }
 +        data = (t_complex *)out_data;
 +
 +        /* y real-to-complex FFTs */
 +        for(i=0;i<nx;i++)
 +        {
 +            gmx_fft_1d_real(fft->next,GMX_FFT_REAL_TO_COMPLEX,data+i*nyc,data+i*nyc);
 +        }
 +       
 +        /* Transform to get X data in place */
 +        gmx_fft_transpose_2d(data,data,nx,nyc);
 +        
 +        /* Complex-to-complex X FFTs */
 +        for(i=0;i<nyc;i++)
 +        {
 +            gmx_fft_1d(fft,GMX_FFT_FORWARD,data+i*nx,data+i*nx);
 +        }
 +  
 +        /* Transpose back */
 +        gmx_fft_transpose_2d(data,data,nyc,nx);
 +        
 +    }
 +    else if(dir==GMX_FFT_COMPLEX_TO_REAL)
 +    {
 +        /* An in-place complex-to-real transform is straightforward,
 +         * since the output array must be large enough for the padding to fit.
 +         *
 +         * For out-of-place complex-to-real transforms we cannot just copy
 +         * data to the output array, since it is smaller than the input.
 +         * In this case there's nothing to do but employing temporary work data,
 +         * starting at work+4*nx and using nx*nyc*2 elements.
 +         */
 +        if(in_data != out_data)
 +        {
 +            memcpy(work,in_data,sizeof(t_complex)*nx*nyc);
 +            data = (t_complex *)work;
 +        }
 +        else
 +        {
 +            /* in-place */
 +            data = (t_complex *)out_data;
 +        }
 +
 +        /* Transpose to get X arrays */
 +        gmx_fft_transpose_2d(data,data,nx,nyc);
 +        
 +        /* Do X iFFTs */
 +        for(i=0;i<nyc;i++)
 +        {
 +            gmx_fft_1d(fft,GMX_FFT_BACKWARD,data+i*nx,data+i*nx);
 +        }
 +        
 +        /* Transpose to get Y arrays */
 +        gmx_fft_transpose_2d(data,data,nyc,nx);
 +        
 +        /* Do Y iFFTs */
 +        for(i=0;i<nx;i++)
 +        {
 +            gmx_fft_1d_real(fft->next,GMX_FFT_COMPLEX_TO_REAL,data+i*nyc,data+i*nyc);
 +        }
 +        
 +        if( in_data != out_data )
 +        {
 +            /* Output (pointed to by data) is now in padded format.
 +             * Pack it into out_data if we were doing an out-of-place transform.
 +             */
 +            p1 = (real *)data;
 +            p2 = (real *)out_data;
 +                
 +            for(i=0;i<nx;i++)
 +            {
 +                for(j=0;j<ny;j++)
 +                {
 +                    p2[i*ny+j] = p1[i*nyc*2+j];
 +                }
 +            }
 +        }
 +    }
 +    else
 +    {
 +        gmx_fatal(FARGS,"FFT plan mismatch - bad plan or direction.");
 +        return EINVAL;
 +    }    
 +    
 +    return 0;
 +}
 +
 +
 +
 +int 
 +gmx_fft_3d          (gmx_fft_t                  fft,
 +                     enum gmx_fft_direction     dir,
 +                     void *                     in_data,
 +                     void *                     out_data)
 +{
 +    int              i,nx,ny,nz,rc;
 +    t_complex *  data;
 +    t_complex *  work;
 +    nx=fft->n;
 +    ny=fft->next->n;
 +    nz=fft->next->next->n;
 +
 +    /* First 4*nx positions are FFTPACK workspace, then ours starts */
 +    work = (t_complex *)(fft->work+4*nx);
 +        
 +    /* FFTPACK only does in-place transforms, so emulate out-of-place
 +     * by copying data to the output array first.
 +     * For 3D there is likely enough data to benefit from memcpy().
 +     */
 +    if( in_data != out_data )
 +    {
 +        memcpy(out_data,in_data,sizeof(t_complex)*nx*ny*nz);
 +    }
 +    
 +    /* Much easier to do pointer arithmetic when base has the correct type */
 +    data = (t_complex *)out_data;
 +
 +    /* Perform z transforms */
 +    for(i=0;i<nx*ny;i++)
 +        gmx_fft_1d(fft->next->next,dir,data+i*nz,data+i*nz);
 +
 +    /* For each X slice, transpose the y & z dimensions inside the slice */
 +    for(i=0;i<nx;i++)
 +    {
 +        gmx_fft_transpose_2d(data+i*ny*nz,data+i*ny*nz,ny,nz);
 +    }
 +
 +    /* Array is now (nx,nz,ny) - perform y transforms */
 +    for(i=0;i<nx*nz;i++)
 +    {
 +        gmx_fft_1d(fft->next,dir,data+i*ny,data+i*ny);
 +    }
 +
 +    /* Transpose back to (nx,ny,nz) */
 +    for(i=0;i<nx;i++)
 +    {
 +        gmx_fft_transpose_2d(data+i*ny*nz,data+i*ny*nz,nz,ny);
 +    }
 +    
 +    /* Transpose entire x & y slices to go from
 +     * (nx,ny,nz) to (ny,nx,nz).
 +     * Use work data elements 4*n .. 4*n+2*nz-1. 
 +     */
 +    rc=gmx_fft_transpose_2d_nelem(data,data,nx,ny,nz,work);
 +    if( rc != 0)
 +    {
 +        gmx_fatal(FARGS,"Cannot transpose X & Y/Z in gmx_fft_3d().");
 +        return rc;
 +    }
 +    
 +    /* Then go from (ny,nx,nz) to (ny,nz,nx) */
 +    for(i=0;i<ny;i++)
 +    {
 +        gmx_fft_transpose_2d(data+i*nx*nz,data+i*nx*nz,nx,nz);
 +    }
 +
 +    /* Perform x transforms */
 +    for(i=0;i<ny*nz;i++)
 +    {
 +        gmx_fft_1d(fft,dir,data+i*nx,data+i*nx);
 +    }
 +    
 +    /* Transpose back from (ny,nz,nx) to (ny,nx,nz) */
 +    for(i=0;i<ny;i++)
 +    {
 +        gmx_fft_transpose_2d(data+i*nz*nx,data+i*nz*nx,nz,nx);
 +    }
 +    
 +    /* Transpose from (ny,nx,nz) to (nx,ny,nz) 
 +     * Use work data elements 4*n .. 4*n+2*nz-1. 
 +     */
 +    rc = gmx_fft_transpose_2d_nelem(data,data,ny,nx,nz,work);
 +    if( rc != 0)
 +    {
 +        gmx_fatal(FARGS,"Cannot transpose Y/Z & X in gmx_fft_3d().");
 +        return rc;
 +    }
 +    
 +    return 0;
 +}
 +
 +
 +int 
 +gmx_fft_3d_real          (gmx_fft_t                  fft,
 +                          enum gmx_fft_direction     dir,
 +                          void *                     in_data,
 +                          void *                     out_data)
 +{
 +    int              i,j,k;
 +    int              nx,ny,nz,nzc,rc;
 +    t_complex *  data;
 +    t_complex *  work_transp;
 +    t_complex *  work_c2r;
 +    real *     p1;
 +    real *     p2;
 +    
 +    nx=fft->n;
 +    ny=fft->next->n;
 +    nz=fft->next->next->n;
 +    nzc=(nz/2+1);
 +        
 +    
 +    /* First 4*nx positions are FFTPACK workspace, then ours starts.
 +     * We have 2*nx*ny*nzc elements for temp complex-to-real storage when
 +     * doing out-of-place transforms, and another 2*nzc for transpose data.
 +     */
 +    work_c2r    = (t_complex *)(fft->work+4*nx);
 +    work_transp = (t_complex *)(fft->work+4*nx+2*nx*ny*nzc);
 +
 +    /* Much easier to do pointer arithmetic when base has the correct type */
 +    data = (t_complex *)out_data;
 +
 +    if(dir==GMX_FFT_REAL_TO_COMPLEX) 
 +    {
 +        /* FFTPACK only does in-place transforms, so emulate out-of-place
 +         * by copying data to the output array first. This is guaranteed to
 +         * work for real-to-complex since complex data is larger than the real.
 +         * For 3D there is likely enough data to benefit from memcpy().
 +         */
 +        if( in_data != out_data )
 +        {
 +            p1 = (real *)in_data;
 +            p2 = (real *)out_data;
 +           
 +            for(i=0;i<nx;i++)
 +            {
 +                for(j=0;j<ny;j++)
 +                {
 +                    for(k=0;k<nz;k++)
 +                    {
 +                        p2[(i*ny+j)*2*nzc+k] = p1[(i*ny+j)*nz+k];
 +                    }
 +                }
 +            }
 +        }
 +        data = (t_complex *)out_data;
 +
 +        /* Transform the Y/Z slices real-to-complex */
 +        for(i=0;i<nx;i++)
 +        {
 +            gmx_fft_2d_real(fft->next,dir,data+i*ny*nzc,data+i*ny*nzc);
 +        }
 +
 +        /* Transpose x & y slices to go from
 +         * (nx,ny,nzc) to (ny,nx,nzc).
 +         */
 +        rc=gmx_fft_transpose_2d_nelem(data,data,nx,ny,nzc,work_transp);
 +        if( rc != 0)
 +        {
 +            gmx_fatal(FARGS,"Cannot transpose X & Y/Z gmx_fft_3d_real().");
 +            return rc;
 +        }
 +        
 +        /* Then transpose from (ny,nx,nzc) to (ny,nzc,nx) */
 +        for(i=0;i<ny;i++)
 +        {
 +            gmx_fft_transpose_2d(data+i*nx*nzc,data+i*nx*nzc,nx,nzc);
 +        }
 +        
 +        /* Perform x transforms */
 +        for(i=0;i<ny*nzc;i++)
 +        {
 +            gmx_fft_1d(fft,GMX_FFT_FORWARD,data+i*nx,data+i*nx);
 +        }
 +        
 +        /* Transpose from (ny,nzc,nx) back to (ny,nx,nzc) */
 +        for(i=0;i<ny;i++)
 +        {
 +            gmx_fft_transpose_2d(data+i*nzc*nx,data+i*nzc*nx,nzc,nx);
 +        }
 +        
 +        /* Transpose back from (ny,nx,nzc) to (nx,ny,nz) */
 +        rc=gmx_fft_transpose_2d_nelem(data,data,ny,nx,nzc,work_transp);
 +        if( rc != 0)
 +        {
 +            gmx_fatal(FARGS,"Cannot transpose Y/Z & X in gmx_fft_3d_real().");
 +            return rc;
 +        }
 +            
 +    }
 +    else if(dir==GMX_FFT_COMPLEX_TO_REAL)
 +    {
 +        /* An in-place complex-to-real transform is straightforward,
 +         * since the output array must be large enough for the padding to fit.
 +         *
 +         * For out-of-place complex-to-real transforms we cannot just copy
 +         * data to the output array, since it is smaller than the input.
 +         * In this case there's nothing to do but employing temporary work data.
 +         */
 +        if(in_data != out_data)
 +        {
 +            memcpy(work_c2r,in_data,sizeof(t_complex)*nx*ny*nzc);
 +            data = (t_complex *)work_c2r;
 +        }
 +        else
 +        {
 +            /* in-place */
 +            data = (t_complex *)out_data;
 +        }
 +        
 +        /* Transpose x & y slices to go from
 +        * (nx,ny,nz) to (ny,nx,nz).
 +        */
 +        gmx_fft_transpose_2d_nelem(data,data,nx,ny,nzc,work_transp);
 +
 +        /* Then go from (ny,nx,nzc) to (ny,nzc,nx) */
 +        for(i=0;i<ny;i++)
 +        {
 +            gmx_fft_transpose_2d(data+i*nx*nzc,data+i*nx*nzc,nx,nzc);
 +        }
 +        
 +
 +        /* Perform x transforms */
 +        for(i=0;i<ny*nzc;i++)
 +        {
 +            gmx_fft_1d(fft,GMX_FFT_BACKWARD,data+i*nx,data+i*nx);
 +        }
 +
 +        /* Transpose back from (ny,nzc,nx) to (ny,nx,nzc) */
 +        for(i=0;i<ny;i++)
 +        {
 +            gmx_fft_transpose_2d(data+i*nzc*nx,data+i*nzc*nx,nzc,nx);
 +        }
 +        
 +        /* Transpose back from (ny,nx,nzc) to (nx,ny,nz) */
 +        gmx_fft_transpose_2d_nelem(data,data,ny,nx,nzc,work_transp);
 +        
 +
 +        /* Do 2D complex-to-real */
 +        for(i=0;i<nx;i++)
 +        {
 +            gmx_fft_2d_real(fft->next,dir,data+i*ny*nzc,data+i*ny*nzc);    
 +        }
 +        
 +        if( in_data != out_data )
 +        {
 +            /* Output (pointed to by data) is now in padded format.
 +             * Pack it into out_data if we were doing an out-of-place transform.
 +             */
 +            p1 = (real *)data;
 +            p2 = (real *)out_data;
 +            
 +            for(i=0;i<nx;i++)
 +            {
 +                for(j=0;j<ny;j++)
 +                {
 +                    for(k=0;k<nz;k++)
 +                    {
 +                        p2[(i*ny+j)*nz+k] = p1[(i*ny+j)*nzc*2+k];
 +                    }
 +                }
 +            }
 +        }
 +        
 +    }
 +    else
 +    {
 +        gmx_fatal(FARGS,"FFT plan mismatch - bad plan or direction.");
 +        return EINVAL;
 +    }    
 +    
 +    return 0;
 +}
 +
 +
 +
 +
 +void
 +gmx_fft_destroy(gmx_fft_t      fft)
 +{
 +    if(fft != NULL) 
 +    {
 +        free(fft->work);
 +        if(fft->next != NULL)
 +            gmx_fft_destroy(fft->next);
 +        free(fft);
 +    }
 +}
 +#endif /* GMX_FFT_FFTPACK */
Simple merge
index dc44cae4368cb9535cdc8debc0fa836e8e244d31,0000000000000000000000000000000000000000..89517cdb1044197244af0c87a58c043d167eecbb
mode 100644,000000..100644
--- /dev/null
@@@ -1,1863 -1,0 +1,1872 @@@
-                bFirstStep,bStateFromTPX,bInitStep,bLastStep,
 +/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
 + *
 + * 
 + *                This source code is part of
 + * 
 + *                 G   R   O   M   A   C   S
 + * 
 + *          GROningen MAchine for Chemical Simulations
 + * 
 + *                        VERSION 3.2.0
 + * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
 + * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
 + * Copyright (c) 2001-2004, The GROMACS development team,
 + * check out http://www.gromacs.org for more information.
 +
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + * 
 + * If you want to redistribute modifications, please consider that
 + * scientific software is very special. Version control is crucial -
 + * bugs must be traceable. We will be happy to consider code for
 + * inclusion in the official distribution, but derived work must not
 + * be called official GROMACS. Details are found in the README & COPYING
 + * files - if they are missing, get the official version at www.gromacs.org.
 + * 
 + * To help us fund GROMACS development, we humbly ask that you cite
 + * the papers on the package - you can find them in the top README file.
 + * 
 + * For more info, check our website at http://www.gromacs.org
 + * 
 + * And Hey:
 + * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
 + */
 +#ifdef HAVE_CONFIG_H
 +#include <config.h>
 +#endif
 +
 +#include "typedefs.h"
 +#include "smalloc.h"
 +#include "sysstuff.h"
 +#include "vec.h"
 +#include "statutil.h"
 +#include "vcm.h"
 +#include "mdebin.h"
 +#include "nrnb.h"
 +#include "calcmu.h"
 +#include "index.h"
 +#include "vsite.h"
 +#include "update.h"
 +#include "ns.h"
 +#include "trnio.h"
 +#include "xtcio.h"
 +#include "mdrun.h"
 +#include "confio.h"
 +#include "network.h"
 +#include "pull.h"
 +#include "xvgr.h"
 +#include "physics.h"
 +#include "names.h"
 +#include "xmdrun.h"
 +#include "ionize.h"
 +#include "disre.h"
 +#include "orires.h"
 +#include "dihre.h"
 +#include "pme.h"
 +#include "mdatoms.h"
 +#include "repl_ex.h"
 +#include "qmmm.h"
 +#include "domdec.h"
 +#include "partdec.h"
 +#include "topsort.h"
 +#include "coulomb.h"
 +#include "constr.h"
 +#include "shellfc.h"
 +#include "compute_io.h"
 +#include "mvdata.h"
 +#include "checkpoint.h"
 +#include "mtop_util.h"
 +#include "sighandler.h"
 +#include "string2.h"
 +#include "membed.h"
 +
 +#ifdef GMX_LIB_MPI
 +#include <mpi.h>
 +#endif
 +#ifdef GMX_THREAD_MPI
 +#include "tmpi.h"
 +#endif
 +
 +#ifdef GMX_FAHCORE
 +#include "corewrap.h"
 +#endif
 +
 +
 +double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
 +             const output_env_t oenv, gmx_bool bVerbose,gmx_bool bCompact,
 +             int nstglobalcomm,
 +             gmx_vsite_t *vsite,gmx_constr_t constr,
 +             int stepout,t_inputrec *ir,
 +             gmx_mtop_t *top_global,
 +             t_fcdata *fcd,
 +             t_state *state_global,
 +             t_mdatoms *mdatoms,
 +             t_nrnb *nrnb,gmx_wallcycle_t wcycle,
 +             gmx_edsam_t ed,t_forcerec *fr,
 +             int repl_ex_nst,int repl_ex_seed,gmx_membed_t membed,
 +             real cpt_period,real max_hours,
 +             const char *deviceOptions,
 +             unsigned long Flags,
 +             gmx_runtime_t *runtime)
 +{
 +    gmx_mdoutf_t *outf;
 +    gmx_large_int_t step,step_rel;
 +    double     run_time;
 +    double     t,t0,lam0;
 +    gmx_bool       bGStatEveryStep,bGStat,bNstEner,bCalcEnerPres;
 +    gmx_bool       bNS,bNStList,bSimAnn,bStopCM,bRerunMD,bNotLastFrame=FALSE,
-         if (opt2bSet("-cpi",nfile,fnm))
++               bFirstStep,bStateFromCP,bStateFromTPX,bInitStep,bLastStep,
 +               bBornRadii,bStartingFromCpt;
 +    gmx_bool       bDoDHDL=FALSE;
 +    gmx_bool       do_ene,do_log,do_verbose,bRerunWarnNoV=TRUE,
 +               bForceUpdate=FALSE,bCPT;
 +    int        mdof_flags;
 +    gmx_bool       bMasterState;
 +    int        force_flags,cglo_flags;
 +    tensor     force_vir,shake_vir,total_vir,tmp_vir,pres;
 +    int        i,m;
 +    t_trxstatus *status;
 +    rvec       mu_tot;
 +    t_vcm      *vcm;
 +    t_state    *bufstate=NULL;   
 +    matrix     *scale_tot,pcoupl_mu,M,ebox;
 +    gmx_nlheur_t nlh;
 +    t_trxframe rerun_fr;
 +    gmx_repl_ex_t repl_ex=NULL;
 +    int        nchkpt=1;
 +
 +    gmx_localtop_t *top;      
 +    t_mdebin *mdebin=NULL;
 +    t_state    *state=NULL;
 +    rvec       *f_global=NULL;
 +    int        n_xtc=-1;
 +    rvec       *x_xtc=NULL;
 +    gmx_enerdata_t *enerd;
 +    rvec       *f=NULL;
 +    gmx_global_stat_t gstat;
 +    gmx_update_t upd=NULL;
 +    t_graph    *graph=NULL;
 +    globsig_t   gs;
 +
 +    gmx_bool        bFFscan;
 +    gmx_groups_t *groups;
 +    gmx_ekindata_t *ekind, *ekind_save;
 +    gmx_shellfc_t shellfc;
 +    int         count,nconverged=0;
 +    real        timestep=0;
 +    double      tcount=0;
 +    gmx_bool        bIonize=FALSE;
 +    gmx_bool        bTCR=FALSE,bConverged=TRUE,bOK,bSumEkinhOld,bExchanged;
 +    gmx_bool        bAppend;
 +    gmx_bool        bResetCountersHalfMaxH=FALSE;
 +    gmx_bool        bVV,bIterations,bFirstIterate,bTemp,bPres,bTrotter;
 +    real        mu_aver=0,dvdl;
 +    int         a0,a1,gnx=0,ii;
 +    atom_id     *grpindex=NULL;
 +    char        *grpname;
 +    t_coupl_rec *tcr=NULL;
 +    rvec        *xcopy=NULL,*vcopy=NULL,*cbuf=NULL;
 +    matrix      boxcopy={{0}},lastbox;
 +      tensor      tmpvir;
 +      real        fom,oldfom,veta_save,pcurr,scalevir,tracevir;
 +      real        vetanew = 0;
 +    double      cycles;
 +      real        saved_conserved_quantity = 0;
 +    real        last_ekin = 0;
 +      int         iter_i;
 +      t_extmass   MassQ;
 +    int         **trotter_seq; 
 +    char        sbuf[STEPSTRSIZE],sbuf2[STEPSTRSIZE];
 +    int         handled_stop_condition=gmx_stop_cond_none; /* compare to get_stop_condition*/
 +    gmx_iterate_t iterate;
 +    gmx_large_int_t multisim_nsteps=-1; /* number of steps to do  before first multisim 
 +                                          simulation stops. If equal to zero, don't
 +                                          communicate any more between multisims.*/
 +#ifdef GMX_FAHCORE
 +    /* Temporary addition for FAHCORE checkpointing */
 +    int chkpt_ret;
 +#endif
 +
 +    /* Check for special mdrun options */
 +    bRerunMD = (Flags & MD_RERUN);
 +    bIonize  = (Flags & MD_IONIZE);
 +    bFFscan  = (Flags & MD_FFSCAN);
 +    bAppend  = (Flags & MD_APPENDFILES);
 +    if (Flags & MD_RESETCOUNTERSHALFWAY)
 +    {
 +        if (ir->nsteps > 0)
 +        {
 +            /* Signal to reset the counters half the simulation steps. */
 +            wcycle_set_reset_counters(wcycle,ir->nsteps/2);
 +        }
 +        /* Signal to reset the counters halfway the simulation time. */
 +        bResetCountersHalfMaxH = (max_hours > 0);
 +    }
 +
 +    /* md-vv uses averaged full step velocities for T-control 
 +       md-vv-avek uses averaged half step velocities for T-control (but full step ekin for P control)
 +       md uses averaged half step kinetic energies to determine temperature unless defined otherwise by GMX_EKIN_AVE_VEL; */
 +    bVV = EI_VV(ir->eI);
 +    if (bVV) /* to store the initial velocities while computing virial */
 +    {
 +        snew(cbuf,top_global->natoms);
 +    }
 +    /* all the iteratative cases - only if there are constraints */ 
 +    bIterations = ((IR_NPT_TROTTER(ir)) && (constr) && (!bRerunMD));
 +    bTrotter = (bVV && (IR_NPT_TROTTER(ir) || (IR_NVT_TROTTER(ir))));        
 +    
 +    if (bRerunMD)
 +    {
 +        /* Since we don't know if the frames read are related in any way,
 +         * rebuild the neighborlist at every step.
 +         */
 +        ir->nstlist       = 1;
 +        ir->nstcalcenergy = 1;
 +        nstglobalcomm     = 1;
 +    }
 +
 +    check_ir_old_tpx_versions(cr,fplog,ir,top_global);
 +
 +    nstglobalcomm = check_nstglobalcomm(fplog,cr,nstglobalcomm,ir);
 +    bGStatEveryStep = (nstglobalcomm == 1);
 +
 +    if (!bGStatEveryStep && ir->nstlist == -1 && fplog != NULL)
 +    {
 +        fprintf(fplog,
 +                "To reduce the energy communication with nstlist = -1\n"
 +                "the neighbor list validity should not be checked at every step,\n"
 +                "this means that exact integration is not guaranteed.\n"
 +                "The neighbor list validity is checked after:\n"
 +                "  <n.list life time> - 2*std.dev.(n.list life time)  steps.\n"
 +                "In most cases this will result in exact integration.\n"
 +                "This reduces the energy communication by a factor of 2 to 3.\n"
 +                "If you want less energy communication, set nstlist > 3.\n\n");
 +    }
 +
 +    if (bRerunMD || bFFscan)
 +    {
 +        ir->nstxtcout = 0;
 +    }
 +    groups = &top_global->groups;
 +
 +    /* Initial values */
 +    init_md(fplog,cr,ir,oenv,&t,&t0,&state_global->lambda,&lam0,
 +            nrnb,top_global,&upd,
 +            nfile,fnm,&outf,&mdebin,
 +            force_vir,shake_vir,mu_tot,&bSimAnn,&vcm,state_global,Flags);
 +
 +    clear_mat(total_vir);
 +    clear_mat(pres);
 +    /* Energy terms and groups */
 +    snew(enerd,1);
 +    init_enerdata(top_global->groups.grps[egcENER].nr,ir->n_flambda,enerd);
 +    if (DOMAINDECOMP(cr))
 +    {
 +        f = NULL;
 +    }
 +    else
 +    {
 +        snew(f,top_global->natoms);
 +    }
 +
 +    /* Kinetic energy data */
 +    snew(ekind,1);
 +    init_ekindata(fplog,top_global,&(ir->opts),ekind);
 +    /* needed for iteration of constraints */
 +    snew(ekind_save,1);
 +    init_ekindata(fplog,top_global,&(ir->opts),ekind_save);
 +    /* Copy the cos acceleration to the groups struct */    
 +    ekind->cosacc.cos_accel = ir->cos_accel;
 +
 +    gstat = global_stat_init(ir);
 +    debug_gmx();
 +
 +    /* Check for polarizable models and flexible constraints */
 +    shellfc = init_shell_flexcon(fplog,
 +                                 top_global,n_flexible_constraints(constr),
 +                                 (ir->bContinuation || 
 +                                  (DOMAINDECOMP(cr) && !MASTER(cr))) ?
 +                                 NULL : state_global->x);
 +
 +    if (DEFORM(*ir))
 +    {
 +#ifdef GMX_THREAD_MPI
 +        tMPI_Thread_mutex_lock(&deform_init_box_mutex);
 +#endif
 +        set_deform_reference_box(upd,
 +                                 deform_init_init_step_tpx,
 +                                 deform_init_box_tpx);
 +#ifdef GMX_THREAD_MPI
 +        tMPI_Thread_mutex_unlock(&deform_init_box_mutex);
 +#endif
 +    }
 +
 +    {
 +        double io = compute_io(ir,top_global->natoms,groups,mdebin->ebin->nener,1);
 +        if ((io > 2000) && MASTER(cr))
 +            fprintf(stderr,
 +                    "\nWARNING: This run will generate roughly %.0f Mb of data\n\n",
 +                    io);
 +    }
 +
 +    if (DOMAINDECOMP(cr)) {
 +        top = dd_init_local_top(top_global);
 +
 +        snew(state,1);
 +        dd_init_local_state(cr->dd,state_global,state);
 +
 +        if (DDMASTER(cr->dd) && ir->nstfout) {
 +            snew(f_global,state_global->natoms);
 +        }
 +    } else {
 +        if (PAR(cr)) {
 +            /* Initialize the particle decomposition and split the topology */
 +            top = split_system(fplog,top_global,ir,cr);
 +
 +            pd_cg_range(cr,&fr->cg0,&fr->hcg);
 +            pd_at_range(cr,&a0,&a1);
 +        } else {
 +            top = gmx_mtop_generate_local_top(top_global,ir);
 +
 +            a0 = 0;
 +            a1 = top_global->natoms;
 +        }
 +
 +        state = partdec_init_local_state(cr,state_global);
 +        f_global = f;
 +
 +        atoms2md(top_global,ir,0,NULL,a0,a1-a0,mdatoms);
 +
 +        if (vsite) {
 +            set_vsite_top(vsite,top,mdatoms,cr);
 +        }
 +
 +        if (ir->ePBC != epbcNONE && !ir->bPeriodicMols) {
 +            graph = mk_graph(fplog,&(top->idef),0,top_global->natoms,FALSE,FALSE);
 +        }
 +
 +        if (shellfc) {
 +            make_local_shells(cr,mdatoms,shellfc);
 +        }
 +
 +        if (ir->pull && PAR(cr)) {
 +            dd_make_local_pull_groups(NULL,ir->pull,mdatoms);
 +        }
 +    }
 +
 +    if (DOMAINDECOMP(cr))
 +    {
 +        /* Distribute the charge groups over the nodes from the master node */
 +        dd_partition_system(fplog,ir->init_step,cr,TRUE,1,
 +                            state_global,top_global,ir,
 +                            state,&f,mdatoms,top,fr,
 +                            vsite,shellfc,constr,
 +                            nrnb,wcycle,FALSE);
 +    }
 +
 +    update_mdatoms(mdatoms,state->lambda);
 +
++    if (opt2bSet("-cpi",nfile,fnm))
++    {
++        bStateFromCP = gmx_fexist_master(opt2fn_master("-cpi",nfile,fnm,cr),cr);
++    }
++    else
++    {
++        bStateFromCP = FALSE;
++    }
++
 +    if (MASTER(cr))
 +    {
-     bStateFromTPX = !opt2bSet("-cpi",nfile,fnm);
++        if (bStateFromCP)
 +        {
 +            /* Update mdebin with energy history if appending to output files */
 +            if ( Flags & MD_APPENDFILES )
 +            {
 +                restore_energyhistory_from_state(mdebin,&state_global->enerhist);
 +            }
 +            else
 +            {
 +                /* We might have read an energy history from checkpoint,
 +                 * free the allocated memory and reset the counts.
 +                 */
 +                done_energyhistory(&state_global->enerhist);
 +                init_energyhistory(&state_global->enerhist);
 +            }
 +        }
 +        /* Set the initial energy history in state by updating once */
 +        update_energyhistory(&state_global->enerhist,mdebin);
 +    } 
 +
 +    if ((state->flags & (1<<estLD_RNG)) && (Flags & MD_READ_RNG)) {
 +        /* Set the random state if we read a checkpoint file */
 +        set_stochd_state(upd,state);
 +    }
 +
 +    /* Initialize constraints */
 +    if (constr) {
 +        if (!DOMAINDECOMP(cr))
 +            set_constraints(constr,top,ir,mdatoms,cr);
 +    }
 +
 +    /* Check whether we have to GCT stuff */
 +    bTCR = ftp2bSet(efGCT,nfile,fnm);
 +    if (bTCR) {
 +        if (MASTER(cr)) {
 +            fprintf(stderr,"Will do General Coupling Theory!\n");
 +        }
 +        gnx = top_global->mols.nr;
 +        snew(grpindex,gnx);
 +        for(i=0; (i<gnx); i++) {
 +            grpindex[i] = i;
 +        }
 +    }
 +
 +    if (repl_ex_nst > 0)
 +    {
 +        /* We need to be sure replica exchange can only occur
 +         * when the energies are current */
 +        check_nst_param(fplog,cr,"nstcalcenergy",ir->nstcalcenergy,
 +                        "repl_ex_nst",&repl_ex_nst);
 +        /* This check needs to happen before inter-simulation
 +         * signals are initialized, too */
 +    }
 +    if (repl_ex_nst > 0 && MASTER(cr))
 +        repl_ex = init_replica_exchange(fplog,cr->ms,state_global,ir,
 +                                        repl_ex_nst,repl_ex_seed);
 +
 +    if (!ir->bContinuation && !bRerunMD)
 +    {
 +        if (mdatoms->cFREEZE && (state->flags & (1<<estV)))
 +        {
 +            /* Set the velocities of frozen particles to zero */
 +            for(i=mdatoms->start; i<mdatoms->start+mdatoms->homenr; i++)
 +            {
 +                for(m=0; m<DIM; m++)
 +                {
 +                    if (ir->opts.nFreeze[mdatoms->cFREEZE[i]][m])
 +                    {
 +                        state->v[i][m] = 0;
 +                    }
 +                }
 +            }
 +        }
 +
 +        if (constr)
 +        {
 +            /* Constrain the initial coordinates and velocities */
 +            do_constrain_first(fplog,constr,ir,mdatoms,state,f,
 +                               graph,cr,nrnb,fr,top,shake_vir);
 +        }
 +        if (vsite)
 +        {
 +            /* Construct the virtual sites for the initial configuration */
 +            construct_vsites(fplog,vsite,state->x,nrnb,ir->delta_t,NULL,
 +                             top->idef.iparams,top->idef.il,
 +                             fr->ePBC,fr->bMolPBC,graph,cr,state->box);
 +        }
 +    }
 +
 +    debug_gmx();
 +  
 +    /* I'm assuming we need global communication the first time! MRS */
 +    cglo_flags = (CGLO_TEMPERATURE | CGLO_GSTAT
 +                  | ((ir->comm_mode != ecmNO) ? CGLO_STOPCM:0)
 +                  | (bVV ? CGLO_PRESSURE:0)
 +                  | (bVV ? CGLO_CONSTRAINT:0)
 +                  | (bRerunMD ? CGLO_RERUNMD:0)
 +                  | ((Flags & MD_READ_EKIN) ? CGLO_READEKIN:0));
 +    
 +    bSumEkinhOld = FALSE;
 +    compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
 +                    NULL,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
 +                    constr,NULL,FALSE,state->box,
 +                    top_global,&pcurr,top_global->natoms,&bSumEkinhOld,cglo_flags);
 +    if (ir->eI == eiVVAK) {
 +        /* a second call to get the half step temperature initialized as well */ 
 +        /* we do the same call as above, but turn the pressure off -- internally to 
 +           compute_globals, this is recognized as a velocity verlet half-step 
 +           kinetic energy calculation.  This minimized excess variables, but 
 +           perhaps loses some logic?*/
 +        
 +        compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
 +                        NULL,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
 +                        constr,NULL,FALSE,state->box,
 +                        top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
 +                        cglo_flags &~ (CGLO_STOPCM | CGLO_PRESSURE));
 +    }
 +    
 +    /* Calculate the initial half step temperature, and save the ekinh_old */
 +    if (!(Flags & MD_STARTFROMCPT)) 
 +    {
 +        for(i=0; (i<ir->opts.ngtc); i++) 
 +        {
 +            copy_mat(ekind->tcstat[i].ekinh,ekind->tcstat[i].ekinh_old);
 +        } 
 +    }
 +    if (ir->eI != eiVV) 
 +    {
 +        enerd->term[F_TEMP] *= 2; /* result of averages being done over previous and current step,
 +                                     and there is no previous step */
 +    }
 +    
 +    /* if using an iterative algorithm, we need to create a working directory for the state. */
 +    if (bIterations) 
 +    {
 +            bufstate = init_bufstate(state);
 +    }
 +    if (bFFscan) 
 +    {
 +        snew(xcopy,state->natoms);
 +        snew(vcopy,state->natoms);
 +        copy_rvecn(state->x,xcopy,0,state->natoms);
 +        copy_rvecn(state->v,vcopy,0,state->natoms);
 +        copy_mat(state->box,boxcopy);
 +    } 
 +    
 +    /* need to make an initiation call to get the Trotter variables set, as well as other constants for non-trotter
 +       temperature control */
 +    trotter_seq = init_npt_vars(ir,state,&MassQ,bTrotter);
 +    
 +    if (MASTER(cr))
 +    {
 +        if (constr && !ir->bContinuation && ir->eConstrAlg == econtLINCS)
 +        {
 +            fprintf(fplog,
 +                    "RMS relative constraint deviation after constraining: %.2e\n",
 +                    constr_rmsd(constr,FALSE));
 +        }
 +        if (EI_STATE_VELOCITY(ir->eI))
 +        {
 +            fprintf(fplog,"Initial temperature: %g K\n",enerd->term[F_TEMP]);
 +        }
 +        if (bRerunMD)
 +        {
 +            fprintf(stderr,"starting md rerun '%s', reading coordinates from"
 +                    " input trajectory '%s'\n\n",
 +                    *(top_global->name),opt2fn("-rerun",nfile,fnm));
 +            if (bVerbose)
 +            {
 +                fprintf(stderr,"Calculated time to finish depends on nsteps from "
 +                        "run input file,\nwhich may not correspond to the time "
 +                        "needed to process input trajectory.\n\n");
 +            }
 +        }
 +        else
 +        {
 +            char tbuf[20];
 +            fprintf(stderr,"starting mdrun '%s'\n",
 +                    *(top_global->name));
 +            if (ir->nsteps >= 0)
 +            {
 +                sprintf(tbuf,"%8.1f",(ir->init_step+ir->nsteps)*ir->delta_t);
 +            }
 +            else
 +            {
 +                sprintf(tbuf,"%s","infinite");
 +            }
 +            if (ir->init_step > 0)
 +            {
 +                fprintf(stderr,"%s steps, %s ps (continuing from step %s, %8.1f ps).\n",
 +                        gmx_step_str(ir->init_step+ir->nsteps,sbuf),tbuf,
 +                        gmx_step_str(ir->init_step,sbuf2),
 +                        ir->init_step*ir->delta_t);
 +            }
 +            else
 +            {
 +                fprintf(stderr,"%s steps, %s ps.\n",
 +                        gmx_step_str(ir->nsteps,sbuf),tbuf);
 +            }
 +        }
 +        fprintf(fplog,"\n");
 +    }
 +
 +    /* Set and write start time */
 +    runtime_start(runtime);
 +    print_date_and_time(fplog,cr->nodeid,"Started mdrun",runtime);
 +    wallcycle_start(wcycle,ewcRUN);
 +    if (fplog)
 +        fprintf(fplog,"\n");
 +
 +    /* safest point to do file checkpointing is here.  More general point would be immediately before integrator call */
 +#ifdef GMX_FAHCORE
 +    chkpt_ret=fcCheckPointParallel( cr->nodeid,
 +                                    NULL,0);
 +    if ( chkpt_ret == 0 ) 
 +        gmx_fatal( 3,__FILE__,__LINE__, "Checkpoint error on step %d\n", 0 );
 +#endif
 +
 +    debug_gmx();
 +    /***********************************************************
 +     *
 +     *             Loop over MD steps 
 +     *
 +     ************************************************************/
 +
 +    /* if rerunMD then read coordinates and velocities from input trajectory */
 +    if (bRerunMD)
 +    {
 +        if (getenv("GMX_FORCE_UPDATE"))
 +        {
 +            bForceUpdate = TRUE;
 +        }
 +
 +        rerun_fr.natoms = 0;
 +        if (MASTER(cr))
 +        {
 +            bNotLastFrame = read_first_frame(oenv,&status,
 +                                             opt2fn("-rerun",nfile,fnm),
 +                                             &rerun_fr,TRX_NEED_X | TRX_READ_V);
 +            if (rerun_fr.natoms != top_global->natoms)
 +            {
 +                gmx_fatal(FARGS,
 +                          "Number of atoms in trajectory (%d) does not match the "
 +                          "run input file (%d)\n",
 +                          rerun_fr.natoms,top_global->natoms);
 +            }
 +            if (ir->ePBC != epbcNONE)
 +            {
 +                if (!rerun_fr.bBox)
 +                {
 +                    gmx_fatal(FARGS,"Rerun trajectory frame step %d time %f does not contain a box, while pbc is used",rerun_fr.step,rerun_fr.time);
 +                }
 +                if (max_cutoff2(ir->ePBC,rerun_fr.box) < sqr(fr->rlistlong))
 +                {
 +                    gmx_fatal(FARGS,"Rerun trajectory frame step %d time %f has too small box dimensions",rerun_fr.step,rerun_fr.time);
 +                }
 +            }
 +        }
 +
 +        if (PAR(cr))
 +        {
 +            rerun_parallel_comm(cr,&rerun_fr,&bNotLastFrame);
 +        }
 +
 +        if (ir->ePBC != epbcNONE)
 +        {
 +            /* Set the shift vectors.
 +             * Necessary here when have a static box different from the tpr box.
 +             */
 +            calc_shifts(rerun_fr.box,fr->shift_vec);
 +        }
 +    }
 +
 +    /* loop over MD steps or if rerunMD to end of input trajectory */
 +    bFirstStep = TRUE;
 +    /* Skip the first Nose-Hoover integration when we get the state from tpx */
++    bStateFromTPX = !bStateFromCP;
 +    bInitStep = bFirstStep && (bStateFromTPX || bVV);
 +    bStartingFromCpt = (Flags & MD_STARTFROMCPT) && bInitStep;
 +    bLastStep    = FALSE;
 +    bSumEkinhOld = FALSE;
 +    bExchanged   = FALSE;
 +
 +    init_global_signals(&gs,cr,ir,repl_ex_nst);
 +
 +    step = ir->init_step;
 +    step_rel = 0;
 +
 +    if (ir->nstlist == -1)
 +    {
 +        init_nlistheuristics(&nlh,bGStatEveryStep,step);
 +    }
 +
 +    if (MULTISIM(cr) && (repl_ex_nst <=0 ))
 +    {
 +        /* check how many steps are left in other sims */
 +        multisim_nsteps=get_multisim_nsteps(cr, ir->nsteps);
 +    }
 +
 +
 +    /* and stop now if we should */
 +    bLastStep = (bRerunMD || (ir->nsteps >= 0 && step_rel > ir->nsteps) ||
 +                 ((multisim_nsteps >= 0) && (step_rel >= multisim_nsteps )));
 +    while (!bLastStep || (bRerunMD && bNotLastFrame)) {
 +
 +        wallcycle_start(wcycle,ewcSTEP);
 +
 +        if (bRerunMD) {
 +            if (rerun_fr.bStep) {
 +                step = rerun_fr.step;
 +                step_rel = step - ir->init_step;
 +            }
 +            if (rerun_fr.bTime) {
 +                t = rerun_fr.time;
 +            }
 +            else
 +            {
 +                t = step;
 +            }
 +        } 
 +        else 
 +        {
 +            bLastStep = (step_rel == ir->nsteps);
 +            t = t0 + step*ir->delta_t;
 +        }
 +
 +        if (ir->efep != efepNO)
 +        {
 +            if (bRerunMD && rerun_fr.bLambda && (ir->delta_lambda!=0))
 +            {
 +                state_global->lambda = rerun_fr.lambda;
 +            }
 +            else
 +            {
 +                state_global->lambda = lam0 + step*ir->delta_lambda;
 +            }
 +            state->lambda = state_global->lambda;
 +            bDoDHDL = do_per_step(step,ir->nstdhdl);
 +        }
 +
 +        if (bSimAnn) 
 +        {
 +            update_annealing_target_temp(&(ir->opts),t);
 +        }
 +
 +        if (bRerunMD)
 +        {
 +            if (!(DOMAINDECOMP(cr) && !MASTER(cr)))
 +            {
 +                for(i=0; i<state_global->natoms; i++)
 +                {
 +                    copy_rvec(rerun_fr.x[i],state_global->x[i]);
 +                }
 +                if (rerun_fr.bV)
 +                {
 +                    for(i=0; i<state_global->natoms; i++)
 +                    {
 +                        copy_rvec(rerun_fr.v[i],state_global->v[i]);
 +                    }
 +                }
 +                else
 +                {
 +                    for(i=0; i<state_global->natoms; i++)
 +                    {
 +                        clear_rvec(state_global->v[i]);
 +                    }
 +                    if (bRerunWarnNoV)
 +                    {
 +                        fprintf(stderr,"\nWARNING: Some frames do not contain velocities.\n"
 +                                "         Ekin, temperature and pressure are incorrect,\n"
 +                                "         the virial will be incorrect when constraints are present.\n"
 +                                "\n");
 +                        bRerunWarnNoV = FALSE;
 +                    }
 +                }
 +            }
 +            copy_mat(rerun_fr.box,state_global->box);
 +            copy_mat(state_global->box,state->box);
 +
 +            if (vsite && (Flags & MD_RERUN_VSITE))
 +            {
 +                if (DOMAINDECOMP(cr))
 +                {
 +                    gmx_fatal(FARGS,"Vsite recalculation with -rerun is not implemented for domain decomposition, use particle decomposition");
 +                }
 +                if (graph)
 +                {
 +                    /* Following is necessary because the graph may get out of sync
 +                     * with the coordinates if we only have every N'th coordinate set
 +                     */
 +                    mk_mshift(fplog,graph,fr->ePBC,state->box,state->x);
 +                    shift_self(graph,state->box,state->x);
 +                }
 +                construct_vsites(fplog,vsite,state->x,nrnb,ir->delta_t,state->v,
 +                                 top->idef.iparams,top->idef.il,
 +                                 fr->ePBC,fr->bMolPBC,graph,cr,state->box);
 +                if (graph)
 +                {
 +                    unshift_self(graph,state->box,state->x);
 +                }
 +            }
 +        }
 +
 +        /* Stop Center of Mass motion */
 +        bStopCM = (ir->comm_mode != ecmNO && do_per_step(step,ir->nstcomm));
 +
 +        /* Copy back starting coordinates in case we're doing a forcefield scan */
 +        if (bFFscan)
 +        {
 +            for(ii=0; (ii<state->natoms); ii++)
 +            {
 +                copy_rvec(xcopy[ii],state->x[ii]);
 +                copy_rvec(vcopy[ii],state->v[ii]);
 +            }
 +            copy_mat(boxcopy,state->box);
 +        }
 +
 +        if (bRerunMD)
 +        {
 +            /* for rerun MD always do Neighbour Searching */
 +            bNS = (bFirstStep || ir->nstlist != 0);
 +            bNStList = bNS;
 +        }
 +        else
 +        {
 +            /* Determine whether or not to do Neighbour Searching and LR */
 +            bNStList = (ir->nstlist > 0  && step % ir->nstlist == 0);
 +            
 +            bNS = (bFirstStep || bExchanged || bNStList ||
 +                   (ir->nstlist == -1 && nlh.nabnsb > 0));
 +
 +            if (bNS && ir->nstlist == -1)
 +            {
 +                set_nlistheuristics(&nlh,bFirstStep || bExchanged,step);
 +            }
 +        } 
 +
 +        /* check whether we should stop because another simulation has 
 +           stopped. */
 +        if (MULTISIM(cr))
 +        {
 +            if ( (multisim_nsteps >= 0) &&  (step_rel >= multisim_nsteps)  &&  
 +                 (multisim_nsteps != ir->nsteps) )  
 +            {
 +                if (bNS)
 +                {
 +                    if (MASTER(cr))
 +                    {
 +                        fprintf(stderr, 
 +                                "Stopping simulation %d because another one has finished\n",
 +                                cr->ms->sim);
 +                    }
 +                    bLastStep=TRUE;
 +                    gs.sig[eglsCHKPT] = 1;
 +                }
 +            }
 +        }
 +
 +        /* < 0 means stop at next step, > 0 means stop at next NS step */
 +        if ( (gs.set[eglsSTOPCOND] < 0 ) ||
 +             ( (gs.set[eglsSTOPCOND] > 0 ) && ( bNS || ir->nstlist==0)) )
 +        {
 +            bLastStep = TRUE;
 +        }
 +
 +        /* Determine whether or not to update the Born radii if doing GB */
 +        bBornRadii=bFirstStep;
 +        if (ir->implicit_solvent && (step % ir->nstgbradii==0))
 +        {
 +            bBornRadii=TRUE;
 +        }
 +        
 +        do_log = do_per_step(step,ir->nstlog) || bFirstStep || bLastStep;
 +        do_verbose = bVerbose &&
 +                  (step % stepout == 0 || bFirstStep || bLastStep);
 +
 +        if (bNS && !(bFirstStep && ir->bContinuation && !bRerunMD))
 +        {
 +            if (bRerunMD)
 +            {
 +                bMasterState = TRUE;
 +            }
 +            else
 +            {
 +                bMasterState = FALSE;
 +                /* Correct the new box if it is too skewed */
 +                if (DYNAMIC_BOX(*ir))
 +                {
 +                    if (correct_box(fplog,step,state->box,graph))
 +                    {
 +                        bMasterState = TRUE;
 +                    }
 +                }
 +                if (DOMAINDECOMP(cr) && bMasterState)
 +                {
 +                    dd_collect_state(cr->dd,state,state_global);
 +                }
 +            }
 +
 +            if (DOMAINDECOMP(cr))
 +            {
 +                /* Repartition the domain decomposition */
 +                wallcycle_start(wcycle,ewcDOMDEC);
 +                dd_partition_system(fplog,step,cr,
 +                                    bMasterState,nstglobalcomm,
 +                                    state_global,top_global,ir,
 +                                    state,&f,mdatoms,top,fr,
 +                                    vsite,shellfc,constr,
 +                                    nrnb,wcycle,do_verbose);
 +                wallcycle_stop(wcycle,ewcDOMDEC);
 +                /* If using an iterative integrator, reallocate space to match the decomposition */
 +            }
 +        }
 +
 +        if (MASTER(cr) && do_log && !bFFscan)
 +        {
 +            print_ebin_header(fplog,step,t,state->lambda);
 +        }
 +
 +        if (ir->efep != efepNO)
 +        {
 +            update_mdatoms(mdatoms,state->lambda); 
 +        }
 +
 +        if (bRerunMD && rerun_fr.bV)
 +        {
 +            
 +            /* We need the kinetic energy at minus the half step for determining
 +             * the full step kinetic energy and possibly for T-coupling.*/
 +            /* This may not be quite working correctly yet . . . . */
 +            compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
 +                            wcycle,enerd,NULL,NULL,NULL,NULL,mu_tot,
 +                            constr,NULL,FALSE,state->box,
 +                            top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
 +                            CGLO_RERUNMD | CGLO_GSTAT | CGLO_TEMPERATURE);
 +        }
 +        clear_mat(force_vir);
 +        
 +        /* Ionize the atoms if necessary */
 +        if (bIonize)
 +        {
 +            ionize(fplog,oenv,mdatoms,top_global,t,ir,state->x,state->v,
 +                   mdatoms->start,mdatoms->start+mdatoms->homenr,state->box,cr);
 +        }
 +        
 +        /* Update force field in ffscan program */
 +        if (bFFscan)
 +        {
 +            if (update_forcefield(fplog,
 +                                  nfile,fnm,fr,
 +                                  mdatoms->nr,state->x,state->box))
 +            {
 +                gmx_finalize_par();
 +
 +                exit(0);
 +            }
 +        }
 +
 +        /* We write a checkpoint at this MD step when:
 +         * either at an NS step when we signalled through gs,
 +         * or at the last step (but not when we do not want confout),
 +         * but never at the first step or with rerun.
 +         */
 +        bCPT = (((gs.set[eglsCHKPT] && (bNS || ir->nstlist == 0)) ||
 +                 (bLastStep && (Flags & MD_CONFOUT))) &&
 +                step > ir->init_step && !bRerunMD);
 +        if (bCPT)
 +        {
 +            gs.set[eglsCHKPT] = 0;
 +        }
 +
 +        /* Determine the energy and pressure:
 +         * at nstcalcenergy steps and at energy output steps (set below).
 +         */
 +        bNstEner = do_per_step(step,ir->nstcalcenergy);
 +        bCalcEnerPres =
 +            (bNstEner ||
 +             (ir->epc != epcNO && do_per_step(step,ir->nstpcouple)));
 +
 +        /* Do we need global communication ? */
 +        bGStat = (bCalcEnerPres || bStopCM ||
 +                  do_per_step(step,nstglobalcomm) ||
 +                  (ir->nstlist == -1 && !bRerunMD && step >= nlh.step_nscheck));
 +
 +        do_ene = (do_per_step(step,ir->nstenergy) || bLastStep);
 +
 +        if (do_ene || do_log)
 +        {
 +            bCalcEnerPres = TRUE;
 +            bGStat        = TRUE;
 +        }
 +        
 +        /* these CGLO_ options remain the same throughout the iteration */
 +        cglo_flags = ((bRerunMD ? CGLO_RERUNMD : 0) |
 +                      (bGStat ? CGLO_GSTAT : 0)
 +            );
 +        
 +        force_flags = (GMX_FORCE_STATECHANGED |
 +                       ((DYNAMIC_BOX(*ir) || bRerunMD) ? GMX_FORCE_DYNAMICBOX : 0) |
 +                       GMX_FORCE_ALLFORCES |
 +                       (bNStList ? GMX_FORCE_DOLR : 0) |
 +                       GMX_FORCE_SEPLRF |
 +                       (bCalcEnerPres ? GMX_FORCE_VIRIAL : 0) |
 +                       (bDoDHDL ? GMX_FORCE_DHDL : 0)
 +            );
 +        
 +        if (shellfc)
 +        {
 +            /* Now is the time to relax the shells */
 +            count=relax_shell_flexcon(fplog,cr,bVerbose,bFFscan ? step+1 : step,
 +                                      ir,bNS,force_flags,
 +                                      bStopCM,top,top_global,
 +                                      constr,enerd,fcd,
 +                                      state,f,force_vir,mdatoms,
 +                                      nrnb,wcycle,graph,groups,
 +                                      shellfc,fr,bBornRadii,t,mu_tot,
 +                                      state->natoms,&bConverged,vsite,
 +                                      outf->fp_field);
 +            tcount+=count;
 +
 +            if (bConverged)
 +            {
 +                nconverged++;
 +            }
 +        }
 +        else
 +        {
 +            /* The coordinates (x) are shifted (to get whole molecules)
 +             * in do_force.
 +             * This is parallellized as well, and does communication too. 
 +             * Check comments in sim_util.c
 +             */
 +        
 +            do_force(fplog,cr,ir,step,nrnb,wcycle,top,top_global,groups,
 +                     state->box,state->x,&state->hist,
 +                     f,force_vir,mdatoms,enerd,fcd,
 +                     state->lambda,graph,
 +                     fr,vsite,mu_tot,t,outf->fp_field,ed,bBornRadii,
 +                     (bNS ? GMX_FORCE_NS : 0) | force_flags);
 +        }
 +        
 +        if (bTCR)
 +        {
 +            mu_aver = calc_mu_aver(cr,state->x,mdatoms->chargeA,
 +                                   mu_tot,&top_global->mols,mdatoms,gnx,grpindex);
 +        }
 +        
 +        if (bTCR && bFirstStep)
 +        {
 +            tcr=init_coupling(fplog,nfile,fnm,cr,fr,mdatoms,&(top->idef));
 +            fprintf(fplog,"Done init_coupling\n"); 
 +            fflush(fplog);
 +        }
 +        
 +        if (bVV && !bStartingFromCpt && !bRerunMD)
 +        /*  ############### START FIRST UPDATE HALF-STEP FOR VV METHODS############### */
 +        {
 +            if (ir->eI==eiVV && bInitStep) 
 +            {
 +                /* if using velocity verlet with full time step Ekin,
 +                 * take the first half step only to compute the 
 +                 * virial for the first step. From there,
 +                 * revert back to the initial coordinates
 +                 * so that the input is actually the initial step.
 +                 */
 +                copy_rvecn(state->v,cbuf,0,state->natoms); /* should make this better for parallelizing? */
 +            } else {
 +                /* this is for NHC in the Ekin(t+dt/2) version of vv */
 +                trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq,ettTSEQ1);            
 +            }
 +
 +            update_coords(fplog,step,ir,mdatoms,state,
 +                          f,fr->bTwinRange && bNStList,fr->f_twin,fcd,
 +                          ekind,M,wcycle,upd,bInitStep,etrtVELOCITY1,
 +                          cr,nrnb,constr,&top->idef);
 +            
 +            if (bIterations)
 +            {
 +                gmx_iterate_init(&iterate,bIterations && !bInitStep);
 +            }
 +            /* for iterations, we save these vectors, as we will be self-consistently iterating
 +               the calculations */
 +
 +            /*#### UPDATE EXTENDED VARIABLES IN TROTTER FORMULATION */
 +            
 +            /* save the state */
 +            if (bIterations && iterate.bIterate) { 
 +                copy_coupling_state(state,bufstate,ekind,ekind_save,&(ir->opts));
 +            }
 +            
 +            bFirstIterate = TRUE;
 +            while (bFirstIterate || (bIterations && iterate.bIterate))
 +            {
 +                if (bIterations && iterate.bIterate) 
 +                {
 +                    copy_coupling_state(bufstate,state,ekind_save,ekind,&(ir->opts));
 +                    if (bFirstIterate && bTrotter) 
 +                    {
 +                        /* The first time through, we need a decent first estimate
 +                           of veta(t+dt) to compute the constraints.  Do
 +                           this by computing the box volume part of the
 +                           trotter integration at this time. Nothing else
 +                           should be changed by this routine here.  If
 +                           !(first time), we start with the previous value
 +                           of veta.  */
 +                        
 +                        veta_save = state->veta;
 +                        trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq,ettTSEQ0);
 +                        vetanew = state->veta;
 +                        state->veta = veta_save;
 +                    } 
 +                } 
 +                
 +                bOK = TRUE;
 +                if ( !bRerunMD || rerun_fr.bV || bForceUpdate) {  /* Why is rerun_fr.bV here?  Unclear. */
 +                    dvdl = 0;
 +                    
 +                    update_constraints(fplog,step,&dvdl,ir,ekind,mdatoms,state,graph,f,
 +                                       &top->idef,shake_vir,NULL,
 +                                       cr,nrnb,wcycle,upd,constr,
 +                                       bInitStep,TRUE,bCalcEnerPres,vetanew);
 +                    
 +                    if (!bOK && !bFFscan)
 +                    {
 +                        gmx_fatal(FARGS,"Constraint error: Shake, Lincs or Settle could not solve the constrains");
 +                    }
 +                    
 +                } 
 +                else if (graph)
 +                { /* Need to unshift here if a do_force has been
 +                     called in the previous step */
 +                    unshift_self(graph,state->box,state->x);
 +                }
 +                
 +                
 +                /* if VV, compute the pressure and constraints */
 +                /* For VV2, we strictly only need this if using pressure
 +                 * control, but we really would like to have accurate pressures
 +                 * printed out.
 +                 * Think about ways around this in the future?
 +                 * For now, keep this choice in comments.
 +                 */
 +                /*bPres = (ir->eI==eiVV || IR_NPT_TROTTER(ir)); */
 +                    /*bTemp = ((ir->eI==eiVV &&(!bInitStep)) || (ir->eI==eiVVAK && IR_NPT_TROTTER(ir)));*/
 +                bPres = TRUE;
 +                bTemp = ((ir->eI==eiVV &&(!bInitStep)) || (ir->eI==eiVVAK));
 +                compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
 +                                wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
 +                                constr,NULL,FALSE,state->box,
 +                                top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
 +                                cglo_flags 
 +                                | CGLO_ENERGY 
 +                                | (bStopCM ? CGLO_STOPCM : 0)
 +                                | (bTemp ? CGLO_TEMPERATURE:0) 
 +                                | (bPres ? CGLO_PRESSURE : 0) 
 +                                | (bPres ? CGLO_CONSTRAINT : 0)
 +                                | ((bIterations && iterate.bIterate) ? CGLO_ITERATE : 0)  
 +                                | (bFirstIterate ? CGLO_FIRSTITERATE : 0)
 +                                | CGLO_SCALEEKIN 
 +                    );
 +                /* explanation of above: 
 +                   a) We compute Ekin at the full time step
 +                   if 1) we are using the AveVel Ekin, and it's not the
 +                   initial step, or 2) if we are using AveEkin, but need the full
 +                   time step kinetic energy for the pressure (always true now, since we want accurate statistics).
 +                   b) If we are using EkinAveEkin for the kinetic energy for the temperture control, we still feed in 
 +                   EkinAveVel because it's needed for the pressure */
 +                
 +                /* temperature scaling and pressure scaling to produce the extended variables at t+dt */
 +                if (!bInitStep) 
 +                {
 +                    if (bTrotter)
 +                    {
 +                        trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq,ettTSEQ2);
 +                    } 
 +                    else 
 +                    {
 +                        update_tcouple(fplog,step,ir,state,ekind,wcycle,upd,&MassQ,mdatoms);
 +                    }
 +                }
 +                
 +                if (bIterations &&
 +                    done_iterating(cr,fplog,step,&iterate,bFirstIterate,
 +                                   state->veta,&vetanew)) 
 +                {
 +                    break;
 +                }
 +                bFirstIterate = FALSE;
 +            }
 +
 +            if (bTrotter && !bInitStep) {
 +                copy_mat(shake_vir,state->svir_prev);
 +                copy_mat(force_vir,state->fvir_prev);
 +                if (IR_NVT_TROTTER(ir) && ir->eI==eiVV) {
 +                    /* update temperature and kinetic energy now that step is over - this is the v(t+dt) point */
 +                    enerd->term[F_TEMP] = sum_ekin(&(ir->opts),ekind,NULL,(ir->eI==eiVV),FALSE,FALSE);
 +                    enerd->term[F_EKIN] = trace(ekind->ekin);
 +                }
 +            }
 +            /* if it's the initial step, we performed this first step just to get the constraint virial */
 +            if (bInitStep && ir->eI==eiVV) {
 +                copy_rvecn(cbuf,state->v,0,state->natoms);
 +            }
 +            
 +            if (fr->bSepDVDL && fplog && do_log) 
 +            {
 +                fprintf(fplog,sepdvdlformat,"Constraint",0.0,dvdl);
 +            }
 +            enerd->term[F_DHDL_CON] += dvdl;
 +        }
 +    
 +        /* MRS -- now done iterating -- compute the conserved quantity */
 +        if (bVV) {
 +            saved_conserved_quantity = compute_conserved_from_auxiliary(ir,state,&MassQ);
 +            if (ir->eI==eiVV) 
 +            {
 +                last_ekin = enerd->term[F_EKIN]; /* does this get preserved through checkpointing? */
 +            }
 +            if ((ir->eDispCorr != edispcEnerPres) && (ir->eDispCorr != edispcAllEnerPres)) 
 +            {
 +                saved_conserved_quantity -= enerd->term[F_DISPCORR];
 +            }
 +        }
 +        
 +        /* ########  END FIRST UPDATE STEP  ############## */
 +        /* ########  If doing VV, we now have v(dt) ###### */
 +        
 +        /* ################## START TRAJECTORY OUTPUT ################# */
 +        
 +        /* Now we have the energies and forces corresponding to the 
 +         * coordinates at time t. We must output all of this before
 +         * the update.
 +         * for RerunMD t is read from input trajectory
 +         */
 +        mdof_flags = 0;
 +        if (do_per_step(step,ir->nstxout)) { mdof_flags |= MDOF_X; }
 +        if (do_per_step(step,ir->nstvout)) { mdof_flags |= MDOF_V; }
 +        if (do_per_step(step,ir->nstfout)) { mdof_flags |= MDOF_F; }
 +        if (do_per_step(step,ir->nstxtcout)) { mdof_flags |= MDOF_XTC; }
 +        if (bCPT) { mdof_flags |= MDOF_CPT; };
 +
 +#if defined(GMX_FAHCORE) || defined(GMX_WRITELASTSTEP)
 +        if (bLastStep)
 +        {
 +            /* Enforce writing positions and velocities at end of run */
 +            mdof_flags |= (MDOF_X | MDOF_V);
 +        }
 +#endif
 +#ifdef GMX_FAHCORE
 +        if (MASTER(cr))
 +            fcReportProgress( ir->nsteps, step );
 +
 +        /* sync bCPT and fc record-keeping */
 +        if (bCPT && MASTER(cr))
 +            fcRequestCheckPoint();
 +#endif
 +        
 +        if (mdof_flags != 0)
 +        {
 +            wallcycle_start(wcycle,ewcTRAJ);
 +            if (bCPT)
 +            {
 +                if (state->flags & (1<<estLD_RNG))
 +                {
 +                    get_stochd_state(upd,state);
 +                }
 +                if (MASTER(cr))
 +                {
 +                    if (bSumEkinhOld)
 +                    {
 +                        state_global->ekinstate.bUpToDate = FALSE;
 +                    }
 +                    else
 +                    {
 +                        update_ekinstate(&state_global->ekinstate,ekind);
 +                        state_global->ekinstate.bUpToDate = TRUE;
 +                    }
 +                    update_energyhistory(&state_global->enerhist,mdebin);
 +                }
 +            }
 +            write_traj(fplog,cr,outf,mdof_flags,top_global,
 +                       step,t,state,state_global,f,f_global,&n_xtc,&x_xtc);
 +            if (bCPT)
 +            {
 +                nchkpt++;
 +                bCPT = FALSE;
 +            }
 +            debug_gmx();
 +            if (bLastStep && step_rel == ir->nsteps &&
 +                (Flags & MD_CONFOUT) && MASTER(cr) &&
 +                !bRerunMD && !bFFscan)
 +            {
 +                /* x and v have been collected in write_traj,
 +                 * because a checkpoint file will always be written
 +                 * at the last step.
 +                 */
 +                fprintf(stderr,"\nWriting final coordinates.\n");
 +                if (ir->ePBC != epbcNONE && !ir->bPeriodicMols &&
 +                    DOMAINDECOMP(cr))
 +                {
 +                    /* Make molecules whole only for confout writing */
 +                    do_pbc_mtop(fplog,ir->ePBC,state->box,top_global,state_global->x);
 +                }
 +                write_sto_conf_mtop(ftp2fn(efSTO,nfile,fnm),
 +                                    *top_global->name,top_global,
 +                                    state_global->x,state_global->v,
 +                                    ir->ePBC,state->box);
 +                debug_gmx();
 +            }
 +            wallcycle_stop(wcycle,ewcTRAJ);
 +        }
 +        
 +        /* kludge -- virial is lost with restart for NPT control. Must restart */
 +        if (bStartingFromCpt && bVV) 
 +        {
 +            copy_mat(state->svir_prev,shake_vir);
 +            copy_mat(state->fvir_prev,force_vir);
 +        }
 +        /*  ################## END TRAJECTORY OUTPUT ################ */
 +        
 +        /* Determine the wallclock run time up till now */
 +        run_time = gmx_gettime() - (double)runtime->real;
 +
 +        /* Check whether everything is still allright */    
 +        if (((int)gmx_get_stop_condition() > handled_stop_condition)
 +#ifdef GMX_THREAD_MPI
 +            && MASTER(cr)
 +#endif
 +            )
 +        {
 +            /* this is just make gs.sig compatible with the hack 
 +               of sending signals around by MPI_Reduce with together with
 +               other floats */
 +            if ( gmx_get_stop_condition() == gmx_stop_cond_next_ns )
 +                gs.sig[eglsSTOPCOND]=1;
 +            if ( gmx_get_stop_condition() == gmx_stop_cond_next )
 +                gs.sig[eglsSTOPCOND]=-1;
 +            /* < 0 means stop at next step, > 0 means stop at next NS step */
 +            if (fplog)
 +            {
 +                fprintf(fplog,
 +                        "\n\nReceived the %s signal, stopping at the next %sstep\n\n",
 +                        gmx_get_signal_name(),
 +                        gs.sig[eglsSTOPCOND]==1 ? "NS " : "");
 +                fflush(fplog);
 +            }
 +            fprintf(stderr,
 +                    "\n\nReceived the %s signal, stopping at the next %sstep\n\n",
 +                    gmx_get_signal_name(),
 +                    gs.sig[eglsSTOPCOND]==1 ? "NS " : "");
 +            fflush(stderr);
 +            handled_stop_condition=(int)gmx_get_stop_condition();
 +        }
 +        else if (MASTER(cr) && (bNS || ir->nstlist <= 0) &&
 +                 (max_hours > 0 && run_time > max_hours*60.0*60.0*0.99) &&
 +                 gs.sig[eglsSTOPCOND] == 0 && gs.set[eglsSTOPCOND] == 0)
 +        {
 +            /* Signal to terminate the run */
 +            gs.sig[eglsSTOPCOND] = 1;
 +            if (fplog)
 +            {
 +                fprintf(fplog,"\nStep %s: Run time exceeded %.3f hours, will terminate the run\n",gmx_step_str(step,sbuf),max_hours*0.99);
 +            }
 +            fprintf(stderr, "\nStep %s: Run time exceeded %.3f hours, will terminate the run\n",gmx_step_str(step,sbuf),max_hours*0.99);
 +        }
 +
 +        if (bResetCountersHalfMaxH && MASTER(cr) &&
 +            run_time > max_hours*60.0*60.0*0.495)
 +        {
 +            gs.sig[eglsRESETCOUNTERS] = 1;
 +        }
 +
 +        if (ir->nstlist == -1 && !bRerunMD)
 +        {
 +            /* When bGStatEveryStep=FALSE, global_stat is only called
 +             * when we check the atom displacements, not at NS steps.
 +             * This means that also the bonded interaction count check is not
 +             * performed immediately after NS. Therefore a few MD steps could
 +             * be performed with missing interactions.
 +             * But wrong energies are never written to file,
 +             * since energies are only written after global_stat
 +             * has been called.
 +             */
 +            if (step >= nlh.step_nscheck)
 +            {
 +                nlh.nabnsb = natoms_beyond_ns_buffer(ir,fr,&top->cgs,
 +                                                     nlh.scale_tot,state->x);
 +            }
 +            else
 +            {
 +                /* This is not necessarily true,
 +                 * but step_nscheck is determined quite conservatively.
 +                 */
 +                nlh.nabnsb = 0;
 +            }
 +        }
 +
 +        /* In parallel we only have to check for checkpointing in steps
 +         * where we do global communication,
 +         *  otherwise the other nodes don't know.
 +         */
 +        if (MASTER(cr) && ((bGStat || !PAR(cr)) &&
 +                           cpt_period >= 0 &&
 +                           (cpt_period == 0 || 
 +                            run_time >= nchkpt*cpt_period*60.0)) &&
 +            gs.set[eglsCHKPT] == 0)
 +        {
 +            gs.sig[eglsCHKPT] = 1;
 +        }
 +  
 +        if (bIterations)
 +        {
 +            gmx_iterate_init(&iterate,bIterations);
 +        }
 +    
 +        /* for iterations, we save these vectors, as we will be redoing the calculations */
 +        if (bIterations && iterate.bIterate) 
 +        {
 +            copy_coupling_state(state,bufstate,ekind,ekind_save,&(ir->opts));
 +        }
 +        bFirstIterate = TRUE;
 +        while (bFirstIterate || (bIterations && iterate.bIterate))
 +        {
 +            /* We now restore these vectors to redo the calculation with improved extended variables */    
 +            if (bIterations) 
 +            { 
 +                copy_coupling_state(bufstate,state,ekind_save,ekind,&(ir->opts));
 +            }
 +
 +            /* We make the decision to break or not -after- the calculation of Ekin and Pressure,
 +               so scroll down for that logic */
 +            
 +            /* #########   START SECOND UPDATE STEP ################# */
 +            /* Box is changed in update() when we do pressure coupling,
 +             * but we should still use the old box for energy corrections and when
 +             * writing it to the energy file, so it matches the trajectory files for
 +             * the same timestep above. Make a copy in a separate array.
 +             */
 +            copy_mat(state->box,lastbox);
 +
 +            bOK = TRUE;
 +            if (!(bRerunMD && !rerun_fr.bV && !bForceUpdate))
 +            {
 +                wallcycle_start(wcycle,ewcUPDATE);
 +                dvdl = 0;
 +                /* UPDATE PRESSURE VARIABLES IN TROTTER FORMULATION WITH CONSTRAINTS */
 +                if (bTrotter) 
 +                {
 +                    if (bIterations && iterate.bIterate) 
 +                    {
 +                        if (bFirstIterate) 
 +                        {
 +                            scalevir = 1;
 +                        }
 +                        else 
 +                        {
 +                            /* we use a new value of scalevir to converge the iterations faster */
 +                            scalevir = tracevir/trace(shake_vir);
 +                        }
 +                        msmul(shake_vir,scalevir,shake_vir); 
 +                        m_add(force_vir,shake_vir,total_vir);
 +                        clear_mat(shake_vir);
 +                    }
 +                    trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq,ettTSEQ3);
 +                /* We can only do Berendsen coupling after we have summed
 +                 * the kinetic energy or virial. Since the happens
 +                 * in global_state after update, we should only do it at
 +                 * step % nstlist = 1 with bGStatEveryStep=FALSE.
 +                 */
 +                }
 +                else 
 +                {
 +                    update_tcouple(fplog,step,ir,state,ekind,wcycle,upd,&MassQ,mdatoms);
 +                    update_pcouple(fplog,step,ir,state,pcoupl_mu,M,wcycle,
 +                                   upd,bInitStep);
 +                }
 +
 +                if (bVV)
 +                {
 +                    /* velocity half-step update */
 +                    update_coords(fplog,step,ir,mdatoms,state,f,
 +                                  fr->bTwinRange && bNStList,fr->f_twin,fcd,
 +                                  ekind,M,wcycle,upd,FALSE,etrtVELOCITY2,
 +                                  cr,nrnb,constr,&top->idef);
 +                }
 +
 +                /* Above, initialize just copies ekinh into ekin,
 +                 * it doesn't copy position (for VV),
 +                 * and entire integrator for MD.
 +                 */
 +                
 +                if (ir->eI==eiVVAK) 
 +                {
 +                    copy_rvecn(state->x,cbuf,0,state->natoms);
 +                }
 +                
 +                update_coords(fplog,step,ir,mdatoms,state,f,fr->bTwinRange && bNStList,fr->f_twin,fcd,
 +                              ekind,M,wcycle,upd,bInitStep,etrtPOSITION,cr,nrnb,constr,&top->idef);
 +                wallcycle_stop(wcycle,ewcUPDATE);
 +
 +                update_constraints(fplog,step,&dvdl,ir,ekind,mdatoms,state,graph,f,
 +                                   &top->idef,shake_vir,force_vir,
 +                                   cr,nrnb,wcycle,upd,constr,
 +                                   bInitStep,FALSE,bCalcEnerPres,state->veta);  
 +                
 +                if (ir->eI==eiVVAK) 
 +                {
 +                    /* erase F_EKIN and F_TEMP here? */
 +                    /* just compute the kinetic energy at the half step to perform a trotter step */
 +                    compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
 +                                    wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
 +                                    constr,NULL,FALSE,lastbox,
 +                                    top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
 +                                    cglo_flags | CGLO_TEMPERATURE    
 +                        );
 +                    wallcycle_start(wcycle,ewcUPDATE);
 +                    trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq,ettTSEQ4);            
 +                    /* now we know the scaling, we can compute the positions again again */
 +                    copy_rvecn(cbuf,state->x,0,state->natoms);
 +
 +                    update_coords(fplog,step,ir,mdatoms,state,f,fr->bTwinRange && bNStList,fr->f_twin,fcd,
 +                                  ekind,M,wcycle,upd,bInitStep,etrtPOSITION,cr,nrnb,constr,&top->idef);
 +                    wallcycle_stop(wcycle,ewcUPDATE);
 +
 +                    /* do we need an extra constraint here? just need to copy out of state->v to upd->xp? */
 +                    /* are the small terms in the shake_vir here due
 +                     * to numerical errors, or are they important
 +                     * physically? I'm thinking they are just errors, but not completely sure. 
 +                     * For now, will call without actually constraining, constr=NULL*/
 +                    update_constraints(fplog,step,&dvdl,ir,ekind,mdatoms,state,graph,f,
 +                                       &top->idef,tmp_vir,force_vir,
 +                                       cr,nrnb,wcycle,upd,NULL,
 +                                       bInitStep,FALSE,bCalcEnerPres,
 +                                       state->veta);  
 +                }
 +                if (!bOK && !bFFscan) 
 +                {
 +                    gmx_fatal(FARGS,"Constraint error: Shake, Lincs or Settle could not solve the constrains");
 +                }
 +                
 +                if (fr->bSepDVDL && fplog && do_log) 
 +                {
 +                    fprintf(fplog,sepdvdlformat,"Constraint",0.0,dvdl);
 +                }
 +                enerd->term[F_DHDL_CON] += dvdl;
 +            } 
 +            else if (graph) 
 +            {
 +                /* Need to unshift here */
 +                unshift_self(graph,state->box,state->x);
 +            }
 +
 +            if (vsite != NULL) 
 +            {
 +                wallcycle_start(wcycle,ewcVSITECONSTR);
 +                if (graph != NULL) 
 +                {
 +                    shift_self(graph,state->box,state->x);
 +                }
 +                construct_vsites(fplog,vsite,state->x,nrnb,ir->delta_t,state->v,
 +                                 top->idef.iparams,top->idef.il,
 +                                 fr->ePBC,fr->bMolPBC,graph,cr,state->box);
 +                
 +                if (graph != NULL) 
 +                {
 +                    unshift_self(graph,state->box,state->x);
 +                }
 +                wallcycle_stop(wcycle,ewcVSITECONSTR);
 +            }
 +            
 +            /* ############## IF NOT VV, Calculate globals HERE, also iterate constraints ############ */
 +            if (ir->nstlist == -1 && bFirstIterate)
 +            {
 +                gs.sig[eglsNABNSB] = nlh.nabnsb;
 +            }
 +            compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
 +                            wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
 +                            constr,
 +                            bFirstIterate ? &gs : NULL, 
 +                            (step_rel % gs.nstms == 0) && 
 +                                (multisim_nsteps<0 || (step_rel<multisim_nsteps)),
 +                            lastbox,
 +                            top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
 +                            cglo_flags 
 +                            | (!EI_VV(ir->eI) ? CGLO_ENERGY : 0) 
 +                            | (!EI_VV(ir->eI) && bStopCM ? CGLO_STOPCM : 0)
 +                            | (!EI_VV(ir->eI) ? CGLO_TEMPERATURE : 0) 
 +                            | (!EI_VV(ir->eI) || bRerunMD ? CGLO_PRESSURE : 0) 
 +                            | (bIterations && iterate.bIterate ? CGLO_ITERATE : 0) 
 +                            | (bFirstIterate ? CGLO_FIRSTITERATE : 0)
 +                            | CGLO_CONSTRAINT 
 +                );
 +            if (ir->nstlist == -1 && bFirstIterate)
 +            {
 +                nlh.nabnsb = gs.set[eglsNABNSB];
 +                gs.set[eglsNABNSB] = 0;
 +            }
 +            /* bIterate is set to keep it from eliminating the old ekin kinetic energy terms */
 +            /* #############  END CALC EKIN AND PRESSURE ################# */
 +        
 +            /* Note: this is OK, but there are some numerical precision issues with using the convergence of
 +               the virial that should probably be addressed eventually. state->veta has better properies,
 +               but what we actually need entering the new cycle is the new shake_vir value. Ideally, we could
 +               generate the new shake_vir, but test the veta value for convergence.  This will take some thought. */
 +
 +            if (bIterations && 
 +                done_iterating(cr,fplog,step,&iterate,bFirstIterate,
 +                               trace(shake_vir),&tracevir)) 
 +            {
 +                break;
 +            }
 +            bFirstIterate = FALSE;
 +        }
 +
 +        update_box(fplog,step,ir,mdatoms,state,graph,f,
 +                   ir->nstlist==-1 ? &nlh.scale_tot : NULL,pcoupl_mu,nrnb,wcycle,upd,bInitStep,FALSE);
 +        
 +        /* ################# END UPDATE STEP 2 ################# */
 +        /* #### We now have r(t+dt) and v(t+dt/2)  ############# */
 +    
 +        /* The coordinates (x) were unshifted in update */
 +        if (bFFscan && (shellfc==NULL || bConverged))
 +        {
 +            if (print_forcefield(fplog,enerd->term,mdatoms->homenr,
 +                                 f,NULL,xcopy,
 +                                 &(top_global->mols),mdatoms->massT,pres))
 +            {
 +                gmx_finalize_par();
 +
 +                fprintf(stderr,"\n");
 +                exit(0);
 +            }
 +        }
 +        if (!bGStat)
 +        {
 +            /* We will not sum ekinh_old,                                                            
 +             * so signal that we still have to do it.                                                
 +             */
 +            bSumEkinhOld = TRUE;
 +        }
 +        
 +        if (bTCR)
 +        {
 +            /* Only do GCT when the relaxation of shells (minimization) has converged,
 +             * otherwise we might be coupling to bogus energies. 
 +             * In parallel we must always do this, because the other sims might
 +             * update the FF.
 +             */
 +
 +            /* Since this is called with the new coordinates state->x, I assume
 +             * we want the new box state->box too. / EL 20040121
 +             */
 +            do_coupling(fplog,oenv,nfile,fnm,tcr,t,step,enerd->term,fr,
 +                        ir,MASTER(cr),
 +                        mdatoms,&(top->idef),mu_aver,
 +                        top_global->mols.nr,cr,
 +                        state->box,total_vir,pres,
 +                        mu_tot,state->x,f,bConverged);
 +            debug_gmx();
 +        }
 +
 +        /* #########  BEGIN PREPARING EDR OUTPUT  ###########  */
 +        
 +        /* sum up the foreign energy and dhdl terms */
 +        sum_dhdl(enerd,state->lambda,ir);
 +
 +        /* use the directly determined last velocity, not actually the averaged half steps */
 +        if (bTrotter && ir->eI==eiVV) 
 +        {
 +            enerd->term[F_EKIN] = last_ekin;
 +        }
 +        enerd->term[F_ETOT] = enerd->term[F_EPOT] + enerd->term[F_EKIN];
 +        
 +        if (bVV)
 +        {
 +            enerd->term[F_ECONSERVED] = enerd->term[F_ETOT] + saved_conserved_quantity;
 +        }
 +        else 
 +        {
 +            enerd->term[F_ECONSERVED] = enerd->term[F_ETOT] + compute_conserved_from_auxiliary(ir,state,&MassQ);
 +        }
 +        /* Check for excessively large energies */
 +        if (bIonize) 
 +        {
 +#ifdef GMX_DOUBLE
 +            real etot_max = 1e200;
 +#else
 +            real etot_max = 1e30;
 +#endif
 +            if (fabs(enerd->term[F_ETOT]) > etot_max) 
 +            {
 +                fprintf(stderr,"Energy too large (%g), giving up\n",
 +                        enerd->term[F_ETOT]);
 +            }
 +        }
 +        /* #########  END PREPARING EDR OUTPUT  ###########  */
 +        
 +        /* Time for performance */
 +        if (((step % stepout) == 0) || bLastStep) 
 +        {
 +            runtime_upd_proc(runtime);
 +        }
 +        
 +        /* Output stuff */
 +        if (MASTER(cr))
 +        {
 +            gmx_bool do_dr,do_or;
 +            
 +            if (!(bStartingFromCpt && (EI_VV(ir->eI)))) 
 +            {
 +                if (bNstEner)
 +                {
 +                    upd_mdebin(mdebin,bDoDHDL, TRUE,
 +                               t,mdatoms->tmass,enerd,state,lastbox,
 +                               shake_vir,force_vir,total_vir,pres,
 +                               ekind,mu_tot,constr);
 +                }
 +                else
 +                {
 +                    upd_mdebin_step(mdebin);
 +                }
 +                
 +                do_dr  = do_per_step(step,ir->nstdisreout);
 +                do_or  = do_per_step(step,ir->nstorireout);
 +                
 +                print_ebin(outf->fp_ene,do_ene,do_dr,do_or,do_log?fplog:NULL,
 +                           step,t,
 +                           eprNORMAL,bCompact,mdebin,fcd,groups,&(ir->opts));
 +            }
 +            if (ir->ePull != epullNO)
 +            {
 +                pull_print_output(ir->pull,step,t);
 +            }
 +            
 +            if (do_per_step(step,ir->nstlog))
 +            {
 +                if(fflush(fplog) != 0)
 +                {
 +                    gmx_fatal(FARGS,"Cannot flush logfile - maybe you are out of disk space?");
 +                }
 +            }
 +        }
 +
 +
 +        /* Remaining runtime */
 +        if (MULTIMASTER(cr) && (do_verbose || gmx_got_usr_signal() ))
 +        {
 +            if (shellfc) 
 +            {
 +                fprintf(stderr,"\n");
 +            }
 +            print_time(stderr,runtime,step,ir,cr);
 +        }
 +
 +        /* Replica exchange */
 +        bExchanged = FALSE;
 +        if ((repl_ex_nst > 0) && (step > 0) && !bLastStep &&
 +            do_per_step(step,repl_ex_nst)) 
 +        {
 +            bExchanged = replica_exchange(fplog,cr,repl_ex,
 +                                          state_global,enerd->term,
 +                                          state,step,t);
 +
 +            if (bExchanged && DOMAINDECOMP(cr)) 
 +            {
 +                dd_partition_system(fplog,step,cr,TRUE,1,
 +                                    state_global,top_global,ir,
 +                                    state,&f,mdatoms,top,fr,
 +                                    vsite,shellfc,constr,
 +                                    nrnb,wcycle,FALSE);
 +            }
 +        }
 +        
 +        bFirstStep = FALSE;
 +        bInitStep = FALSE;
 +        bStartingFromCpt = FALSE;
 +
 +        /* #######  SET VARIABLES FOR NEXT ITERATION IF THEY STILL NEED IT ###### */
 +        /* With all integrators, except VV, we need to retain the pressure
 +         * at the current step for coupling at the next step.
 +         */
 +        if ((state->flags & (1<<estPRES_PREV)) &&
 +            (bGStatEveryStep ||
 +             (ir->nstpcouple > 0 && step % ir->nstpcouple == 0)))
 +        {
 +            /* Store the pressure in t_state for pressure coupling
 +             * at the next MD step.
 +             */
 +            copy_mat(pres,state->pres_prev);
 +        }
 +        
 +        /* #######  END SET VARIABLES FOR NEXT ITERATION ###### */
 +
 +        if ( (membed!=NULL) && (!bLastStep) )
 +        {
 +            rescale_membed(step_rel,membed,state_global->x);
 +        }
 +
 +        if (bRerunMD) 
 +        {
 +            if (MASTER(cr))
 +            {
 +                /* read next frame from input trajectory */
 +                bNotLastFrame = read_next_frame(oenv,status,&rerun_fr);
 +            }
 +
 +            if (PAR(cr))
 +            {
 +                rerun_parallel_comm(cr,&rerun_fr,&bNotLastFrame);
 +            }
 +        }
 +        
 +        if (!bRerunMD || !rerun_fr.bStep)
 +        {
 +            /* increase the MD step number */
 +            step++;
 +            step_rel++;
 +        }
 +        
 +        cycles = wallcycle_stop(wcycle,ewcSTEP);
 +        if (DOMAINDECOMP(cr) && wcycle)
 +        {
 +            dd_cycles_add(cr->dd,cycles,ddCyclStep);
 +        }
 +        
 +        if (step_rel == wcycle_get_reset_counters(wcycle) ||
 +            gs.set[eglsRESETCOUNTERS] != 0)
 +        {
 +            /* Reset all the counters related to performance over the run */
 +            reset_all_counters(fplog,cr,step,&step_rel,ir,wcycle,nrnb,runtime);
 +            wcycle_set_reset_counters(wcycle,-1);
 +            /* Correct max_hours for the elapsed time */
 +            max_hours -= run_time/(60.0*60.0);
 +            bResetCountersHalfMaxH = FALSE;
 +            gs.set[eglsRESETCOUNTERS] = 0;
 +        }
 +
 +    }
 +    /* End of main MD loop */
 +    debug_gmx();
 +    
 +    /* Stop the time */
 +    runtime_end(runtime);
 +    
 +    if (bRerunMD && MASTER(cr))
 +    {
 +        close_trj(status);
 +    }
 +    
 +    if (!(cr->duty & DUTY_PME))
 +    {
 +        /* Tell the PME only node to finish */
 +        gmx_pme_finish(cr);
 +    }
 +    
 +    if (MASTER(cr))
 +    {
 +        if (ir->nstcalcenergy > 0 && !bRerunMD) 
 +        {
 +            print_ebin(outf->fp_ene,FALSE,FALSE,FALSE,fplog,step,t,
 +                       eprAVER,FALSE,mdebin,fcd,groups,&(ir->opts));
 +        }
 +    }
 +
 +    done_mdoutf(outf);
 +
 +    debug_gmx();
 +
 +    if (ir->nstlist == -1 && nlh.nns > 0 && fplog)
 +    {
 +        fprintf(fplog,"Average neighborlist lifetime: %.1f steps, std.dev.: %.1f steps\n",nlh.s1/nlh.nns,sqrt(nlh.s2/nlh.nns - sqr(nlh.s1/nlh.nns)));
 +        fprintf(fplog,"Average number of atoms that crossed the half buffer length: %.1f\n\n",nlh.ab/nlh.nns);
 +    }
 +    
 +    if (shellfc && fplog)
 +    {
 +        fprintf(fplog,"Fraction of iterations that converged:           %.2f %%\n",
 +                (nconverged*100.0)/step_rel);
 +        fprintf(fplog,"Average number of force evaluations per MD step: %.2f\n\n",
 +                tcount/step_rel);
 +    }
 +    
 +    if (repl_ex_nst > 0 && MASTER(cr))
 +    {
 +        print_replica_exchange_statistics(fplog,repl_ex);
 +    }
 +    
 +    runtime->nsteps_done = step_rel;
 +    
 +    return 0;
 +}
Simple merge
Simple merge
Simple merge
index feb728cbdd56461d69399653146bccf27ec47f7b,b09f2f39ef39cc2bb0fe92e26f81f643294cef00..3b44d6d7df4a2d77f035d048e2b4fa6852b2d210
  #include "readinp.h"
  #include "calcgrid.h"
  #include "checkpoint.h"
++#include "macros.h"
  #include "gmx_ana.h"
  #include "names.h"
- #include "macros.h"
+ #include "perf_est.h"
  
  
- enum {
-   ddnoSEL, ddnoINTERLEAVE, ddnoPP_PME, ddnoCARTESIAN, ddnoNR
- };
  
  /* Enum for situations that can occur during log file parsing, the
   * corresponding string entries can be found in do_the_tests() in