mirror of
https://github.com/iperov/DeepFaceLive
synced 2025-08-14 18:57:24 -07:00
add xlib.avecl
This commit is contained in:
parent
932edfe875
commit
0058474da7
56 changed files with 5569 additions and 0 deletions
74
xlib/avecl/_internal/info/BroadcastInfo.py
Normal file
74
xlib/avecl/_internal/info/BroadcastInfo.py
Normal file
|
@ -0,0 +1,74 @@
|
|||
from typing import List
|
||||
|
||||
import numpy as np
|
||||
|
||||
from ..AShape import AShape
|
||||
from ..AAxes import AAxes
|
||||
|
||||
class BroadcastInfo:
|
||||
"""
|
||||
Broadcast info for multi shapes.
|
||||
|
||||
arguments
|
||||
|
||||
shapes List[AShape]
|
||||
|
||||
errors during the construction:
|
||||
|
||||
ValueError
|
||||
|
||||
Example:
|
||||
shapes = ( 3,),
|
||||
(3, 1,)
|
||||
#Example | comment
|
||||
|
||||
o_shape #(3, 3) broadcasted together o_shape
|
||||
|
||||
br_shapes #(1, 3) shape[0] broadcasted to o_shape ndim
|
||||
#(3, 1) shape[1] broadcasted to o_shape ndim
|
||||
|
||||
shapes_tiles #(3, 1) tiles to make o_shape from br_shapes[0]
|
||||
#(1, 3) tiles to make o_shape from br_shapes[1]
|
||||
|
||||
shapes_reduction_axes #(0,) reduction_axes to make shapes[0] from o_shape
|
||||
#(1,) reduction_axes to make shapes[1] from o_shape
|
||||
"""
|
||||
|
||||
__slots__ = ['o_shape', 'br_shapes', 'shapes_tiles', 'shapes_reduction_axes']
|
||||
|
||||
def __init__(self, shapes : List[AShape]):
|
||||
|
||||
highest_rank = sorted([shape.ndim for shape in shapes])[-1]
|
||||
|
||||
# Broadcasted all shapes to highest ndim with (1,)-s in from left side
|
||||
br_shapes = [ (1,)*(highest_rank-shape.ndim) + shape for shape in shapes ]
|
||||
|
||||
# Determine o_shape from all shapes
|
||||
o_shape = AShape( np.max( [ [ br_shape.shape[axis] for br_shape in br_shapes] for axis in range(highest_rank) ], axis=1 ) )
|
||||
|
||||
shapes_tiles = []
|
||||
shapes_reduction_axes = []
|
||||
for br_shape in br_shapes:
|
||||
shape_tile = []
|
||||
shape_reduction_axes = []
|
||||
for axis, (x,y) in enumerate(zip(br_shape.shape, o_shape.shape)):
|
||||
if x != y:
|
||||
if x == 1 and y != 1:
|
||||
shape_tile.append(y)
|
||||
shape_reduction_axes.append(axis)
|
||||
elif x != 1 and y == 1:
|
||||
shape_tile.append(1)
|
||||
else:
|
||||
raise ValueError(f'operands could not be broadcast together with shapes {br_shape} {o_shape}')
|
||||
else:
|
||||
shape_tile.append(1)
|
||||
|
||||
shapes_tiles.append(shape_tile)
|
||||
shapes_reduction_axes.append( AAxes(shape_reduction_axes) )
|
||||
|
||||
|
||||
self.o_shape : AShape = AShape(o_shape)
|
||||
self.br_shapes : List[AShape] = br_shapes
|
||||
self.shapes_tiles : List[List] = shapes_tiles
|
||||
self.shapes_reduction_axes : List [AAxes] = shapes_reduction_axes
|
||||
|
62
xlib/avecl/_internal/info/ConcatInfo.py
Normal file
62
xlib/avecl/_internal/info/ConcatInfo.py
Normal file
|
@ -0,0 +1,62 @@
|
|||
from ..AShape import AShape
|
||||
|
||||
class ConcatInfo:
|
||||
__slots__ = ['o_shape', 'axis', 'axis_sizes', 'axis_offsets']
|
||||
|
||||
def __init__(self, shapes, axis):
|
||||
"""
|
||||
Concat info
|
||||
|
||||
arguments
|
||||
|
||||
shapes Iterable of shapes
|
||||
|
||||
errors during the construction:
|
||||
|
||||
ValueError
|
||||
|
||||
result
|
||||
|
||||
.o_shape AShape
|
||||
|
||||
.axis Int fixed axis argument
|
||||
|
||||
.axis_sizes List[Int] axis sizes for every shape in shapes
|
||||
|
||||
.axis_offsets List[Int] axis offset in o_shape
|
||||
for every shape in shapes
|
||||
"""
|
||||
|
||||
shapes = tuple(shapes)
|
||||
|
||||
if len(shapes) == 0:
|
||||
raise ValueError('shapes is empty')
|
||||
|
||||
|
||||
shape = shapes[0]
|
||||
|
||||
if axis < 0:
|
||||
axis = shape.ndim + axis
|
||||
if axis < 0 or axis >= shape.ndim:
|
||||
raise ValueError(f'Wrong axis {axis}')
|
||||
|
||||
fixed_shapes = [ tuple(a for i,a in enumerate(shape) if i != axis) for shape in shapes ]
|
||||
req_shape = fixed_shapes[0]
|
||||
if not all(shape == req_shape for shape in fixed_shapes[1:]):
|
||||
raise ValueError(f'All shapes must match shape {tuple(a if i != axis else "*" for i,a in enumerate(shape))}')
|
||||
|
||||
axis_sizes = [ shape[axis] for shape in shapes ]
|
||||
|
||||
axis_offset = 0
|
||||
axis_offsets = []
|
||||
for axis_size in axis_sizes:
|
||||
axis_offsets.append(axis_offset)
|
||||
axis_offset += axis_size
|
||||
|
||||
self.o_shape = AShape( tuple(shape)[0:axis] + (sum(axis_sizes),) + tuple(shape)[axis+1:] )
|
||||
self.axis = axis
|
||||
self.axis_sizes = axis_sizes
|
||||
self.axis_offsets = tuple(axis_offsets)
|
||||
|
||||
|
||||
|
78
xlib/avecl/_internal/info/Conv2DInfo.py
Normal file
78
xlib/avecl/_internal/info/Conv2DInfo.py
Normal file
|
@ -0,0 +1,78 @@
|
|||
from collections import Iterable
|
||||
import math
|
||||
|
||||
class Conv2DInfo:
|
||||
"""
|
||||
Conv2DInfo
|
||||
|
||||
arguments
|
||||
|
||||
H, W int axes sizes
|
||||
KH, KW int kernel sizes
|
||||
stride int
|
||||
dilation int
|
||||
|
||||
padding 'valid' no padding
|
||||
'same' output size will be the same
|
||||
or divided by stride
|
||||
int padding value for all sides
|
||||
|
||||
Iterable of 4 ints
|
||||
paddings for left,top,right,bottom sides
|
||||
|
||||
errors during the construction:
|
||||
|
||||
ValueError
|
||||
|
||||
result:
|
||||
|
||||
.PADL .PADR paddings for W axis
|
||||
.PADT .PADB paddings for H axis
|
||||
|
||||
.OH .OW result axes
|
||||
|
||||
.OH_T .OW_T result transposed axes.
|
||||
it is None if padding != 'valid','same'
|
||||
"""
|
||||
|
||||
__slots__ = ['PADL', 'PADR', 'PADT', 'PADB', 'OH', 'OW', 'OH_T', 'OW_T']
|
||||
|
||||
def __init__(self, H, W, KH, KW, stride, dilation, padding):
|
||||
# Effective kernel sizes with dilation
|
||||
EKH = (KH-1)*dilation + 1
|
||||
EKW = (KW-1)*dilation + 1
|
||||
|
||||
# Determine pad size of sides
|
||||
OH_T = OW_T = None
|
||||
if padding == 'valid':
|
||||
PADL = PADT = PADR = PADB = 0
|
||||
OH_T = H * stride + max(EKH - stride, 0)
|
||||
OW_T = W * stride + max(EKW - stride, 0)
|
||||
elif padding == 'same':
|
||||
PADL = int(math.floor((EKW - 1)/2))
|
||||
PADT = int(math.floor((EKH - 1)/2))
|
||||
PADR = int(math.ceil((EKW - 1)/2))
|
||||
PADB = int(math.ceil((EKH - 1)/2))
|
||||
OH_T = H * stride
|
||||
OW_T = W * stride
|
||||
elif isinstance(padding, int):
|
||||
PADL = PADT = PADR = PADB = padding
|
||||
elif isinstance(padding, Iterable):
|
||||
padding = tuple(int(x) for x in padding)
|
||||
if len(padding) != 4:
|
||||
raise ValueError("Invalid paddings list length.")
|
||||
PADL, PADT, PADR, PADB = padding
|
||||
else:
|
||||
raise ValueError("Invalid padding value.")
|
||||
|
||||
self.PADL = PADL
|
||||
self.PADT = PADT
|
||||
self.PADR = PADR
|
||||
self.PADB = PADB
|
||||
|
||||
self.OH = max(1, int((H + PADT + PADB - EKH) / stride + 1) )
|
||||
self.OW = max(1, int((W + PADL + PADR - EKW) / stride + 1) )
|
||||
self.OH_T = OH_T
|
||||
self.OW_T = OW_T
|
||||
|
||||
|
56
xlib/avecl/_internal/info/PadInfo.py
Normal file
56
xlib/avecl/_internal/info/PadInfo.py
Normal file
|
@ -0,0 +1,56 @@
|
|||
from typing import List
|
||||
|
||||
import numpy as np
|
||||
|
||||
from ..AShape import AShape
|
||||
|
||||
|
||||
class PadInfo:
|
||||
"""
|
||||
Pad info.
|
||||
|
||||
arguments
|
||||
|
||||
shape AShape
|
||||
|
||||
axes_paddings list of (l_pad, r_pad)
|
||||
|
||||
if [0] == ... (Ellipsis), then left-side paddings will be filled with (0,0) for remain axes
|
||||
if [-1] == ... , same for ride-side
|
||||
|
||||
errors during the construction:
|
||||
|
||||
ValueError
|
||||
|
||||
result:
|
||||
|
||||
.o_shape AShape
|
||||
|
||||
"""
|
||||
|
||||
__slots__ = ['o_shape','axes_paddings']
|
||||
|
||||
def __init__(self, shape, axes_paddings : List):
|
||||
|
||||
if Ellipsis in axes_paddings:
|
||||
if sum(1 if x == Ellipsis else 0 for x in axes_paddings) > 1:
|
||||
raise ValueError('only 1 ...(ellipsis) allowed in axes_paddings')
|
||||
if axes_paddings[0] == Ellipsis:
|
||||
axes_paddings = ((0,0),)*(shape.ndim-(len(axes_paddings)-1))+ axes_paddings[1:]
|
||||
elif axes_paddings[-1] == Ellipsis:
|
||||
axes_paddings = axes_paddings[:-1] + ((0,0),)*(shape.ndim-(len(axes_paddings)-1))
|
||||
else:
|
||||
raise ValueError('...(ellipsis) must be at the begin or the end of axes_paddings')
|
||||
|
||||
if len(axes_paddings) != shape.ndim:
|
||||
raise ValueError(f'axes_paddings should match shape.ndim {shape.ndim}')
|
||||
|
||||
|
||||
self.axes_paddings = axes_paddings
|
||||
o_shape = []
|
||||
|
||||
for axis, (axis_size, (l_pad, r_pad)) in enumerate(zip(shape, axes_paddings)):
|
||||
new_axis_size = l_pad + axis_size + r_pad
|
||||
o_shape.append(new_axis_size)
|
||||
|
||||
self.o_shape = AShape(o_shape)
|
50
xlib/avecl/_internal/info/ReductionInfo.py
Normal file
50
xlib/avecl/_internal/info/ReductionInfo.py
Normal file
|
@ -0,0 +1,50 @@
|
|||
from ..AShape import AShape
|
||||
|
||||
class ReductionInfo:
|
||||
"""
|
||||
Reduction info
|
||||
|
||||
arguments
|
||||
|
||||
shape AShape
|
||||
|
||||
axes AAxes
|
||||
|
||||
keepdims bool
|
||||
|
||||
can raise ValueError, TypeError during the construction
|
||||
"""
|
||||
|
||||
__slots__ = [
|
||||
'reduction_axes', # sorted reduction AAxes
|
||||
'o_axes', # remain AAxes after reduction
|
||||
'o_shape', # result AShape of reduction
|
||||
'o_shape_kd', # result AShape of reduction with keepdims
|
||||
]
|
||||
|
||||
def __init__(self, shape, axes, keepdims):
|
||||
shape_axes = shape.axes_arange()
|
||||
|
||||
if axes.is_none_axes():
|
||||
axes = shape_axes
|
||||
|
||||
# Check correctness of axes
|
||||
for axis in axes:
|
||||
if axis not in shape_axes:
|
||||
raise ValueError(f'Wrong axis {axis} not in {shape_axes}')
|
||||
|
||||
self.reduction_axes = reduction_axes = axes.sorted()
|
||||
|
||||
# Output axes. Remove axes from shape_axes
|
||||
self.o_axes = o_axes = shape_axes - axes
|
||||
|
||||
if o_axes.is_none_axes():
|
||||
o_shape = AShape( (1,) )
|
||||
else:
|
||||
o_shape = shape[o_axes]
|
||||
|
||||
self.o_shape = o_shape
|
||||
self.o_shape_kd = AShape( 1 if axis in reduction_axes else shape[axis] for axis in range(shape.ndim))
|
||||
|
||||
if keepdims:
|
||||
self.o_shape = self.o_shape_kd
|
44
xlib/avecl/_internal/info/ReshapeInfo.py
Normal file
44
xlib/avecl/_internal/info/ReshapeInfo.py
Normal file
|
@ -0,0 +1,44 @@
|
|||
from ..AShape import AShape
|
||||
|
||||
class ReshapeInfo:
|
||||
"""
|
||||
Reshape info.
|
||||
can raise ValueError,TypeError during the construction
|
||||
|
||||
arguments
|
||||
|
||||
shape AShape
|
||||
|
||||
target_shape Iterable of ints
|
||||
can be any len and contains only one '-1'
|
||||
Example
|
||||
|
||||
shape (2, 512, 8, 8, 64)
|
||||
target_shape (2, 512, -1)
|
||||
o_shape (2, 512, 4096)
|
||||
"""
|
||||
|
||||
__slots__ = ['o_shape']
|
||||
|
||||
def __init__(self, shape, target_shape):
|
||||
o_shape = []
|
||||
|
||||
remain_size = shape.size
|
||||
|
||||
unk_axis = None
|
||||
for t_size in target_shape:
|
||||
t_size = int(t_size)
|
||||
if t_size != -1:
|
||||
mod = remain_size % t_size
|
||||
if mod != 0:
|
||||
raise ValueError(f'Cannot reshape {shape} to {target_shape}.')
|
||||
remain_size /= t_size
|
||||
else:
|
||||
if unk_axis is not None:
|
||||
raise ValueError('Can specify only one unknown dimension.')
|
||||
unk_axis = len(o_shape)
|
||||
o_shape.append( t_size )
|
||||
|
||||
if unk_axis is not None:
|
||||
o_shape[unk_axis] = int(remain_size)
|
||||
self.o_shape = AShape(o_shape)
|
148
xlib/avecl/_internal/info/SliceInfo.py
Normal file
148
xlib/avecl/_internal/info/SliceInfo.py
Normal file
|
@ -0,0 +1,148 @@
|
|||
import math
|
||||
|
||||
import numpy as np
|
||||
|
||||
from ..AShape import AShape
|
||||
|
||||
|
||||
class SliceInfo:
|
||||
__slots__ = ['o_shape', 'o_shape_kd', 'just_reshaped','axes_bes','axes_abs_bes']
|
||||
|
||||
def __init__(self, shape : AShape, slices):
|
||||
"""
|
||||
Slice info.
|
||||
can raise ValueError,TypeError during the construction
|
||||
|
||||
arguments
|
||||
|
||||
slices
|
||||
|
||||
Example
|
||||
|
||||
|
||||
o_shape result shape after slice
|
||||
|
||||
axes_bes list of (begin,step,end) per axis
|
||||
if s==0, then single axis element is fetched from position b
|
||||
s can be negative.
|
||||
"""
|
||||
# Validate slices argument for given shape.
|
||||
new_slices = []
|
||||
before_ellipsis = None
|
||||
|
||||
for s in slices:
|
||||
if s is Ellipsis:
|
||||
before_ellipsis = new_slices
|
||||
new_slices = []
|
||||
continue
|
||||
elif s is not None and not isinstance(s, (int,tuple) ):
|
||||
raise ValueError(f'unknown slice argument {s} of type {s.__class__}')
|
||||
|
||||
new_slices.append(s)
|
||||
|
||||
if before_ellipsis is not None:
|
||||
# Process Ellipsis separator
|
||||
new_slices_n_axes = sum([ 1 for x in new_slices if x != None])
|
||||
before_ellipsis_n_axes = sum([ 1 for x in before_ellipsis if x != None])
|
||||
|
||||
# Expand slices by filling intermediate (None,None,None) for each remaining axis
|
||||
new_slices = before_ellipsis + \
|
||||
[(None,None,None)]*max(0, shape.ndim-before_ellipsis_n_axes-new_slices_n_axes) + \
|
||||
new_slices
|
||||
|
||||
new_slices_n_axes = sum([ 1 for x in new_slices if x != None])
|
||||
if new_slices_n_axes > shape.ndim:
|
||||
raise ValueError('slices arguments more than shape axes')
|
||||
elif new_slices_n_axes < shape.ndim:
|
||||
# Fill remaining axes
|
||||
new_slices += [(None,None,None)]*( shape.ndim - new_slices_n_axes )
|
||||
|
||||
slices = tuple(new_slices)
|
||||
|
||||
# Compute shapes
|
||||
output_is_reshaped = True # Flag determines that output_tensor
|
||||
# can be just reshaped without any computation
|
||||
o_shape = [] # output tensor shape
|
||||
o_shape_kd = [] # output shape used in kernel, must match input shape
|
||||
axes_bes = []
|
||||
axes_abs_bes = []
|
||||
|
||||
i_axis = 0
|
||||
|
||||
# Process slices arguments
|
||||
for v in slices:
|
||||
if v is None:
|
||||
# None is new axis
|
||||
# We can add unlimited number of (1,) axes at any place of shape
|
||||
o_shape.append(1)
|
||||
continue
|
||||
|
||||
i_axis_size = shape[i_axis]
|
||||
i_axis += 1
|
||||
|
||||
if isinstance(v, int):
|
||||
if v < 0:
|
||||
v += i_axis_size
|
||||
if v < 0 or v >= i_axis_size:
|
||||
raise ValueError(f'index {v} is out of bounds for axis {i_axis} with size {i_axis_size}')
|
||||
b,e,s = v,v,0
|
||||
else:
|
||||
b,e,s = v
|
||||
if s == 0:
|
||||
raise ValueError(f'slice step cannot be zero')
|
||||
|
||||
# Fix begin, end, step values
|
||||
if s is None:
|
||||
s = 1
|
||||
if b is None:
|
||||
b = 0 if s >= 0 else i_axis_size-1
|
||||
if e is None:
|
||||
e = i_axis_size if s >= 0 else -1
|
||||
elif e < 0:
|
||||
e += i_axis_size
|
||||
if b < 0:
|
||||
b += i_axis_size
|
||||
|
||||
if s >= 0:
|
||||
b = np.clip(b, 0, i_axis_size)
|
||||
e = np.clip(e, 0, i_axis_size)
|
||||
if b > e:
|
||||
raise ValueError('for positive step, begin cannot be > end.')
|
||||
|
||||
abs_b, abs_e, abs_s = b,e,s
|
||||
else:
|
||||
b = np.clip(b, 0, i_axis_size-1)
|
||||
e = np.clip(e, -1, i_axis_size)
|
||||
|
||||
if b <= e:
|
||||
raise ValueError('for negative step, begin cannot be <= end.')
|
||||
|
||||
abs_s = -s
|
||||
abs_e = b + 1
|
||||
abs_b = b - (math.ceil( (b-e) / abs_s ) -1) * abs_s
|
||||
|
||||
# for every o_shape_kd axis
|
||||
# we have exact begin,step values to fetch value from input
|
||||
axes_bes.append( (b,e,s))
|
||||
axes_abs_bes.append( (abs_b, abs_e, abs_s))
|
||||
|
||||
if i_axis_size != 1 and not (b == 0 and e == i_axis_size and s == 1):
|
||||
# Such params of axis slice will change input, thus output cannot be as just reshaped input
|
||||
output_is_reshaped = False
|
||||
|
||||
# Compute output_axis_size based on begin,end,step
|
||||
o_axis_size = max(0, math.ceil ( (e-b) / (s if s != 0 else 1) ) )
|
||||
|
||||
if o_axis_size >= 1:
|
||||
# >= 1 : select range of indexes, axis will remain
|
||||
o_shape.append(o_axis_size)
|
||||
# ^ othwerwise axis will be supressed
|
||||
|
||||
# o_shape with keepdims, must match ndim of input shape
|
||||
o_shape_kd.append( max(1,o_axis_size) )
|
||||
|
||||
self.just_reshaped = output_is_reshaped
|
||||
self.o_shape = AShape(o_shape)
|
||||
self.o_shape_kd = AShape(o_shape_kd)
|
||||
self.axes_bes = axes_bes
|
||||
self.axes_abs_bes = axes_abs_bes
|
37
xlib/avecl/_internal/info/StackInfo.py
Normal file
37
xlib/avecl/_internal/info/StackInfo.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
from ..AShape import AShape
|
||||
|
||||
class StackInfo:
|
||||
__slots__ = ['o_shape', 'axis']
|
||||
|
||||
def __init__(self, shape, axis, stack_count):
|
||||
"""
|
||||
Stack info
|
||||
|
||||
arguments
|
||||
|
||||
shape AShape
|
||||
|
||||
axis Int
|
||||
|
||||
stack_count Int
|
||||
|
||||
errors during the construction:
|
||||
|
||||
ValueError
|
||||
|
||||
result:
|
||||
|
||||
.o_shape AShape
|
||||
|
||||
.axis Int positive axis argument
|
||||
"""
|
||||
if axis < 0:
|
||||
axis = shape.ndim + 1 + axis
|
||||
if axis < 0 or axis > shape.ndim:
|
||||
raise ValueError(f'Wrong axis {axis}')
|
||||
|
||||
if stack_count <= 0:
|
||||
raise ValueError(f'Invalid stack_count {stack_count}')
|
||||
|
||||
self.o_shape = AShape( tuple(shape)[0:axis] + (stack_count,) + tuple(shape)[axis:] )
|
||||
self.axis = axis
|
52
xlib/avecl/_internal/info/TileInfo.py
Normal file
52
xlib/avecl/_internal/info/TileInfo.py
Normal file
|
@ -0,0 +1,52 @@
|
|||
import numpy as np
|
||||
from ..AShape import AShape, AShape
|
||||
|
||||
class TileInfo:
|
||||
"""
|
||||
Tile info.
|
||||
|
||||
arguments
|
||||
|
||||
shape AShape
|
||||
|
||||
tiles Iterable of ints
|
||||
|
||||
errors during the construction:
|
||||
|
||||
ValueError
|
||||
|
||||
result:
|
||||
|
||||
.o_shape AShape
|
||||
|
||||
.axes_slices list of slice() to fetch original shape
|
||||
from o_shape for each tile
|
||||
"""
|
||||
|
||||
__slots__ = ['o_shape', 'axes_slices']
|
||||
|
||||
def __init__(self, shape, tiles):
|
||||
if len(tiles) != shape.ndim:
|
||||
raise ValueError(f'tiles should match shape.ndim {shape.ndim}')
|
||||
|
||||
self.o_shape = AShape(dim*tiles[i] for i,dim in enumerate(shape))
|
||||
|
||||
c = [0]*shape.ndim
|
||||
|
||||
axes_offsets = []
|
||||
for n in range(np.prod(tiles)):
|
||||
axes_offsets.append( c.copy() )
|
||||
for i in range(shape.ndim-1,-1,-1):
|
||||
c[i] += 1
|
||||
if c[i] < tiles[i]:
|
||||
break
|
||||
c[i] = 0
|
||||
|
||||
axes_slices = []
|
||||
for axes_offset in axes_offsets:
|
||||
sl = []
|
||||
for axis,tile in enumerate(axes_offset):
|
||||
axis_size = shape[axis]
|
||||
sl.append( slice(axis_size*tile, axis_size*(tile+1)) )
|
||||
axes_slices.append(tuple(sl))
|
||||
self.axes_slices = tuple(axes_slices)
|
37
xlib/avecl/_internal/info/TransposeInfo.py
Normal file
37
xlib/avecl/_internal/info/TransposeInfo.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
from ..AShape import AShape
|
||||
from ..AAxes import AAxes
|
||||
|
||||
class TransposeInfo:
|
||||
"""
|
||||
TransposeInfo
|
||||
|
||||
arguments
|
||||
|
||||
shape AShape
|
||||
|
||||
axes_order AAxes
|
||||
|
||||
errors during the construction:
|
||||
|
||||
ValueError
|
||||
|
||||
result
|
||||
|
||||
.o_shape AShape
|
||||
|
||||
.no_changes bool transpose changes nothing
|
||||
|
||||
"""
|
||||
|
||||
__slots__ = ['no_changes', 'o_shape']
|
||||
|
||||
def __init__(self, shape : AShape, axes_order : AAxes):
|
||||
if shape.ndim != axes_order.ndim:
|
||||
raise ValueError('axes must match the shape')
|
||||
|
||||
# Axes order changes nothing?
|
||||
self.o_shape = shape[axes_order]
|
||||
self.no_changes = axes_order == shape.axes_arange()
|
||||
|
||||
|
||||
|
10
xlib/avecl/_internal/info/__init__.py
Normal file
10
xlib/avecl/_internal/info/__init__.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
from .BroadcastInfo import BroadcastInfo
|
||||
from .ConcatInfo import ConcatInfo
|
||||
from .PadInfo import PadInfo
|
||||
from .ReductionInfo import ReductionInfo
|
||||
from .ReshapeInfo import ReshapeInfo
|
||||
from .SliceInfo import SliceInfo
|
||||
from .StackInfo import StackInfo
|
||||
from .TileInfo import TileInfo
|
||||
from .TransposeInfo import TransposeInfo
|
||||
from .Conv2DInfo import Conv2DInfo
|
Loading…
Add table
Add a link
Reference in a new issue