1"""
2Standard container-class for easy multiple-inheritance.
3
4Try to inherit from the ndarray instead of using this class as this is not
5complete.
6
7"""
8from numpy.core import (
9    array, asarray, absolute, add, subtract, multiply, divide,
10    remainder, power, left_shift, right_shift, bitwise_and, bitwise_or,
11    bitwise_xor, invert, less, less_equal, not_equal, equal, greater,
12    greater_equal, shape, reshape, arange, sin, sqrt, transpose
13)
14
15
16class container:
17    """
18    container(data, dtype=None, copy=True)
19
20    Standard container-class for easy multiple-inheritance.
21
22    Methods
23    -------
24    copy
25    tostring
26    byteswap
27    astype
28
29    """
30    def __init__(self, data, dtype=None, copy=True):
31        self.array = array(data, dtype, copy=copy)
32
33    def __repr__(self):
34        if self.ndim > 0:
35            return self.__class__.__name__ + repr(self.array)[len("array"):]
36        else:
37            return self.__class__.__name__ + "(" + repr(self.array) + ")"
38
39    def __array__(self, t=None):
40        if t:
41            return self.array.astype(t)
42        return self.array
43
44    # Array as sequence
45    def __len__(self):
46        return len(self.array)
47
48    def __getitem__(self, index):
49        return self._rc(self.array[index])
50
51    def __setitem__(self, index, value):
52        self.array[index] = asarray(value, self.dtype)
53
54    def __abs__(self):
55        return self._rc(absolute(self.array))
56
57    def __neg__(self):
58        return self._rc(-self.array)
59
60    def __add__(self, other):
61        return self._rc(self.array + asarray(other))
62
63    __radd__ = __add__
64
65    def __iadd__(self, other):
66        add(self.array, other, self.array)
67        return self
68
69    def __sub__(self, other):
70        return self._rc(self.array - asarray(other))
71
72    def __rsub__(self, other):
73        return self._rc(asarray(other) - self.array)
74
75    def __isub__(self, other):
76        subtract(self.array, other, self.array)
77        return self
78
79    def __mul__(self, other):
80        return self._rc(multiply(self.array, asarray(other)))
81
82    __rmul__ = __mul__
83
84    def __imul__(self, other):
85        multiply(self.array, other, self.array)
86        return self
87
88    def __div__(self, other):
89        return self._rc(divide(self.array, asarray(other)))
90
91    def __rdiv__(self, other):
92        return self._rc(divide(asarray(other), self.array))
93
94    def __idiv__(self, other):
95        divide(self.array, other, self.array)
96        return self
97
98    def __mod__(self, other):
99        return self._rc(remainder(self.array, other))
100
101    def __rmod__(self, other):
102        return self._rc(remainder(other, self.array))
103
104    def __imod__(self, other):
105        remainder(self.array, other, self.array)
106        return self
107
108    def __divmod__(self, other):
109        return (self._rc(divide(self.array, other)),
110                self._rc(remainder(self.array, other)))
111
112    def __rdivmod__(self, other):
113        return (self._rc(divide(other, self.array)),
114                self._rc(remainder(other, self.array)))
115
116    def __pow__(self, other):
117        return self._rc(power(self.array, asarray(other)))
118
119    def __rpow__(self, other):
120        return self._rc(power(asarray(other), self.array))
121
122    def __ipow__(self, other):
123        power(self.array, other, self.array)
124        return self
125
126    def __lshift__(self, other):
127        return self._rc(left_shift(self.array, other))
128
129    def __rshift__(self, other):
130        return self._rc(right_shift(self.array, other))
131
132    def __rlshift__(self, other):
133        return self._rc(left_shift(other, self.array))
134
135    def __rrshift__(self, other):
136        return self._rc(right_shift(other, self.array))
137
138    def __ilshift__(self, other):
139        left_shift(self.array, other, self.array)
140        return self
141
142    def __irshift__(self, other):
143        right_shift(self.array, other, self.array)
144        return self
145
146    def __and__(self, other):
147        return self._rc(bitwise_and(self.array, other))
148
149    def __rand__(self, other):
150        return self._rc(bitwise_and(other, self.array))
151
152    def __iand__(self, other):
153        bitwise_and(self.array, other, self.array)
154        return self
155
156    def __xor__(self, other):
157        return self._rc(bitwise_xor(self.array, other))
158
159    def __rxor__(self, other):
160        return self._rc(bitwise_xor(other, self.array))
161
162    def __ixor__(self, other):
163        bitwise_xor(self.array, other, self.array)
164        return self
165
166    def __or__(self, other):
167        return self._rc(bitwise_or(self.array, other))
168
169    def __ror__(self, other):
170        return self._rc(bitwise_or(other, self.array))
171
172    def __ior__(self, other):
173        bitwise_or(self.array, other, self.array)
174        return self
175
176    def __pos__(self):
177        return self._rc(self.array)
178
179    def __invert__(self):
180        return self._rc(invert(self.array))
181
182    def _scalarfunc(self, func):
183        if self.ndim == 0:
184            return func(self[0])
185        else:
186            raise TypeError(
187                "only rank-0 arrays can be converted to Python scalars.")
188
189    def __complex__(self):
190        return self._scalarfunc(complex)
191
192    def __float__(self):
193        return self._scalarfunc(float)
194
195    def __int__(self):
196        return self._scalarfunc(int)
197
198    def __hex__(self):
199        return self._scalarfunc(hex)
200
201    def __oct__(self):
202        return self._scalarfunc(oct)
203
204    def __lt__(self, other):
205        return self._rc(less(self.array, other))
206
207    def __le__(self, other):
208        return self._rc(less_equal(self.array, other))
209
210    def __eq__(self, other):
211        return self._rc(equal(self.array, other))
212
213    def __ne__(self, other):
214        return self._rc(not_equal(self.array, other))
215
216    def __gt__(self, other):
217        return self._rc(greater(self.array, other))
218
219    def __ge__(self, other):
220        return self._rc(greater_equal(self.array, other))
221
222    def copy(self):
223        ""
224        return self._rc(self.array.copy())
225
226    def tostring(self):
227        ""
228        return self.array.tostring()
229
230    def tobytes(self):
231        ""
232        return self.array.tobytes()
233
234    def byteswap(self):
235        ""
236        return self._rc(self.array.byteswap())
237
238    def astype(self, typecode):
239        ""
240        return self._rc(self.array.astype(typecode))
241
242    def _rc(self, a):
243        if len(shape(a)) == 0:
244            return a
245        else:
246            return self.__class__(a)
247
248    def __array_wrap__(self, *args):
249        return self.__class__(args[0])
250
251    def __setattr__(self, attr, value):
252        if attr == 'array':
253            object.__setattr__(self, attr, value)
254            return
255        try:
256            self.array.__setattr__(attr, value)
257        except AttributeError:
258            object.__setattr__(self, attr, value)
259
260    # Only called after other approaches fail.
261    def __getattr__(self, attr):
262        if (attr == 'array'):
263            return object.__getattribute__(self, attr)
264        return self.array.__getattribute__(attr)
265
266#############################################################
267# Test of class container
268#############################################################
269if __name__ == '__main__':
270    temp = reshape(arange(10000), (100, 100))
271
272    ua = container(temp)
273    # new object created begin test
274    print(dir(ua))
275    print(shape(ua), ua.shape)  # I have changed Numeric.py
276
277    ua_small = ua[:3, :5]
278    print(ua_small)
279    # this did not change ua[0,0], which is not normal behavior
280    ua_small[0, 0] = 10
281    print(ua_small[0, 0], ua[0, 0])
282    print(sin(ua_small) / 3. * 6. + sqrt(ua_small ** 2))
283    print(less(ua_small, 103), type(less(ua_small, 103)))
284    print(type(ua_small * reshape(arange(15), shape(ua_small))))
285    print(reshape(ua_small, (5, 3)))
286    print(transpose(ua_small))
287