Add tf.MatrixBandPartOp ODS definition and corresponding verifier.
PiperOrigin-RevId: 297174451 Change-Id: I77400245d526dc647dd17f532b935bf6f942db62
This commit is contained in:
parent
e012e9a786
commit
4a010cc04c
@ -3111,6 +3111,70 @@ cublas.
|
||||
TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>;
|
||||
}
|
||||
|
||||
def TF_MatrixBandPartOp : TF_Op<"MatrixBandPart", [NoSideEffect, AllTypesMatch<["input", "band"]>]> {
|
||||
let summary = [{
|
||||
Copy a tensor setting everything outside a central band in each innermost matrix
|
||||
to zero.
|
||||
}];
|
||||
|
||||
let description = [{
|
||||
The `band` part is computed as follows:
|
||||
Assume `input` has `k` dimensions `[I, J, K, ..., M, N]`, then the output is a
|
||||
tensor with the same shape where
|
||||
|
||||
`band[i, j, k, ..., m, n] = in_band(m, n) * input[i, j, k, ..., m, n]`.
|
||||
|
||||
The indicator function
|
||||
|
||||
`in_band(m, n) = (num_lower < 0 || (m-n) <= num_lower)) &&
|
||||
(num_upper < 0 || (n-m) <= num_upper)`.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
# if 'input' is [[ 0, 1, 2, 3]
|
||||
[-1, 0, 1, 2]
|
||||
[-2, -1, 0, 1]
|
||||
[-3, -2, -1, 0]],
|
||||
|
||||
tf.matrix_band_part(input, 1, -1) ==> [[ 0, 1, 2, 3]
|
||||
[-1, 0, 1, 2]
|
||||
[ 0, -1, 0, 1]
|
||||
[ 0, 0, -1, 0]],
|
||||
|
||||
tf.matrix_band_part(input, 2, 1) ==> [[ 0, 1, 0, 0]
|
||||
[-1, 0, 1, 0]
|
||||
[-2, -1, 0, 1]
|
||||
[ 0, -2, -1, 0]]
|
||||
```
|
||||
|
||||
Useful special cases:
|
||||
|
||||
```
|
||||
tf.matrix_band_part(input, 0, -1) ==> Upper triangular part.
|
||||
tf.matrix_band_part(input, -1, 0) ==> Lower triangular part.
|
||||
tf.matrix_band_part(input, 0, 0) ==> Diagonal.
|
||||
```
|
||||
}];
|
||||
|
||||
let arguments = (ins
|
||||
TF_Tensor:$input,
|
||||
TF_I32OrI64Tensor:$num_lower,
|
||||
TF_I32OrI64Tensor:$num_upper
|
||||
);
|
||||
|
||||
let results = (outs
|
||||
TF_Tensor:$band
|
||||
);
|
||||
|
||||
TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>;
|
||||
TF_DerivedOperandTypeAttr Tindex = TF_DerivedOperandTypeAttr<1>;
|
||||
|
||||
let verifier = [{
|
||||
return Verify(*this);
|
||||
}];
|
||||
}
|
||||
|
||||
def TF_MatrixDiagOp : TF_Op<"MatrixDiag", [NoSideEffect]> {
|
||||
let summary = [{
|
||||
Returns a batched diagonal tensor with a given batched diagonal values.
|
||||
|
@ -1506,6 +1506,29 @@ void LogicalNotOp::getCanonicalizationPatterns(
|
||||
LogicalNotOfLess, LogicalNotOfLessEqual>(context);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MatrixBandPartOp
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static LogicalResult Verify(MatrixBandPartOp op) {
|
||||
if (!HasRankAtLeast(op.input(), 2)) {
|
||||
return op.emitOpError()
|
||||
<< "requires `input` to have rank of at least 2, but found "
|
||||
<< op.input().getType();
|
||||
}
|
||||
if (!IsOfRankOrUnranked(op.num_lower(), 0)) {
|
||||
return op.emitOpError()
|
||||
<< "requires `num_lower` to have 0 dimensions, but found "
|
||||
<< op.num_lower().getType();
|
||||
}
|
||||
if (!IsOfRankOrUnranked(op.num_upper(), 0)) {
|
||||
return op.emitOpError()
|
||||
<< "requires `num_upper` to have 0 dimensions, but found "
|
||||
<< op.num_upper().getType();
|
||||
}
|
||||
return success();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MaxOp
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -854,6 +854,78 @@ func @testInvalidIfOp(tensor<i1>, tensor<*xf32>) -> tensor<2xf32> {
|
||||
|
||||
// -----
|
||||
|
||||
// Test valid tf.MatrixBandPart
|
||||
// CHECK-LABEL: func @testValidMatrixBandPartOp
|
||||
func @testValidMatrixBandPartOp(%arg0: tensor<64x64xbf16>, %arg1: tensor<i64>, %arg2: tensor<i64>) -> tensor<64x64xbf16> {
|
||||
%0 = "tf.MatrixBandPart"(%arg0, %arg1, %arg2) : (tensor<64x64xbf16>, tensor<i64>, tensor<i64>) -> tensor<64x64xbf16>
|
||||
return %0 : tensor<64x64xbf16>
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
// Test valid tf.MatrixBandPart
|
||||
// CHECK-LABEL: func @testValidMatrixBandPartOp3D
|
||||
func @testValidMatrixBandPartOp3D(%arg0: tensor<64x64x64xbf16>, %arg1: tensor<i64>, %arg2: tensor<i64>) -> tensor<64x64x64xbf16> {
|
||||
%0 = "tf.MatrixBandPart"(%arg0, %arg1, %arg2) : (tensor<64x64x64xbf16>, tensor<i64>, tensor<i64>) -> tensor<64x64x64xbf16>
|
||||
return %0 : tensor<64x64x64xbf16>
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
// Test valid tf.MatrixBandPart
|
||||
// CHECK-LABEL: func @testValidMatrixBandPartOpUnranked
|
||||
func @testValidMatrixBandPartOpUnranked(%arg0: tensor<*xbf16>, %arg1: tensor<i64>, %arg2: tensor<i64>) -> tensor<*xbf16> {
|
||||
%0 = "tf.MatrixBandPart"(%arg0, %arg1, %arg2) : (tensor<*xbf16>, tensor<i64>, tensor<i64>) -> tensor<*xbf16>
|
||||
return %0 : tensor<*xbf16>
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
// Test invalid tf.MatrixBandPart
|
||||
func @testInvalidMatrixBandPartOp(%arg0: tensor<64x64x64xbf16>, %arg1: tensor<i64>, %arg2: tensor<i64>) -> tensor<64x64xbf16> {
|
||||
// expected-error @+1 {{op failed to verify that all of {input, band} have same type}}
|
||||
%0 = "tf.MatrixBandPart"(%arg0, %arg1, %arg2) : (tensor<64x64x64xbf16>, tensor<i64>, tensor<i64>) -> tensor<64x64xbf16>
|
||||
return %0 : tensor<64x64xbf16>
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
// Test invalid tf.MatrixBandPart
|
||||
func @testInvalidMatrixBandPartOp(%arg0: tensor<64x64x64xbf16>, %arg1: tensor<i64>, %arg2: tensor<i64>) -> tensor<*xbf16> {
|
||||
// expected-error @+1 {{op failed to verify that all of {input, band} have same type}}
|
||||
%0 = "tf.MatrixBandPart"(%arg0, %arg1, %arg2) : (tensor<64x64x64xbf16>, tensor<i64>, tensor<i64>) -> tensor<*xbf16>
|
||||
return %0 : tensor<*xbf16>
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
// Test invalid tf.MatrixBandPart
|
||||
func @testInvalidMatrixBandPartOp(%arg0: tensor<i64>, %arg1: tensor<64x64xi64>, %arg2: tensor<i64>) -> tensor<i64> {
|
||||
// expected-error @+1 {{op requires `input` to have rank of at least 2, but found 'tensor<i64>'}}
|
||||
%0 = "tf.MatrixBandPart"(%arg0, %arg1, %arg2) : (tensor<i64>, tensor<64x64xi64>, tensor<i64>) -> tensor<i64>
|
||||
return %0 : tensor<i64>
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
// Test invalid tf.MatrixBandPart
|
||||
func @testInvalidMatrixBandPartOp(%arg0: tensor<64x64xi64>, %arg1: tensor<32xi64>, %arg2: tensor<i64>) -> tensor<64x64xi64> {
|
||||
// expected-error @+1 {{op requires `num_lower` to have 0 dimensions, but found 'tensor<32xi64>'}}
|
||||
%0 = "tf.MatrixBandPart"(%arg0, %arg1, %arg2) : (tensor<64x64xi64>, tensor<32xi64>, tensor<i64>) -> tensor<64x64xi64>
|
||||
return %0 : tensor<64x64xi64>
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
// Test invalid tf.MatrixBandPart
|
||||
func @testInvalidMatrixBandPartOp(%arg0: tensor<64x64xi64>, %arg1: tensor<i64>, %arg2: tensor<32xi64>) -> tensor<64x64xi64> {
|
||||
// expected-error @+1 {{op requires `num_upper` to have 0 dimensions, but found 'tensor<32xi64>'}}
|
||||
%0 = "tf.MatrixBandPart"(%arg0, %arg1, %arg2) : (tensor<64x64xi64>, tensor<i64>, tensor<32xi64>) -> tensor<64x64xi64>
|
||||
return %0 : tensor<64x64xi64>
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// tf.{|Stateful}PartitionedCall
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
Loading…
Reference in New Issue
Block a user