You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
3.2 KiB

  1. # -*- coding: utf-8 -*-
  2. # © 2014-2015 ACSONE SA/NV (<http://acsone.eu>)
  3. # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
  4. """ A trivial immutable array that supports basic arithmetic operations.
  5. >>> a = SimpleArray((1.0, 2.0, 3.0))
  6. >>> b = SimpleArray((4.0, 5.0, 6.0))
  7. >>> t = (4.0, 5.0, 6.0)
  8. >>> +a
  9. SimpleArray((1.0, 2.0, 3.0))
  10. >>> -a
  11. SimpleArray((-1.0, -2.0, -3.0))
  12. >>> a + b
  13. SimpleArray((5.0, 7.0, 9.0))
  14. >>> b + a
  15. SimpleArray((5.0, 7.0, 9.0))
  16. >>> a + t
  17. SimpleArray((5.0, 7.0, 9.0))
  18. >>> t + a
  19. SimpleArray((5.0, 7.0, 9.0))
  20. >>> a - b
  21. SimpleArray((-3.0, -3.0, -3.0))
  22. >>> a - t
  23. SimpleArray((-3.0, -3.0, -3.0))
  24. >>> t - a
  25. SimpleArray((3.0, 3.0, 3.0))
  26. >>> a * b
  27. SimpleArray((4.0, 10.0, 18.0))
  28. >>> b * a
  29. SimpleArray((4.0, 10.0, 18.0))
  30. >>> a * t
  31. SimpleArray((4.0, 10.0, 18.0))
  32. >>> t * a
  33. SimpleArray((4.0, 10.0, 18.0))
  34. >>> a / b
  35. SimpleArray((0.25, 0.4, 0.5))
  36. >>> b / a
  37. SimpleArray((4.0, 2.5, 2.0))
  38. >>> a / t
  39. SimpleArray((0.25, 0.4, 0.5))
  40. >>> t / a
  41. SimpleArray((4.0, 2.5, 2.0))
  42. >>> b / 2
  43. SimpleArray((2.0, 2.5, 3.0))
  44. >>> 2 * b
  45. SimpleArray((8.0, 10.0, 12.0))
  46. >>> b += 2 ; b
  47. SimpleArray((6.0, 7.0, 8.0))
  48. >>> a / ((1.0, 0.0, 1.0))
  49. SimpleArray((1.0, DataError(), 3.0))
  50. >>> a / 0.0
  51. SimpleArray((DataError(), DataError(), DataError()))
  52. """
  53. import operator
  54. import traceback
  55. from .data_error import DataError
  56. __all__ = ['SimpleArray']
  57. # TODO named tuple-like behaviour, so expressions can work on subkpis
  58. class SimpleArray(tuple):
  59. def _op(self, op, other):
  60. def _o2(x, y):
  61. try:
  62. return op(x, y)
  63. except ZeroDivisionError:
  64. return DataError('#DIV/0', traceback.format_exc())
  65. except:
  66. return DataError('#ERR', traceback.format_exc())
  67. if isinstance(other, tuple):
  68. if len(other) != len(self):
  69. raise TypeError("tuples must have same length for %s" % op)
  70. return SimpleArray(map(_o2, self, other))
  71. else:
  72. return SimpleArray(map(lambda z: _o2(z, other), self))
  73. def __add__(self, other):
  74. return self._op(operator.add, other)
  75. __radd__ = __add__
  76. def __pos__(self):
  77. return SimpleArray(map(operator.pos, self))
  78. def __neg__(self):
  79. return SimpleArray(map(operator.neg, self))
  80. def __sub__(self, other):
  81. return self._op(operator.sub, other)
  82. def __rsub__(self, other):
  83. return SimpleArray(other)._op(operator.sub, self)
  84. def __mul__(self, other):
  85. return self._op(operator.mul, other)
  86. __rmul__ = __mul__
  87. def __div__(self, other):
  88. return self._op(operator.div, other)
  89. def __floordiv__(self, other):
  90. return self._op(operator.floordiv, other)
  91. def __truediv__(self, other):
  92. return self._op(operator.truediv, other)
  93. def __rdiv__(self, other):
  94. return SimpleArray(other)._op(operator.div, self)
  95. def __rfloordiv__(self, other):
  96. return SimpleArray(other)._op(operator.floordiv, self)
  97. def __rtruediv__(self, other):
  98. return SimpleArray(other)._op(operator.truediv, self)
  99. def __repr__(self):
  100. return "SimpleArray(%s)" % tuple.__repr__(self)
  101. if __name__ == '__main__':
  102. import doctest
  103. doctest.testmod()