xnd 0.2.0dev6 → 0.2.0dev7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -0
  3. data/Rakefile +1 -1
  4. data/ext/ruby_xnd/GPATH +0 -0
  5. data/ext/ruby_xnd/GRTAGS +0 -0
  6. data/ext/ruby_xnd/GTAGS +0 -0
  7. data/ext/ruby_xnd/extconf.rb +8 -5
  8. data/ext/ruby_xnd/gc_guard.c +53 -2
  9. data/ext/ruby_xnd/gc_guard.h +8 -2
  10. data/ext/ruby_xnd/include/overflow.h +147 -0
  11. data/ext/ruby_xnd/include/ruby_xnd.h +62 -0
  12. data/ext/ruby_xnd/include/xnd.h +590 -0
  13. data/ext/ruby_xnd/lib/libxnd.a +0 -0
  14. data/ext/ruby_xnd/lib/libxnd.so +1 -0
  15. data/ext/ruby_xnd/lib/libxnd.so.0 +1 -0
  16. data/ext/ruby_xnd/lib/libxnd.so.0.2.0dev3 +0 -0
  17. data/ext/ruby_xnd/ruby_xnd.c +556 -47
  18. data/ext/ruby_xnd/ruby_xnd.h +2 -1
  19. data/ext/ruby_xnd/xnd/Makefile +80 -0
  20. data/ext/ruby_xnd/xnd/config.h +26 -0
  21. data/ext/ruby_xnd/xnd/config.h.in +3 -0
  22. data/ext/ruby_xnd/xnd/config.log +421 -0
  23. data/ext/ruby_xnd/xnd/config.status +1023 -0
  24. data/ext/ruby_xnd/xnd/configure +376 -8
  25. data/ext/ruby_xnd/xnd/configure.ac +48 -7
  26. data/ext/ruby_xnd/xnd/doc/xnd/index.rst +3 -1
  27. data/ext/ruby_xnd/xnd/doc/xnd/{types.rst → xnd.rst} +3 -18
  28. data/ext/ruby_xnd/xnd/libxnd/Makefile +142 -0
  29. data/ext/ruby_xnd/xnd/libxnd/Makefile.in +43 -3
  30. data/ext/ruby_xnd/xnd/libxnd/Makefile.vc +19 -3
  31. data/ext/ruby_xnd/xnd/libxnd/bitmaps.c +42 -3
  32. data/ext/ruby_xnd/xnd/libxnd/bitmaps.o +0 -0
  33. data/ext/ruby_xnd/xnd/libxnd/bounds.c +366 -0
  34. data/ext/ruby_xnd/xnd/libxnd/bounds.o +0 -0
  35. data/ext/ruby_xnd/xnd/libxnd/contrib.h +98 -0
  36. data/ext/ruby_xnd/xnd/libxnd/contrib/bfloat16.h +213 -0
  37. data/ext/ruby_xnd/xnd/libxnd/copy.c +155 -4
  38. data/ext/ruby_xnd/xnd/libxnd/copy.o +0 -0
  39. data/ext/ruby_xnd/xnd/libxnd/cuda/cuda_memory.cu +121 -0
  40. data/ext/ruby_xnd/xnd/libxnd/cuda/cuda_memory.h +58 -0
  41. data/ext/ruby_xnd/xnd/libxnd/equal.c +195 -7
  42. data/ext/ruby_xnd/xnd/libxnd/equal.o +0 -0
  43. data/ext/ruby_xnd/xnd/libxnd/inline.h +32 -0
  44. data/ext/ruby_xnd/xnd/libxnd/libxnd.a +0 -0
  45. data/ext/ruby_xnd/xnd/libxnd/libxnd.so +1 -0
  46. data/ext/ruby_xnd/xnd/libxnd/libxnd.so.0 +1 -0
  47. data/ext/ruby_xnd/xnd/libxnd/libxnd.so.0.2.0dev3 +0 -0
  48. data/ext/ruby_xnd/xnd/libxnd/shape.c +207 -0
  49. data/ext/ruby_xnd/xnd/libxnd/shape.o +0 -0
  50. data/ext/ruby_xnd/xnd/libxnd/split.c +2 -2
  51. data/ext/ruby_xnd/xnd/libxnd/split.o +0 -0
  52. data/ext/ruby_xnd/xnd/libxnd/tests/Makefile +39 -0
  53. data/ext/ruby_xnd/xnd/libxnd/xnd.c +613 -91
  54. data/ext/ruby_xnd/xnd/libxnd/xnd.h +145 -4
  55. data/ext/ruby_xnd/xnd/libxnd/xnd.o +0 -0
  56. data/ext/ruby_xnd/xnd/python/test_xnd.py +1125 -50
  57. data/ext/ruby_xnd/xnd/python/xnd/__init__.py +609 -124
  58. data/ext/ruby_xnd/xnd/python/xnd/_version.py +1 -0
  59. data/ext/ruby_xnd/xnd/python/xnd/_xnd.c +1652 -101
  60. data/ext/ruby_xnd/xnd/python/xnd/libxnd.a +0 -0
  61. data/ext/ruby_xnd/xnd/python/xnd/libxnd.so +1 -0
  62. data/ext/ruby_xnd/xnd/python/xnd/libxnd.so.0 +1 -0
  63. data/ext/ruby_xnd/xnd/python/xnd/libxnd.so.0.2.0dev3 +0 -0
  64. data/ext/ruby_xnd/xnd/python/xnd/pyxnd.h +1 -1
  65. data/ext/ruby_xnd/xnd/python/xnd/util.h +25 -0
  66. data/ext/ruby_xnd/xnd/python/xnd/xnd.h +590 -0
  67. data/ext/ruby_xnd/xnd/python/xnd_randvalue.py +106 -6
  68. data/ext/ruby_xnd/xnd/python/xnd_support.py +4 -0
  69. data/ext/ruby_xnd/xnd/setup.py +46 -4
  70. data/lib/ruby_xnd.so +0 -0
  71. data/lib/xnd.rb +39 -3
  72. data/lib/xnd/version.rb +2 -2
  73. data/xnd.gemspec +2 -1
  74. metadata +58 -5
@@ -43,14 +43,14 @@ data.
43
43
  Importing PEP-3118 buffers is supported.
44
44
  """
45
45
 
46
+ from ._version import __version__
46
47
 
47
48
  # Ensure that libndtypes is loaded and initialized.
48
49
  from ndtypes import ndt, instantiate, MAX_DIM
49
- from ._xnd import Xnd, XndEllipsis
50
- from itertools import accumulate
50
+ from ._xnd import Xnd, XndEllipsis, data_shapes, _typeof
51
51
  from .contrib.pretty import pretty
52
52
 
53
- __all__ = ['xnd', 'XndEllipsis', 'typeof', '_typeof']
53
+ __all__ = ['xnd', 'array', 'XndEllipsis', 'typeof']
54
54
 
55
55
 
56
56
  # ======================================================================
@@ -99,7 +99,7 @@ class xnd(Xnd):
99
99
  """
100
100
 
101
101
  def __new__(cls, value, *, type=None, dtype=None, levels=None,
102
- typedef=None, dtypedef=None):
102
+ typedef=None, dtypedef=None, device=None):
103
103
  if (type, dtype, levels, typedef, dtypedef).count(None) < 2:
104
104
  raise TypeError(
105
105
  "the 'type', 'dtype', 'levels' and 'typedef' arguments are "
@@ -124,7 +124,13 @@ class xnd(Xnd):
124
124
  type = typeof(value, dtype=dtype)
125
125
  else:
126
126
  type = typeof(value)
127
- return super().__new__(cls, type=type, value=value)
127
+
128
+ if device is not None:
129
+ name, no = device.split(":")
130
+ no = -1 if no == "managed" else int(no)
131
+ device = (name, no)
132
+
133
+ return super().__new__(cls, type=type, value=value, device=device)
128
134
 
129
135
  def __repr__(self):
130
136
  value = self.short_value(maxshape=10)
@@ -134,157 +140,636 @@ class xnd(Xnd):
134
140
  fmt = fmt.replace("\n", "\n ")
135
141
  return "xnd%s" % fmt
136
142
 
143
+ def __reduce__(self):
144
+ b = self.serialize()
145
+ return (xnd.deserialize, (b,))
146
+
147
+ def copy_contiguous(self, dtype=None):
148
+ if isinstance(dtype, str):
149
+ dtype = ndt(dtype)
150
+ return super().copy_contiguous(dtype=dtype)
151
+
152
+ def reshape(self, *args, order=None):
153
+ return super()._reshape(args, order=order)
154
+
155
+ def serialize(self):
156
+ if not self.type.is_c_contiguous() and \
157
+ not self.type.is_f_contiguous() and \
158
+ not self.type.is_var_contiguous():
159
+ self = self.copy_contiguous()
160
+ return self._serialize()
161
+
137
162
  @classmethod
138
- def unsafe_from_data(cls, obj=None, type=None):
163
+ def empty(cls, type=None, device=None):
164
+ if device is not None:
165
+ name, no = device.split(":")
166
+ no = -1 if no == "managed" else no
167
+ device = (name, int(no))
168
+
169
+ return super(xnd, cls).empty(type, device)
170
+
171
+ @classmethod
172
+ def from_buffer_and_type(cls, obj=None, type=None):
139
173
  """Return an xnd object that obtains memory from 'obj' via the
140
- buffer protocol. The buffer protocol's type is overridden by
141
- 'type'. No safety checks are performed, the user is responsible
142
- for passing a suitable type.
174
+ buffer protocol. 'obj' must be a simple writable buffer with
175
+ format 'B'. The xnd object uses the provided type, which must
176
+ have the same data size as 'obj'.
143
177
  """
144
178
  if isinstance(type, str):
145
179
  type = ndt(type)
146
- return cls._unsafe_from_data(obj, type)
180
+ return super().from_buffer_and_type(obj, type)
181
+
182
+ def typeof(v, dtype=None):
183
+ if isinstance(dtype, str):
184
+ dtype = ndt(dtype)
185
+ return _typeof(v, dtype=dtype, shortcut=True)
147
186
 
148
187
 
149
188
  # ======================================================================
150
- # Type inference
189
+ # array object
151
190
  # ======================================================================
152
191
 
153
- def typeof(value, *, dtype=None):
154
- return ndt(_typeof(value, dtype=dtype))
192
+ def _convert_smallest(v, device=None):
193
+ """Inefficient hack to make dask work (this needs to be in _typeof)."""
194
+ try:
195
+ return array.from_buffer(v)
196
+ except (TypeError, BufferError):
197
+ pass
198
+ x = array(v, device=device)
199
+ if x.type.hidden_dtype == ndt("int64"):
200
+ for dtype in ("int8", "int16", "int32"):
201
+ try:
202
+ return array(v, dtype=dtype, device=device)
203
+ except:
204
+ continue
205
+ return x
206
+
207
+ class array(xnd):
208
+ """Extended array type that relies on gumath for the array functions."""
209
+
210
+ _functions = None
211
+ _cuda = None
212
+ _np = None
213
+
214
+ @property
215
+ def shape(self):
216
+ return self.type.shape
217
+
218
+ @property
219
+ def strides(self):
220
+ return self.type.strides
221
+
222
+ @property
223
+ def T(self):
224
+ return self.transpose()
225
+
226
+ def tolist(self):
227
+ return self.value
228
+
229
+ def _get_module(self):
230
+ if self.device == "cuda:managed":
231
+ if array._cuda is None:
232
+ import gumath.cuda
233
+ array._cuda = gumath.cuda
234
+ return array._cuda
235
+ else:
236
+ if array._functions is None:
237
+ import gumath.functions
238
+ array._functions = gumath.functions
239
+ return array._functions
240
+
241
+ def _get_numpy(self):
242
+ if array._np is None:
243
+ import numpy
244
+ array._np = numpy
245
+ return array._np
246
+
247
+ def _convert(self, other, raiseit=False):
248
+ if isinstance(other, array):
249
+ if other.device != self.device:
250
+ raise NotImplementedError("arrays must be on the same device")
251
+ return other
252
+ try:
253
+ return _convert_smallest(other, device=self.device)
254
+ except TypeError:
255
+ if raiseit:
256
+ raise TypeError("unable to convert %s to array" % other)
257
+ return NotImplemented
258
+
259
+ def _call_unary(self, name, out=None):
260
+ m = self._get_module()
261
+ return getattr(m, name)(self, out=out, cls=array)
262
+
263
+ def _call_binary(self, name, other, out=None, raiseit=False):
264
+ other = self._convert(other, raiseit)
265
+ m = self._get_module()
266
+ return getattr(m, name)(self, other, out=out, cls=array)
267
+
268
+ def _call_binary_np(self, name, other, out=None, raiseit=False):
269
+ """redirect unimplemented binary methods"""
270
+ np = self._get_numpy()
271
+ other = self._convert(other, raiseit)
272
+ x = getattr(np, name)(self, other, out=out)
273
+ if out is not None:
274
+ return out
275
+ return array.from_buffer(x)
276
+
277
+ __array_priority__ = 1000
278
+
279
+ @property
280
+ def __array_interface__(self):
281
+ shape = self.shape
282
+ typestr = ndt.to_format(self.dtype)
283
+ return dict(shape=shape, typestr=typestr, version=3)
284
+
285
+ def __array__(self, dtype=None):
286
+ if dtype is not None:
287
+ np = self._get_numpy()
288
+ x = np.array([], dtype=dtype)
289
+ t = ndt.from_format(memoryview(x).format)
290
+ return self.copy(dtype=t)
291
+ return self
292
+
293
+ def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
294
+ np = self._get_numpy()
295
+
296
+ def conv_args(t):
297
+ if isinstance(t, tuple):
298
+ return tuple(conv_args(v) for v in t)
299
+ if isinstance(t, list):
300
+ return list(conv_args(v) for v in t)
301
+ elif isinstance(t, array):
302
+ return np.array(t, copy=False)
303
+ elif isinstance(t, np.ndarray):
304
+ return t
305
+ else:
306
+ raise NotImplementedError
307
+
308
+ np_self = np.array(self, copy=False)
309
+ try:
310
+ np_inputs = conv_args(inputs)
311
+ except NotImplementedError:
312
+ return NotImplemented
313
+
314
+ np_kwargs = kwargs.copy()
315
+ out = np_kwargs.pop("out", None)
316
+ if out is not None:
317
+ try:
318
+ np_out = conv_args(out)
319
+ except NotImplementedError:
320
+ return NotImplemented
321
+ np_kwargs["out"] = np_out
322
+
323
+ np_res = np_self.__array_ufunc__(ufunc, method, *np_inputs, **np_kwargs)
324
+ if np_res is NotImplemented:
325
+ return NotImplemented
326
+
327
+ if out is None:
328
+ if isinstance(np_res, tuple):
329
+ out = tuple(array.from_buffer(v) for v in np_res)
330
+ elif isinstance(np_res, list):
331
+ out = list(array.from_buffer(v) for v in np_res)
332
+ else:
333
+ out = array.from_buffer(np_res)
155
334
 
156
- def _choose_dtype(lst):
157
- for x in lst:
158
- if x is not None:
159
- return _typeof(x)
160
- return "float64"
335
+ return out
161
336
 
162
- def _typeof(value, *, dtype=None):
163
- """Infer the type of a Python value. Only a subset of Datashape is
164
- supported. In general, types need to be explicitly specified when
165
- creating xnd objects.
166
- """
167
- if isinstance(value, list):
168
- data, shapes = data_shapes(value)
169
- opt = None in data
337
+ def __array_function__(self, func, types, args, kwargs):
338
+ np = self._get_numpy()
170
339
 
171
- if dtype is None:
172
- if not data:
173
- dtype = 'float64'
340
+ def conv_types(t):
341
+ if isinstance(t, tuple):
342
+ return tuple(conv_types(v) for v in t)
343
+ if isinstance(t, list):
344
+ return list(conv_types(v) for v in t)
345
+ elif issubclass(t, (array, np.ndarray)):
346
+ return np.ndarray
347
+ else:
348
+ raise NotImplementedError
349
+
350
+ def conv_args(t, allow_ndarray=True):
351
+ if isinstance(t, tuple):
352
+ return tuple(conv_args(v) for v in t)
353
+ if isinstance(t, list):
354
+ return list(conv_args(v) for v in t)
355
+ elif isinstance(t, array):
356
+ return np.array(t, copy=False)
357
+ elif isinstance(t, np.ndarray):
358
+ return t if allow_ndarray else NotImplemented
174
359
  else:
175
- dtype = _choose_dtype(data)
176
- for x in data:
177
- if x is not None:
178
- t = _typeof(x)
179
- if t != dtype:
180
- raise ValueError("dtype mismatch: have %s and %s" % (dtype, t))
360
+ return t
361
+
362
+ def conv_res(t):
363
+ if isinstance(t, tuple):
364
+ return tuple(conv_res(v) for v in t)
365
+ if isinstance(t, list):
366
+ return list(conv_res(v) for v in t)
367
+ elif isinstance(t, np.ndarray):
368
+ return array.from_buffer(t)
369
+ else:
370
+ try:
371
+ return array.from_buffer(memoryview(t))
372
+ except TypeError:
373
+ return t
374
+
375
+ np_self = np.array(self, copy=False)
376
+ try:
377
+ np_types = conv_types(types)
378
+ except NotImplementedError:
379
+ return NotImplemented
380
+
381
+ try:
382
+ np_args = conv_args(args)
383
+ except NotImplementedError:
384
+ return NotImplemented
385
+
386
+ np_kwargs = kwargs.copy()
387
+ out = np_kwargs.pop("out", None)
388
+ if out is not None:
389
+ try:
390
+ np_out = conv_args(out, allow_ndarray=False)
391
+ except NotImplementedError:
392
+ return NotImplemented
393
+ np_kwargs["out"] = np_out
394
+
395
+ np_res = np_self.__array_function__(func, np_types, np_args, np_kwargs)
396
+ if np_res is NotImplemented:
397
+ return NotImplemented
398
+
399
+ if out is None:
400
+ return conv_res(np_res)
401
+ else:
402
+ return out
181
403
 
182
- if opt:
183
- dtype = '?' + dtype
404
+ def __repr__(self):
405
+ value = self.short_value(maxshape=10)
406
+ fmt = pretty((value, "@type='%s'@" % self.type), max_width=120)
407
+ fmt = fmt.replace('"@', "")
408
+ fmt = fmt.replace('@"', "")
409
+ fmt = fmt.replace("\n", "\n ")
410
+ return "array%s" % fmt
184
411
 
185
- t = dtype
186
- var = any(len(set(lst)) > 1 or None in lst for lst in shapes)
187
- for lst in shapes:
188
- opt = None in lst
189
- lst = [0 if x is None else x for x in lst]
190
- t = add_dim(opt=opt, shapes=lst, typ=t, use_var=var)
412
+ def __copy__(self):
413
+ return self.copy()
191
414
 
192
- return t
415
+ def __deepcopy__(self, memo):
416
+ return self.copy()
193
417
 
194
- elif dtype is not None:
195
- raise TypeError("dtype argument is only supported for arrays")
418
+ def __bool__(self):
419
+ np = self._get_numpy()
420
+ return bool(np.array(self, copy=False))
196
421
 
197
- elif isinstance(value, tuple):
198
- return "(" + ", ".join([_typeof(x) for x in value]) + ")"
422
+ def __neg__(self):
423
+ return self._call_unary("negative")
199
424
 
200
- elif isinstance(value, dict):
201
- if all(isinstance(k, str) for k in value):
202
- return "{" + ", ".join(["%s: %s" % (k, _typeof(v)) for k, v in value.items()]) + "}"
203
- raise ValueError("all dict keys must be strings")
425
+ def __pos__(self):
426
+ return self.copy()
204
427
 
205
- elif value is None:
206
- return '?float64'
428
+ def __abs__(self):
429
+ return self._call_unary("abs")
207
430
 
208
- elif isinstance(value, float):
209
- return 'float64'
431
+ def __invert__(self):
432
+ return self._call_unary("invert")
210
433
 
211
- elif isinstance(value, complex):
212
- return 'complex128'
434
+ def __complex__(self):
435
+ np = self._get_numpy()
436
+ return complex(np.array(self, copy=False))
213
437
 
214
- elif isinstance(value, int):
215
- return 'int64'
438
+ def __int__(self):
439
+ np = self._get_numpy()
440
+ return int(np.array(self, copy=False))
216
441
 
217
- elif isinstance(value, str):
218
- return 'string'
442
+ def __oct__(self):
443
+ np = self._get_numpy()
444
+ return oct(np.array(self, copy=False))
219
445
 
220
- elif isinstance(value, bytes):
221
- return 'bytes'
446
+ def __hex__(self):
447
+ np = self._get_numpy()
448
+ return hex(np.array(self, copy=False))
222
449
 
223
- else:
224
- raise ValueError("cannot infer type for %r" % value)
450
+ def __float__(self):
451
+ np = self._get_numpy()
452
+ return float(np.array(self, copy=False))
225
453
 
454
+ def __index__(self):
455
+ np = self._get_numpy()
456
+ return np.array(self, copy=False).__index__()
226
457
 
227
- def add_dim(*, opt=False, shapes=None, typ=None, use_var=False):
228
- """Construct a new dimension type based on the list of 'shapes' that
229
- are present in a dimension.
230
- """
231
- if use_var:
232
- offsets = [0] + list(accumulate(shapes))
233
- return "%svar(offsets=%s) * %s" % ('?' if opt else '', offsets, typ)
234
- else:
235
- n = len(set(shapes))
236
- assert n <= 1 and not None in shapes
237
- shape = 0 if n == 0 else shapes[0]
238
- return "%d * %s" % (shape, typ)
239
-
240
- def data_shapes(tree):
241
- """Extract array data and dimension shapes from a nested list. The
242
- list may contain None for missing data or dimensions.
243
-
244
- >>> data_shapes([[0, 1], [2, 3, 4], [5, 6, 7, 8]])
245
- ([0, 1, 2, 3, 4, 5, 6, 7, 8], [[2, 3, 4], [3]])
246
- ^ ^ ^
247
- | | `--- ndim=2: single shape 3
248
- | `-- ndim=1: shapes 2, 3, 4
249
- `--- ndim=0: extracted array data
250
- """
251
- acc = [[] for _ in range(MAX_DIM+1)]
252
- min_level = MAX_DIM + 1
253
- max_level = 0
254
-
255
- def search(level, a):
256
- nonlocal min_level, max_level
257
-
258
- if level > MAX_DIM:
259
- raise ValueError("too many dimensions")
260
-
261
- current = acc[level]
262
- if a is None:
263
- current.append(a)
264
- elif isinstance(a, list):
265
- current.append(len(a))
266
- next_level = level + 1
267
- max_level = max(next_level, max_level)
268
- if not a:
269
- min_level = min(next_level, min_level)
270
- else:
271
- for item in a:
272
- search(level+1, item)
273
- else:
274
- acc[max_level].append(a)
275
- min_level = min(level, min_level)
458
+ def __floor__(self):
459
+ np = self._get_numpy()
460
+ return np.array(self, copy=False).__floor__()
461
+
462
+ def __ceil__(self):
463
+ np = self._get_numpy()
464
+ return np.array(self, copy=False).__ceil__()
465
+
466
+ def __eq__(self, other):
467
+ other = self._convert(other)
468
+ if other is NotImplemented:
469
+ return other
470
+
471
+ return self._call_binary("equal", other)
472
+
473
+ def __ne__(self, other):
474
+ other = self._convert(other)
475
+ if other is NotImplemented:
476
+ return other
477
+
478
+ return self._call_binary("not_equal", other)
479
+
480
+ def __lt__(self, other):
481
+ other = self._convert(other)
482
+ if other is NotImplemented:
483
+ return other
484
+
485
+ return self._call_binary("less", other)
486
+
487
+ def __le__(self, other):
488
+ other = self._convert(other)
489
+ if other is NotImplemented:
490
+ return other
491
+
492
+ return self._call_binary("less_equal", other)
493
+
494
+ def __ge__(self, other):
495
+ other = self._convert(other)
496
+ if other is NotImplemented:
497
+ return other
498
+
499
+ return self._call_binary("greater_equal", other)
500
+
501
+ def __gt__(self, other):
502
+ other = self._convert(other)
503
+ if other is NotImplemented:
504
+ return other
505
+
506
+ return self._call_binary("greater", other)
507
+
508
+ def __add__(self, other):
509
+ return self._call_binary("add", other)
510
+
511
+ def __radd__(self, other):
512
+ other = self._convert(other)
513
+ if other is NotImplemented:
514
+ return other
515
+
516
+ return other._call_binary("add", self)
517
+
518
+ def __sub__(self, other):
519
+ return self._call_binary("subtract", other)
520
+
521
+ def __rsub__(self, other):
522
+ other = self._convert(other)
523
+ if other is NotImplemented:
524
+ return other
525
+
526
+ return other._call_binary("subtract", self)
527
+
528
+ def __mul__(self, other):
529
+ return self._call_binary("multiply", other)
530
+
531
+ def __rmul__(self, other):
532
+ other = self._convert(other)
533
+ if other is NotImplemented:
534
+ return other
535
+
536
+ return other._call_binary("multiply", self)
537
+
538
+ def __matmul__(self, other):
539
+ return self._call_binary_np("matmul", other)
540
+
541
+ def __rmatmul__(self, other):
542
+ other = self._convert(other)
543
+ if other is NotImplemented:
544
+ return other
545
+
546
+ return other._call_binary_np("matmul", self)
547
+
548
+ def __truediv__(self, other):
549
+ return self._call_binary("divide", other)
550
+
551
+ def __rtruediv__(self, other):
552
+ other = self._convert(other)
553
+ if other is NotImplemented:
554
+ return other
555
+
556
+ return other._call_binary("divide", self)
557
+
558
+ def __floordiv__(self, other):
559
+ return self._call_binary("floor_divide", other)
560
+
561
+ def __rfloordiv__(self, other):
562
+ other = self._convert(other)
563
+ if other is NotImplemented:
564
+ return other
565
+
566
+ return other._call_binary("floor_divide", self)
567
+
568
+ def __mod__(self, other):
569
+ return self._call_binary("remainder", other)
570
+
571
+ def __rmod__(self, other):
572
+ other = self._convert(other)
573
+ if other is NotImplemented:
574
+ return other
575
+
576
+ return other._call_binary("remainder", self)
577
+
578
+ def __divmod__(self, other):
579
+ return self._call_binary("divmod", other)
580
+
581
+ def __rdivmod__(self, other):
582
+ other = self._convert(other)
583
+ if other is NotImplemented:
584
+ return other
585
+
586
+ return other._call_binary("divmod", self)
587
+
588
+ def __pow__(self, other):
589
+ return self._call_binary("power", other)
590
+
591
+ def __rpow__(self, other):
592
+ other = self._convert(other)
593
+ if other is NotImplemented:
594
+ return other
595
+
596
+ return other._call_binary("power", self)
597
+
598
+ def __lshift__(self, other):
599
+ return self._call_binary_np("left_shift", other)
600
+
601
+ def __rlshift__(self, other):
602
+ other = self._convert(other)
603
+ if other is NotImplemented:
604
+ return other
605
+
606
+ return other._call_binary_np("left_shift", self)
607
+
608
+ def __rshift__(self, other):
609
+ return self._call_binary_np("right_shift", other)
610
+
611
+ def __rrshift__(self, other):
612
+ other = self._convert(other)
613
+ if other is NotImplemented:
614
+ return other
615
+
616
+ return other._call_binary_np("right_shift", self)
617
+
618
+ def __and__(self, other):
619
+ return self._call_binary("bitwise_and", other)
620
+
621
+ def __rand__(self, other):
622
+ other = self._convert(other)
623
+ if other is NotImplemented:
624
+ return other
625
+
626
+ return other._call_binary("bitwise_and", self)
627
+
628
+ def __or__(self, other):
629
+ return self._call_binary("bitwise_or", other)
630
+
631
+ def __ror__(self, other):
632
+ other = self._convert(other)
633
+ if other is NotImplemented:
634
+ return other
635
+
636
+ return other._call_binary("bitwise_or", self)
637
+
638
+ def __xor__(self, other):
639
+ return self._call_binary("bitwise_xor", other)
640
+
641
+ def __rxor__(self, other):
642
+ other = self._convert(other)
643
+ if other is NotImplemented:
644
+ return other
645
+
646
+ return other._call_binary("bitwise_xor", self)
647
+
648
+ def __iadd__(self, other):
649
+ return self._call_binary("add", other, out=self)
650
+
651
+ def __isub__(self, other):
652
+ return self._call_binary("subtract", other, out=self)
653
+
654
+ def __imul__(self, other):
655
+ return self._call_binary("multiply", other, out=self)
656
+
657
+ def __imatmul__(self, other):
658
+ return self._call_binary_np("matmul", other, out=self)
659
+
660
+ def __itruediv__(self, other):
661
+ return self._call_binary("divide", other, out=self)
662
+
663
+ def __ifloordiv__(self, other):
664
+ return self._call_binary("floor_divide", other, out=self)
665
+
666
+ def __imod__(self, other):
667
+ return self._call_binary("remainder", other, out=self)
668
+
669
+ def __ipow__(self, other):
670
+ return self._call_binary("power", other, out=self)
671
+
672
+ def __ilshift__(self, other):
673
+ return self._call_binary_np("left_shift", other, out=self)
674
+
675
+ def __irshift__(self, other):
676
+ return self._call_binary_np("right_shift", other, out=self)
677
+
678
+ def __iand__(self, other):
679
+ return self._call_binary("bitwise_and", other, out=self)
680
+
681
+ def __ior__(self, other):
682
+ return self._call_binary("bitwise_or", other, out=self)
683
+
684
+ def __ixor__(self, other):
685
+ return self._call_binary("bitwise_xor", other, out=self)
686
+
687
+ def copy(self, out=None):
688
+ return self._call_unary("copy", out=out)
689
+
690
+ def acos(self, out=None):
691
+ return self._call_unary("acos", out=out)
692
+
693
+ def acosh(self, out=None):
694
+ return self._call_unary("acosh", out=out)
695
+
696
+ def asin(self, out=None):
697
+ return self._call_unary("asin", out=out)
698
+
699
+ def asinh(self, out=None):
700
+ return self._call_unary("asinh", out=out)
701
+
702
+ def atan(self, out=None):
703
+ return self._call_unary("atan", out=out)
704
+
705
+ def atanh(self, out=None):
706
+ return self._call_unary("atanh", out=out)
707
+
708
+ def cbrt(self, out=None):
709
+ return self._call_unary("cbrt", out=out)
710
+
711
+ def cos(self, out=None):
712
+ return self._call_unary("cos", out=out)
713
+
714
+ def cosh(self, out=None):
715
+ return self._call_unary("cosh", out=out)
716
+
717
+ def erf(self, out=None):
718
+ return self._call_unary("erf", out=out)
719
+
720
+ def erfc(self, out=None):
721
+ return self._call_unary("erfc", out=out)
722
+
723
+ def exp(self, out=None):
724
+ return self._call_unary("exp", out=out)
725
+
726
+ def exp2(self, out=None):
727
+ return self._call_unary("exp2", out=out)
728
+
729
+ def expm1(self, out=None):
730
+ return self._call_unary("expm1", out=out)
731
+
732
+ def fabs(self, out=None):
733
+ return self._call_unary("fabs", out=out)
734
+
735
+ def lgamma(self, out=None):
736
+ return self._call_unary("lgamma", out=out)
737
+
738
+ def log(self, out=None):
739
+ return self._call_unary("log", out=out)
740
+
741
+ def log10(self, out=None):
742
+ return self._call_unary("log10", out=out)
743
+
744
+ def log1p(self, out=None):
745
+ return self._call_unary("log1p", out=out)
746
+
747
+ def log2(self, out=None):
748
+ return self._call_unary("log2", out=out)
749
+
750
+ def logb(self, out=None):
751
+ return self._call_unary("logb", out=out)
752
+
753
+ def nearbyint(self, out=None):
754
+ return self._call_unary("nearbyint", out=out)
755
+
756
+ def sin(self, out=None):
757
+ return self._call_unary("sin", out=out)
276
758
 
277
- search(max_level, tree)
278
- if acc[max_level] and all(x is None for x in acc[max_level]):
279
- pass # min_level is not set in this special case, hence the check.
280
- elif min_level != max_level:
281
- raise ValueError("unbalanced tree: min depth: %d max depth: %d" %
282
- (min_level, max_level))
759
+ def sinh(self, out=None):
760
+ return self._call_unary("sinh", out=out)
283
761
 
284
- data = acc[max_level]
285
- shapes = list(reversed(acc[0:max_level]))
762
+ def sqrt(self, out=None):
763
+ return self._call_unary("sqrt", out=out)
286
764
 
287
- return data, shapes
765
+ def tan(self, out=None):
766
+ return self._call_unary("tan", out=out)
288
767
 
768
+ def tanh(self, out=None):
769
+ return self._call_unary("tanh", out=out)
289
770
 
771
+ def tanh(self, out=None):
772
+ return self._call_unary("tgamma", out=out)
290
773
 
774
+ def equaln(self, other, out=None):
775
+ return self._call_binary("equaln", other, out=out, raiseit=True)