comparison DEPENDENCIES/mingw32/Python27/Lib/site-packages/numpy/lib/shape_base.py @ 87:2a2c65a20a8b

Add Python libs and headers
author Chris Cannam
date Wed, 25 Feb 2015 14:05:22 +0000
parents
children
comparison
equal deleted inserted replaced
86:413a9d26189e 87:2a2c65a20a8b
1 from __future__ import division, absolute_import, print_function
2
3 import warnings
4
5 import numpy.core.numeric as _nx
6 from numpy.core.numeric import (
7 asarray, zeros, outer, concatenate, isscalar, array, asanyarray
8 )
9 from numpy.core.fromnumeric import product, reshape
10 from numpy.core import vstack, atleast_3d
11
12
13 __all__ = [
14 'column_stack', 'row_stack', 'dstack', 'array_split', 'split',
15 'hsplit', 'vsplit', 'dsplit', 'apply_over_axes', 'expand_dims',
16 'apply_along_axis', 'kron', 'tile', 'get_array_wrap'
17 ]
18
19
20 def apply_along_axis(func1d, axis, arr, *args, **kwargs):
21 """
22 Apply a function to 1-D slices along the given axis.
23
24 Execute `func1d(a, *args)` where `func1d` operates on 1-D arrays and `a`
25 is a 1-D slice of `arr` along `axis`.
26
27 Parameters
28 ----------
29 func1d : function
30 This function should accept 1-D arrays. It is applied to 1-D
31 slices of `arr` along the specified axis.
32 axis : integer
33 Axis along which `arr` is sliced.
34 arr : ndarray
35 Input array.
36 args : any
37 Additional arguments to `func1d`.
38 kwargs: any
39 Additional named arguments to `func1d`.
40
41 .. versionadded:: 1.9.0
42
43
44 Returns
45 -------
46 apply_along_axis : ndarray
47 The output array. The shape of `outarr` is identical to the shape of
48 `arr`, except along the `axis` dimension, where the length of `outarr`
49 is equal to the size of the return value of `func1d`. If `func1d`
50 returns a scalar `outarr` will have one fewer dimensions than `arr`.
51
52 See Also
53 --------
54 apply_over_axes : Apply a function repeatedly over multiple axes.
55
56 Examples
57 --------
58 >>> def my_func(a):
59 ... \"\"\"Average first and last element of a 1-D array\"\"\"
60 ... return (a[0] + a[-1]) * 0.5
61 >>> b = np.array([[1,2,3], [4,5,6], [7,8,9]])
62 >>> np.apply_along_axis(my_func, 0, b)
63 array([ 4., 5., 6.])
64 >>> np.apply_along_axis(my_func, 1, b)
65 array([ 2., 5., 8.])
66
67 For a function that doesn't return a scalar, the number of dimensions in
68 `outarr` is the same as `arr`.
69
70 >>> b = np.array([[8,1,7], [4,3,9], [5,2,6]])
71 >>> np.apply_along_axis(sorted, 1, b)
72 array([[1, 7, 8],
73 [3, 4, 9],
74 [2, 5, 6]])
75
76 """
77 arr = asarray(arr)
78 nd = arr.ndim
79 if axis < 0:
80 axis += nd
81 if (axis >= nd):
82 raise ValueError("axis must be less than arr.ndim; axis=%d, rank=%d."
83 % (axis, nd))
84 ind = [0]*(nd-1)
85 i = zeros(nd, 'O')
86 indlist = list(range(nd))
87 indlist.remove(axis)
88 i[axis] = slice(None, None)
89 outshape = asarray(arr.shape).take(indlist)
90 i.put(indlist, ind)
91 res = func1d(arr[tuple(i.tolist())], *args, **kwargs)
92 # if res is a number, then we have a smaller output array
93 if isscalar(res):
94 outarr = zeros(outshape, asarray(res).dtype)
95 outarr[tuple(ind)] = res
96 Ntot = product(outshape)
97 k = 1
98 while k < Ntot:
99 # increment the index
100 ind[-1] += 1
101 n = -1
102 while (ind[n] >= outshape[n]) and (n > (1-nd)):
103 ind[n-1] += 1
104 ind[n] = 0
105 n -= 1
106 i.put(indlist, ind)
107 res = func1d(arr[tuple(i.tolist())], *args, **kwargs)
108 outarr[tuple(ind)] = res
109 k += 1
110 return outarr
111 else:
112 Ntot = product(outshape)
113 holdshape = outshape
114 outshape = list(arr.shape)
115 outshape[axis] = len(res)
116 outarr = zeros(outshape, asarray(res).dtype)
117 outarr[tuple(i.tolist())] = res
118 k = 1
119 while k < Ntot:
120 # increment the index
121 ind[-1] += 1
122 n = -1
123 while (ind[n] >= holdshape[n]) and (n > (1-nd)):
124 ind[n-1] += 1
125 ind[n] = 0
126 n -= 1
127 i.put(indlist, ind)
128 res = func1d(arr[tuple(i.tolist())], *args, **kwargs)
129 outarr[tuple(i.tolist())] = res
130 k += 1
131 return outarr
132
133
134 def apply_over_axes(func, a, axes):
135 """
136 Apply a function repeatedly over multiple axes.
137
138 `func` is called as `res = func(a, axis)`, where `axis` is the first
139 element of `axes`. The result `res` of the function call must have
140 either the same dimensions as `a` or one less dimension. If `res`
141 has one less dimension than `a`, a dimension is inserted before
142 `axis`. The call to `func` is then repeated for each axis in `axes`,
143 with `res` as the first argument.
144
145 Parameters
146 ----------
147 func : function
148 This function must take two arguments, `func(a, axis)`.
149 a : array_like
150 Input array.
151 axes : array_like
152 Axes over which `func` is applied; the elements must be integers.
153
154 Returns
155 -------
156 apply_over_axis : ndarray
157 The output array. The number of dimensions is the same as `a`,
158 but the shape can be different. This depends on whether `func`
159 changes the shape of its output with respect to its input.
160
161 See Also
162 --------
163 apply_along_axis :
164 Apply a function to 1-D slices of an array along the given axis.
165
166 Notes
167 ------
168 This function is equivalent to tuple axis arguments to reorderable ufuncs
169 with keepdims=True. Tuple axis arguments to ufuncs have been availabe since
170 version 1.7.0.
171
172 Examples
173 --------
174 >>> a = np.arange(24).reshape(2,3,4)
175 >>> a
176 array([[[ 0, 1, 2, 3],
177 [ 4, 5, 6, 7],
178 [ 8, 9, 10, 11]],
179 [[12, 13, 14, 15],
180 [16, 17, 18, 19],
181 [20, 21, 22, 23]]])
182
183 Sum over axes 0 and 2. The result has same number of dimensions
184 as the original array:
185
186 >>> np.apply_over_axes(np.sum, a, [0,2])
187 array([[[ 60],
188 [ 92],
189 [124]]])
190
191 Tuple axis arguments to ufuncs are equivalent:
192
193 >>> np.sum(a, axis=(0,2), keepdims=True)
194 array([[[ 60],
195 [ 92],
196 [124]]])
197
198 """
199 val = asarray(a)
200 N = a.ndim
201 if array(axes).ndim == 0:
202 axes = (axes,)
203 for axis in axes:
204 if axis < 0:
205 axis = N + axis
206 args = (val, axis)
207 res = func(*args)
208 if res.ndim == val.ndim:
209 val = res
210 else:
211 res = expand_dims(res, axis)
212 if res.ndim == val.ndim:
213 val = res
214 else:
215 raise ValueError("function is not returning "
216 "an array of the correct shape")
217 return val
218
219 def expand_dims(a, axis):
220 """
221 Expand the shape of an array.
222
223 Insert a new axis, corresponding to a given position in the array shape.
224
225 Parameters
226 ----------
227 a : array_like
228 Input array.
229 axis : int
230 Position (amongst axes) where new axis is to be inserted.
231
232 Returns
233 -------
234 res : ndarray
235 Output array. The number of dimensions is one greater than that of
236 the input array.
237
238 See Also
239 --------
240 doc.indexing, atleast_1d, atleast_2d, atleast_3d
241
242 Examples
243 --------
244 >>> x = np.array([1,2])
245 >>> x.shape
246 (2,)
247
248 The following is equivalent to ``x[np.newaxis,:]`` or ``x[np.newaxis]``:
249
250 >>> y = np.expand_dims(x, axis=0)
251 >>> y
252 array([[1, 2]])
253 >>> y.shape
254 (1, 2)
255
256 >>> y = np.expand_dims(x, axis=1) # Equivalent to x[:,newaxis]
257 >>> y
258 array([[1],
259 [2]])
260 >>> y.shape
261 (2, 1)
262
263 Note that some examples may use ``None`` instead of ``np.newaxis``. These
264 are the same objects:
265
266 >>> np.newaxis is None
267 True
268
269 """
270 a = asarray(a)
271 shape = a.shape
272 if axis < 0:
273 axis = axis + len(shape) + 1
274 return a.reshape(shape[:axis] + (1,) + shape[axis:])
275
276 row_stack = vstack
277
278 def column_stack(tup):
279 """
280 Stack 1-D arrays as columns into a 2-D array.
281
282 Take a sequence of 1-D arrays and stack them as columns
283 to make a single 2-D array. 2-D arrays are stacked as-is,
284 just like with `hstack`. 1-D arrays are turned into 2-D columns
285 first.
286
287 Parameters
288 ----------
289 tup : sequence of 1-D or 2-D arrays.
290 Arrays to stack. All of them must have the same first dimension.
291
292 Returns
293 -------
294 stacked : 2-D array
295 The array formed by stacking the given arrays.
296
297 See Also
298 --------
299 hstack, vstack, concatenate
300
301 Examples
302 --------
303 >>> a = np.array((1,2,3))
304 >>> b = np.array((2,3,4))
305 >>> np.column_stack((a,b))
306 array([[1, 2],
307 [2, 3],
308 [3, 4]])
309
310 """
311 arrays = []
312 for v in tup:
313 arr = array(v, copy=False, subok=True)
314 if arr.ndim < 2:
315 arr = array(arr, copy=False, subok=True, ndmin=2).T
316 arrays.append(arr)
317 return _nx.concatenate(arrays, 1)
318
319 def dstack(tup):
320 """
321 Stack arrays in sequence depth wise (along third axis).
322
323 Takes a sequence of arrays and stack them along the third axis
324 to make a single array. Rebuilds arrays divided by `dsplit`.
325 This is a simple way to stack 2D arrays (images) into a single
326 3D array for processing.
327
328 Parameters
329 ----------
330 tup : sequence of arrays
331 Arrays to stack. All of them must have the same shape along all
332 but the third axis.
333
334 Returns
335 -------
336 stacked : ndarray
337 The array formed by stacking the given arrays.
338
339 See Also
340 --------
341 vstack : Stack along first axis.
342 hstack : Stack along second axis.
343 concatenate : Join arrays.
344 dsplit : Split array along third axis.
345
346 Notes
347 -----
348 Equivalent to ``np.concatenate(tup, axis=2)``.
349
350 Examples
351 --------
352 >>> a = np.array((1,2,3))
353 >>> b = np.array((2,3,4))
354 >>> np.dstack((a,b))
355 array([[[1, 2],
356 [2, 3],
357 [3, 4]]])
358
359 >>> a = np.array([[1],[2],[3]])
360 >>> b = np.array([[2],[3],[4]])
361 >>> np.dstack((a,b))
362 array([[[1, 2]],
363 [[2, 3]],
364 [[3, 4]]])
365
366 """
367 return _nx.concatenate([atleast_3d(_m) for _m in tup], 2)
368
369 def _replace_zero_by_x_arrays(sub_arys):
370 for i in range(len(sub_arys)):
371 if len(_nx.shape(sub_arys[i])) == 0:
372 sub_arys[i] = _nx.empty(0, dtype=sub_arys[i].dtype)
373 elif _nx.sometrue(_nx.equal(_nx.shape(sub_arys[i]), 0)):
374 sub_arys[i] = _nx.empty(0, dtype=sub_arys[i].dtype)
375 return sub_arys
376
377 def array_split(ary, indices_or_sections, axis=0):
378 """
379 Split an array into multiple sub-arrays.
380
381 Please refer to the ``split`` documentation. The only difference
382 between these functions is that ``array_split`` allows
383 `indices_or_sections` to be an integer that does *not* equally
384 divide the axis.
385
386 See Also
387 --------
388 split : Split array into multiple sub-arrays of equal size.
389
390 Examples
391 --------
392 >>> x = np.arange(8.0)
393 >>> np.array_split(x, 3)
394 [array([ 0., 1., 2.]), array([ 3., 4., 5.]), array([ 6., 7.])]
395
396 """
397 try:
398 Ntotal = ary.shape[axis]
399 except AttributeError:
400 Ntotal = len(ary)
401 try:
402 # handle scalar case.
403 Nsections = len(indices_or_sections) + 1
404 div_points = [0] + list(indices_or_sections) + [Ntotal]
405 except TypeError:
406 # indices_or_sections is a scalar, not an array.
407 Nsections = int(indices_or_sections)
408 if Nsections <= 0:
409 raise ValueError('number sections must be larger than 0.')
410 Neach_section, extras = divmod(Ntotal, Nsections)
411 section_sizes = ([0] +
412 extras * [Neach_section+1] +
413 (Nsections-extras) * [Neach_section])
414 div_points = _nx.array(section_sizes).cumsum()
415
416 sub_arys = []
417 sary = _nx.swapaxes(ary, axis, 0)
418 for i in range(Nsections):
419 st = div_points[i]
420 end = div_points[i + 1]
421 sub_arys.append(_nx.swapaxes(sary[st:end], axis, 0))
422
423 # This "kludge" was introduced here to replace arrays shaped (0, 10)
424 # or similar with an array shaped (0,).
425 # There seems no need for this, so give a FutureWarning to remove later.
426 if sub_arys[-1].size == 0 and sub_arys[-1].ndim != 1:
427 warnings.warn("in the future np.array_split will retain the shape of "
428 "arrays with a zero size, instead of replacing them by "
429 "`array([])`, which always has a shape of (0,).",
430 FutureWarning)
431 sub_arys = _replace_zero_by_x_arrays(sub_arys)
432
433 return sub_arys
434
435 def split(ary,indices_or_sections,axis=0):
436 """
437 Split an array into multiple sub-arrays.
438
439 Parameters
440 ----------
441 ary : ndarray
442 Array to be divided into sub-arrays.
443 indices_or_sections : int or 1-D array
444 If `indices_or_sections` is an integer, N, the array will be divided
445 into N equal arrays along `axis`. If such a split is not possible,
446 an error is raised.
447
448 If `indices_or_sections` is a 1-D array of sorted integers, the entries
449 indicate where along `axis` the array is split. For example,
450 ``[2, 3]`` would, for ``axis=0``, result in
451
452 - ary[:2]
453 - ary[2:3]
454 - ary[3:]
455
456 If an index exceeds the dimension of the array along `axis`,
457 an empty sub-array is returned correspondingly.
458 axis : int, optional
459 The axis along which to split, default is 0.
460
461 Returns
462 -------
463 sub-arrays : list of ndarrays
464 A list of sub-arrays.
465
466 Raises
467 ------
468 ValueError
469 If `indices_or_sections` is given as an integer, but
470 a split does not result in equal division.
471
472 See Also
473 --------
474 array_split : Split an array into multiple sub-arrays of equal or
475 near-equal size. Does not raise an exception if
476 an equal division cannot be made.
477 hsplit : Split array into multiple sub-arrays horizontally (column-wise).
478 vsplit : Split array into multiple sub-arrays vertically (row wise).
479 dsplit : Split array into multiple sub-arrays along the 3rd axis (depth).
480 concatenate : Join arrays together.
481 hstack : Stack arrays in sequence horizontally (column wise).
482 vstack : Stack arrays in sequence vertically (row wise).
483 dstack : Stack arrays in sequence depth wise (along third dimension).
484
485 Examples
486 --------
487 >>> x = np.arange(9.0)
488 >>> np.split(x, 3)
489 [array([ 0., 1., 2.]), array([ 3., 4., 5.]), array([ 6., 7., 8.])]
490
491 >>> x = np.arange(8.0)
492 >>> np.split(x, [3, 5, 6, 10])
493 [array([ 0., 1., 2.]),
494 array([ 3., 4.]),
495 array([ 5.]),
496 array([ 6., 7.]),
497 array([], dtype=float64)]
498
499 """
500 try:
501 len(indices_or_sections)
502 except TypeError:
503 sections = indices_or_sections
504 N = ary.shape[axis]
505 if N % sections:
506 raise ValueError(
507 'array split does not result in an equal division')
508 res = array_split(ary, indices_or_sections, axis)
509 return res
510
511 def hsplit(ary, indices_or_sections):
512 """
513 Split an array into multiple sub-arrays horizontally (column-wise).
514
515 Please refer to the `split` documentation. `hsplit` is equivalent
516 to `split` with ``axis=1``, the array is always split along the second
517 axis regardless of the array dimension.
518
519 See Also
520 --------
521 split : Split an array into multiple sub-arrays of equal size.
522
523 Examples
524 --------
525 >>> x = np.arange(16.0).reshape(4, 4)
526 >>> x
527 array([[ 0., 1., 2., 3.],
528 [ 4., 5., 6., 7.],
529 [ 8., 9., 10., 11.],
530 [ 12., 13., 14., 15.]])
531 >>> np.hsplit(x, 2)
532 [array([[ 0., 1.],
533 [ 4., 5.],
534 [ 8., 9.],
535 [ 12., 13.]]),
536 array([[ 2., 3.],
537 [ 6., 7.],
538 [ 10., 11.],
539 [ 14., 15.]])]
540 >>> np.hsplit(x, np.array([3, 6]))
541 [array([[ 0., 1., 2.],
542 [ 4., 5., 6.],
543 [ 8., 9., 10.],
544 [ 12., 13., 14.]]),
545 array([[ 3.],
546 [ 7.],
547 [ 11.],
548 [ 15.]]),
549 array([], dtype=float64)]
550
551 With a higher dimensional array the split is still along the second axis.
552
553 >>> x = np.arange(8.0).reshape(2, 2, 2)
554 >>> x
555 array([[[ 0., 1.],
556 [ 2., 3.]],
557 [[ 4., 5.],
558 [ 6., 7.]]])
559 >>> np.hsplit(x, 2)
560 [array([[[ 0., 1.]],
561 [[ 4., 5.]]]),
562 array([[[ 2., 3.]],
563 [[ 6., 7.]]])]
564
565 """
566 if len(_nx.shape(ary)) == 0:
567 raise ValueError('hsplit only works on arrays of 1 or more dimensions')
568 if len(ary.shape) > 1:
569 return split(ary, indices_or_sections, 1)
570 else:
571 return split(ary, indices_or_sections, 0)
572
573 def vsplit(ary, indices_or_sections):
574 """
575 Split an array into multiple sub-arrays vertically (row-wise).
576
577 Please refer to the ``split`` documentation. ``vsplit`` is equivalent
578 to ``split`` with `axis=0` (default), the array is always split along the
579 first axis regardless of the array dimension.
580
581 See Also
582 --------
583 split : Split an array into multiple sub-arrays of equal size.
584
585 Examples
586 --------
587 >>> x = np.arange(16.0).reshape(4, 4)
588 >>> x
589 array([[ 0., 1., 2., 3.],
590 [ 4., 5., 6., 7.],
591 [ 8., 9., 10., 11.],
592 [ 12., 13., 14., 15.]])
593 >>> np.vsplit(x, 2)
594 [array([[ 0., 1., 2., 3.],
595 [ 4., 5., 6., 7.]]),
596 array([[ 8., 9., 10., 11.],
597 [ 12., 13., 14., 15.]])]
598 >>> np.vsplit(x, np.array([3, 6]))
599 [array([[ 0., 1., 2., 3.],
600 [ 4., 5., 6., 7.],
601 [ 8., 9., 10., 11.]]),
602 array([[ 12., 13., 14., 15.]]),
603 array([], dtype=float64)]
604
605 With a higher dimensional array the split is still along the first axis.
606
607 >>> x = np.arange(8.0).reshape(2, 2, 2)
608 >>> x
609 array([[[ 0., 1.],
610 [ 2., 3.]],
611 [[ 4., 5.],
612 [ 6., 7.]]])
613 >>> np.vsplit(x, 2)
614 [array([[[ 0., 1.],
615 [ 2., 3.]]]),
616 array([[[ 4., 5.],
617 [ 6., 7.]]])]
618
619 """
620 if len(_nx.shape(ary)) < 2:
621 raise ValueError('vsplit only works on arrays of 2 or more dimensions')
622 return split(ary, indices_or_sections, 0)
623
624 def dsplit(ary, indices_or_sections):
625 """
626 Split array into multiple sub-arrays along the 3rd axis (depth).
627
628 Please refer to the `split` documentation. `dsplit` is equivalent
629 to `split` with ``axis=2``, the array is always split along the third
630 axis provided the array dimension is greater than or equal to 3.
631
632 See Also
633 --------
634 split : Split an array into multiple sub-arrays of equal size.
635
636 Examples
637 --------
638 >>> x = np.arange(16.0).reshape(2, 2, 4)
639 >>> x
640 array([[[ 0., 1., 2., 3.],
641 [ 4., 5., 6., 7.]],
642 [[ 8., 9., 10., 11.],
643 [ 12., 13., 14., 15.]]])
644 >>> np.dsplit(x, 2)
645 [array([[[ 0., 1.],
646 [ 4., 5.]],
647 [[ 8., 9.],
648 [ 12., 13.]]]),
649 array([[[ 2., 3.],
650 [ 6., 7.]],
651 [[ 10., 11.],
652 [ 14., 15.]]])]
653 >>> np.dsplit(x, np.array([3, 6]))
654 [array([[[ 0., 1., 2.],
655 [ 4., 5., 6.]],
656 [[ 8., 9., 10.],
657 [ 12., 13., 14.]]]),
658 array([[[ 3.],
659 [ 7.]],
660 [[ 11.],
661 [ 15.]]]),
662 array([], dtype=float64)]
663
664 """
665 if len(_nx.shape(ary)) < 3:
666 raise ValueError('dsplit only works on arrays of 3 or more dimensions')
667 return split(ary, indices_or_sections, 2)
668
669 def get_array_prepare(*args):
670 """Find the wrapper for the array with the highest priority.
671
672 In case of ties, leftmost wins. If no wrapper is found, return None
673 """
674 wrappers = sorted((getattr(x, '__array_priority__', 0), -i,
675 x.__array_prepare__) for i, x in enumerate(args)
676 if hasattr(x, '__array_prepare__'))
677 if wrappers:
678 return wrappers[-1][-1]
679 return None
680
681 def get_array_wrap(*args):
682 """Find the wrapper for the array with the highest priority.
683
684 In case of ties, leftmost wins. If no wrapper is found, return None
685 """
686 wrappers = sorted((getattr(x, '__array_priority__', 0), -i,
687 x.__array_wrap__) for i, x in enumerate(args)
688 if hasattr(x, '__array_wrap__'))
689 if wrappers:
690 return wrappers[-1][-1]
691 return None
692
693 def kron(a, b):
694 """
695 Kronecker product of two arrays.
696
697 Computes the Kronecker product, a composite array made of blocks of the
698 second array scaled by the first.
699
700 Parameters
701 ----------
702 a, b : array_like
703
704 Returns
705 -------
706 out : ndarray
707
708 See Also
709 --------
710 outer : The outer product
711
712 Notes
713 -----
714 The function assumes that the number of dimenensions of `a` and `b`
715 are the same, if necessary prepending the smallest with ones.
716 If `a.shape = (r0,r1,..,rN)` and `b.shape = (s0,s1,...,sN)`,
717 the Kronecker product has shape `(r0*s0, r1*s1, ..., rN*SN)`.
718 The elements are products of elements from `a` and `b`, organized
719 explicitly by::
720
721 kron(a,b)[k0,k1,...,kN] = a[i0,i1,...,iN] * b[j0,j1,...,jN]
722
723 where::
724
725 kt = it * st + jt, t = 0,...,N
726
727 In the common 2-D case (N=1), the block structure can be visualized::
728
729 [[ a[0,0]*b, a[0,1]*b, ... , a[0,-1]*b ],
730 [ ... ... ],
731 [ a[-1,0]*b, a[-1,1]*b, ... , a[-1,-1]*b ]]
732
733
734 Examples
735 --------
736 >>> np.kron([1,10,100], [5,6,7])
737 array([ 5, 6, 7, 50, 60, 70, 500, 600, 700])
738 >>> np.kron([5,6,7], [1,10,100])
739 array([ 5, 50, 500, 6, 60, 600, 7, 70, 700])
740
741 >>> np.kron(np.eye(2), np.ones((2,2)))
742 array([[ 1., 1., 0., 0.],
743 [ 1., 1., 0., 0.],
744 [ 0., 0., 1., 1.],
745 [ 0., 0., 1., 1.]])
746
747 >>> a = np.arange(100).reshape((2,5,2,5))
748 >>> b = np.arange(24).reshape((2,3,4))
749 >>> c = np.kron(a,b)
750 >>> c.shape
751 (2, 10, 6, 20)
752 >>> I = (1,3,0,2)
753 >>> J = (0,2,1)
754 >>> J1 = (0,) + J # extend to ndim=4
755 >>> S1 = (1,) + b.shape
756 >>> K = tuple(np.array(I) * np.array(S1) + np.array(J1))
757 >>> c[K] == a[I]*b[J]
758 True
759
760 """
761 b = asanyarray(b)
762 a = array(a, copy=False, subok=True, ndmin=b.ndim)
763 ndb, nda = b.ndim, a.ndim
764 if (nda == 0 or ndb == 0):
765 return _nx.multiply(a, b)
766 as_ = a.shape
767 bs = b.shape
768 if not a.flags.contiguous:
769 a = reshape(a, as_)
770 if not b.flags.contiguous:
771 b = reshape(b, bs)
772 nd = ndb
773 if (ndb != nda):
774 if (ndb > nda):
775 as_ = (1,)*(ndb-nda) + as_
776 else:
777 bs = (1,)*(nda-ndb) + bs
778 nd = nda
779 result = outer(a, b).reshape(as_+bs)
780 axis = nd-1
781 for _ in range(nd):
782 result = concatenate(result, axis=axis)
783 wrapper = get_array_prepare(a, b)
784 if wrapper is not None:
785 result = wrapper(result)
786 wrapper = get_array_wrap(a, b)
787 if wrapper is not None:
788 result = wrapper(result)
789 return result
790
791
792 def tile(A, reps):
793 """
794 Construct an array by repeating A the number of times given by reps.
795
796 If `reps` has length ``d``, the result will have dimension of
797 ``max(d, A.ndim)``.
798
799 If ``A.ndim < d``, `A` is promoted to be d-dimensional by prepending new
800 axes. So a shape (3,) array is promoted to (1, 3) for 2-D replication,
801 or shape (1, 1, 3) for 3-D replication. If this is not the desired
802 behavior, promote `A` to d-dimensions manually before calling this
803 function.
804
805 If ``A.ndim > d``, `reps` is promoted to `A`.ndim by pre-pending 1's to it.
806 Thus for an `A` of shape (2, 3, 4, 5), a `reps` of (2, 2) is treated as
807 (1, 1, 2, 2).
808
809 Parameters
810 ----------
811 A : array_like
812 The input array.
813 reps : array_like
814 The number of repetitions of `A` along each axis.
815
816 Returns
817 -------
818 c : ndarray
819 The tiled output array.
820
821 See Also
822 --------
823 repeat : Repeat elements of an array.
824
825 Examples
826 --------
827 >>> a = np.array([0, 1, 2])
828 >>> np.tile(a, 2)
829 array([0, 1, 2, 0, 1, 2])
830 >>> np.tile(a, (2, 2))
831 array([[0, 1, 2, 0, 1, 2],
832 [0, 1, 2, 0, 1, 2]])
833 >>> np.tile(a, (2, 1, 2))
834 array([[[0, 1, 2, 0, 1, 2]],
835 [[0, 1, 2, 0, 1, 2]]])
836
837 >>> b = np.array([[1, 2], [3, 4]])
838 >>> np.tile(b, 2)
839 array([[1, 2, 1, 2],
840 [3, 4, 3, 4]])
841 >>> np.tile(b, (2, 1))
842 array([[1, 2],
843 [3, 4],
844 [1, 2],
845 [3, 4]])
846
847 """
848 try:
849 tup = tuple(reps)
850 except TypeError:
851 tup = (reps,)
852 d = len(tup)
853 c = _nx.array(A, copy=False, subok=True, ndmin=d)
854 shape = list(c.shape)
855 n = max(c.size, 1)
856 if (d < c.ndim):
857 tup = (1,)*(c.ndim-d) + tup
858 for i, nrep in enumerate(tup):
859 if nrep != 1:
860 c = c.reshape(-1, n).repeat(nrep, 0)
861 dim_in = shape[i]
862 dim_out = dim_in*nrep
863 shape[i] = dim_out
864 n //= max(dim_in, 1)
865 return c.reshape(shape)