@@ -468,6 +468,28 @@ TEST_F(OpUpsampleBilinear2dTest, ZeroComputedOutputSizeDies) {
468468 out));
469469}
470470
471+ TEST_F (OpUpsampleBilinear2dTest, MismatchedDimOrderDies) {
472+ TensorFactory<ScalarType::Float> tf;
473+
474+ if (torch::executor::testing::SupportedFeatures::get ()->is_aten ) {
475+ GTEST_SKIP () << " ATen kernel can implicitly convert dim order" ;
476+ }
477+
478+ const auto input = tf.ones ({1 , 1 , 1 , 2 });
479+ auto out = tf.zeros_channels_last ({1 , 1 , 1 , 4 });
480+ std::array<double , 2 > scale_factors = {2 , 2 };
481+
482+ ET_EXPECT_KERNEL_FAILURE (
483+ context_,
484+ op_upsample_bilinear2d_vec_out (
485+ input,
486+ {},
487+ false ,
488+ OptionalArrayRef<double >(
489+ {scale_factors.data (), scale_factors.size ()}),
490+ out));
491+ }
492+
471493TEST_F (OpUpsampleBilinear2dTest, NumericsCheck) {
472494 TensorFactory<ScalarType::Float> tf;
473495
@@ -577,3 +599,129 @@ TEST_F(OpUpsampleBilinear2dTest, Simple5x1To4x1AlignCorners) {
577599
578600 EXPECT_TENSOR_CLOSE (out, expected);
579601}
602+
603+ TEST_F (OpUpsampleBilinear2dTest, Simple1x2To1x4ChannelsLast) {
604+ TensorFactory<ScalarType::Float> tf;
605+
606+ const auto input = tf.make_channels_last ({1 , 1 , 1 , 2 }, {1.0 , 4.0 });
607+ std::array<int64_t , 2 > output_size = {1 , 4 };
608+ auto out = tf.zeros_channels_last ({1 , 1 , 1 , 4 });
609+
610+ op_upsample_bilinear2d_vec_out (
611+ input,
612+ OptionalArrayRef<int64_t >({output_size.data (), output_size.size ()}),
613+ false ,
614+ {},
615+ out);
616+
617+ const auto expected =
618+ tf.make_channels_last ({1 , 1 , 1 , 4 }, {1.0 , 1.75 , 3.25 , 4.0 });
619+
620+ EXPECT_TENSOR_EQ (out, expected);
621+ }
622+
623+ TEST_F (OpUpsampleBilinear2dTest, SmokeTestChannelsLast) {
624+ TensorFactory<ScalarType::Float> tf;
625+
626+ const auto input = tf.make_channels_last (
627+ {1 , 2 , 3 , 4 }, {0.0 , 12 , 1 , 13 , 2 , 14 , 3 , 15 , 4 , 16 , 5 , 17 ,
628+ 6 , 18 , 7 , 19 , 8 , 20 , 9 , 21 , 10 , 22 , 11 , 23 });
629+ std::array<int64_t , 2 > output_size = {6 , 8 };
630+ auto out = tf.zeros_channels_last ({1 , 2 , 6 , 8 });
631+
632+ op_upsample_bilinear2d_vec_out (
633+ input,
634+ OptionalArrayRef<int64_t >({output_size.data (), output_size.size ()}),
635+ false ,
636+ {},
637+ out);
638+
639+ const auto expected = tf.make_channels_last (
640+ {1 , 2 , 6 , 8 },
641+ {0.0000 , 12.0000 , 0.2500 , 12.2500 , 0.7500 , 12.7500 , 1.2500 , 13.2500 ,
642+ 1.7500 , 13.7500 , 2.2500 , 14.2500 , 2.7500 , 14.7500 , 3.0000 , 15.0000 ,
643+ 1.0000 , 13.0000 , 1.2500 , 13.2500 , 1.7500 , 13.7500 , 2.2500 , 14.2500 ,
644+ 2.7500 , 14.7500 , 3.2500 , 15.2500 , 3.7500 , 15.7500 , 4.0000 , 16.0000 ,
645+ 3.0000 , 15.0000 , 3.2500 , 15.2500 , 3.7500 , 15.7500 , 4.2500 , 16.2500 ,
646+ 4.7500 , 16.7500 , 5.2500 , 17.2500 , 5.7500 , 17.7500 , 6.0000 , 18.0000 ,
647+ 5.0000 , 17.0000 , 5.2500 , 17.2500 , 5.7500 , 17.7500 , 6.2500 , 18.2500 ,
648+ 6.7500 , 18.7500 , 7.2500 , 19.2500 , 7.7500 , 19.7500 , 8.0000 , 20.0000 ,
649+ 7.0000 , 19.0000 , 7.2500 , 19.2500 , 7.7500 , 19.7500 , 8.2500 , 20.2500 ,
650+ 8.7500 , 20.7500 , 9.2500 , 21.2500 , 9.7500 , 21.7500 , 10.0000 , 22.0000 ,
651+ 8.0000 , 20.0000 , 8.2500 , 20.2500 , 8.7500 , 20.7500 , 9.2500 , 21.2500 ,
652+ 9.7500 , 21.7500 , 10.2500 , 22.2500 , 10.7500 , 22.7500 , 11.0000 , 23.0000 });
653+
654+ EXPECT_TENSOR_CLOSE (out, expected);
655+ }
656+
657+ TEST_F (OpUpsampleBilinear2dTest, NumericsCheckChannelsLast) {
658+ TensorFactory<ScalarType::Float> tf;
659+
660+ const auto input = tf.zeros_channels_last ({3 , 7 , 47 , 99 });
661+ auto out = tf.zeros_channels_last ({3 , 7 , 291 , 512 });
662+ std::array<int64_t , 2 > output_size = {291 , 512 };
663+
664+ auto input_ptr = static_cast <float *>(input.mutable_data_ptr ());
665+ for (auto i = 0ul ; i < input.numel (); i++) {
666+ input_ptr[i] = static_cast <float >(i);
667+ }
668+
669+ op_upsample_bilinear2d_vec_out (
670+ input,
671+ OptionalArrayRef<int64_t >({output_size.data (), output_size.size ()}),
672+ false ,
673+ {},
674+ out);
675+
676+ // Indices and expected values to evaluate.
677+ std::vector<std::tuple<int , int , int , int , float >> test_values = {
678+ {0 , 2 , 60 , 200 , 6695.0137 },
679+ {1 , 6 , 5 , 503 , 33524.098 },
680+ {2 , 0 , 111 , 300 , 77678.68 },
681+ };
682+
683+ const auto output_data = static_cast <const float *>(out.const_data_ptr ());
684+ for (const auto & test_case : test_values) {
685+ const auto [n, c, h, w, expected] = test_case;
686+ const auto actual = output_data
687+ [n * out.strides ()[0 ] + c * out.strides ()[1 ] + h * out.strides ()[2 ] +
688+ w * out.strides ()[3 ]];
689+ EXPECT_FLOAT_EQ (expected, actual);
690+ }
691+ }
692+
693+ TEST_F (OpUpsampleBilinear2dTest, NumericsCheckAlignCornersChannelsLast) {
694+ TensorFactory<ScalarType::Float> tf;
695+
696+ const auto input = tf.zeros_channels_last ({3 , 7 , 47 , 99 });
697+ auto out = tf.zeros_channels_last ({3 , 7 , 291 , 512 });
698+ std::array<int64_t , 2 > output_size = {291 , 512 };
699+
700+ auto input_ptr = static_cast <float *>(input.mutable_data_ptr ());
701+ for (auto i = 0ul ; i < input.numel (); i++) {
702+ input_ptr[i] = static_cast <float >(i);
703+ }
704+
705+ op_upsample_bilinear2d_vec_out (
706+ input,
707+ OptionalArrayRef<int64_t >({output_size.data (), output_size.size ()}),
708+ true ,
709+ {},
710+ out);
711+
712+ // Indices and expected values to evaluate.
713+ std::vector<std::tuple<int , int , int , int , float >> test_values = {
714+ {0 , 2 , 60 , 200 , 6865.9414 },
715+ {1 , 6 , 5 , 503 , 33801.883 },
716+ {2 , 0 , 111 , 300 , 77746.32 },
717+ };
718+
719+ const auto output_data = static_cast <const float *>(out.const_data_ptr ());
720+ for (const auto & test_case : test_values) {
721+ const auto [n, c, h, w, expected] = test_case;
722+ const auto actual = output_data
723+ [n * out.strides ()[0 ] + c * out.strides ()[1 ] + h * out.strides ()[2 ] +
724+ w * out.strides ()[3 ]];
725+ EXPECT_FLOAT_EQ (expected, actual);
726+ }
727+ }
0 commit comments