| Chris@82 | 1 /* | 
| Chris@82 | 2  * Copyright (c) 2003, 2007-14 Matteo Frigo | 
| Chris@82 | 3  * Copyright (c) 2003, 2007-14 Massachusetts Institute of Technology | 
| Chris@82 | 4  * | 
| Chris@82 | 5  * This program is free software; you can redistribute it and/or modify | 
| Chris@82 | 6  * it under the terms of the GNU General Public License as published by | 
| Chris@82 | 7  * the Free Software Foundation; either version 2 of the License, or | 
| Chris@82 | 8  * (at your option) any later version. | 
| Chris@82 | 9  * | 
| Chris@82 | 10  * This program is distributed in the hope that it will be useful, | 
| Chris@82 | 11  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| Chris@82 | 12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
| Chris@82 | 13  * GNU General Public License for more details. | 
| Chris@82 | 14  * | 
| Chris@82 | 15  * You should have received a copy of the GNU General Public License | 
| Chris@82 | 16  * along with this program; if not, write to the Free Software | 
| Chris@82 | 17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | 
| Chris@82 | 18  * | 
| Chris@82 | 19  */ | 
| Chris@82 | 20 | 
| Chris@82 | 21 | 
| Chris@82 | 22 #include "kernel/ifftw.h" | 
| Chris@82 | 23 | 
| Chris@82 | 24 INT X(tensor_max_index)(const tensor *sz) | 
| Chris@82 | 25 { | 
| Chris@82 | 26      int i; | 
| Chris@82 | 27      INT ni = 0, no = 0; | 
| Chris@82 | 28 | 
| Chris@82 | 29      A(FINITE_RNK(sz->rnk)); | 
| Chris@82 | 30      for (i = 0; i < sz->rnk; ++i) { | 
| Chris@82 | 31           const iodim *p = sz->dims + i; | 
| Chris@82 | 32           ni += (p->n - 1) * X(iabs)(p->is); | 
| Chris@82 | 33           no += (p->n - 1) * X(iabs)(p->os); | 
| Chris@82 | 34      } | 
| Chris@82 | 35      return X(imax)(ni, no); | 
| Chris@82 | 36 } | 
| Chris@82 | 37 | 
| Chris@82 | 38 #define tensor_min_xstride(sz, xs) {			\ | 
| Chris@82 | 39      A(FINITE_RNK(sz->rnk));				\ | 
| Chris@82 | 40      if (sz->rnk == 0) return 0;			\ | 
| Chris@82 | 41      else {						\ | 
| Chris@82 | 42           int i;					\ | 
| Chris@82 | 43           INT s = X(iabs)(sz->dims[0].xs);		\ | 
| Chris@82 | 44           for (i = 1; i < sz->rnk; ++i)			\ | 
| Chris@82 | 45                s = X(imin)(s, X(iabs)(sz->dims[i].xs));	\ | 
| Chris@82 | 46           return s;					\ | 
| Chris@82 | 47      }							\ | 
| Chris@82 | 48 } | 
| Chris@82 | 49 | 
| Chris@82 | 50 INT X(tensor_min_istride)(const tensor *sz) tensor_min_xstride(sz, is) | 
| Chris@82 | 51 INT X(tensor_min_ostride)(const tensor *sz) tensor_min_xstride(sz, os) | 
| Chris@82 | 52 | 
| Chris@82 | 53 INT X(tensor_min_stride)(const tensor *sz) | 
| Chris@82 | 54 { | 
| Chris@82 | 55      return X(imin)(X(tensor_min_istride)(sz), X(tensor_min_ostride)(sz)); | 
| Chris@82 | 56 } | 
| Chris@82 | 57 | 
| Chris@82 | 58 int X(tensor_inplace_strides)(const tensor *sz) | 
| Chris@82 | 59 { | 
| Chris@82 | 60      int i; | 
| Chris@82 | 61      A(FINITE_RNK(sz->rnk)); | 
| Chris@82 | 62      for (i = 0; i < sz->rnk; ++i) { | 
| Chris@82 | 63           const iodim *p = sz->dims + i; | 
| Chris@82 | 64           if (p->is != p->os) | 
| Chris@82 | 65                return 0; | 
| Chris@82 | 66      } | 
| Chris@82 | 67      return 1; | 
| Chris@82 | 68 } | 
| Chris@82 | 69 | 
| Chris@82 | 70 int X(tensor_inplace_strides2)(const tensor *a, const tensor *b) | 
| Chris@82 | 71 { | 
| Chris@82 | 72      return X(tensor_inplace_strides(a)) && X(tensor_inplace_strides(b)); | 
| Chris@82 | 73 } | 
| Chris@82 | 74 | 
| Chris@82 | 75 /* return true (1) iff *any* strides of sz decrease when we | 
| Chris@82 | 76    tensor_inplace_copy(sz, k). */ | 
| Chris@82 | 77 static int tensor_strides_decrease(const tensor *sz, inplace_kind k) | 
| Chris@82 | 78 { | 
| Chris@82 | 79      if (FINITE_RNK(sz->rnk)) { | 
| Chris@82 | 80           int i; | 
| Chris@82 | 81           for (i = 0; i < sz->rnk; ++i) | 
| Chris@82 | 82                if ((sz->dims[i].os - sz->dims[i].is) | 
| Chris@82 | 83                    * (k == INPLACE_OS ? (INT)1 : (INT)-1) < 0) | 
| Chris@82 | 84                     return 1; | 
| Chris@82 | 85      } | 
| Chris@82 | 86      return 0; | 
| Chris@82 | 87 } | 
| Chris@82 | 88 | 
| Chris@82 | 89 /* Return true (1) iff *any* strides of sz decrease when we | 
| Chris@82 | 90    tensor_inplace_copy(k) *or* if *all* strides of sz are unchanged | 
| Chris@82 | 91    but *any* strides of vecsz decrease.  This is used in indirect.c | 
| Chris@82 | 92    to determine whether to use INPLACE_IS or INPLACE_OS. | 
| Chris@82 | 93 | 
| Chris@82 | 94    Note: X(tensor_strides_decrease)(sz, vecsz, INPLACE_IS) | 
| Chris@82 | 95          || X(tensor_strides_decrease)(sz, vecsz, INPLACE_OS) | 
| Chris@82 | 96          || X(tensor_inplace_strides2)(p->sz, p->vecsz) | 
| Chris@82 | 97    must always be true. */ | 
| Chris@82 | 98 int X(tensor_strides_decrease)(const tensor *sz, const tensor *vecsz, | 
| Chris@82 | 99 			       inplace_kind k) | 
| Chris@82 | 100 { | 
| Chris@82 | 101      return(tensor_strides_decrease(sz, k) | 
| Chris@82 | 102 	    || (X(tensor_inplace_strides)(sz) | 
| Chris@82 | 103 		&& tensor_strides_decrease(vecsz, k))); | 
| Chris@82 | 104 } |