| cannam@95 | 1 /* | 
| cannam@95 | 2  * Copyright (c) 2003, 2007-11 Matteo Frigo | 
| cannam@95 | 3  * Copyright (c) 2003, 2007-11 Massachusetts Institute of Technology | 
| cannam@95 | 4  * | 
| cannam@95 | 5  * This program is free software; you can redistribute it and/or modify | 
| cannam@95 | 6  * it under the terms of the GNU General Public License as published by | 
| cannam@95 | 7  * the Free Software Foundation; either version 2 of the License, or | 
| cannam@95 | 8  * (at your option) any later version. | 
| cannam@95 | 9  * | 
| cannam@95 | 10  * This program is distributed in the hope that it will be useful, | 
| cannam@95 | 11  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| cannam@95 | 12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
| cannam@95 | 13  * GNU General Public License for more details. | 
| cannam@95 | 14  * | 
| cannam@95 | 15  * You should have received a copy of the GNU General Public License | 
| cannam@95 | 16  * along with this program; if not, write to the Free Software | 
| cannam@95 | 17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | 
| cannam@95 | 18  * | 
| cannam@95 | 19  */ | 
| cannam@95 | 20 | 
| cannam@95 | 21 #include "ifftw.h" | 
| cannam@95 | 22 | 
| cannam@95 | 23 | 
| cannam@95 | 24 /* Given a solver which_dim, a vector sz, and whether or not the | 
| cannam@95 | 25    transform is out-of-place, return the actual dimension index that | 
| cannam@95 | 26    it corresponds to.  The basic idea here is that we return the | 
| cannam@95 | 27    which_dim'th valid dimension, starting from the end if | 
| cannam@95 | 28    which_dim < 0. */ | 
| cannam@95 | 29 static int really_pickdim(int which_dim, const tensor *sz, int oop, int *dp) | 
| cannam@95 | 30 { | 
| cannam@95 | 31      int i; | 
| cannam@95 | 32      int count_ok = 0; | 
| cannam@95 | 33      if (which_dim > 0) { | 
| cannam@95 | 34           for (i = 0; i < sz->rnk; ++i) { | 
| cannam@95 | 35                if (oop || sz->dims[i].is == sz->dims[i].os) | 
| cannam@95 | 36                     if (++count_ok == which_dim) { | 
| cannam@95 | 37                          *dp = i; | 
| cannam@95 | 38                          return 1; | 
| cannam@95 | 39                     } | 
| cannam@95 | 40           } | 
| cannam@95 | 41      } | 
| cannam@95 | 42      else if (which_dim < 0) { | 
| cannam@95 | 43           for (i = sz->rnk - 1; i >= 0; --i) { | 
| cannam@95 | 44                if (oop || sz->dims[i].is == sz->dims[i].os) | 
| cannam@95 | 45                     if (++count_ok == -which_dim) { | 
| cannam@95 | 46                          *dp = i; | 
| cannam@95 | 47                          return 1; | 
| cannam@95 | 48                     } | 
| cannam@95 | 49           } | 
| cannam@95 | 50      } | 
| cannam@95 | 51      else { /* zero: pick the middle, if valid */ | 
| cannam@95 | 52 	  i = (sz->rnk - 1) / 2; | 
| cannam@95 | 53 	  if (i >= 0 && (oop || sz->dims[i].is == sz->dims[i].os)) { | 
| cannam@95 | 54 	       *dp = i; | 
| cannam@95 | 55 	       return 1; | 
| cannam@95 | 56 	  } | 
| cannam@95 | 57      } | 
| cannam@95 | 58      return 0; | 
| cannam@95 | 59 } | 
| cannam@95 | 60 | 
| cannam@95 | 61 /* Like really_pickdim, but only returns 1 if no previous "buddy" | 
| cannam@95 | 62    which_dim in the buddies list would give the same dim. */ | 
| cannam@95 | 63 int X(pickdim)(int which_dim, const int *buddies, int nbuddies, | 
| cannam@95 | 64 	       const tensor *sz, int oop, int *dp) | 
| cannam@95 | 65 { | 
| cannam@95 | 66      int i, d1; | 
| cannam@95 | 67 | 
| cannam@95 | 68      if (!really_pickdim(which_dim, sz, oop, dp)) | 
| cannam@95 | 69           return 0; | 
| cannam@95 | 70 | 
| cannam@95 | 71      /* check whether some buddy solver would produce the same dim. | 
| cannam@95 | 72         If so, consider this solver unapplicable and let the buddy | 
| cannam@95 | 73         take care of it.  The smallest-indexed buddy is applicable. */ | 
| cannam@95 | 74      for (i = 0; i < nbuddies; ++i) { | 
| cannam@95 | 75           if (buddies[i] == which_dim) | 
| cannam@95 | 76                break;  /* found self */ | 
| cannam@95 | 77           if (really_pickdim(buddies[i], sz, oop, &d1) && *dp == d1) | 
| cannam@95 | 78                return 0; /* found equivalent buddy */ | 
| cannam@95 | 79      } | 
| cannam@95 | 80      return 1; | 
| cannam@95 | 81 } |