@@ -59,6 +59,7 @@ REGISTER_CPU_OPERATOR(GatherRanges, GatherRangesOp<CPUContext>);
59
59
REGISTER_CPU_OPERATOR (LengthsGather, LengthsGatherOp<CPUContext>);
60
60
REGISTER_CPU_OPERATOR (LengthsToSegmentIds, LengthsToSegmentIdsOp<CPUContext>);
61
61
REGISTER_CPU_OPERATOR (LengthsToRanges, LengthsToRangesOp<CPUContext>);
62
+ REGISTER_CPU_OPERATOR (LengthsToOffsets, LengthsToOffsetsOp<CPUContext>);
62
63
REGISTER_CPU_OPERATOR (SegmentIdsToLengths, SegmentIdsToLengthsOp<CPUContext>);
63
64
REGISTER_CPU_OPERATOR (SegmentIdsToRanges, SegmentIdsToRangesOp<CPUContext>);
64
65
REGISTER_CPU_OPERATOR (LengthsToWeights, LengthsToWeightsOp<CPUContext>);
@@ -522,20 +523,20 @@ Another output LENGTHS represents each example length within OUTPUT
522
523
" LENGTHS" ,
523
524
" 1-D tensor of size N with lengths over gathered data"
524
525
" for each row in a batch. sum(LENGTHS) == OUTPUT.size()" )
525
- .TensorInferenceFunction(OpSchema::NeedsAllInputShapes([](
526
- const OperatorDef& /* unused */ , const vector<TensorShape>& in) {
527
- std::vector<TensorShape> out (2 );
528
-
529
- int total = 1 ;
530
- for (auto d : in[0 ].dims ()) {
531
- total *= d;
532
- }
533
- out[0 ].add_dims (total);
534
- out[0 ].set_data_type (in[0 ].data_type ());
535
- out[1 ].add_dims (in[1 ].dims (0 ));
536
- out[1 ].set_data_type (in[1 ].data_type ());
537
- return out;
538
- }));
526
+ .TensorInferenceFunction(OpSchema::NeedsAllInputShapes(
527
+ []( const OperatorDef& /* unused */ , const vector<TensorShape>& in) {
528
+ std::vector<TensorShape> out (2 );
529
+
530
+ int total = 1 ;
531
+ for (auto d : in[0 ].dims ()) {
532
+ total *= d;
533
+ }
534
+ out[0 ].add_dims (total);
535
+ out[0 ].set_data_type (in[0 ].data_type ());
536
+ out[1 ].add_dims (in[1 ].dims (0 ));
537
+ out[1 ].set_data_type (in[1 ].data_type ());
538
+ return out;
539
+ }));
539
540
540
541
OPERATOR_SCHEMA (LengthsGather)
541
542
.NumInputs(3 )
@@ -636,6 +637,30 @@ For example, `[1, 3, 0, 2]` transforms into `[[0, 1], [1, 3], [4, 0], [4, 2]]`.
636
637
" ranges" ,
637
638
" 2D tensor of shape len(lengths) X 2 and the same type as `lengths`" );
638
639
640
+ OPERATOR_SCHEMA (LengthsToOffsets)
641
+ .NumInputs(1 )
642
+ .NumOutputs(1 )
643
+ .SetDoc(R"DOC(
644
+ Given a vector of segment lengths, returns a vector of offsets from these lengths,
645
+ which will have the same size as the input vector. Output is going to have
646
+ the same type as input. For long tensors explicit casting from int32 to int64
647
+ might be necessary prior to this op.
648
+
649
+ For example, `[1, 3, 0, 2]` transforms into `[0, 1, 4, 4]`.
650
+ )DOC" )
651
+ .Input(0 , " lengths" , " 1D tensor of int32 or int64 segment lengths." )
652
+ .Output(0 , " offsets" , " 1D tensor of the same shape and type as `lengths`" )
653
+ .TensorInferenceFunction([](const OperatorDef& def,
654
+ const vector<TensorShape>& in) {
655
+ const ArgumentHelper args (def);
656
+ bool include_last_offset =
657
+ args.GetSingleArgument <bool >(" include_last_offset" , false );
658
+ vector<int > out_shape (in[0 ].dims ().begin (), in[0 ].dims ().end ());
659
+ out_shape[0 ] += include_last_offset ? 1 : 0 ;
660
+ return vector<TensorShape>{
661
+ CreateTensorShape (out_shape, in[0 ].data_type ())};
662
+ });
663
+
639
664
OPERATOR_SCHEMA (SegmentIdsToLengths)
640
665
.NumInputs(1 , 2 )
641
666
.NumOutputs(1 )
0 commit comments