1.1 --- a/iixr/data.py Tue Feb 15 00:13:21 2011 +0100
1.2 +++ b/iixr/data.py Fri Sep 30 00:41:34 2011 +0200
1.3 @@ -23,7 +23,18 @@
1.4
1.5 # High-level representations.
1.6
1.7 -def convert_sequence(values, op, last_from_old):
1.8 +def convert_sequence(values, op, last_from_preceding):
1.9 +
1.10 + """
1.11 + Convert the given sequence of 'values' either to a sequence of delta values
1.12 + if 'op' is a subtractor of some kind, using the preceding value in the
1.13 + sequence as the basis of the calculation of a delta for the current value
1.14 + (with 'last_from_preceding' set to a true value), or from a sequence of
1.15 + delta values if 'op' is an adder of some kind, using the last result as the
1.16 + basis of the calculation of an absolute value (with 'last_from_preceding'
1.17 + set to a false value).
1.18 + """
1.19 +
1.20 if values:
1.21 new_values = list(values)
1.22 last = new_values[0]
1.23 @@ -36,7 +47,7 @@
1.24 # Subtracting entries requires the old value to be used.
1.25 # Adding entries requires the new value.
1.26
1.27 - if last_from_old:
1.28 + if last_from_preceding:
1.29 last = current
1.30 else:
1.31 last = new_values[i]
1.32 @@ -47,6 +58,13 @@
1.33 else:
1.34 return values
1.35
1.36 +# Monotonic operators where an input sequence must always, when combined with an
1.37 +# operand, produce a result whose elements are all greater than or equal to the
1.38 +# values of the input sequence (for addition) or all less than or equal to the
1.39 +# values of the input sequence (for subtraction).
1.40 +#
1.41 +# For example: (1, 2) -> (2, 2) -> (2, 3) -> (3, 4)
1.42 +
1.43 def op_seq_monotonic(x, y, op):
1.44 return tuple([op(a, b) for a, b in zip(x, y)])
1.45
1.46 @@ -56,37 +74,66 @@
1.47 def sub_seq_monotonic(x, y):
1.48 return op_seq_monotonic(x, y, operator.sub)
1.49
1.50 -def add_seq(x, y):
1.51 - length = min(len(x), len(y))
1.52 - seq = list(x)[:length]
1.53 +# Operators where an input sequence, when combined with an operand, may produce
1.54 +# a result whose elements generally obey the properties for a monotonic sequence
1.55 +# as described above, but where an element in the result may be reset with
1.56 +# respect to the corresponding element in the input sequence and be less than
1.57 +# that element (for addition) or greater than that element (for subtraction).
1.58 +#
1.59 +# For example: (1, 2) -> (2, 0) -> (2, 3) -> (3, 1)
1.60 +
1.61 +def add_seq(delta, input):
1.62 +
1.63 + "Add 'delta' to 'input'."
1.64 +
1.65 + length = min(len(delta), len(input))
1.66 + seq = list(delta)[:length]
1.67 i = 0
1.68 while i < length:
1.69 - if x[i] != 0:
1.70 - seq[i] = x[i] + y[i]
1.71 +
1.72 + # If the delta is not zero, apply it to the input and retain the rest of
1.73 + # the delta sequence as absolute values in the result.
1.74 +
1.75 + if delta[i] != 0:
1.76 + seq[i] = delta[i] + input[i]
1.77 break
1.78 - seq[i] = y[i]
1.79 +
1.80 + seq[i] = input[i]
1.81 i += 1
1.82 return tuple(seq)
1.83
1.84 -def sub_seq(x, y):
1.85 - length = min(len(x), len(y))
1.86 - seq = list(x)[:length]
1.87 +def sub_seq(current, last):
1.88 +
1.89 + "Subtract 'current' from 'last'."
1.90 +
1.91 + length = min(len(current), len(last))
1.92 + seq = list(current)[:length]
1.93 i = 0
1.94 while i < length:
1.95 - replacement = x[i] - y[i]
1.96 +
1.97 + # Calculate a suitable delta value. If it is not zero, record it and
1.98 + # retain the rest of the current value to reset the sequence in the
1.99 + # result.
1.100 +
1.101 + replacement = current[i] - last[i]
1.102 if replacement != 0:
1.103 seq[i] = replacement
1.104 break
1.105 +
1.106 seq[i] = 0
1.107 i += 1
1.108 return tuple(seq)
1.109
1.110 +# Data inspection functions.
1.111 +
1.112 def is_sequence(value):
1.113 return isinstance(value, (list, tuple))
1.114
1.115 def sizeof(value):
1.116 return is_sequence(value) and len(value) or 0
1.117
1.118 +# Functions returning operators appropriate for the given structure size.
1.119 +
1.120 def get_monotonic_adder(size):
1.121 return size and add_seq_monotonic or operator.add
1.122