def tile(a, reps):
if type(reps) in _numberTypes: reps = (reps,)
reps = tuple(reps) # for generator expressions
if type(a) in _numberTypes:
ret = empty(reps)
ret._base.assign(a)
return ret
a = as_garray(a)
if len(reps) > a.ndim: a = a._add_axes(len(reps))
if len(reps) < a.ndim: reps = _extend_shape(reps, a.ndim) # now len(reps)==a.ndim
retShape = tuple([ a.shape[i] * reps[i] for i in tuple(xrange(len(reps)))])
if _prodT(retShape)==0: return zeros(retShape)
if _prodT(reps)==1: return a
for i in range(a.ndim-1): # merge replication requests on adjacent axes, for efficiency.
if reps[i]!=1 and reps[i+1]!=1 and a.shape[i]==1: return a.reshape(_deleteT2(a.shape, i)).tile(reps[:i]+(_prodT(reps[i:i+2]),)+reps[i+2:]).reshape(map(operator.mul, a.shape, reps))
def dataIDone(nextA, i): return nextA.reshape(_modifyT(a.shape, i, a.shape[i]*reps[i])).tile(_modifyT(reps, i, 1))
if reps[0]!=1: # replicating rows is easy and efficient: just repeat the data a number of times.
temp = empty((reps[0], a.size)) # shape doesn't matter because dataIDone changes it
tempCm = temp._base_shaped(1)
if reps[0]>=1:
_cm_row_slice_read(tempCm, 0, 1).assign(a._base_as_row())
nCopiesDone = 1
while nCopiesDone < reps[0]:
nNow = __builtin__.min(nCopiesDone, reps[0]-nCopiesDone)
_cm_row_slice_read(tempCm, nCopiesDone, nCopiesDone + nNow).assign(_cm_row_slice_read(tempCm, 0, nNow))
nCopiesDone += nNow
return dataIDone(temp, 0)
# the general case is repeating a subset (aot the whole array) n times, before moving on to the next subset
# using a transpose with the right shape, the subsets can become columns. those can be lengthened because that is replicating rows; a second transpose makes them now-lengthened subsets again
axis = __builtin__.min( i for i in range(a.ndim) if reps[i]!=1)
return dataIDone(a.reshape_2d(axis).T.tile((reps[axis], 1)).T, axis)
评论列表
文章目录