tensorflow/compiler/tf2xla/kernels/lower_upper_bound_ops.cc
// Builds a LowerBound or UpperBound op, the distinction lying in
// comparison_direction: GT => LowerBoundOp, GE => UpperBoundOp.
// Note that this is an O(MN) algorithm: all entries in each sorted_inputs row
// are considered, and their sorted nature is not fully exploited.
Builds a LowerBound or UpperBound op, the distinction lying in
comparison_direction: GT => LowerBoundOp, GE => UpperBoundOp.
Note that this is an O(MN) algorithm: all entries in each sorted_inputs row
are considered, and their sorted nature is not fully exploited.
Builds a LowerBound or UpperBound op the distinction lying in comparison_direction : GT = > LowerBoundOp GE = > UpperBoundOp . Note that this is an O ( MN ) algorithm : all entries in each sorted_inputs row are considered and their sorted nature is not fully exploited .
void BuildLowerUpperBoundOp(XlaOpKernelContext* ctx, DataType out_dtype,
                            xla::ComparisonDirection comparison_direction) {
  const TensorShape sorted_inputs_shape = ctx->InputShape("sorted_inputs");
  const TensorShape values_shape = ctx->InputShape("values");
  const xla::XlaOp sorted_inputs = ctx->Input("sorted_inputs");
  const xla::XlaOp values = ctx->Input("values");
  OP_REQUIRES(ctx, sorted_inputs_shape.dims() == 2,
              errors::FailedPrecondition("sorted_inputs must be 2D"));
  OP_REQUIRES(ctx, values_shape.dims() == 2,
              errors::FailedPrecondition("values must be 2D"));
  auto new_values_shape = values_shape;
  new_values_shape.InsertDim( 2,  1);
  auto values_reshaped = xla::Reshape(values, new_values_shape.dim_sizes());
  auto new_sorted_inputs_shape = sorted_inputs_shape;
  new_sorted_inputs_shape.InsertDim( 1,  1);
  auto sorted_inputs_reshaped =
      xla::Reshape(sorted_inputs, new_sorted_inputs_shape.dim_sizes());
  auto comparison = xla::Compare(values_reshaped, sorted_inputs_reshaped, {},
                                 comparison_direction);
  const DataType accumulation_type = XlaHelpers::SumAccumulationType(out_dtype);
  auto comparison_int =
      XlaHelpers::ConvertElementType(comparison, accumulation_type);
  xla::XlaBuilder* builder = ctx->builder();
  auto reduced =
      xla::Reduce(comparison_int, XlaHelpers::Zero(builder, accumulation_type),
                  *ctx->GetOrCreateAdd(accumulation_type), {2});
  ctx->SetOutput(0, reduced);
}
void BuildLowerUpperBoundOp ( XlaOpKernelContext * ctx , DataType out_dtype , xla :: ComparisonDirection comparison_direction ) { const TensorShape sorted_inputs_shape = ctx -> InputShape ( " " ) ; const TensorShape values_shape = ctx -> InputShape ( " " ) ; const xla :: XlaOp sorted_inputs = ctx -> Input ( " " ) ; const xla :: XlaOp values = ctx -> Input ( " " ) ; OP_REQUIRES ( ctx , sorted_inputs_shape . dims ( ) == 2 , errors :: FailedPrecondition ( " " ) ) ; OP_REQUIRES ( ctx , values_shape . dims ( ) == 2 , errors :: FailedPrecondition ( " " ) ) ; auto new_values_shape = values_shape ; new_values_shape . InsertDim ( 2 , 1 ) ; auto values_reshaped = xla :: Reshape ( values , new_values_shape . dim_sizes ( ) ) ; auto new_sorted_inputs_shape = sorted_inputs_shape ; new_sorted_inputs_shape . InsertDim ( 1 , 1 ) ; auto sorted_inputs_reshaped = xla :: Reshape ( sorted_inputs , new_sorted_inputs_shape . dim_sizes ( ) ) ; auto comparison = xla :: Compare ( values_reshaped , sorted_inputs_reshaped , { } , comparison_direction ) ; const DataType accumulation_type = XlaHelpers :: SumAccumulationType ( out_dtype ) ; auto comparison_int = XlaHelpers :: ConvertElementType ( comparison , accumulation_type ) ; xla :: XlaBuilder * builder = ctx -> builder ( ) ; auto reduced = xla :: Reduce ( comparison_int , XlaHelpers :: Zero ( builder , accumulation_type ) , * ctx -> GetOrCreateAdd ( accumulation_type ) , { 2 } ) ; ctx -> SetOutput ( 0 , reduced ) ; }
Builds a LowerBound or UpperBound op, the distinction lying in
comparison_direction: GT => LowerBoundOp, GE => UpperBoundOp.
Builds a LowerBound or UpperBound op the distinction lying in comparison_direction : GT = > LowerBoundOp GE = > UpperBoundOp .
// We are assuming both inputs are 2D, which they will be given the current // implementation of tf.searchsorted. // Add a new inner dimension to values, to allow broadcasting along the inner // dimension of sorted_sequence. /* d */ /* size */ // Add a new penultimate dimension to sorted_inputs, to allow broadcasting of // sorted_sequence entries for each value. /* d */ /* size */ // We are relying on broadcasting to compare each value against each entry in // the associated sorted_inputs row. // The reshapes above leave the tensors with equal rank of 3, so broadcast // dimensions are not explicitly specified. // Convert boolean comparison results to integers so we can sum them. // Sum the comparison results over the inner dimension to find the index for // each value.