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 '''
00022 Module with number of iterable objects (steppers).
00023
00024 Execute 'python /path_to_module/Steppers.py' to see the examples.
00025
00026 NOTE: Subclassing those objects was not tested.
00027 '''
00028
00029 def Sign (a):
00030 '''
00031 Module-internal sign function.
00032 Returns sign(a).
00033 '''
00034 if a >= 0: return 1
00035 else: return -1
00036
00037 def SignDiff (a,b):
00038 '''
00039 Module-internal sign function.
00040 Returns sign(b-a).
00041 '''
00042 if b >= a: return 1
00043 else: return -1
00044
00045 class OneDimStep1:
00046 '''
00047 One-dimensional stepper w/ abs(increment)=1.
00048 Object holds integer values to be used only in
00049 'for * in [Stepper]:' loop.
00050 '''
00051 def __init__(self,start,stop):
00052 self.__sign = SignDiff(start,stop)
00053 self.__start = start
00054 self.__val = -1
00055 self.__end = (stop - start) * self.__sign
00056 def __iter__(self):
00057 return self
00058 def next(self):
00059 if self.__val == self.__end:
00060 raise StopIteration
00061 self.__val += 1
00062 index = self.__start + self.__val * self.__sign
00063 return index
00064
00065 class OneDimStepF:
00066 '''
00067 One-dimensional stepper w/ float abs(increment)
00068 Object holds float values to be used only in
00069 'for * in [Stepper]:' loop.
00070 '''
00071 def __init__(self,start,stop,incr):
00072 self.__sign = SignDiff(start,stop)
00073 self.__start = start
00074 self.__incr = abs(incr)
00075 self.__val = -1
00076 self.__end = int(float(stop - start)/float(abs(incr))) * self.__sign
00077 def __iter__(self):
00078 return self
00079 def next(self):
00080 if self.__val == self.__end:
00081 raise StopIteration
00082 self.__val += 1
00083 index = self.__start + self.__val * self.__incr * self.__sign
00084 return index
00085
00086 class OneDimStepN:
00087 '''
00088 One-dimensional stepper w/ fixed number of elements
00089 Object holds float values to be used only in
00090 'for * in [Stepper]:' loop.
00091 '''
00092 def __init__(self,start,stop,cnt):
00093 self.__sign = SignDiff(start,stop)
00094 self.__start = start
00095 self.__incr = abs(float(stop-start)/float(abs(cnt)-1))
00096 self.__val = -1
00097 self.__end = abs(cnt)-1
00098 def __iter__(self):
00099 return self
00100 def next(self):
00101 if self.__val == self.__end:
00102 raise StopIteration
00103 self.__val += 1
00104 index = self.__start + self.__val * self.__incr * self.__sign
00105 return index
00106
00107 class MultiDimStep1:
00108 '''
00109 Multi-dimensional stepper w/ abs(increments)=1.
00110 Object holds lists of integer values to be used only in
00111 'for * in [Stepper]:' loop.
00112 '''
00113 def __init__(self,limits):
00114 self.__lngth = len(limits)
00115 self.__starts = []
00116 self.__signs = []
00117 self.__sizes = []
00118 for limit in limits:
00119 if len(limit) != 2:
00120 print 'Fatal error: wrong limits', limit, 'in', limits
00121 raise TypeError
00122 return
00123 self.__starts.append(limit[0])
00124 self.__signs.append(SignDiff(limit[0],limit[1]))
00125 self.__sizes.append(SignDiff(limit[0],limit[1])*(limit[1]-limit[0])+1)
00126 self.__val = -1
00127 self.__end = 1
00128 for size in self.__sizes:
00129 self.__end *= size
00130 self.__end -= 1
00131 self.__divs = self.__sizes[1:]
00132 for i in range(self.__lngth-3,-1,-1):
00133 self.__divs[i]*=self.__divs[i+1]
00134 def __iter__(self):
00135 return self
00136 def next(self):
00137 if self.__val == self.__end:
00138 raise StopIteration
00139 self.__val += 1
00140 indxs = []
00141 val = self.__val
00142 for div in self.__divs:
00143 indx = val / div
00144 indxs.append(indx)
00145 val = val % div
00146 indxs.append(val)
00147 for i in range(0,self.__lngth):
00148 indxs[i] = self.__starts[i] + indxs[i] * self.__signs[i]
00149 return indxs
00150
00151 class MultiDimStepF:
00152 '''
00153 Multi-dimensional stepper w/ float abs(increments).
00154 Object holds lists of float values to be used only in
00155 'for * in [Stepper]:' loop.
00156 '''
00157 def __init__(self,limits):
00158 self.__lngth = len(limits)
00159 self.__starts = []
00160 self.__signs = []
00161 self.__incrs = []
00162 self.__sizes = []
00163 for limit in limits:
00164 if len(limit) != 3:
00165 print 'Fatal error: wrong limits', limit, 'in', limits
00166 raise TypeError
00167 return
00168 self.__starts.append(limit[0])
00169 self.__signs.append(SignDiff(limit[0],limit[1]))
00170 self.__incrs.append(abs(limit[2]))
00171 self.__sizes.append(SignDiff(limit[0],limit[1])*int(float(limit[1]-limit[0])/limit[2])+1)
00172
00173 self.__val = -1
00174 self.__end = 1
00175 for size in self.__sizes:
00176 self.__end *= size
00177 self.__end -= 1
00178 self.__divs = self.__sizes[1:]
00179 for i in range(self.__lngth-3,-1,-1):
00180 self.__divs[i]*=self.__divs[i+1]
00181 def __iter__(self):
00182 return self
00183 def next(self):
00184 if self.__val == self.__end:
00185 raise StopIteration
00186 self.__val += 1
00187 indxs = []
00188 val = self.__val
00189 for div in self.__divs:
00190 indx = val / div
00191 indxs.append(indx)
00192 val = val % div
00193 indxs.append(val)
00194 for i in range(0,self.__lngth):
00195 indxs[i] = self.__starts[i] + indxs[i] * self.__incrs[i] * self.__signs[i]
00196 return indxs
00197
00198 class MultiDimStepN:
00199 '''
00200 Multi-dimensional stepper w/ fixed number of elements.
00201 Object holds lists of float values to be used only in
00202 'for * in [Stepper]:' loop.
00203 '''
00204 def __init__(self,limits):
00205 self.__lngth = len(limits)
00206 self.__starts = []
00207 self.__signs = []
00208 self.__incrs = []
00209 self.__sizes = []
00210 for limit in limits:
00211 if len(limit) != 3:
00212 print 'Fatal error: wrong limits', limit, 'in', limits
00213 raise TypeError
00214 return
00215 self.__starts.append(limit[0])
00216 self.__signs.append(SignDiff(limit[0],limit[1]))
00217 self.__incrs.append(abs(float(limit[1]-limit[0])/float(abs(limit[2])-1)))
00218 self.__sizes.append(abs(limit[2]))
00219 self.__val = -1
00220 self.__end = 1
00221 for size in self.__sizes:
00222 self.__end *= size
00223 self.__end -= 1
00224 self.__divs = self.__sizes[1:]
00225 for i in range(self.__lngth-3,-1,-1):
00226 self.__divs[i]*=self.__divs[i+1]
00227 def __iter__(self):
00228 return self
00229 def next(self):
00230 if self.__val == self.__end:
00231 raise StopIteration
00232 self.__val += 1
00233 indxs = []
00234 val = self.__val
00235 for div in self.__divs:
00236 indx = val / div
00237 indxs.append(indx)
00238 val = val % div
00239 indxs.append(val)
00240 for i in range(0,self.__lngth):
00241 indxs[i] = self.__starts[i] + indxs[i] * self.__incrs[i] * self.__signs[i]
00242 return indxs
00243
00244
00245 if __name__ == '__main__':
00246 print __doc__
00247
00248 print 80*'-'
00249 print OneDimStep1.__doc__
00250 print 'Example: OneDimStep1(',0,',',-3,')'
00251 print 'iterates through:'
00252 Ns = OneDimStep1(0,-3)
00253 for n in Ns:
00254 print '\t',n
00255
00256 print 80*'-'
00257 print OneDimStepF.__doc__
00258 print 'Example: OneDimStepF(',0.1,',',0.35,',',0.1,')'
00259 print 'iterates through:'
00260 Ns = OneDimStepF(0.1,0.35,0.1)
00261 for n in Ns:
00262 print '\t',n
00263
00264 print 80*'-'
00265 print OneDimStepN.__doc__
00266 print 'Example: OneDimStepN(',0.1,',',0.35,',',6,')'
00267 print 'iterates through:'
00268 Ns = OneDimStepN(0.1,0.35,6)
00269 for n in Ns:
00270 print '\t',n
00271
00272 print 80*'-'
00273 print MultiDimStep1.__doc__
00274 limits = [[0,1],[4,2]]
00275 print 'Example: MultiDimStep1(',limits,')'
00276 print 'iterates through:'
00277 NNs = MultiDimStep1(limits)
00278 for nn in NNs:
00279 print '\t',nn
00280
00281 print 80*'-'
00282 print MultiDimStepF.__doc__
00283 limits = [[0,1,0.5],[4,2,0.6]]
00284 print 'Example: MultiDimStepF(',limits,')'
00285 print 'iterates through:'
00286 NNs = MultiDimStepF(limits)
00287 for nn in NNs:
00288 print '\t',nn
00289
00290 print 80*'-'
00291 print MultiDimStepN.__doc__
00292 limits = [[0,1,3],[4,2,2]]
00293 print 'Example: MultiDimStepN(',limits,')'
00294 print 'iterates through:'
00295 NNs = MultiDimStepN(limits)
00296 for nn in NNs:
00297 print '\t',nn
00298
00299 print 80*'-'