| /* | 
 |  *  Copyright (c) 2015 The WebM project authors. All Rights Reserved. | 
 |  * | 
 |  *  Use of this source code is governed by a BSD-style license | 
 |  *  that can be found in the LICENSE file in the root of the source | 
 |  *  tree. An additional intellectual property rights grant can be found | 
 |  *  in the file PATENTS.  All contributing project authors may | 
 |  *  be found in the AUTHORS file in the root of the source tree. | 
 |  */ | 
 |  | 
 | #include <math.h> | 
 | #include <stdio.h> | 
 | #include <stdlib.h> | 
 |  | 
 | #include "test/acm_random.h" | 
 | #include "test/util.h" | 
 | #include "test/av1_txfm_test.h" | 
 | #include "av1/common/av1_txfm.h" | 
 | #include "./av1_rtcd.h" | 
 |  | 
 | using libaom_test::ACMRandom; | 
 | using libaom_test::input_base; | 
 | using libaom_test::bd; | 
 | using libaom_test::compute_avg_abs_error; | 
 | using libaom_test::Fwd_Txfm2d_Func; | 
 | using libaom_test::TYPE_TXFM; | 
 |  | 
 | namespace { | 
 | #if CONFIG_AOM_HIGHBITDEPTH | 
 | // tx_type_, tx_size_, max_error_, max_avg_error_ | 
 | typedef std::tr1::tuple<TX_TYPE, TX_SIZE, double, double> AV1FwdTxfm2dParam; | 
 |  | 
 | class AV1FwdTxfm2d : public ::testing::TestWithParam<AV1FwdTxfm2dParam> { | 
 |  public: | 
 |   virtual void SetUp() { | 
 |     tx_type_ = GET_PARAM(0); | 
 |     tx_size_ = GET_PARAM(1); | 
 |     max_error_ = GET_PARAM(2); | 
 |     max_avg_error_ = GET_PARAM(3); | 
 |     count_ = 500; | 
 |     TXFM_2D_FLIP_CFG fwd_txfm_flip_cfg = | 
 |         av1_get_fwd_txfm_cfg(tx_type_, tx_size_); | 
 |     const TXFM_2D_CFG *fwd_txfm_cfg = fwd_txfm_flip_cfg.cfg; | 
 |     int amplify_bit = fwd_txfm_cfg->shift[0] + fwd_txfm_cfg->shift[1] + | 
 |                       fwd_txfm_cfg->shift[2]; | 
 |     ud_flip_ = fwd_txfm_flip_cfg.ud_flip; | 
 |     lr_flip_ = fwd_txfm_flip_cfg.lr_flip; | 
 |     amplify_factor_ = | 
 |         amplify_bit >= 0 ? (1 << amplify_bit) : (1.0 / (1 << -amplify_bit)); | 
 |  | 
 |     fwd_txfm_ = libaom_test::fwd_txfm_func_ls[tx_size_]; | 
 |     txfm1d_size_ = libaom_test::get_txfm1d_size(tx_size_); | 
 |     txfm2d_size_ = txfm1d_size_ * txfm1d_size_; | 
 |     get_txfm1d_type(tx_type_, &type0_, &type1_); | 
 |     input_ = reinterpret_cast<int16_t *>( | 
 |         aom_memalign(16, sizeof(input_[0]) * txfm2d_size_)); | 
 |     output_ = reinterpret_cast<int32_t *>( | 
 |         aom_memalign(16, sizeof(output_[0]) * txfm2d_size_)); | 
 |     ref_input_ = reinterpret_cast<double *>( | 
 |         aom_memalign(16, sizeof(ref_input_[0]) * txfm2d_size_)); | 
 |     ref_output_ = reinterpret_cast<double *>( | 
 |         aom_memalign(16, sizeof(ref_output_[0]) * txfm2d_size_)); | 
 |   } | 
 |  | 
 |   void RunFwdAccuracyCheck() { | 
 |     ACMRandom rnd(ACMRandom::DeterministicSeed()); | 
 |     double avg_abs_error = 0; | 
 |     for (int ci = 0; ci < count_; ci++) { | 
 |       for (int ni = 0; ni < txfm2d_size_; ++ni) { | 
 |         input_[ni] = rnd.Rand16() % input_base; | 
 |         ref_input_[ni] = static_cast<double>(input_[ni]); | 
 |         output_[ni] = 0; | 
 |         ref_output_[ni] = 0; | 
 |       } | 
 |  | 
 |       fwd_txfm_(input_, output_, txfm1d_size_, tx_type_, bd); | 
 |  | 
 |       if (lr_flip_ && ud_flip_) | 
 |         libaom_test::fliplrud(ref_input_, txfm1d_size_, txfm1d_size_); | 
 |       else if (lr_flip_) | 
 |         libaom_test::fliplr(ref_input_, txfm1d_size_, txfm1d_size_); | 
 |       else if (ud_flip_) | 
 |         libaom_test::flipud(ref_input_, txfm1d_size_, txfm1d_size_); | 
 |  | 
 |       reference_hybrid_2d(ref_input_, ref_output_, txfm1d_size_, type0_, | 
 |                           type1_); | 
 |  | 
 |       for (int ni = 0; ni < txfm2d_size_; ++ni) { | 
 |         ref_output_[ni] = round(ref_output_[ni] * amplify_factor_); | 
 |         EXPECT_GE(max_error_, | 
 |                   fabs(output_[ni] - ref_output_[ni]) / amplify_factor_); | 
 |       } | 
 |       avg_abs_error += compute_avg_abs_error<int32_t, double>( | 
 |           output_, ref_output_, txfm2d_size_); | 
 |     } | 
 |  | 
 |     avg_abs_error /= amplify_factor_; | 
 |     avg_abs_error /= count_; | 
 |     // max_abs_avg_error comes from upper bound of avg_abs_error | 
 |     // printf("type0: %d type1: %d txfm_size: %d accuracy_avg_abs_error: | 
 |     // %f\n", type0_, type1_, txfm1d_size_, avg_abs_error); | 
 |     EXPECT_GE(max_avg_error_, avg_abs_error); | 
 |   } | 
 |  | 
 |   virtual void TearDown() { | 
 |     aom_free(input_); | 
 |     aom_free(output_); | 
 |     aom_free(ref_input_); | 
 |     aom_free(ref_output_); | 
 |   } | 
 |  | 
 |  private: | 
 |   double max_error_; | 
 |   double max_avg_error_; | 
 |   int count_; | 
 |   double amplify_factor_; | 
 |   TX_TYPE tx_type_; | 
 |   TX_SIZE tx_size_; | 
 |   int txfm1d_size_; | 
 |   int txfm2d_size_; | 
 |   Fwd_Txfm2d_Func fwd_txfm_; | 
 |   TYPE_TXFM type0_; | 
 |   TYPE_TXFM type1_; | 
 |   int16_t *input_; | 
 |   int32_t *output_; | 
 |   double *ref_input_; | 
 |   double *ref_output_; | 
 |   int ud_flip_;  // flip upside down | 
 |   int lr_flip_;  // flip left to right | 
 | }; | 
 |  | 
 | TEST_P(AV1FwdTxfm2d, RunFwdAccuracyCheck) { RunFwdAccuracyCheck(); } | 
 | const AV1FwdTxfm2dParam av1_fwd_txfm2d_param_c[] = { | 
 | #if CONFIG_EXT_TX | 
 |   AV1FwdTxfm2dParam(FLIPADST_DCT, TX_4X4, 2, 0.2), | 
 |   AV1FwdTxfm2dParam(DCT_FLIPADST, TX_4X4, 2, 0.2), | 
 |   AV1FwdTxfm2dParam(FLIPADST_FLIPADST, TX_4X4, 2, 0.2), | 
 |   AV1FwdTxfm2dParam(ADST_FLIPADST, TX_4X4, 2, 0.2), | 
 |   AV1FwdTxfm2dParam(FLIPADST_ADST, TX_4X4, 2, 0.2), | 
 |   AV1FwdTxfm2dParam(FLIPADST_DCT, TX_8X8, 5, 0.6), | 
 |   AV1FwdTxfm2dParam(DCT_FLIPADST, TX_8X8, 5, 0.6), | 
 |   AV1FwdTxfm2dParam(FLIPADST_FLIPADST, TX_8X8, 5, 0.6), | 
 |   AV1FwdTxfm2dParam(ADST_FLIPADST, TX_8X8, 5, 0.6), | 
 |   AV1FwdTxfm2dParam(FLIPADST_ADST, TX_8X8, 5, 0.6), | 
 |   AV1FwdTxfm2dParam(FLIPADST_DCT, TX_16X16, 11, 1.5), | 
 |   AV1FwdTxfm2dParam(DCT_FLIPADST, TX_16X16, 11, 1.5), | 
 |   AV1FwdTxfm2dParam(FLIPADST_FLIPADST, TX_16X16, 11, 1.5), | 
 |   AV1FwdTxfm2dParam(ADST_FLIPADST, TX_16X16, 11, 1.5), | 
 |   AV1FwdTxfm2dParam(FLIPADST_ADST, TX_16X16, 11, 1.5), | 
 |   AV1FwdTxfm2dParam(FLIPADST_DCT, TX_32X32, 70, 7), | 
 |   AV1FwdTxfm2dParam(DCT_FLIPADST, TX_32X32, 70, 7), | 
 |   AV1FwdTxfm2dParam(FLIPADST_FLIPADST, TX_32X32, 70, 7), | 
 |   AV1FwdTxfm2dParam(ADST_FLIPADST, TX_32X32, 70, 7), | 
 |   AV1FwdTxfm2dParam(FLIPADST_ADST, TX_32X32, 70, 7), | 
 | #endif | 
 |   AV1FwdTxfm2dParam(DCT_DCT, TX_4X4, 2, 0.2), | 
 |   AV1FwdTxfm2dParam(ADST_DCT, TX_4X4, 2, 0.2), | 
 |   AV1FwdTxfm2dParam(DCT_ADST, TX_4X4, 2, 0.2), | 
 |   AV1FwdTxfm2dParam(ADST_ADST, TX_4X4, 2, 0.2), | 
 |   AV1FwdTxfm2dParam(DCT_DCT, TX_8X8, 5, 0.6), | 
 |   AV1FwdTxfm2dParam(ADST_DCT, TX_8X8, 5, 0.6), | 
 |   AV1FwdTxfm2dParam(DCT_ADST, TX_8X8, 5, 0.6), | 
 |   AV1FwdTxfm2dParam(ADST_ADST, TX_8X8, 5, 0.6), | 
 |   AV1FwdTxfm2dParam(DCT_DCT, TX_16X16, 11, 1.5), | 
 |   AV1FwdTxfm2dParam(ADST_DCT, TX_16X16, 11, 1.5), | 
 |   AV1FwdTxfm2dParam(DCT_ADST, TX_16X16, 11, 1.5), | 
 |   AV1FwdTxfm2dParam(ADST_ADST, TX_16X16, 11, 1.5), | 
 |   AV1FwdTxfm2dParam(DCT_DCT, TX_32X32, 70, 7), | 
 |   AV1FwdTxfm2dParam(ADST_DCT, TX_32X32, 70, 7), | 
 |   AV1FwdTxfm2dParam(DCT_ADST, TX_32X32, 70, 7), | 
 |   AV1FwdTxfm2dParam(ADST_ADST, TX_32X32, 70, 7) | 
 | }; | 
 |  | 
 | INSTANTIATE_TEST_CASE_P(C, AV1FwdTxfm2d, | 
 |                         ::testing::ValuesIn(av1_fwd_txfm2d_param_c)); | 
 |  | 
 | #endif  // CONFIG_AOM_HIGHBITDEPTH | 
 | }  // namespace |