NZMATH  1.2.0 About: NZMATH is a Python based number theory oriented calculation system.   Fossies Dox: NZMATH-1.2.0.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)
bigrange.py
Go to the documentation of this file.
1 """
2 bigrange
3
4 Generators for range like sequences.
5 """
6
7
8 def count(n=0):
9  """
10  Count up infinitely from 'n' (default to 0),
11
12  see itertools.count
13  """
14  while True:
15  yield n
16  n += 1
17
18
19 def range(start, stop=None, step=None):
20  """
21  Generate range like finite integer sequence but can generate more
22  than sys.maxint elements.
23  """
24  if step is None:
25  step = 1
26  elif not isinstance(step, (int, long)):
27  raise ValueError("non-integer step for range()")
28  if not isinstance(start, (int, long)):
29  raise ValueError("non-integer arg 1 for range()")
30  if stop is None:
31  start, stop = 0, start
32  elif not isinstance(stop, (int, long)):
33  raise ValueError("non-integer stop for range()")
34
35  if step > 0:
36  n = start
37  while n < stop:
38  yield n
39  n += step
40  elif step < 0:
41  n = start
42  while n > stop:
43  yield n
44  n += step
45  else:
46  raise ValueError("zero step for range()")
47
48
49 def arithmetic_progression(init, difference):
50  """
51  Generate an arithmetic progression start form 'init' and
52  'difference' step.
53  """
54  return _iterate(lambda x: x + difference, init)
55
56
57 def geometric_progression(init, ratio):
58  """
59  Generate a geometric progression start form 'init' and multiplying
60  'ratio'.
61  """
62  return _iterate(lambda x: x * ratio, init)
63
64
65 def _iterate(func, init):
66  """
67  Generate (infinitely) a sequence (init, func(init), func(func(init)), ...)
68  """
69  val = init
70  while True:
71  yield val
72  val = func(val)
73
74
75 def multirange(triples):
76  """
77  multirange(list of range triples) is an iterator over cartesian
78  product of elements of ranges.
79
80  For example, multirange([(1, 10, 3), (1, 10, 4)]) yields
81  (1, 1), (1, 5), (1, 9), (4, 1), (4, 5), (4, 9), (7, 1), (7, 5),
82  and (7, 9).
83
84  The range triples may be doubles (start, stop) or single (stop,),
85  but they have to be always tuples.
86
87  Be cautious that using this module usually means you are trying to
88  do brute force looping.
89  """
90  starts, stops, steps = _split_triples(triples)
91  if _empty(starts, stops, steps):
92  raise StopIteration("empty range")
93  i, values = len(triples) - 1, list(starts)
94  yield tuple(values)
95  while i >= 0:
96  values[i] += steps[i]
97  if _range_exhausted(i, values, steps, stops):
98  values[i] = starts[i]
99  i -= 1
100  continue
101  yield tuple(values)
102  i = len(triples) - 1
103
104 def _split_triples(triples):
105  """
106  Convert a list of triples into three lists each consists of 1st,
107  2nd and 3rd element of each triples.
108
109  The range triples may be doubles (start, stop) or single (stop,),
110  but they have to be always tuples.
111  """
112  starts, stops, steps = [], [], []
113  for triple in triples:
114  if len(triple) == 3:
115  start, stop, step = triple
116  elif len(triple) == 2:
117  start, stop, step = triple[0], triple[1], 1
118  elif len(triple) == 1:
119  start, stop, step = 0, triple[0], 1
120  else:
121  raise TypeError("tuple is longer or shorter than expected 1 to 3")
122  starts.append(start)
123  stops.append(stop)
124  steps.append(step)
125  return starts, stops, steps
126
127 def _empty(starts, stops, steps):
128  """
129  Report whether there is an empty range in the triples or not.
130  """
131  for start, stop, step in zip(starts, stops, steps):
132  if step * (stop - start) <= 0:
133  return True
134  return False
135
136 def _range_exhausted(i, values, steps, stops):
137  """
138  Check if a range at i is exhausted.
139  """
140  return steps[i] * (values[i] - stops[i]) >= 0
141
142
143 def multirange_restrictions(triples, ascending=(), descending=(), strictly_ascending=(), strictly_descending=()):
144  """
145  multirange_restrictions is an iterator similar to the multirange
146  but putting restrictions on each ranges. A restriction ascending
147  is a sequence that specifies the indices where the number emitted
148  by the range should be greater than or equal to the number at the
149  previous index. Other restrictions descending, strictly_ascending
150  and strictly_descending are similar.
151
152  For example, while multirange([(1, 10, 3), (1, 10, 4)]) yields
153  (1, 1), (1, 5), (1, 9), (4, 1), (4, 5), (4, 9), (7, 1), (7, 5),
154  and (7, 9),
155  multirange_restrictions([(1, 10, 3), (1, 10, 4)], ascending=(1,))
156  yields only (1, 1), (1, 5), (1, 9), (4, 5), (4, 9) and (7, 9).
157
158  The range triples may be doubles (start, stop) or single (stop,),
159  but they have to be always tuples.
160  """
161  starts, stops, steps = _split_triples(triples)
162  if _empty(starts, stops, steps):
163  raise StopIteration("empty range")
164  i, values = len(triples) - 1, list(starts)
165  while i >= 0:
166  if _range_exhausted(i, values, steps, stops):
167  values[i] = starts[i]
168  i -= 1
169  elif (strictly_ascending and _violate_strictly_ascending(values, strictly_ascending) or
170  ascending and _violate_ascending(values, ascending) or
171  strictly_descending and _violate_strictly_descending(values, strictly_descending) or
172  descending and _violate_descending(values, descending)):
173  i = min(i + 1, len(triples) - 1)
174  else:
175  yield tuple(values)
176  i = len(triples) - 1
177  values[i] += steps[i]
178
179 def _violate_ascending(values, ascending):
180  """
181  Check if values violate ascending restrictions.
182  """
183  for i in ascending:
184  if values[i - 1] > values[i]:
185  return True
186  return False
187
188 def _violate_strictly_ascending(values, ascending):
189  """
190  Check if values violate strictly-ascending restrictions.
191  """
192  for i in ascending:
193  if values[i - 1] >= values[i]:
194  return True
195  return False
196
197 def _violate_descending(values, descending):
198  """
199  Check if values violate descending restrictions.
200  """
201  for i in descending:
202  if values[i - 1] < values[i]:
203  return True
204  return False
205
206 def _violate_strictly_descending(values, descending):
207  """
208  Check if values violate strictly-descending restrictions.
209  """
210  for i in descending:
211  if values[i - 1] <= values[i]:
212  return True
213  return False
nzmath.bigrange.geometric_progression
def geometric_progression(init, ratio)
Definition: bigrange.py:57
nzmath.bigrange.range
def range(start, stop=None, step=None)
Definition: bigrange.py:19
nzmath.bigrange.arithmetic_progression
def arithmetic_progression(init, difference)
Definition: bigrange.py:49
nzmath.bigrange._violate_strictly_descending
def _violate_strictly_descending(values, descending)
Definition: bigrange.py:206
nzmath.bigrange._violate_descending
def _violate_descending(values, descending)
Definition: bigrange.py:197
nzmath.bigrange._violate_strictly_ascending
def _violate_strictly_ascending(values, ascending)
Definition: bigrange.py:188
nzmath.bigrange._violate_ascending
def _violate_ascending(values, ascending)
Definition: bigrange.py:179
nzmath.bigrange._iterate
def _iterate(func, init)
Definition: bigrange.py:65
nzmath.bigrange.count
def count(n=0)
Definition: bigrange.py:8
nzmath.bigrange.multirange_restrictions
def multirange_restrictions(triples, ascending=(), descending=(), strictly_ascending=(), strictly_descending=())
Definition: bigrange.py:143
nzmath.bigrange.multirange
def multirange(triples)
Definition: bigrange.py:75
nzmath.bigrange._empty
def _empty(starts, stops, steps)
Definition: bigrange.py:127
nzmath.bigrange._range_exhausted
def _range_exhausted(i, values, steps, stops)
Definition: bigrange.py:136
nzmath.bigrange._split_triples
def _split_triples(triples)
Definition: bigrange.py:104