00001 __copyright__ = """
00002 Copyright 2008 Henryk Modzelewski
00003 """
00004 __license__ = """
00005 This file is part of SLIMpy .
00006
00007 SLIMpy is free software: you can redistribute it and/or modify
00008 it under the terms of the GNU Lesser General Public License as published by
00009 the Free Software Foundation, either version 3 of the License, or
00010 (at your option) any later version.
00011
00012 SLIMpy is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00015 GNU Lesser General Public License for more details.
00016
00017 You should have received a copy of the GNU Lesser General Public License
00018 along with SLIMpy . If not, see <http://www.gnu.org/licenses/>.
00019 """
00020
00021 def Sign (a):
00022 '''
00023 Module-internal sign function.
00024 Returns sign(a).
00025 '''
00026 if a >= 0: return 1
00027 else: return -1
00028
00029 def SignDiff (a,b):
00030 '''
00031 Module-internal sign function.
00032 Returns sign(b-a).
00033 '''
00034 if b >= a: return 1
00035 else: return -1
00036
00037 class OneDimStep1:
00038 '''
00039 One-dimensional stepper w/ abs(increment)=1.
00040 Object holds integer values to be used only in
00041 'for * in [Stepper]:' loop.
00042 '''
00043 def __init__(self,start,stop):
00044 self.__sign = SignDiff(start,stop)
00045 self.__start = start
00046 self.__val = -1
00047 self.__end = (stop - start) * self.__sign
00048 def __iter__(self):
00049 return self
00050 def next(self):
00051 if self.__val == self.__end:
00052 raise StopIteration
00053 self.__val += 1
00054 index = self.__start + self.__val * self.__sign
00055 return index
00056
00057 class OneDimStepF:
00058 '''
00059 One-dimensional stepper w/ float abs(increment)
00060 Object holds float values to be used only in
00061 'for * in [Stepper]:' loop.
00062 '''
00063 def __init__(self,start,stop,incr):
00064 self.__sign = SignDiff(start,stop)
00065 self.__start = start
00066 self.__incr = abs(incr)
00067 self.__val = -1
00068 self.__end = int(float(stop - start)/float(abs(incr))) * self.__sign
00069 def __iter__(self):
00070 return self
00071 def next(self):
00072 if self.__val == self.__end:
00073 raise StopIteration
00074 self.__val += 1
00075 index = self.__start + self.__val * self.__incr * self.__sign
00076 return index
00077
00078 class OneDimStepN:
00079 '''
00080 One-dimensional stepper w/ fixed number of elements
00081 Object holds float values to be used only in
00082 'for * in [Stepper]:' loop.
00083 '''
00084 def __init__(self,start,stop,cnt):
00085 self.__sign = SignDiff(start,stop)
00086 self.__start = start
00087 self.__incr = abs(float(stop-start)/float(abs(cnt)-1))
00088 self.__val = -1
00089 self.__end = abs(cnt)-1
00090 def __iter__(self):
00091 return self
00092 def next(self):
00093 if self.__val == self.__end:
00094 raise StopIteration
00095 self.__val += 1
00096 index = self.__start + self.__val * self.__incr * self.__sign
00097 return index
00098
00099 class MultiDimStep1:
00100 '''
00101 Multi-dimensional stepper w/ abs(increments)=1.
00102 Object holds lists of integer values to be used only in
00103 'for * in [Stepper]:' loop.
00104 '''
00105 def __init__(self,limits):
00106 self.__lngth = len(limits)
00107 self.__starts = []
00108 self.__signs = []
00109 self.__sizes = []
00110 for limit in limits:
00111 if len(limit) != 2:
00112 print 'Fatal error: wrong limits', limit, 'in', limits
00113 raise TypeError
00114 return
00115 self.__starts.append(limit[0])
00116 self.__signs.append(SignDiff(limit[0],limit[1]))
00117 self.__sizes.append(SignDiff(limit[0],limit[1])*(limit[1]-limit[0])+1)
00118 self.__val = -1
00119 self.__end = 1
00120 for size in self.__sizes:
00121 self.__end *= size
00122 self.__end -= 1
00123 self.__divs = self.__sizes[1:]
00124 for i in range(self.__lngth-3,-1,-1):
00125 self.__divs[i]*=self.__divs[i+1]
00126 def __iter__(self):
00127 return self
00128 def next(self):
00129 if self.__val == self.__end:
00130 raise StopIteration
00131 self.__val += 1
00132 indxs = []
00133 val = self.__val
00134 for div in self.__divs:
00135 indx = val / div
00136 indxs.append(indx)
00137 val = val % div
00138 indxs.append(val)
00139 for i in range(0,self.__lngth):
00140 indxs[i] = self.__starts[i] + indxs[i] * self.__signs[i]
00141 return indxs
00142
00143 class MultiDimStepF:
00144 '''
00145 Multi-dimensional stepper w/ float abs(increments).
00146 Object holds lists of float values to be used only in
00147 'for * in [Stepper]:' loop.
00148 '''
00149 def __init__(self,limits):
00150 self.__lngth = len(limits)
00151 self.__starts = []
00152 self.__signs = []
00153 self.__incrs = []
00154 self.__sizes = []
00155 for limit in limits:
00156 if len(limit) != 3:
00157 print 'Fatal error: wrong limits', limit, 'in', limits
00158 raise TypeError
00159 return
00160 self.__starts.append(limit[0])
00161 self.__signs.append(SignDiff(limit[0],limit[1]))
00162 self.__incrs.append(abs(limit[2]))
00163 self.__sizes.append(SignDiff(limit[0],limit[1])*int(float(limit[1]-limit[0])/limit[2])+1)
00164
00165 self.__val = -1
00166 self.__end = 1
00167 for size in self.__sizes:
00168 self.__end *= size
00169 self.__end -= 1
00170 self.__divs = self.__sizes[1:]
00171 for i in range(self.__lngth-3,-1,-1):
00172 self.__divs[i]*=self.__divs[i+1]
00173 def __iter__(self):
00174 return self
00175 def next(self):
00176 if self.__val == self.__end:
00177 raise StopIteration
00178 self.__val += 1
00179 indxs = []
00180 val = self.__val
00181 for div in self.__divs:
00182 indx = val / div
00183 indxs.append(indx)
00184 val = val % div
00185 indxs.append(val)
00186 for i in range(0,self.__lngth):
00187 indxs[i] = self.__starts[i] + indxs[i] * self.__incrs[i] * self.__signs[i]
00188 return indxs
00189
00190 class MultiDimStepN:
00191 '''
00192 Multi-dimensional stepper w/ fixed number of elements.
00193 Object holds lists of float values to be used only in
00194 'for * in [Stepper]:' loop.
00195 '''
00196 def __init__(self,limits):
00197 self.__lngth = len(limits)
00198 self.__starts = []
00199 self.__signs = []
00200 self.__incrs = []
00201 self.__sizes = []
00202 for limit in limits:
00203 if len(limit) != 3:
00204 print 'Fatal error: wrong limits', limit, 'in', limits
00205 raise TypeError
00206 return
00207 self.__starts.append(limit[0])
00208 self.__signs.append(SignDiff(limit[0],limit[1]))
00209 self.__incrs.append(abs(float(limit[1]-limit[0])/float(abs(limit[2])-1)))
00210 self.__sizes.append(abs(limit[2]))
00211 self.__val = -1
00212 self.__end = 1
00213 for size in self.__sizes:
00214 self.__end *= size
00215 self.__end -= 1
00216 self.__divs = self.__sizes[1:]
00217 for i in range(self.__lngth-3,-1,-1):
00218 self.__divs[i]*=self.__divs[i+1]
00219 def __iter__(self):
00220 return self
00221 def next(self):
00222 if self.__val == self.__end:
00223 raise StopIteration
00224 self.__val += 1
00225 indxs = []
00226 val = self.__val
00227 for div in self.__divs:
00228 indx = val / div
00229 indxs.append(indx)
00230 val = val % div
00231 indxs.append(val)
00232 for i in range(0,self.__lngth):
00233 indxs[i] = self.__starts[i] + indxs[i] * self.__incrs[i] * self.__signs[i]
00234 return indxs
00235
00236
00237 if __name__ == '__main__':
00238 print __doc__
00239
00240 print 80*'-'
00241 print OneDimStep1.__doc__
00242 print 'Example: OneDimStep1(',0,',',-3,')'
00243 print 'iterates through:'
00244 Ns = OneDimStep1(0,-3)
00245 for n in Ns:
00246 print '\t',n
00247
00248 print 80*'-'
00249 print OneDimStepF.__doc__
00250 print 'Example: OneDimStepF(',0.1,',',0.35,',',0.1,')'
00251 print 'iterates through:'
00252 Ns = OneDimStepF(0.1,0.35,0.1)
00253 for n in Ns:
00254 print '\t',n
00255
00256 print 80*'-'
00257 print OneDimStepN.__doc__
00258 print 'Example: OneDimStepN(',0.1,',',0.35,',',6,')'
00259 print 'iterates through:'
00260 Ns = OneDimStepN(0.1,0.35,6)
00261 for n in Ns:
00262 print '\t',n
00263
00264 print 80*'-'
00265 print MultiDimStep1.__doc__
00266 limits = [[0,1],[4,2]]
00267 print 'Example: MultiDimStep1(',limits,')'
00268 print 'iterates through:'
00269 NNs = MultiDimStep1(limits)
00270 for nn in NNs:
00271 print '\t',nn
00272
00273 print 80*'-'
00274 print MultiDimStepF.__doc__
00275 limits = [[0,1,0.5],[4,2,0.6]]
00276 print 'Example: MultiDimStepF(',limits,')'
00277 print 'iterates through:'
00278 NNs = MultiDimStepF(limits)
00279 for nn in NNs:
00280 print '\t',nn
00281
00282 print 80*'-'
00283 print MultiDimStepN.__doc__
00284 limits = [[0,1,3],[4,2,2]]
00285 print 'Example: MultiDimStepN(',limits,')'
00286 print 'iterates through:'
00287 NNs = MultiDimStepN(limits)
00288 for nn in NNs:
00289 print '\t',nn
00290
00291 print 80*'-'