/*############################################################################
  # Copyright 2016 Intel Corporation
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #     http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  ############################################################################*/

/*!
 * \file
 * \brief FfElement unit tests.
 */

#include <cstring>
#include <limits>
#include <algorithm>

#include "gtest/gtest.h"

#include "epid/common-testhelper/errors-testhelper.h"
#include "epid/common-testhelper/prng-testhelper.h"
#include "epid/common-testhelper/octstr-testhelper.h"
#include "epid/common-testhelper/finite_field_wrapper-testhelper.h"
#include "epid/common-testhelper/ffelement_wrapper-testhelper.h"
#include "epid/common-testhelper/bignum_wrapper-testhelper.h"

extern "C" {
#include "epid/common/math/finitefield.h"
}

#include "epid/common/types.h"

#ifndef COUNT_OF
#define COUNT_OF(a) (sizeof(a) / sizeof((a)[0]))
#endif  // COUNT_OF

/// compares BigNumStr values
bool operator==(BigNumStr const& lhs, BigNumStr const& rhs) {
  return 0 == std::memcmp(&lhs, &rhs, sizeof(lhs));
}
/// compares BigNumStr to FqElemStr values
bool operator==(BigNumStr const& lhs, FqElemStr const& rhs) {
  return 0 == std::memcmp(&lhs, &rhs, sizeof(lhs));
}
/// compares FqElemStr to BigNumStr values
bool operator==(FqElemStr const& lhs, BigNumStr const& rhs) {
  return 0 == std::memcmp(&lhs, &rhs, sizeof(lhs));
}
/// compares FqElemStr values
bool operator==(FqElemStr const& lhs, FqElemStr const& rhs) {
  return 0 == std::memcmp(&lhs, &rhs, sizeof(lhs));
}
/// compares Fq2ElemStr values
bool operator==(Fq2ElemStr const& lhs, Fq2ElemStr const& rhs) {
  return 0 == std::memcmp(&lhs, &rhs, sizeof(lhs));
}
/// compares Fq6ElemStr values
bool operator==(Fq6ElemStr const& lhs, Fq6ElemStr const& rhs) {
  return 0 == std::memcmp(&lhs, &rhs, sizeof(lhs));
}
/// compares Fq12ElemStr values
bool operator==(Fq12ElemStr const& lhs, Fq12ElemStr const& rhs) {
  return 0 == std::memcmp(&lhs, &rhs, sizeof(lhs));
}
/// compares FpElemStr values
bool operator==(FpElemStr const& lhs, FpElemStr const& rhs) {
  return 0 == std::memcmp(&lhs, &rhs, sizeof(lhs));
}

/// compares FfElementObj values
bool operator==(FfElementObj const& lhs, FfElementObj const& rhs) {
  auto lhs_data = lhs.data();
  auto rhs_data = rhs.data();
  return lhs_data.size() == rhs_data.size() &&
         std::equal(lhs_data.begin(), lhs_data.end(), rhs_data.begin());
}

namespace {

class FfElementTest : public ::testing::Test {
 public:
  virtual void SetUp() {
    fq = FiniteFieldObj(bn_q_str);

    // construct Fq^2 finite field
    FfElementObj neg_beta(&fq);
    THROW_ON_EPIDERR(FfNeg(fq, FfElementObj(&fq, fq_qm1_str), neg_beta));
    fq2 = FiniteFieldObj(fq, neg_beta, 2);

    // construct Fq^6 finite field
    FfElementObj neg_xi(&fq2);
    THROW_ON_EPIDERR(FfNeg(fq2, FfElementObj(&fq2, this->fq2_2_1_str), neg_xi));
    fq6 = FiniteFieldObj(fq2, neg_xi, 3);

    // construct Fq^12 finite field
    FfElementObj neg_v(&fq6);
    THROW_ON_EPIDERR(
        FfNeg(fq6, FfElementObj(&fq6, this->fq6_0_0_1_0_0_0_str), neg_v));
    fq12 = FiniteFieldObj(fq6, neg_v, 2);

    fq_0 = FfElementObj(&fq, &bn_0_str, sizeof(bn_0_str));
    fq_2 = FfElementObj(&fq, &fq_2_str, sizeof(fq_2_str));
    fq_qm2 = FfElementObj(&fq, &fq_qm2_str, sizeof(fq_qm2_str));
    fq_3 = FfElementObj(&fq, &fq_3_str, sizeof(fq_3_str));
    fq_4 = FfElementObj(&fq, &fq_4_str, sizeof(fq_4_str));
    fq_5 = FfElementObj(&fq, &fq_5_str, sizeof(fq_5_str));
    fq_a = FfElementObj(&fq, &bn_a_str, sizeof(bn_a_str));
    // construct EPID 1.1 Fq finite field
    epid11_fq = FiniteFieldObj(bn_epid11_bn_q_str);

    // construct EPID 1.1 Fqd finite field
    epid11_fqd = FiniteFieldObj(epid11_fq, bn_epid11_fq_coeffs,
                                COUNT_OF(bn_epid11_fq_coeffs));

    // Fqk ground element is {-qnr, 0, 0}
    FfElementObj epid11_neg_qnr(&epid11_fq);
    THROW_ON_EPIDERR(FfNeg(
        epid11_fq, FfElementObj(&epid11_fq, fq_epid11_fq_qnr), epid11_neg_qnr));
    Fq3ElemStr epid11_ground_element_str = {0};
    THROW_ON_EPIDERR(WriteFfElement(epid11_fq, epid11_neg_qnr,
                                    &epid11_ground_element_str.a[0],
                                    sizeof(epid11_ground_element_str.a[0])));
    // construct EPID 1.1 Fqk finite field
    epid11_GT = FiniteFieldObj(
        epid11_fqd, FfElementObj(&epid11_fqd, epid11_ground_element_str), 2);

    fq_0 = FfElementObj(&fq, &bn_0_str, sizeof((bn_0_str)));
    fq_1 = FfElementObj(&fq, &bn_1_str, sizeof(bn_1_str));
    fq_a = FfElementObj(&fq, &bn_a_str, sizeof(bn_a_str));
    fq_b = FfElementObj(&fq, &bn_b_str, sizeof(bn_b_str));
    fq_result = FfElementObj(&fq);
    fq_sum_ab = FfElementObj(&fq, &fq_sum_ab_str, sizeof(fq_sum_ab_str));

    fp = FiniteFieldObj(bn_p_str);

    bn_0 = BigNumObj(bn_0_str);
    bn_1 = BigNumObj(bn_1_str);
    bn_a = BigNumObj(bn_a_str);

    fq2_a = FfElementObj(&fq2, &fq2_a_str, sizeof(fq2_a_str));
    fq2_result = FfElementObj(&fq2);

    fq12_g = FfElementObj(&fq12, &fq12_g_str, sizeof(fq12_g_str));
    fq12_h = FfElementObj(&fq12, &fq12_h_str, sizeof(fq12_h_str));
    fq12_i = FfElementObj(&fq12, &fq12_i_str, sizeof(fq12_i_str));
    fq12_j = FfElementObj(&fq12, &fq12_j_str, sizeof(fq12_j_str));
    fq12_k = FfElementObj(&fq12, &fq12_k_str, sizeof(fq12_k_str));
    fq12_result = FfElementObj(&fq12);
  }

  FiniteFieldObj fq;
  FiniteFieldObj fq2;
  FiniteFieldObj fq6;
  FiniteFieldObj fq12;
  FiniteFieldObj epid11_fq;
  FiniteFieldObj epid11_fqd;
  FiniteFieldObj epid11_GT;

  FfElementObj fq_0;
  FfElementObj fq_1;
  FfElementObj fq_2;
  FfElementObj fq_qm2;  // Intel(R) EPID 2.0 parameter q - 2
  FfElementObj fq_3;
  FfElementObj fq_4;
  FfElementObj fq_5;
  FfElementObj fq_a;
  FfElementObj fq_b;
  FfElementObj fq_result;
  FfElementObj fq_sum_ab;

  FfElementObj fq2_a;
  FfElementObj fq2_result;

  FfElementObj fq12_g;
  FfElementObj fq12_h;
  FfElementObj fq12_i;
  FfElementObj fq12_j;
  FfElementObj fq12_k;
  FfElementObj fq12_result;

  FiniteFieldObj fp;

  BigNumObj bn_0;
  BigNumObj bn_1;
  BigNumObj bn_a;

  // Intel(R) EPID 2.0 parameter p
  static const BigNumStr bn_p_str;
  static const FpElemStr fp_p_str;

  // Intel(R) EPID 2.0 parameter p - 1
  static const BigNumStr fp_pm1_str;

  // Intel(R) EPID 2.0 parameter q
  static const BigNumStr bn_q_str;

  // Intel(R) EPID 2.0 parameter q - 1
  static const FqElemStr fq_qm1_str;
  static const BigNumStr bn_qm1_str;

  // Intel(R) EPID 2.0 parameter q - 2
  static const FqElemStr fq_qm2_str;

  // Intel(R) EPID 2.0 parameter q + 1
  static const BigNumStr bn_qp1_str;

  // Intel(R) EPID 2.0 parameter q - 0x3013
  static const BigNumStr fq_qm0x3013_str;

  // Intel(R) EPID 1.1 parameter q
  static const BigNumStr bn_epid11_bn_q_str;

  // Intel(R) EPID 1.1 parameter qnr
  static const FqElemStr fq_epid11_fq_qnr;

  // Intel(R) EPID 1.1 parameter coeff
  static const BigNumStr bn_epid11_fq_coeffs[3];

  // zero
  static const BigNumStr bn_0_str;
  static const FqElemStr fq_0_str;

  // one
  static const BigNumStr bn_1_str;
  static const FqElemStr fq_1_str;

  // two
  static const BigNumStr bn_2_str;
  static const FqElemStr fq_2_str;

  // three
  static const FqElemStr fq_3_str;

  // four
  static const FqElemStr fq_4_str;

  // five
  static const FqElemStr fq_5_str;

  // 0x0000FFFF
  static const BigNumStr bn_0xffff_str;

  // Fq2 element containing {2, 1}
  static const Fq2ElemStr fq2_2_1_str;

  // Fq6 element containing {0, 0, 1, 0, 0, 0}
  static const Fq6ElemStr fq6_0_0_1_0_0_0_str;

  // arbitrary constant a (256 bit value)
  static const BigNumStr bn_a_str;
  static const FqElemStr fq_a_str;
  static const Fq2ElemStr fq2_a_str;

  // arbitrary constant b (256 bit value)
  static const BigNumStr bn_b_str;
  static const FqElemStr fq_b_str;

  // a + b
  static const FqElemStr fq_sum_ab_str;
  static const Fq2ElemStr fq2_sum_ab_str;
  static const Fq6ElemStr fq6_sum_ab_str;
  static const Fq12ElemStr fq12_sum_ab_str;

  // a * b
  static const FqElemStr fq_mul_ab_str;
  static const Fq2ElemStr fq2_mul_ab_str;

  // 1/a
  static const FqElemStr fq_inv_a_str;

  // -a
  static const FqElemStr fq_neg_a_str;

  // pow(a, b), that is a raised to the power b
  static const FqElemStr fq_exp_ab_str;

  static const uint8_t sha_msg[3];  // predefined message for tests "abc"
  static const FqElemStr fq_abc_sha256_str;
  static const FqElemStr fq_abc_sha384_str;
  static const FqElemStr fq_abc_sha512_str;

  // arbitrary Fq12 constant a (unrelated to a above)
  static const Fq12ElemStr fq12_g_str;
  // arbitrary Fq12 constant b (unrelated to a above)
  static const Fq12ElemStr fq12_h_str;
  // arbitrary Fq12 constant c
  static const Fq12ElemStr fq12_i_str;
  // arbitrary Fq12 constant d
  static const Fq12ElemStr fq12_j_str;
  // arbitrary Fq12 constant e
  static const Fq12ElemStr fq12_k_str;
  // c * d
  static const Fq12ElemStr fq12_mul_ij_str;
  // e * b
  static const Fq12ElemStr fq12_mul_gb_str;

  // Fq Multi Exp Data
  static const FqElemStr fq_multi_exp_base_1[1];
  static const BigNumStr fq_multi_exp_exp_1[1];
  static const FqElemStr fq_multi_exp_res_1;
  static const std::vector<uint8_t> fq_multi_exp_exp_1_264;
  static const FqElemStr fq_multi_exp_res_1_264;
  static const FqElemStr fq_multi_exp_res_1_256_264;
  static const FqElemStr fq_multi_exp_base_2[2];
  static const BigNumStr fq_multi_exp_exp_2[2];
  static const FqElemStr fq_multi_exp_res_2;
  static const FqElemStr fq_multi_exp_base_3[3];
  static const BigNumStr fq_multi_exp_exp_3[3];
  static const FqElemStr fq_multi_exp_res_3;
  static const FqElemStr fq_multi_exp_base_4[4];
  static const BigNumStr fq_multi_exp_exp_4[4];
  static const FqElemStr fq_multi_exp_res_4;
  static const FqElemStr fq_multi_exp_base_5[5];
  static const BigNumStr fq_multi_exp_exp_5[5];
  static const FqElemStr fq_multi_exp_res_5;
  static const FqElemStr fq_multi_exp_base_6[6];
  static const BigNumStr fq_multi_exp_exp_6[6];
  static const FqElemStr fq_multi_exp_res_6;

  // EPID 1.1 GT Multi Exp Data
  static const Fq6ElemStr epid11_GT_multi_exp_base_3[3];
  static const std::vector<uint8_t> epid11_GT_multi_exp_exp_3[3];
  static const Fq6ElemStr epid11_GT_multi_exp_res_3;

  // Fq12 Multi Exp Data
  static const Fq12ElemStr fq12_multi_exp_base_4[4];
  static const BigNumStr fq12_multi_exp_exp_4[4];
  static const Fq12ElemStr fq12_multi_exp_res_4;
};

const Fq2ElemStr FfElementTest::fq2_2_1_str = {
    {{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}}},
     {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}}}};
const Fq6ElemStr FfElementTest::fq6_0_0_1_0_0_0_str = {
    {{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
     {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
     {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}}};

// Intel(R) EPID 2.0 parameter p
const BigNumStr FfElementTest::bn_p_str = {
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xCD, 0x46, 0xE5, 0xF2,
    0x5E, 0xEE, 0x71, 0xA4, 0x9E, 0x0C, 0xDC, 0x65, 0xFB, 0x12, 0x99,
    0x92, 0x1A, 0xF6, 0x2D, 0x53, 0x6C, 0xD1, 0x0B, 0x50, 0x0D};

// Intel(R) EPID 2.0 parameter p - 0x0D
const FpElemStr FfElementTest::fp_p_str = {
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xCD, 0x46, 0xE5, 0xF2,
    0x5E, 0xEE, 0x71, 0xA4, 0x9E, 0x0C, 0xDC, 0x65, 0xFB, 0x12, 0x99,
    0x92, 0x1A, 0xF6, 0x2D, 0x53, 0x6C, 0xD1, 0x0B, 0x50, 0x00};

// Intel(R) EPID 2.0 parameter p - 1
const BigNumStr FfElementTest::fp_pm1_str = {
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xCD, 0x46, 0xE5, 0xF2,
    0x5E, 0xEE, 0x71, 0xA4, 0x9E, 0x0C, 0xDC, 0x65, 0xFB, 0x12, 0x99,
    0x92, 0x1A, 0xF6, 0x2D, 0x53, 0x6C, 0xD1, 0x0B, 0x50, 0x0C,
};

// Intel(R) EPID 2.0 parameter q
const BigNumStr FfElementTest::bn_q_str = {
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xCD, 0x46, 0xE5, 0xF2,
    0x5E, 0xEE, 0x71, 0xA4, 0x9F, 0x0C, 0xDC, 0x65, 0xFB, 0x12, 0x98,
    0x0A, 0x82, 0xD3, 0x29, 0x2D, 0xDB, 0xAE, 0xD3, 0x30, 0x13};

// Intel(R) EPID 2.0 parameter q - 1
const FqElemStr FfElementTest::fq_qm1_str = {
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xCD, 0x46, 0xE5, 0xF2,
    0x5E, 0xEE, 0x71, 0xA4, 0x9F, 0x0C, 0xDC, 0x65, 0xFB, 0x12, 0x98,
    0x0A, 0x82, 0xD3, 0x29, 0x2D, 0xDB, 0xAE, 0xD3, 0x30, 0x12};

const BigNumStr FfElementTest::bn_qm1_str = {
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xCD, 0x46, 0xE5, 0xF2,
    0x5E, 0xEE, 0x71, 0xA4, 0x9F, 0x0C, 0xDC, 0x65, 0xFB, 0x12, 0x98,
    0x0A, 0x82, 0xD3, 0x29, 0x2D, 0xDB, 0xAE, 0xD3, 0x30, 0x12};

// Intel(R) EPID 2.0 parameter q - 2
const FqElemStr FfElementTest::fq_qm2_str = {
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xCD, 0x46, 0xE5, 0xF2,
    0x5E, 0xEE, 0x71, 0xA4, 0x9F, 0x0C, 0xDC, 0x65, 0xFB, 0x12, 0x98,
    0x0A, 0x82, 0xD3, 0x29, 0x2D, 0xDB, 0xAE, 0xD3, 0x30, 0x11};

// Intel(R) EPID 2.0 parameter q + 1
const BigNumStr FfElementTest::bn_qp1_str = {
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xCD, 0x46, 0xE5, 0xF2,
    0x5E, 0xEE, 0x71, 0xA4, 0x9F, 0x0C, 0xDC, 0x65, 0xFB, 0x12, 0x98,
    0x0A, 0x82, 0xD3, 0x29, 0x2D, 0xDB, 0xAE, 0xD3, 0x30, 0x14};

// Intel(R) EPID 2.0 parameter q - 0x3013
const BigNumStr FfElementTest::fq_qm0x3013_str = {
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xCD, 0x46, 0xE5, 0xF2,
    0x5E, 0xEE, 0x71, 0xA4, 0x9F, 0x0C, 0xDC, 0x65, 0xFB, 0x12, 0x98,
    0x0A, 0x82, 0xD3, 0x29, 0x2D, 0xDB, 0xAE, 0xD3, 0x00, 0x00};

// Intel(R) EPID 1.1 parameter q
const BigNumStr FfElementTest::bn_epid11_bn_q_str = {
    0x09, 0xF9, 0x24, 0xE5, 0xD9, 0xBC, 0x67, 0x7F, 0x81, 0x0D, 0xF0,
    0x25, 0x58, 0xF7, 0x53, 0x13, 0xA9, 0x8A, 0xA6, 0x10, 0x47, 0x65,
    0x5D, 0x73, 0x9E, 0xF1, 0x94, 0xEB, 0x05, 0xB1, 0xA7, 0x11};

// Intel(R) EPID 1.1 parameter qnr
const FqElemStr FfElementTest::fq_epid11_fq_qnr = {
    {0x08, 0x66, 0xA7, 0x67, 0x36, 0x6E, 0x62, 0x71, 0xB7, 0xA6, 0x52, 0x94,
     0x8F, 0xFB, 0x25, 0x9E, 0xE6, 0x4F, 0x25, 0xE5, 0x26, 0x9A, 0x2B, 0x6E,
     0x7E, 0xF8, 0xA6, 0x39, 0xAE, 0x46, 0xAA, 0x24}};

// Intel(R) EPID 1.1 parameter coeff
const BigNumStr FfElementTest::bn_epid11_fq_coeffs[3] = {
    {{{0x02, 0x16, 0x7A, 0x61, 0x53, 0xDD, 0xF6, 0xE2, 0x89, 0x15, 0xA0, 0x94,
       0xF1, 0xB5, 0xDC, 0x65, 0x21, 0x15, 0x62, 0xE1, 0x7D, 0xC5, 0x43, 0x89,
       0xEE, 0xB4, 0xEF, 0xC8, 0xA0, 0x8E, 0x34, 0x0F}}},

    {{{0x04, 0x82, 0x27, 0xE1, 0xEB, 0x98, 0x64, 0xC2, 0x8D, 0x8F, 0xDD, 0x0E,
       0x82, 0x40, 0xAE, 0xD4, 0x31, 0x63, 0xD6, 0x46, 0x32, 0x16, 0x85, 0x7A,
       0xB7, 0x18, 0x68, 0xB8, 0x17, 0x02, 0x81, 0xA6}}},

    {{{0x06, 0x20, 0x76, 0xE8, 0x54, 0x54, 0x53, 0xB4, 0xA9, 0xD8, 0x44, 0x4B,
       0xAA, 0xFB, 0x1C, 0xFD, 0xAE, 0x15, 0xCA, 0x29, 0x79, 0xA6, 0x24, 0xA4,
       0x0A, 0xF6, 0x1E, 0xAC, 0xED, 0xFB, 0x10, 0x41}}}};

// zero
const BigNumStr FfElementTest::bn_0_str = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

const FqElemStr FfElementTest::fq_0_str = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

// one
const BigNumStr FfElementTest::bn_1_str = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};

const FqElemStr FfElementTest::fq_1_str = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};

// two
const BigNumStr FfElementTest::bn_2_str = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02};

const FqElemStr FfElementTest::fq_2_str = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02};

// three
const FqElemStr FfElementTest::fq_3_str = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};

// four
const FqElemStr FfElementTest::fq_4_str = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04};

// five
const FqElemStr FfElementTest::fq_5_str = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05};

const BigNumStr FfElementTest::bn_0xffff_str = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff};

// arbitrary constant a (256 bit value)
const BigNumStr FfElementTest::bn_a_str = {
    0x12, 0xA6, 0x5B, 0xD6, 0x91, 0x8D, 0x50, 0xA7, 0x66, 0xEB, 0x7D,
    0x52, 0xE3, 0x40, 0x17, 0x60, 0x7F, 0xDF, 0x6C, 0xA1, 0x2C, 0x1A,
    0x37, 0xE0, 0x92, 0xC0, 0xF7, 0xB9, 0x76, 0xAB, 0xB1, 0x8A};

const FqElemStr FfElementTest::fq_a_str = {
    0x12, 0xA6, 0x5B, 0xD6, 0x91, 0x8D, 0x50, 0xA7, 0x66, 0xEB, 0x7D,
    0x52, 0xE3, 0x40, 0x17, 0x60, 0x7F, 0xDF, 0x6C, 0xA1, 0x2C, 0x1A,
    0x37, 0xE0, 0x92, 0xC0, 0xF7, 0xB9, 0x76, 0xAB, 0xB1, 0x8A};

const Fq2ElemStr FfElementTest::fq2_a_str = {
    {{{{0x12, 0xA6, 0x5B, 0xD6, 0x91, 0x8D, 0x50, 0xA7, 0x66, 0xEB, 0x7D, 0x52,
        0xE3, 0x40, 0x17, 0x60, 0x7F, 0xDF, 0x6C, 0xA1, 0x2C, 0x1A, 0x37, 0xE0,
        0x92, 0xC0, 0xF7, 0xB9, 0x76, 0xAB, 0xB1, 0x8A}}},
     {{{0xDD, 0x2B, 0xE9, 0x59, 0x24, 0xA5, 0xB3, 0xFD, 0xEB, 0xE1, 0x3C, 0xC0,
        0x73, 0x4E, 0x99, 0xEE, 0x36, 0xF6, 0xC0, 0x1A, 0x76, 0x01, 0x0A, 0xF0,
        0xCB, 0xB4, 0x71, 0x88, 0x95, 0xCB, 0x35, 0xBA}}}}};

// arbitrary constant b (256 bit value)
const BigNumStr FfElementTest::bn_b_str = {
    0xE6, 0x65, 0x23, 0x9B, 0xD4, 0x07, 0x16, 0x83, 0x38, 0x23, 0xB2,
    0x67, 0x57, 0xEB, 0x0F, 0x23, 0x3A, 0xF4, 0x8E, 0xDA, 0x71, 0x5E,
    0xD9, 0x98, 0x63, 0x98, 0x2B, 0xBC, 0x78, 0xD1, 0x94, 0xF2};

const FqElemStr FfElementTest::fq_b_str = {
    0xE6, 0x65, 0x23, 0x9B, 0xD4, 0x07, 0x16, 0x83, 0x38, 0x23, 0xB2,
    0x67, 0x57, 0xEB, 0x0F, 0x23, 0x3A, 0xF4, 0x8E, 0xDA, 0x71, 0x5E,
    0xD9, 0x98, 0x63, 0x98, 0x2B, 0xBC, 0x78, 0xD1, 0x94, 0xF2};

// a + b
const FqElemStr FfElementTest::fq_sum_ab_str = {
    0xF9, 0x0B, 0x7F, 0x72, 0x65, 0x94, 0x67, 0x2A, 0x9F, 0x0F, 0x2F,
    0xBA, 0x3B, 0x2B, 0x26, 0x83, 0xBA, 0xD3, 0xFB, 0x7B, 0x9D, 0x79,
    0x11, 0x78, 0xF6, 0x59, 0x23, 0x75, 0xEF, 0x7D, 0x46, 0x7C};

const Fq2ElemStr FfElementTest::fq2_sum_ab_str = {
    {{{{0xF9, 0x0B, 0x7F, 0x72, 0x65, 0x94, 0x67, 0x2A, 0x9F, 0x0F, 0x2F, 0xBA,
        0x3B, 0x2B, 0x26, 0x83, 0xBA, 0xD3, 0xFB, 0x7B, 0x9D, 0x79, 0x11, 0x78,
        0xF6, 0x59, 0x23, 0x75, 0xEF, 0x7D, 0x46, 0x7C}}},
     {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}}};

const Fq6ElemStr FfElementTest::fq6_sum_ab_str = {
    {{{{0xF9, 0x0B, 0x7F, 0x72, 0x65, 0x94, 0x67, 0x2A, 0x9F, 0x0F, 0x2F, 0xBA,
        0x3B, 0x2B, 0x26, 0x83, 0xBA, 0xD3, 0xFB, 0x7B, 0x9D, 0x79, 0x11, 0x78,
        0xF6, 0x59, 0x23, 0x75, 0xEF, 0x7D, 0x46, 0x7C},
       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
     {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
     {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}}};

const Fq12ElemStr FfElementTest::fq12_sum_ab_str = {
    {{{{{{0xF9, 0x0B, 0x7F, 0x72, 0x65, 0x94, 0x67, 0x2A, 0x9F, 0x0F, 0x2F,
          0xBA, 0x3B, 0x2B, 0x26, 0x83, 0xBA, 0xD3, 0xFB, 0x7B, 0x9D, 0x79,
          0x11, 0x78, 0xF6, 0x59, 0x23, 0x75, 0xEF, 0x7D, 0x46, 0x7C},
         {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
       {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
         {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
       {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
         {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}}},

     {{{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
         {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
       {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
         {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
       {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
         {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}}}}};

// a * b
const FqElemStr FfElementTest::fq_mul_ab_str = {
    0xE4, 0xAB, 0xE3, 0xE4, 0x08, 0xC3, 0x8A, 0x00, 0x78, 0x50, 0x01,
    0xA9, 0x4A, 0xFC, 0x43, 0x15, 0xA2, 0x99, 0x51, 0x20, 0x6B, 0x9C,
    0x00, 0xCF, 0x82, 0x88, 0xBD, 0x39, 0x0B, 0xA2, 0x0B, 0x58};

const Fq2ElemStr FfElementTest::fq2_mul_ab_str = {
    {{{{0xE4, 0xAB, 0xE3, 0xE4, 0x08, 0xC3, 0x8A, 0x00, 0x78, 0x50, 0x01, 0xA9,
        0x4A, 0xFC, 0x43, 0x15, 0xA2, 0x99, 0x51, 0x20, 0x6B, 0x9C, 0x00, 0xCF,
        0x82, 0x88, 0xBD, 0x39, 0x0B, 0xA2, 0x0B, 0x58}}},
     {{{0xB4, 0xE4, 0x39, 0xEA, 0x70, 0xDE, 0x15, 0xC3, 0xC6, 0x91, 0xFD, 0x7F,
        0xBE, 0x2B, 0xF5, 0xD2, 0xC0, 0xB7, 0x20, 0xFC, 0x1F, 0x02, 0x33, 0xC9,
        0x39, 0x93, 0xB9, 0x5E, 0x55, 0x51, 0xB6, 0x46}}}}};

// 1/a
const FqElemStr FfElementTest::fq_inv_a_str = {
    0x15, 0x17, 0x1A, 0x1E, 0x93, 0x71, 0x1B, 0x39, 0xC5, 0x97, 0xEF,
    0x78, 0xA5, 0x51, 0x34, 0x62, 0x44, 0xAD, 0x8D, 0x51, 0xDF, 0x90,
    0x7C, 0x6F, 0x56, 0xB6, 0xAB, 0x63, 0x5A, 0x68, 0x6D, 0xF6};

// -a
const FqElemStr FfElementTest::fq_neg_a_str = {
    0xED, 0x59, 0xA4, 0x29, 0x6E, 0x6F, 0xA0, 0x25, 0xDF, 0xFA, 0x75,
    0x0C, 0x0B, 0x31, 0x8D, 0x3E, 0x8C, 0xFC, 0xF9, 0x59, 0xE6, 0x7D,
    0xD2, 0xA2, 0x40, 0x68, 0x36, 0x22, 0x38, 0x27, 0x7E, 0x89};

// pow(a, b)
const FqElemStr FfElementTest::fq_exp_ab_str = {
    0x29, 0x65, 0x68, 0x0E, 0x56, 0xB9, 0x8F, 0xBA, 0xA6, 0xEA, 0x8F,
    0xE1, 0x13, 0x44, 0x3B, 0x12, 0x5C, 0xB9, 0xF8, 0x76, 0x42, 0x12,
    0xCB, 0xB2, 0xED, 0xC0, 0x23, 0xA3, 0x5C, 0xAD, 0x38, 0xD1};

const uint8_t FfElementTest::sha_msg[] = {'a', 'b', 'c'};

const FqElemStr FfElementTest::fq_abc_sha256_str = {
    0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, 0x41, 0x41, 0x40,
    0xDE, 0x5D, 0xAE, 0x22, 0x23, 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17,
    0x7A, 0x9C, 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD,
};
const FqElemStr FfElementTest::fq_abc_sha384_str = {
    0x10, 0xAC, 0xE4, 0xE8, 0x8F, 0xBB, 0x96, 0xBF, 0x53, 0xB6, 0xAF,
    0xE4, 0x4E, 0x95, 0xDE, 0xA5, 0x98, 0x8F, 0x10, 0xBF, 0x59, 0xC4,
    0x11, 0xFE, 0x1F, 0x7A, 0xA6, 0x1E, 0x57, 0x3E, 0xE3, 0x3C,
};
const FqElemStr FfElementTest::fq_abc_sha512_str = {
    0x14, 0xB4, 0x28, 0x89, 0xD2, 0x86, 0xA4, 0x79, 0xE3, 0x5B, 0xC4,
    0x50, 0xD1, 0x3B, 0xF2, 0x35, 0xF7, 0x97, 0x91, 0x05, 0x3D, 0x64,
    0xC0, 0x06, 0x45, 0x9F, 0xEC, 0xD8, 0xDB, 0x53, 0x3E, 0xC3,
};
const Fq12ElemStr FfElementTest::fq12_g_str = {
    {{{{{{0xBA, 0x10, 0x1F, 0xF6, 0x46, 0x8B, 0xE9, 0x32, 0x4F, 0xC0, 0xA5,
          0x01, 0xAD, 0x5E, 0xE2, 0x31, 0x16, 0x29, 0x96, 0xED, 0xA7, 0xDE,
          0x4C, 0xE1, 0xD2, 0x8D, 0x33, 0xCA, 0x50, 0xAB, 0x7B, 0xC6},
         {0x15, 0xEB, 0x79, 0xF4, 0xEB, 0xDE, 0x30, 0xB6, 0xC4, 0x07, 0x7C,
          0x42, 0xCB, 0x04, 0x54, 0xF2, 0x1F, 0x4D, 0x1F, 0xC0, 0xDF, 0xA2,
          0x2B, 0x9E, 0x34, 0xC4, 0x4C, 0x84, 0x14, 0xD3, 0x62, 0x07}}},
       {{{0xF1, 0x8B, 0x84, 0xD1, 0x46, 0x57, 0xB6, 0xE7, 0x80, 0xE1, 0x46,
          0x49, 0x1C, 0x0D, 0xEF, 0x81, 0x31, 0xB0, 0xBE, 0x8C, 0xB9, 0x08,
          0xD0, 0xD3, 0xC4, 0x56, 0xCA, 0xAD, 0xF9, 0x1D, 0x75, 0x19},
         {0x3F, 0xEE, 0x7C, 0x43, 0xC1, 0xFA, 0x4E, 0x50, 0xB7, 0x19, 0x01,
          0x00, 0x6F, 0xD5, 0x16, 0xB6, 0xF4, 0x85, 0xE0, 0xEB, 0x2E, 0x5F,
          0x0A, 0x7E, 0xF8, 0xAC, 0xBC, 0x05, 0xEC, 0x73, 0xB5, 0x57}}},
       {{{0xE3, 0xB3, 0x18, 0x29, 0xBB, 0xEF, 0x86, 0x50, 0x87, 0xCF, 0x70,
          0xBA, 0x13, 0x8B, 0xB1, 0xB6, 0x2D, 0x6F, 0x65, 0x3D, 0xA1, 0x0B,
          0xE3, 0x92, 0xC5, 0x72, 0x86, 0x6A, 0xB3, 0xEB, 0xE0, 0xE5},
         {0xDA, 0x0E, 0x57, 0x87, 0xD5, 0xA9, 0x61, 0xA5, 0x1E, 0xCB, 0x04,
          0x86, 0xCD, 0xC3, 0x18, 0x2A, 0x36, 0xA0, 0x81, 0x73, 0xE7, 0x13,
          0x87, 0x80, 0x8D, 0x1A, 0xFE, 0x6E, 0x4B, 0xA3, 0x13, 0x03}}}}},
     {{{{{0x66, 0x9E, 0x80, 0x4D, 0x8A, 0xAA, 0x00, 0x95, 0x72, 0xCE, 0xBB,
          0x51, 0xE8, 0x01, 0x09, 0x41, 0xD3, 0x63, 0x28, 0x05, 0xA4, 0xBE,
          0xD6, 0x41, 0xA6, 0x2F, 0x5F, 0xBF, 0x0B, 0x13, 0xB4, 0x54},
         {0x5B, 0x50, 0x65, 0xDC, 0x6F, 0x29, 0xD6, 0xDA, 0xBF, 0xC2, 0x06,
          0xEA, 0x3B, 0xB2, 0xF1, 0xD4, 0x26, 0x5C, 0x92, 0x6B, 0x95, 0x6D,
          0x88, 0xAB, 0x8F, 0xC6, 0x9D, 0x31, 0xE4, 0x9B, 0x71, 0x49}}},
       {{{0xE0, 0xCE, 0x97, 0x8F, 0xC9, 0x9F, 0xBC, 0xA8, 0x4A, 0xC6, 0xAA,
          0x4A, 0xC8, 0x0D, 0x2A, 0x60, 0x1A, 0x43, 0x40, 0x03, 0xB3, 0x53,
          0x30, 0x98, 0x1F, 0x3F, 0xDF, 0x5C, 0x0F, 0xF0, 0x84, 0x8E},
         {0x5A, 0x5D, 0x41, 0xD2, 0x47, 0x78, 0x6D, 0x9F, 0x89, 0xCE, 0xF5,
          0x8E, 0xB6, 0x54, 0xA2, 0x26, 0xE5, 0x40, 0x39, 0x5C, 0x59, 0x08,
          0xB3, 0xDA, 0xF5, 0xF8, 0xA0, 0x18, 0x33, 0x57, 0xD1, 0x72}}},
       {{{0xBB, 0xBA, 0x6C, 0xED, 0xE8, 0xA0, 0x5E, 0xC8, 0x81, 0xC5, 0xAC,
          0x15, 0x1B, 0xD0, 0xE6, 0xC8, 0x92, 0xF9, 0x43, 0x03, 0x5A, 0x00,
          0x42, 0xE3, 0x49, 0xA5, 0xF7, 0x19, 0x78, 0x8A, 0x39, 0x89},
         {0x32, 0xAE, 0xBF, 0x4D, 0x4B, 0xB3, 0x33, 0x76, 0x16, 0xFD, 0x0B,
          0xFE, 0x42, 0x1E, 0x17, 0x37, 0x2A, 0x04, 0xEA, 0x26, 0xBA, 0x6E,
          0x2C, 0x36, 0xAF, 0x35, 0x1B, 0x75, 0x6D, 0x17, 0xDC, 0x8E}}}}}}};

const Fq12ElemStr FfElementTest::fq12_h_str = {
    {{{{{{0x41, 0xFB, 0xBE, 0xD2, 0x20, 0x95, 0xE5, 0xBA, 0x87, 0x54, 0x23,
          0xCC, 0x04, 0x97, 0x38, 0x4B, 0x69, 0x28, 0x18, 0x6D, 0xAE, 0x19,
          0xE3, 0x3D, 0xFE, 0x39, 0xE2, 0x1C, 0xC2, 0x53, 0x17, 0xF6},
         {0xEA, 0xA3, 0x0F, 0x62, 0x6E, 0xBF, 0x6F, 0x8F, 0xBC, 0xFA, 0x6E,
          0x07, 0xD3, 0xD3, 0xAE, 0x5C, 0xAA, 0xB5, 0x9C, 0xD7, 0xB8, 0x5B,
          0x1B, 0x69, 0x52, 0x93, 0xBF, 0xDB, 0x87, 0x5C, 0x19, 0x07}}},
       {{{0x1B, 0x03, 0xE1, 0x79, 0x3C, 0x10, 0x0B, 0x65, 0xBF, 0xD7, 0xF3,
          0x45, 0x1A, 0xD4, 0xDD, 0xB8, 0x67, 0x1A, 0x8F, 0x41, 0x1A, 0xD4,
          0x04, 0x3C, 0xD2, 0xA4, 0x3B, 0x47, 0xFE, 0xBD, 0xEA, 0x87},
         {0xDF, 0x7F, 0x94, 0x9C, 0xB8, 0x65, 0x54, 0x8D, 0xD7, 0x0B, 0x33,
          0x26, 0x25, 0x89, 0xD4, 0x60, 0x0C, 0x89, 0x5F, 0x2C, 0x00, 0x7F,
          0xAF, 0x89, 0x35, 0xE5, 0xB9, 0x23, 0x7F, 0x79, 0x1A, 0x86}}},
       {{{0xCE, 0x01, 0x4F, 0x24, 0x3C, 0x3A, 0xC3, 0x61, 0x5B, 0xD9, 0x2D,
          0x87, 0x94, 0xA3, 0xD2, 0x8B, 0x57, 0xC4, 0x07, 0xF8, 0x29, 0x5E,
          0x09, 0x23, 0xCA, 0xE9, 0x85, 0xA1, 0xDB, 0xF2, 0x0C, 0x8F},
         {0xC2, 0xFB, 0x9A, 0xCC, 0xD9, 0x82, 0x63, 0x28, 0x83, 0xB7, 0x4F,
          0x99, 0x3A, 0x19, 0x11, 0xB0, 0xB4, 0xE7, 0x73, 0x94, 0x35, 0x19,
          0x6B, 0xC2, 0x5D, 0x2E, 0x8C, 0x33, 0xFF, 0x13, 0xCD, 0xBE}}}}},
     {{{{{0x29, 0x43, 0xF6, 0xA0, 0xE9, 0xDC, 0x27, 0x27, 0x9B, 0x0A, 0x33,
          0xBC, 0x85, 0x6A, 0xBF, 0x8B, 0xC5, 0x89, 0x10, 0x92, 0xAE, 0x73,
          0xC9, 0x32, 0x46, 0x8D, 0x24, 0x1F, 0x32, 0x96, 0xED, 0x0B},
         {0x44, 0x8C, 0x6D, 0xF6, 0x1A, 0x2F, 0xCA, 0x18, 0x8E, 0x84, 0xFF,
          0x5F, 0x5F, 0xAF, 0xC0, 0x52, 0x35, 0xA1, 0xB3, 0xA0, 0xDE, 0xEE,
          0x97, 0xBF, 0xB8, 0xFA, 0x8B, 0x9E, 0x00, 0x13, 0xE7, 0x26}}},
       {{{0xFB, 0x78, 0xA1, 0x6D, 0x41, 0x92, 0xA6, 0xC6, 0x7F, 0xAD, 0xB7,
          0xFC, 0x4F, 0x5F, 0x48, 0x94, 0x7D, 0xB7, 0xF5, 0xCC, 0xB5, 0x7E,
          0x08, 0xCD, 0xBF, 0x58, 0xC9, 0x30, 0xEB, 0xE4, 0xA0, 0xBF},
         {0x0C, 0x6A, 0x89, 0x18, 0x97, 0x37, 0x54, 0x76, 0x79, 0x3E, 0x8E,
          0xA6, 0x5B, 0x77, 0xCE, 0x4A, 0xCB, 0xD9, 0x8B, 0x7B, 0x32, 0x1A,
          0x30, 0x40, 0x49, 0xFF, 0x84, 0xE7, 0xBE, 0xD8, 0xCF, 0xFD}}},
       {{{0x2D, 0x23, 0x54, 0xB5, 0x2E, 0x29, 0xE9, 0xC7, 0x62, 0x1B, 0x03,
          0x34, 0x3A, 0xEB, 0xC9, 0x69, 0x38, 0x9F, 0xD1, 0x2B, 0xDA, 0x8B,
          0x07, 0x58, 0x30, 0xF8, 0x38, 0x08, 0x09, 0x07, 0xCA, 0x5B},
         {0x3A, 0x13, 0xED, 0xF4, 0x5D, 0xC9, 0x23, 0x66, 0x85, 0x8C, 0x6A,
          0x7D, 0xE9, 0x11, 0x17, 0xE6, 0x43, 0x2F, 0x12, 0xC5, 0x07, 0x63,
          0x84, 0x98, 0xA0, 0x1C, 0xDC, 0xF3, 0x91, 0x91, 0x11, 0x55}}}}}}};

const Fq12ElemStr FfElementTest::fq12_i_str = {
    {{{{{{0x0F, 0xD0, 0x1C, 0x59, 0x98, 0x52, 0x5A, 0x40, 0xFF, 0x26, 0x0A,
          0xFD, 0x70, 0xEC, 0x23, 0x48, 0x1B, 0x4B, 0x70, 0xA0, 0x15, 0xC5,
          0xB1, 0x8B, 0xA5, 0x75, 0xAC, 0xCE, 0xF3, 0x6C, 0xE8, 0xBA},
         {0xA7, 0xFB, 0xF9, 0xEA, 0x18, 0x70, 0xD8, 0x9B, 0x3C, 0xC3, 0x66,
          0x10, 0x38, 0xAC, 0x16, 0x32, 0xDC, 0x9D, 0xF0, 0xD4, 0x2C, 0xE7,
          0xF6, 0x69, 0x47, 0x69, 0x84, 0xEE, 0x39, 0x5F, 0xD8, 0xCC}}},
       {{{0x1B, 0xEF, 0x81, 0x13, 0x81, 0xB9, 0x56, 0xAE, 0xD0, 0xD4, 0xAE,
          0xCB, 0x24, 0x7C, 0x7B, 0x7F, 0xC0, 0x41, 0x42, 0x0A, 0x9D, 0x90,
          0x6B, 0x1E, 0x3A, 0xAD, 0x39, 0x7A, 0x1F, 0xEF, 0x56, 0x9E},
         {0xBD, 0x84, 0x48, 0xAF, 0x65, 0x66, 0x33, 0xE5, 0x67, 0xF1, 0xC4,
          0x48, 0xF0, 0xB6, 0x61, 0x06, 0xC7, 0x78, 0xB3, 0xC1, 0x12, 0xB8,
          0x31, 0xD4, 0x69, 0x2E, 0x0E, 0xD3, 0xD4, 0x91, 0x81, 0x9A}}},
       {{{0x23, 0x62, 0x9B, 0x83, 0x95, 0xF6, 0x7F, 0xF6, 0xCC, 0x6B, 0xEE,
          0x84, 0xF0, 0x5B, 0x93, 0xA6, 0x90, 0x48, 0x1A, 0xA7, 0xA8, 0xE8,
          0x10, 0xA5, 0x53, 0x7E, 0x4F, 0xD5, 0x0D, 0xB0, 0x86, 0xF7},
         {0x1F, 0xB8, 0xB7, 0xD4, 0x2E, 0x41, 0x83, 0x2C, 0xFC, 0x62, 0x14,
          0xB8, 0xC2, 0xF6, 0xC1, 0x5E, 0xC1, 0xC1, 0x40, 0x8B, 0x28, 0xB5,
          0x1B, 0x85, 0xEE, 0x71, 0xC8, 0x14, 0x56, 0xB9, 0x3B, 0x90}}}}},
     {{{{{0x4A, 0xFE, 0x73, 0xFA, 0xCF, 0x20, 0x67, 0x0E, 0x89, 0x1D, 0xCB,
          0x05, 0x38, 0x27, 0x1C, 0xD5, 0x7A, 0x0C, 0xAC, 0x92, 0x17, 0x94,
          0x7F, 0x10, 0x3E, 0xFF, 0x97, 0x23, 0x66, 0x8D, 0x70, 0xAE},
         {0x80, 0x97, 0xFF, 0x88, 0xF8, 0x01, 0x2B, 0x99, 0x81, 0xEB, 0xF8,
          0x19, 0xEF, 0xDA, 0xE3, 0xAE, 0xD9, 0x9B, 0x4C, 0x13, 0xFC, 0x9E,
          0x18, 0xD6, 0xB0, 0xCF, 0x4E, 0x29, 0xA8, 0xCF, 0x01, 0xFA}}},
       {{{0xDA, 0x22, 0x85, 0x18, 0x9A, 0x51, 0x17, 0xAC, 0x26, 0x57, 0xF6,
          0x73, 0x59, 0x24, 0xD5, 0xC9, 0x4D, 0xAC, 0xB6, 0xE4, 0x51, 0xF7,
          0x5E, 0x30, 0x5B, 0x25, 0x3D, 0x52, 0xA3, 0xE0, 0x4B, 0xA2},
         {0xC3, 0x4C, 0x2F, 0x53, 0xD5, 0x92, 0x33, 0x7E, 0x8B, 0x66, 0x5F,
          0x48, 0x48, 0xCA, 0xA8, 0x98, 0x0F, 0x73, 0xD3, 0x60, 0xAF, 0x25,
          0x02, 0xEE, 0x64, 0xE7, 0x02, 0x89, 0x9A, 0xD2, 0x96, 0x45}}},
       {{{0x04, 0xE1, 0x30, 0x9B, 0xD8, 0x85, 0xF0, 0x99, 0x7C, 0x01, 0xD5,
          0x58, 0x5A, 0x74, 0x0B, 0xD4, 0xF2, 0xFA, 0xC7, 0x59, 0x36, 0xFD,
          0x91, 0x07, 0x60, 0xF7, 0xDC, 0x11, 0x3E, 0x8A, 0xC6, 0x48},
         {0x0D, 0x02, 0x30, 0x18, 0xD0, 0xB9, 0x6B, 0xD6, 0x39, 0x6A, 0x41,
          0x82, 0xDD, 0xE3, 0xCE, 0xB8, 0xB6, 0xF5, 0x61, 0x80, 0x61, 0x16,
          0xF4, 0x9A, 0xB8, 0x58, 0x1D, 0x3F, 0x4D, 0xC2, 0xCA, 0xCF}}}}}}};

const Fq12ElemStr FfElementTest::fq12_j_str = {
    {{{{{{0x3A, 0x30, 0x33, 0xA2, 0x14, 0xDF, 0xDC, 0x70, 0x48, 0xF3, 0xBA,
          0x3F, 0xCE, 0xFC, 0x69, 0x24, 0xAE, 0xA1, 0xF3, 0xCF, 0xD8, 0x77,
          0x69, 0x38, 0x38, 0xF4, 0x8E, 0xFB, 0x51, 0xFB, 0x10, 0x7C},
         {0x73, 0xB4, 0xEE, 0xF9, 0x76, 0xBB, 0x45, 0xEC, 0x07, 0x24, 0x23,
          0xA3, 0x38, 0x64, 0x39, 0x4C, 0x03, 0x94, 0xF5, 0xEE, 0x5F, 0xC9,
          0x83, 0x4F, 0xD1, 0xA6, 0x4A, 0x05, 0x25, 0x0C, 0x46, 0x33}}},
       {{{0xD4, 0x40, 0x47, 0xAE, 0xEC, 0xDA, 0x30, 0xF9, 0xE1, 0x28, 0xFB,
          0xB1, 0x4C, 0x62, 0xFB, 0x6C, 0x90, 0x0D, 0xB1, 0xEC, 0xAF, 0x2D,
          0x95, 0x64, 0x11, 0x93, 0xDA, 0x8E, 0xB8, 0x7D, 0xE4, 0xA3},
         {0x8E, 0xA6, 0x9B, 0xAA, 0x58, 0xD5, 0xDC, 0x59, 0x1A, 0x51, 0x53,
          0x47, 0x30, 0x1C, 0x2B, 0xB0, 0xBB, 0x57, 0x57, 0x0A, 0x8C, 0x5F,
          0x62, 0x9C, 0x52, 0x28, 0xC0, 0x25, 0x27, 0xAE, 0xCD, 0x36}}},
       {{{0xBF, 0x2D, 0x03, 0xB1, 0x33, 0xFD, 0x24, 0x81, 0x3C, 0x91, 0x43,
          0x90, 0x0C, 0x20, 0xC4, 0xE3, 0x69, 0x3F, 0xA9, 0xA2, 0x7C, 0xC2,
          0x48, 0x28, 0x1B, 0xF0, 0x81, 0x1F, 0x2B, 0x8F, 0x8D, 0x43},
         {0x38, 0x18, 0x12, 0xA3, 0x89, 0xF1, 0xD7, 0x60, 0x89, 0x68, 0x6A,
          0xC4, 0xCC, 0x5D, 0xF4, 0xCE, 0x43, 0x95, 0x84, 0xCD, 0x01, 0x55,
          0xB8, 0x5D, 0x24, 0x50, 0xCD, 0xE3, 0x68, 0x1C, 0xFF, 0x59}}}}},
     {{{{{0x0D, 0xAC, 0xCB, 0xE7, 0x9D, 0x68, 0x0F, 0x4A, 0xAF, 0xEB, 0xB5,
          0xFB, 0xF9, 0xB1, 0x58, 0x80, 0xD5, 0x71, 0x53, 0x26, 0x2E, 0x9C,
          0xCE, 0x10, 0xAC, 0xD2, 0x0A, 0xEB, 0xB4, 0x5C, 0xC8, 0xD7},
         {0x16, 0x26, 0x66, 0x71, 0xDD, 0x67, 0xBA, 0xDB, 0x35, 0x76, 0x64,
          0xC6, 0x0B, 0x0B, 0x07, 0x4B, 0x65, 0xA2, 0xF7, 0x68, 0x9E, 0xFE,
          0xE8, 0xE3, 0xA7, 0x09, 0x79, 0xC5, 0xDF, 0x5E, 0x9C, 0xEC}}},
       {{{0xEE, 0x83, 0x59, 0xB5, 0x89, 0x81, 0xA2, 0x87, 0xD7, 0x75, 0x65,
          0x90, 0xDE, 0x78, 0x37, 0x59, 0x04, 0x9B, 0x50, 0xC3, 0xBA, 0x90,
          0x09, 0x15, 0xAB, 0x17, 0xC5, 0xBF, 0x5B, 0xB9, 0xE4, 0x6C},
         {0xA9, 0xB1, 0x49, 0x76, 0x25, 0x74, 0x5D, 0x9C, 0x78, 0xC5, 0x09,
          0xEE, 0xEB, 0xEB, 0x9D, 0x1C, 0x6C, 0xC0, 0x27, 0x9D, 0x66, 0xE6,
          0x7F, 0x31, 0xCD, 0xB0, 0x8A, 0xE4, 0x9E, 0xBD, 0x70, 0x18}}},
       {{{0x88, 0xA1, 0x08, 0x39, 0xA2, 0x48, 0xA5, 0x98, 0xB6, 0xAD, 0x10,
          0x54, 0x07, 0xCD, 0xFC, 0x6D, 0xB1, 0x02, 0xFF, 0xE3, 0x92, 0xD7,
          0x9D, 0x48, 0xFB, 0xCE, 0x88, 0x46, 0x92, 0x07, 0x02, 0xBA},
         {0xEE, 0xEB, 0xAE, 0x88, 0xB1, 0x4E, 0xD0, 0xF2, 0xCE, 0xD7, 0x57,
          0x07, 0xD4, 0x39, 0xD2, 0x7D, 0x1A, 0x0C, 0xEF, 0xF2, 0x84, 0x84,
          0x22, 0x8A, 0xB1, 0x80, 0x0D, 0xDC, 0x64, 0x86, 0xFD, 0x70}}}}}}};

const Fq12ElemStr FfElementTest::fq12_mul_ij_str = {
    {{{{{{0x4A, 0x0E, 0x83, 0x4F, 0x62, 0xCA, 0x56, 0x0B, 0x0F, 0x2E, 0xF3,
          0x1A, 0xC6, 0xFC, 0x76, 0x4F, 0x4B, 0x85, 0x78, 0x6F, 0x9D, 0xB9,
          0xBD, 0xC8, 0xBB, 0x7C, 0x73, 0x12, 0x28, 0xFF, 0xBC, 0x8F},
         {0x18, 0x8E, 0x5E, 0x4B, 0x72, 0xA5, 0x4A, 0x99, 0xFC, 0xE7, 0x05,
          0xE5, 0xD2, 0x2C, 0x06, 0x95, 0xF5, 0xE4, 0xA5, 0x87, 0xCB, 0x85,
          0x25, 0xF8, 0xDA, 0x71, 0x7B, 0x9A, 0xF1, 0x52, 0xF9, 0x33}}},
       {{{0x05, 0x5F, 0x15, 0x72, 0xA3, 0x61, 0xA6, 0x6C, 0xB8, 0x43, 0xBB,
          0xCA, 0x33, 0xB2, 0xDB, 0x59, 0xCA, 0xAB, 0xAD, 0xA0, 0x4D, 0xE3,
          0xB8, 0xF5, 0xC9, 0x8C, 0x06, 0x91, 0xE5, 0xE4, 0x5A, 0xAD},
         {0xE7, 0x66, 0xCC, 0x2B, 0x2C, 0x11, 0x88, 0x29, 0xB1, 0x3C, 0x52,
          0xFE, 0x50, 0xDF, 0x8F, 0x15, 0x6A, 0x6B, 0xB8, 0x32, 0x96, 0x90,
          0x85, 0x03, 0x78, 0x88, 0x97, 0x7B, 0x5B, 0x50, 0x2E, 0xDE}}},
       {{{0xE7, 0x53, 0x22, 0x11, 0xEB, 0xFF, 0x1B, 0x19, 0xAE, 0x5F, 0x58,
          0x3A, 0x4F, 0x6F, 0x34, 0xFB, 0x2A, 0x49, 0xCA, 0x4B, 0x9C, 0x31,
          0xFC, 0x74, 0x0F, 0x11, 0xCC, 0x45, 0xCD, 0xA2, 0x12, 0xCA},
         {0xF4, 0x2F, 0x30, 0x9A, 0x6A, 0xCB, 0xEE, 0x88, 0x15, 0x56, 0x29,
          0x2A, 0xBF, 0x33, 0x7B, 0xDB, 0x59, 0x74, 0x4D, 0xC0, 0x64, 0xF0,
          0x0B, 0x9F, 0xF2, 0x65, 0xB7, 0x3A, 0xDA, 0xE2, 0xB5, 0x63}}}}},
     {{{{{0x3A, 0x3E, 0x06, 0xEF, 0x73, 0xA3, 0xBC, 0xEA, 0xCC, 0x68, 0xD9,
          0xF5, 0x6E, 0x94, 0x1C, 0x54, 0x47, 0xF1, 0x99, 0x2C, 0x44, 0x64,
          0x45, 0x84, 0x50, 0x10, 0xFD, 0xC5, 0x16, 0x65, 0x89, 0xEC},
         {0x72, 0xA6, 0x7E, 0x82, 0x7F, 0xE2, 0xE3, 0xEA, 0x82, 0xA3, 0x18,
          0xF4, 0x9B, 0x93, 0x4D, 0x79, 0xA0, 0x2C, 0xBF, 0x90, 0x0E, 0xDB,
          0x41, 0x09, 0x27, 0x44, 0x19, 0xD1, 0xB4, 0xE5, 0xC6, 0x8C}}},
       {{{0xA5, 0xC7, 0x82, 0xBF, 0x00, 0x7B, 0x8D, 0x7A, 0x05, 0x7B, 0x7E,
          0x33, 0x60, 0x28, 0x34, 0x9C, 0x86, 0x5A, 0x6B, 0xCE, 0xA5, 0xED,
          0x26, 0x22, 0x63, 0x4A, 0xE9, 0x57, 0xCD, 0x55, 0xD2, 0xD3},
         {0x0E, 0x73, 0x14, 0xE4, 0xEE, 0xE7, 0x3C, 0x43, 0xFC, 0xAE, 0x84,
          0x59, 0x2F, 0xEA, 0x35, 0x84, 0xA5, 0x77, 0xCE, 0xA8, 0xC5, 0xAA,
          0xB8, 0xDC, 0xB9, 0xD6, 0x71, 0x11, 0xE2, 0x95, 0x00, 0x97}}},
       {{{0xBD, 0x50, 0xDA, 0x58, 0x1B, 0xDA, 0xB3, 0x25, 0x19, 0x2F, 0x9D,
          0xFA, 0x2C, 0xFB, 0x96, 0x26, 0xBB, 0x4A, 0x41, 0x82, 0xA9, 0x45,
          0x24, 0xEE, 0xEE, 0xEA, 0xD3, 0xC5, 0x94, 0xFC, 0x2A, 0x37},
         {0x6A, 0x43, 0xB8, 0x6C, 0xBB, 0x98, 0xB7, 0x17, 0x03, 0xC0, 0x3D,
          0x6D, 0x59, 0x56, 0x3D, 0x23, 0x42, 0x94, 0x25, 0x64, 0xB9, 0x62,
          0xAD, 0x4D, 0x84, 0x9B, 0x3C, 0x05, 0x8C, 0xF0, 0xD3, 0xD3}}}}}},
};

const Fq12ElemStr FfElementTest::fq12_k_str = {
    {{{{{{0xE4, 0xCA, 0x0B, 0xA8, 0x9C, 0x70, 0xE2, 0x20, 0x24, 0xD9, 0x8F,
          0x09, 0x12, 0x79, 0x55, 0x44, 0x8C, 0x58, 0x42, 0x8F, 0x18, 0x97,
          0x0A, 0xC3, 0x0A, 0x40, 0x68, 0x0E, 0x1E, 0x21, 0x7F, 0xB4},
         {0x73, 0xCF, 0x8D, 0x54, 0x68, 0xAE, 0x1C, 0xC4, 0x95, 0x01, 0xE3,
          0x52, 0x33, 0xFE, 0x69, 0xB5, 0x23, 0x45, 0xEF, 0xFF, 0x79, 0x14,
          0xEF, 0x98, 0xA8, 0x4E, 0xB1, 0x2E, 0xE1, 0x15, 0x81, 0x0C}}},
       {{{0x9F, 0x65, 0x90, 0x6A, 0x53, 0xD7, 0xF6, 0x73, 0x08, 0xDA, 0x45,
          0x11, 0xDE, 0xCF, 0xED, 0x4C, 0x8C, 0x21, 0x02, 0xF5, 0x3F, 0x97,
          0xB6, 0xB2, 0xF5, 0xC6, 0x58, 0xFC, 0x9A, 0xA6, 0xBB, 0xF9},
         {0x3C, 0xD8, 0xFC, 0x86, 0x09, 0x1C, 0x16, 0xA4, 0x6F, 0x5E, 0x7A,
          0x81, 0x01, 0xF9, 0x8A, 0x6D, 0x38, 0xB5, 0xC9, 0x5F, 0xE9, 0x7D,
          0x6F, 0x46, 0x92, 0x49, 0x5B, 0xB8, 0x61, 0x03, 0x6F, 0x5E}}},
       {{{0xDA, 0x53, 0xCB, 0x62, 0xCD, 0x82, 0x63, 0x96, 0xC7, 0xC0, 0x39,
          0xA4, 0x31, 0xEE, 0x15, 0x26, 0x1C, 0xE6, 0x4E, 0xE4, 0xB4, 0x40,
          0xFA, 0x65, 0xA3, 0xF4, 0x73, 0x03, 0x85, 0x84, 0x41, 0xF9},
         {0x77, 0xF3, 0x90, 0xDC, 0x88, 0x26, 0xBD, 0x27, 0x9A, 0x9D, 0x37,
          0xF0, 0x80, 0xEE, 0x02, 0x1D, 0x3E, 0x4F, 0x88, 0xED, 0x8F, 0x89,
          0x90, 0xF1, 0x6D, 0x5D, 0x70, 0x49, 0x99, 0x07, 0x61, 0x22}}}}},
     {{{{{0x43, 0x52, 0xBA, 0xEE, 0xA8, 0xE9, 0x8E, 0x2E, 0x83, 0x30, 0x41,
          0x85, 0xE3, 0x51, 0xB0, 0x8C, 0x86, 0x31, 0xEC, 0x02, 0x76, 0xE8,
          0x41, 0x1F, 0x88, 0xBC, 0x39, 0xA2, 0xE4, 0xC1, 0x34, 0xA7},
         {0x1D, 0x5F, 0x8C, 0x23, 0x0F, 0xF0, 0xDC, 0xCD, 0xBA, 0x67, 0xD5,
          0x78, 0xD6, 0x8D, 0x32, 0x6A, 0xC1, 0x7F, 0x6F, 0x97, 0xCF, 0x46,
          0xF0, 0x04, 0x7B, 0xE3, 0x5A, 0xEE, 0x31, 0xC4, 0xC0, 0x79}}},
       {{{0x96, 0xBC, 0x01, 0x78, 0x9F, 0xBE, 0x8B, 0xBA, 0x59, 0x22, 0xFB,
          0x64, 0x1B, 0x37, 0x5C, 0x33, 0x57, 0xAF, 0x83, 0x5A, 0x96, 0xEA,
          0x56, 0xAA, 0x6E, 0x9C, 0xFA, 0xE6, 0xF9, 0xDF, 0xD8, 0x44},
         {0xBB, 0x4E, 0xBF, 0xA8, 0xEC, 0x0F, 0x16, 0xA8, 0x59, 0x1F, 0x49,
          0xF4, 0x8C, 0x80, 0x6C, 0x52, 0x7F, 0x74, 0x94, 0xC2, 0xE3, 0x29,
          0x34, 0x9C, 0x97, 0xB9, 0x5E, 0xED, 0xFD, 0x59, 0x9D, 0xD4}}},
       {{{0x83, 0xFB, 0xC2, 0xAD, 0x72, 0xE8, 0xF3, 0x68, 0x43, 0xD0, 0xD4,
          0xDC, 0xB2, 0x36, 0xC1, 0xDB, 0x03, 0x29, 0xEE, 0x8C, 0x1A, 0x10,
          0xD7, 0xFB, 0xC2, 0xEA, 0xDA, 0xBA, 0x42, 0x18, 0xE6, 0xE4},
         {0x63, 0x41, 0x6E, 0x8C, 0xB3, 0x14, 0x68, 0x9A, 0x0F, 0x64, 0x87,
          0x16, 0x02, 0xA3, 0x59, 0xF4, 0x60, 0x80, 0x04, 0x2B, 0xA4, 0xE6,
          0x10, 0x2D, 0x61, 0x59, 0x14, 0xFE, 0xAF, 0x84, 0xA0, 0x67}}}}}}};
const Fq12ElemStr FfElementTest::fq12_mul_gb_str = {
    {{{{{{0xE4, 0xCA, 0x0B, 0xA8, 0x9C, 0x70, 0xE2, 0x20, 0x24, 0xD9, 0x8F,
          0x09, 0x12, 0x79, 0x55, 0x44, 0x8C, 0x58, 0x42, 0x8F, 0x18, 0x97,
          0x0A, 0xC3, 0x0A, 0x40, 0x68, 0x0E, 0x1E, 0x21, 0x7F, 0xB4},
         {0x73, 0xCF, 0x8D, 0x54, 0x68, 0xAE, 0x1C, 0xC4, 0x95, 0x01, 0xE3,
          0x52, 0x33, 0xFE, 0x69, 0xB5, 0x23, 0x45, 0xEF, 0xFF, 0x79, 0x14,
          0xEF, 0x98, 0xA8, 0x4E, 0xB1, 0x2E, 0xE1, 0x15, 0x81, 0x0C}}},
       {{{0x9F, 0x65, 0x90, 0x6A, 0x53, 0xD7, 0xF6, 0x73, 0x08, 0xDA, 0x45,
          0x11, 0xDE, 0xCF, 0xED, 0x4C, 0x8C, 0x21, 0x02, 0xF5, 0x3F, 0x97,
          0xB6, 0xB2, 0xF5, 0xC6, 0x58, 0xFC, 0x9A, 0xA6, 0xBB, 0xF9},
         {0x3C, 0xD8, 0xFC, 0x86, 0x09, 0x1C, 0x16, 0xA4, 0x6F, 0x5E, 0x7A,
          0x81, 0x01, 0xF9, 0x8A, 0x6D, 0x38, 0xB5, 0xC9, 0x5F, 0xE9, 0x7D,
          0x6F, 0x46, 0x92, 0x49, 0x5B, 0xB8, 0x61, 0x03, 0x6F, 0x5E}}},
       {{{0xDA, 0x53, 0xCB, 0x62, 0xCD, 0x82, 0x63, 0x96, 0xC7, 0xC0, 0x39,
          0xA4, 0x31, 0xEE, 0x15, 0x26, 0x1C, 0xE6, 0x4E, 0xE4, 0xB4, 0x40,
          0xFA, 0x65, 0xA3, 0xF4, 0x73, 0x03, 0x85, 0x84, 0x41, 0xF9},
         {0x77, 0xF3, 0x90, 0xDC, 0x88, 0x26, 0xBD, 0x27, 0x9A, 0x9D, 0x37,
          0xF0, 0x80, 0xEE, 0x02, 0x1D, 0x3E, 0x4F, 0x88, 0xED, 0x8F, 0x89,
          0x90, 0xF1, 0x6D, 0x5D, 0x70, 0x49, 0x99, 0x07, 0x61, 0x22}}}}},
     {{{{{0xBC, 0xAD, 0x45, 0x11, 0x57, 0x13, 0x62, 0x9E, 0xC3, 0xB5, 0xB0,
          0xD9, 0x0B, 0x1F, 0xF4, 0x12, 0x86, 0xAA, 0x79, 0xF8, 0x9B, 0xAF,
          0xC9, 0x63, 0x4A, 0x6C, 0xF4, 0x38, 0xCA, 0x11, 0xFB, 0x6C},
         {0xE2, 0xA0, 0x73, 0xDC, 0xF0, 0x0C, 0x13, 0xFF, 0x8C, 0x7E, 0x1C,
          0xE6, 0x17, 0xE4, 0x72, 0x34, 0x4B, 0x5C, 0xF6, 0x63, 0x43, 0x51,
          0x1A, 0x7E, 0x57, 0x45, 0xD2, 0xED, 0x7D, 0x0E, 0x6F, 0x9A}}},
       {{{0x69, 0x43, 0xFE, 0x87, 0x60, 0x3E, 0x65, 0x12, 0xED, 0xC2, 0xF6,
          0xFA, 0xD3, 0x3A, 0x48, 0x6B, 0xB5, 0x2C, 0xE2, 0xA0, 0x7B, 0xAD,
          0xB3, 0xD8, 0x64, 0x8C, 0x32, 0xF4, 0xB4, 0xF3, 0x57, 0xCF},
         {0x44, 0xB1, 0x40, 0x57, 0x13, 0xED, 0xDA, 0x24, 0xED, 0xC6, 0xA8,
          0x6A, 0x61, 0xF1, 0x38, 0x4C, 0x8D, 0x67, 0xD1, 0x38, 0x2F, 0x6E,
          0xD5, 0xE6, 0x3B, 0x6F, 0xCE, 0xED, 0xB1, 0x79, 0x92, 0x3F}}},
       {{{0x7C, 0x04, 0x3D, 0x52, 0x8D, 0x13, 0xFD, 0x65, 0x03, 0x15, 0x1D,
          0x82, 0x3C, 0x3A, 0xE2, 0xC4, 0x09, 0xB2, 0x77, 0x6E, 0xF8, 0x87,
          0x32, 0x87, 0x10, 0x3E, 0x53, 0x21, 0x6C, 0xBA, 0x49, 0x2F},
         {0x9C, 0xBE, 0x91, 0x73, 0x4C, 0xE8, 0x88, 0x33, 0x37, 0x81, 0x6B,
          0x48, 0xEB, 0xCE, 0x4A, 0xAA, 0xAC, 0x5C, 0x61, 0xCF, 0x6D, 0xB1,
          0xFA, 0x55, 0x71, 0xD0, 0x18, 0xDC, 0xFF, 0x4E, 0x8F, 0xAC}}}}}},
};

const FqElemStr FfElementTest::fq_multi_exp_base_1[1] = {{
    0x12, 0xA6, 0x5B, 0xD6, 0x91, 0x8D, 0x50, 0xA7, 0x66, 0xEB, 0x7D, 0x52,
    0xE3, 0x40, 0x17, 0x60, 0x7F, 0xDF, 0x6C, 0xA1, 0x2C, 0x1A, 0x37, 0xE0,
    0x92, 0xC0, 0xF7, 0xB9, 0x76, 0xAB, 0xB1, 0x8A,
}};
const BigNumStr FfElementTest::fq_multi_exp_exp_1[1] = {{
    0xFF, 0xFB, 0x3E, 0x5D, 0xFF, 0x9A, 0xFF, 0x02, 0x00, 0xFF, 0xFF, 0xFF,
    0xF2, 0xE1, 0x85, 0x81, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x81,
    0xFF, 0xFD, 0xFF, 0xEB, 0xFF, 0x29, 0xA7, 0xFF,
}};
const FqElemStr FfElementTest::fq_multi_exp_res_1 = {
    0x6A, 0x21, 0xEC, 0x89, 0xCC, 0x13, 0x2F, 0x6F, 0x29, 0x1B, 0x3A,
    0x94, 0xF6, 0xE6, 0xA8, 0xBD, 0x98, 0x25, 0x43, 0x7A, 0xDC, 0xC1,
    0x20, 0xBA, 0x30, 0xD8, 0x1C, 0x8E, 0x79, 0xFC, 0xDA, 0x67,
};

const std::vector<uint8_t> FfElementTest::fq_multi_exp_exp_1_264({
    0x08, 0xFF, 0xFB, 0x3E, 0x5D, 0xFF, 0x9A, 0xFF, 0x02, 0x00, 0xFF, 0xFF,
    0xFF, 0xF2, 0xE1, 0x85, 0x81, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0x81, 0xFF, 0xFD, 0xFF, 0xEB, 0xFF, 0x29, 0xA7, 0xFF,
});
const FqElemStr FfElementTest::fq_multi_exp_res_1_264 = {
    0x71, 0x41, 0xa1, 0xdb, 0xd1, 0xd1, 0x50, 0xc2, 0x73, 0x07, 0xc1,
    0x93, 0xeb, 0xae, 0x89, 0x4c, 0x6e, 0x49, 0x74, 0xf7, 0x46, 0x23,
    0x75, 0xca, 0xc8, 0x67, 0x82, 0xaf, 0xcf, 0x35, 0x34, 0x1c};
const FqElemStr FfElementTest::fq_multi_exp_res_1_256_264 = {
    0x10, 0x2f, 0x3a, 0xe5, 0x6e, 0x95, 0x92, 0x8f, 0x98, 0x03, 0x67,
    0x79, 0xec, 0x0c, 0xc9, 0x46, 0x07, 0xd9, 0xd9, 0x40, 0x46, 0x29,
    0x99, 0xe9, 0x23, 0xf9, 0x6b, 0x10, 0x35, 0x7c, 0xf1, 0xa3};

const FqElemStr FfElementTest::fq_multi_exp_base_2[2] = {
    {0xE6, 0x65, 0x23, 0x9B, 0xD4, 0x07, 0x16, 0x83, 0x38, 0x23, 0xB2, 0x67,
     0x57, 0xEB, 0x0F, 0x23, 0x3A, 0xF4, 0x8E, 0xDA, 0x71, 0x5E, 0xD9, 0x98,
     0x63, 0x98, 0x2B, 0xBC, 0x78, 0xD1, 0x94, 0xF2},
    {0xDD, 0x2B, 0xE9, 0x59, 0x24, 0xA5, 0xB3, 0xFD, 0xEB, 0xE1, 0x3C, 0xC0,
     0x73, 0x4E, 0x99, 0xEE, 0x36, 0xF6, 0xC0, 0x1A, 0x76, 0x01, 0x0A, 0xF0,
     0xCB, 0xB4, 0x71, 0x88, 0x95, 0xCB, 0x35, 0xBA}};
const BigNumStr FfElementTest::fq_multi_exp_exp_2[2] = {
    {0x11, 0xFF, 0xFF, 0xFF, 0x4F, 0x59, 0xB1, 0xD3, 0x6B, 0x08, 0xFF, 0xFF,
     0x0B, 0xF3, 0xAF, 0x27, 0xFF, 0xB8, 0xFF, 0xFF, 0x98, 0xFF, 0xEB, 0xFF,
     0xF2, 0x6A, 0xFF, 0xFF, 0xEA, 0x31, 0xFF, 0xFF},
    {0xE2, 0xFF, 0x03, 0x1D, 0xFF, 0x19, 0x81, 0xCB, 0xFF, 0xFF, 0x6B, 0xD5,
     0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xBD, 0xFF, 0x5A, 0xFF, 0x5C, 0x7C, 0xFF,
     0x84, 0xFF, 0xFF, 0x8C, 0x03, 0xB2, 0x26, 0xFF}};
const FqElemStr FfElementTest::fq_multi_exp_res_2 = {
    0x8A, 0xF7, 0x96, 0x53, 0x9C, 0xC3, 0x57, 0x89, 0x50, 0xE3, 0xAB,
    0x12, 0x62, 0xEA, 0x0C, 0xE4, 0x65, 0xA6, 0x91, 0x09, 0x93, 0x81,
    0xFC, 0xBB, 0x0E, 0xFA, 0xC1, 0xC4, 0xDC, 0x3F, 0x0A, 0xD1,
};

const FqElemStr FfElementTest::fq_multi_exp_base_3[3] = {
    {0x24, 0x9D, 0xDD, 0x1A, 0xC0, 0x07, 0x1F, 0x65, 0xDF, 0xBB, 0xC7, 0x39,
     0x99, 0x44, 0x63, 0x8E, 0x7E, 0xB2, 0x85, 0x82, 0xC6, 0x4E, 0x2D, 0x39,
     0xA8, 0x3F, 0x12, 0xB4, 0xE9, 0x9D, 0x67, 0x28},
    {0x6B, 0x51, 0x6B, 0x33, 0x0B, 0x2E, 0x2A, 0x94, 0x34, 0xCC, 0x7E, 0x97,
     0xFA, 0x85, 0x51, 0x44, 0x30, 0xE5, 0xF2, 0x68, 0x23, 0x31, 0x84, 0xFF,
     0xBB, 0x95, 0x9A, 0xB2, 0x80, 0x95, 0xC4, 0x91},
    {0x77, 0xED, 0xA2, 0x53, 0xA3, 0xBF, 0x6C, 0x58, 0x16, 0x7D, 0xEF, 0x8A,
     0x7D, 0x38, 0x65, 0x3F, 0x92, 0xA6, 0x85, 0xD7, 0x9F, 0x80, 0xA4, 0xA1,
     0x70, 0x02, 0xE5, 0x66, 0xF2, 0xD8, 0xD7, 0xD2}};
const BigNumStr FfElementTest::fq_multi_exp_exp_3[3] = {
    {0xFF, 0xFF, 0xFF, 0xB4, 0x48, 0xFF, 0xFF, 0xFF, 0xA3, 0xFF, 0xE3, 0xFF,
     0x61, 0xFF, 0xA2, 0x97, 0x9A, 0xFF, 0x6F, 0x04, 0xC6, 0xB9, 0xFF, 0x22,
     0xFF, 0x20, 0x9E, 0xFF, 0x43, 0xFF, 0xFF, 0xFF},
    {0xB1, 0x19, 0xBF, 0xFF, 0x74, 0x7F, 0xCC, 0x34, 0x1E, 0x30, 0x7D, 0xC5,
     0xC4, 0xFF, 0xE7, 0xF8, 0xFF, 0x5F, 0xFF, 0x73, 0xFF, 0x58, 0xFF, 0xD6,
     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0xFF, 0xFF},
    {0xFF, 0xFF, 0x0D, 0xFF, 0xFF, 0xFF, 0xFF, 0x26, 0xA8, 0xFF, 0xFF, 0xFF,
     0x3E, 0xFF, 0xFF, 0xFF, 0xE0, 0x4F, 0xFF, 0xE3, 0xFF, 0xFF, 0xEB, 0x04,
     0x4B, 0xFF, 0x5D, 0x55, 0xFF, 0x2D, 0xFF, 0xFF}};
const FqElemStr FfElementTest::fq_multi_exp_res_3 = {
    0x04, 0x22, 0x21, 0xE7, 0x9F, 0xE3, 0x07, 0x2F, 0xA4, 0xBB, 0x56,
    0x84, 0xD5, 0x93, 0x4A, 0xDA, 0x5B, 0x89, 0x07, 0xBE, 0xC5, 0x5F,
    0xE6, 0x5C, 0x18, 0xF0, 0xF8, 0x8E, 0x8E, 0x00, 0xB9, 0x87,
};
const FqElemStr FfElementTest::fq_multi_exp_base_4[4] = {
    {0x81, 0xEE, 0x78, 0x31, 0x4C, 0xC0, 0x3C, 0xDD, 0x16, 0x52, 0xC6, 0x7E,
     0x07, 0x4C, 0xFE, 0xC4, 0x50, 0x63, 0x5A, 0x40, 0xC8, 0xDF, 0x94, 0x23,
     0x1A, 0x90, 0xDD, 0x24, 0x61, 0x23, 0xDD, 0x87},
    {0x76, 0xBB, 0x2C, 0x1C, 0xB3, 0x78, 0x93, 0x7E, 0x10, 0x29, 0xC3, 0xEC,
     0xBD, 0xA3, 0x75, 0x3A, 0xF1, 0x0B, 0xE1, 0xCA, 0xEE, 0x02, 0x58, 0x74,
     0xC7, 0xDC, 0xB8, 0x4F, 0x3F, 0x7B, 0xA2, 0xFC},
    {0x3A, 0xD3, 0x04, 0xAA, 0x9D, 0x2A, 0xDE, 0x86, 0x56, 0x84, 0x80, 0x42,
     0xA5, 0x68, 0xD8, 0x6E, 0x65, 0xC4, 0x08, 0x07, 0x87, 0x4B, 0xC1, 0x92,
     0xCB, 0x68, 0x52, 0x6C, 0x5A, 0x4F, 0x7C, 0xFB},
    {0x56, 0xE7, 0xBD, 0x59, 0x54, 0xCC, 0x20, 0x16, 0xAE, 0x36, 0xD1, 0xB0,
     0xE4, 0x82, 0x47, 0x27, 0x32, 0xD1, 0x38, 0x7C, 0x53, 0x7F, 0xDD, 0xF4,
     0xDE, 0xFA, 0xF7, 0x0F, 0xDD, 0xDF, 0x48, 0xA9}};
const BigNumStr FfElementTest::fq_multi_exp_exp_4[4] = {
    {0xFF, 0xA5, 0xC3, 0xFF, 0xFF, 0x09, 0x18, 0x18, 0x95, 0x40, 0xFF, 0xFF,
     0xDB, 0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0xFF, 0x25, 0xFF, 0xFF, 0x42, 0x07,
     0xB5, 0xFF, 0x26, 0xE0, 0x4F, 0xB5, 0xB4, 0xFF},
    {0x1F, 0xFF, 0xAA, 0xF1, 0xFF, 0xFF, 0x7E, 0xFF, 0xFF, 0xFF, 0x07, 0xFF,
     0xE7, 0xDF, 0xFF, 0xEE, 0xFF, 0x57, 0xFF, 0xFF, 0xFF, 0xB8, 0xB3, 0x9C,
     0xFF, 0x8A, 0x89, 0xFF, 0xFE, 0x32, 0xFF, 0xC1},
    {0x9A, 0xFF, 0xFF, 0x9B, 0xFF, 0xAB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
     0xFF, 0x36, 0xF0, 0xC5, 0xAE, 0x87, 0x41, 0xFF, 0x5C, 0xDD, 0xFF, 0xFF,
     0xFF, 0xFF, 0x59, 0xC9, 0xFF, 0x44, 0x5C, 0x58},
    {0x00, 0xFF, 0x95, 0xFF, 0x21, 0xFF, 0xFF, 0x1D, 0x1A, 0x06, 0xD3, 0xFF,
     0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xB0, 0x31, 0xFF, 0xFF, 0x1F,
     0x61, 0x48, 0xFF, 0xFF, 0xFF, 0x17, 0xC9, 0x79}};
const FqElemStr FfElementTest::fq_multi_exp_res_4 = {
    0x26, 0x2C, 0x23, 0x55, 0xD5, 0xBD, 0x7B, 0x67, 0x60, 0xFE, 0x06,
    0x7B, 0xCC, 0xB8, 0x6B, 0xC9, 0x00, 0x81, 0xAE, 0xCB, 0xEC, 0x91,
    0x6D, 0x1B, 0x9E, 0x1C, 0xD8, 0xC0, 0x8D, 0x3F, 0x1B, 0x20,
};
const Fq12ElemStr FfElementTest::fq12_multi_exp_base_4[4] = {
    {
        {{{{{{0x2C, 0x86, 0xEE, 0x80, 0x61, 0x45, 0x8F, 0xFD, 0x96, 0xC2, 0x81,
              0x11, 0xE8, 0x96, 0xE2, 0xCA, 0x21, 0x78, 0xF7, 0xA3, 0x4B, 0xBA,
              0xDC, 0x0D, 0x34, 0x8A, 0x56, 0x12, 0x67, 0x8D, 0x72, 0x37},
             {0xA8, 0xEB, 0x5F, 0x1A, 0x1B, 0xF0, 0x5C, 0xC6, 0x6F, 0xC2, 0xC5,
              0x03, 0xC4, 0x19, 0x85, 0xA6, 0xE0, 0x64, 0xFE, 0x71, 0x51, 0x46,
              0xDF, 0xC2, 0xD6, 0xF9, 0xA0, 0xD6, 0x84, 0xC1, 0x4A, 0x11}}},
           {{{0xE0, 0x33, 0xA3, 0x1C, 0x73, 0x71, 0x62, 0x17, 0x10, 0x4C, 0xD8,
              0x3E, 0xEE, 0xA1, 0x38, 0x9F, 0xA5, 0xFB, 0x1D, 0xC4, 0x9D, 0x2F,
              0x08, 0x4A, 0xD3, 0x61, 0x37, 0x79, 0xAB, 0xC1, 0x37, 0x7E},
             {0x90, 0xFD, 0xA3, 0x9D, 0x0C, 0x81, 0x52, 0xF4, 0x58, 0x24, 0x89,
              0xC4, 0xF4, 0xD4, 0x82, 0x33, 0xCA, 0x5D, 0xB4, 0x58, 0xA6, 0x1E,
              0xE6, 0x2B, 0x86, 0xEF, 0x56, 0xC4, 0x4F, 0x9B, 0x27, 0x3C}}},
           {{{0x96, 0x54, 0xDA, 0xB5, 0x32, 0x23, 0x8A, 0x93, 0xCC, 0xA5, 0x7D,
              0x28, 0x4A, 0x97, 0xA4, 0x30, 0xA8, 0x11, 0xBC, 0x43, 0x22, 0x7F,
              0x02, 0x73, 0x0E, 0x5C, 0x63, 0x52, 0x2F, 0x4B, 0x5F, 0x7D},
             {0xC3, 0x1E, 0x30, 0xAE, 0xAC, 0x8C, 0xE8, 0x93, 0xD6, 0xCE, 0x05,
              0x4B, 0x6B, 0x21, 0x01, 0x14, 0x4A, 0x1D, 0xD9, 0x08, 0x0C, 0xA1,
              0x4C, 0x0B, 0x44, 0x28, 0x9C, 0xB6, 0xD1, 0x96, 0xBD, 0x07}}}}},
         {{{{{0x8B, 0x3D, 0x77, 0x4E, 0xBD, 0x7B, 0x9F, 0x65, 0x20, 0xDB, 0xA0,
              0x95, 0x25, 0x44, 0x44, 0x7A, 0xE3, 0xDC, 0xDD, 0x2F, 0xBA, 0x75,
              0x16, 0x19, 0xCB, 0x90, 0x31, 0x79, 0x38, 0xB6, 0x1A, 0x82},
             {0xBC, 0xB6, 0x85, 0xCD, 0xEB, 0xB9, 0x13, 0x43, 0xEA, 0xC2, 0x78,
              0xBE, 0x25, 0x97, 0x1C, 0x6E, 0x18, 0x55, 0xFD, 0xCB, 0xE6, 0x7E,
              0x1E, 0x92, 0xAD, 0x48, 0xE7, 0xA7, 0x02, 0x87, 0x0B, 0x8F}}},
           {{{0x16, 0xD7, 0x8E, 0x95, 0x8E, 0x62, 0x0A, 0xAD, 0x20, 0x2D, 0x6A,
              0x2B, 0x4E, 0x6F, 0xC1, 0xC2, 0x63, 0xBA, 0x82, 0xF3, 0x8C, 0xD0,
              0xA2, 0x09, 0xD3, 0xE5, 0xBA, 0x1F, 0x65, 0x35, 0xD0, 0x1C},
             {0x09, 0x98, 0x47, 0x65, 0xF2, 0x90, 0xD4, 0xE2, 0xD0, 0x6F, 0x9E,
              0xDB, 0xA2, 0x14, 0x9B, 0x4B, 0x3D, 0xAA, 0x75, 0x25, 0x67, 0xF4,
              0x7D, 0x77, 0xE9, 0x24, 0xED, 0xEE, 0x1B, 0x07, 0x7F, 0xE0}}},
           {{{0x7A, 0x34, 0xB7, 0x3C, 0x36, 0x0D, 0xCE, 0xF9, 0xBF, 0xF9, 0xE5,
              0x09, 0x86, 0xEB, 0xB9, 0xD8, 0xC4, 0x67, 0xC5, 0xCD, 0xD4, 0xBC,
              0xEE, 0x45, 0xF7, 0x11, 0x68, 0xD9, 0x23, 0x6D, 0xD6, 0x24},
             {0x6E, 0x97, 0x83, 0x13, 0x76, 0x9F, 0x35, 0xEA, 0xB8, 0x47, 0x57,
              0x9B, 0x74, 0x47, 0x1F, 0x19, 0xE7, 0x97, 0x74, 0x1B, 0xB1, 0xA0,
              0xF3, 0x92, 0xDC, 0x35, 0xFD, 0x7F, 0x4F, 0x07, 0x22, 0xAC}}}}}},
    },
    {{{{{{{0xFD, 0x05, 0x41, 0x27, 0x00, 0x7A, 0xAD, 0x17, 0xBC, 0xBF, 0x22,
           0x5E, 0xDA, 0xEB, 0x7D, 0xAA, 0xB5, 0x2D, 0xC8, 0x61, 0xFE, 0x2C,
           0xBA, 0x9E, 0x54, 0x43, 0x94, 0xDC, 0xFD, 0x0E, 0x6D, 0x6D},
          {0xA1, 0x5E, 0x05, 0xA5, 0x05, 0x55, 0xE7, 0x2A, 0xF7, 0x53, 0x37,
           0x2C, 0xEF, 0x44, 0x95, 0xCA, 0x2C, 0xE8, 0xEB, 0xAE, 0x61, 0x05,
           0x33, 0xE7, 0x0F, 0x30, 0x67, 0xBE, 0xCD, 0xB2, 0x93, 0x44}}},
        {{{0x44, 0x31, 0x96, 0x4D, 0x72, 0x61, 0xCD, 0x23, 0x1F, 0x7B, 0x57,
           0x33, 0x39, 0xAC, 0x57, 0x53, 0x3D, 0x70, 0x57, 0xB3, 0x6D, 0xD5,
           0x8A, 0x89, 0x30, 0xBC, 0xED, 0x29, 0x19, 0x39, 0x6E, 0x6A},
          {0x80, 0x21, 0x1E, 0xB7, 0x84, 0xB1, 0x0A, 0xA4, 0xD0, 0xFF, 0x59,
           0x31, 0xE9, 0xBA, 0x39, 0xF7, 0x81, 0xDF, 0x1B, 0x7B, 0xD9, 0xDB,
           0x02, 0x17, 0xBE, 0x97, 0x63, 0xBD, 0x37, 0x14, 0xB8, 0x8B}}},
        {{{0x6C, 0xCC, 0x5B, 0xA3, 0xEE, 0xC8, 0x0B, 0x7B, 0xF5, 0xDE, 0xBC,
           0xB7, 0xA8, 0x25, 0x35, 0xAE, 0x0B, 0x30, 0x96, 0x33, 0x52, 0x13,
           0xA3, 0x89, 0x3A, 0x2E, 0xA4, 0x7E, 0x5F, 0x4E, 0xB1, 0xF7},
          {0x87, 0xBA, 0x08, 0xB0, 0xFB, 0xCB, 0x31, 0xA6, 0x2B, 0x3E, 0xE7,
           0xC4, 0xCC, 0xA5, 0x14, 0x61, 0xC9, 0x18, 0xFC, 0x74, 0x59, 0x06,
           0xF4, 0xAD, 0xFC, 0x2D, 0x0C, 0x7D, 0xDB, 0x2A, 0xEC, 0xD4}}}}},
      {{{{{0xE9, 0x31, 0x31, 0x50, 0x25, 0xB7, 0x0C, 0x48, 0x30, 0xD5, 0x78,
           0xB1, 0x10, 0xEA, 0x5D, 0xAA, 0xAA, 0x03, 0xEC, 0xE3, 0x0F, 0x36,
           0xA6, 0xBC, 0x18, 0x3A, 0x76, 0x87, 0xA3, 0xE9, 0x33, 0xDA},
          {0x48, 0x78, 0x93, 0x64, 0x72, 0x9B, 0x2A, 0x1E, 0x0D, 0x50, 0x9F,
           0x6F, 0xBD, 0xA5, 0x18, 0xB1, 0xA8, 0x14, 0x9A, 0x1B, 0xB9, 0xB4,
           0x2C, 0x1F, 0x46, 0xB8, 0x9B, 0x7A, 0xC7, 0x84, 0xAE, 0x27}}},
        {{{0xD1, 0xEC, 0x1C, 0xEC, 0x69, 0xF0, 0x35, 0x40, 0x77, 0x7E, 0x27,
           0x22, 0x36, 0x38, 0xDF, 0x15, 0xC2, 0xB3, 0xB8, 0x63, 0x4A, 0x6E,
           0x68, 0x8C, 0xC1, 0x39, 0x3C, 0x02, 0x4C, 0x2A, 0x31, 0x18},
          {0x2E, 0x35, 0xF5, 0xCA, 0xA2, 0xE9, 0x24, 0x92, 0xD5, 0xE5, 0x2E,
           0x5D, 0x1C, 0x94, 0xD9, 0xC7, 0xF0, 0x22, 0x16, 0x20, 0xA8, 0x37,
           0xDD, 0x0E, 0xAB, 0x1B, 0x5E, 0x8B, 0xEE, 0x81, 0xC6, 0x17}}},
        {{{0xF1, 0x29, 0x5D, 0x1D, 0x6F, 0x53, 0x5A, 0xB2, 0x20, 0x88, 0x3D,
           0xA4, 0x98, 0x81, 0xA4, 0xEF, 0x11, 0x1B, 0x64, 0x9E, 0x2C, 0x95,
           0xDD, 0xD7, 0x57, 0xB3, 0x95, 0xCA, 0x40, 0xB9, 0x0D, 0x62},
          {0xDC, 0x86, 0x8B, 0xE6, 0xD3, 0x7B, 0x33, 0xEA, 0x50, 0x25, 0xE2,
           0x77, 0xE3, 0x0B, 0x5A, 0xC8, 0x81, 0xFC, 0xAE, 0x74, 0x38, 0x69,
           0x07, 0xF8, 0x4E, 0xD7, 0x85, 0xA6, 0x2F, 0x13, 0xB7, 0x0A}}}}}}},
    {{{{{{{0xF4, 0xDC, 0xAC, 0x02, 0xC0, 0x95, 0x07, 0xDC, 0x12, 0x4F, 0x3A,
           0x01, 0xA9, 0xEE, 0xF3, 0x07, 0x46, 0x94, 0x47, 0x15, 0x63, 0xA6,
           0x8E, 0x0A, 0xC4, 0xC4, 0xE4, 0x23, 0x85, 0x63, 0xE4, 0x4E},
          {0x9A, 0x9E, 0x9F, 0xC1, 0xED, 0x4E, 0x94, 0x10, 0xFE, 0x7D, 0x90,
           0xEF, 0x82, 0x21, 0xAC, 0x67, 0x24, 0x99, 0x86, 0xC6, 0x85, 0x8B,
           0x19, 0x9A, 0x9B, 0x90, 0x0B, 0xA4, 0x90, 0x78, 0x34, 0x53}}},
        {{{0xB1, 0x4C, 0xBA, 0xB8, 0xC6, 0x40, 0x71, 0xC2, 0x17, 0x51, 0x05,
           0xC2, 0xC9, 0xBC, 0x03, 0x10, 0x4E, 0xFE, 0x2F, 0x94, 0xED, 0x13,
           0x35, 0x7B, 0x20, 0xA6, 0x59, 0x44, 0x81, 0xD0, 0xEC, 0x12},
          {0x74, 0xA2, 0x4A, 0xFB, 0xD7, 0x28, 0x70, 0xAD, 0xDE, 0x86, 0x2F,
           0xEF, 0xF9, 0x50, 0x5D, 0x1E, 0x46, 0x3B, 0x82, 0x1C, 0x6A, 0xC9,
           0x3F, 0x32, 0xAE, 0xCD, 0x93, 0x2C, 0xA5, 0x70, 0x45, 0x24}}},
        {{{0x38, 0x19, 0x79, 0xBF, 0x35, 0xF5, 0xC1, 0x53, 0x06, 0x42, 0xAA,
           0x6B, 0xF3, 0xB7, 0x8F, 0xFB, 0xFC, 0x28, 0x46, 0x9A, 0x65, 0x2A,
           0x45, 0x3D, 0x4C, 0x3C, 0x6B, 0x9C, 0x44, 0xC5, 0x82, 0xB8},
          {0x80, 0xF9, 0xB3, 0x44, 0x95, 0x17, 0x39, 0x01, 0x6B, 0xD6, 0x1D,
           0x73, 0x22, 0x94, 0xFF, 0x6F, 0x7B, 0x4E, 0xB6, 0xA4, 0xE4, 0x6C,
           0xA8, 0xDB, 0x38, 0x74, 0x0B, 0xDB, 0xFA, 0x14, 0x99, 0x39}}}}},
      {{{{{0x28, 0xEE, 0xFC, 0x62, 0xE5, 0x33, 0x9C, 0x63, 0xD5, 0x7F, 0x2C,
           0x4C, 0xF4, 0x76, 0x4C, 0xF7, 0x7B, 0x27, 0x2C, 0xA9, 0xB9, 0x01,
           0x3C, 0x58, 0xF7, 0xCE, 0xAA, 0x0A, 0x21, 0xC0, 0xA3, 0xA7},
          {0xA1, 0x85, 0xBC, 0xFE, 0x55, 0xFC, 0x3B, 0x9B, 0x3D, 0xEF, 0x14,
           0x85, 0x8A, 0x4E, 0x5E, 0x1F, 0x4F, 0xC9, 0x86, 0xB8, 0xF2, 0xB2,
           0xE3, 0xE7, 0x7E, 0x87, 0xE2, 0x20, 0xD7, 0x85, 0x2C, 0xD1}}},
        {{{0x13, 0xCB, 0x46, 0xAD, 0xD7, 0xEC, 0x66, 0xD5, 0x2B, 0x6E, 0x87,
           0x92, 0x13, 0xB2, 0x7D, 0x18, 0x69, 0x35, 0xCB, 0xF1, 0xBE, 0xC2,
           0x9D, 0xEB, 0xF5, 0x00, 0x0B, 0x73, 0xA3, 0xFD, 0x51, 0xDC},
          {0x91, 0x0E, 0xE4, 0x46, 0x41, 0x23, 0xDD, 0x85, 0x53, 0x0C, 0xAE,
           0xF9, 0x74, 0xCF, 0x1C, 0x32, 0x22, 0xDA, 0x4A, 0x14, 0x80, 0x71,
           0x51, 0x23, 0xC3, 0xAB, 0x7E, 0xEC, 0x77, 0xCC, 0x59, 0x12}}},
        {{{0x1C, 0x0F, 0x65, 0x6B, 0xD8, 0x41, 0xE0, 0x1B, 0x51, 0x9C, 0x89,
           0x26, 0xAB, 0x88, 0x63, 0x5D, 0xBB, 0x95, 0x92, 0x5B, 0x2C, 0x1D,
           0xDE, 0xC1, 0x88, 0xD6, 0xF1, 0x02, 0x48, 0xE0, 0xE2, 0xD1},
          {0x40, 0x7F, 0xF1, 0x23, 0x4A, 0xCF, 0x36, 0xD5, 0xCF, 0x76, 0x0D,
           0x00, 0x2A, 0xF7, 0x5F, 0x31, 0xBB, 0xCC, 0x46, 0x84, 0x07, 0x04,
           0x98, 0x9C, 0xB4, 0x31, 0x15, 0x2D, 0x91, 0xF6, 0x29, 0x33}}}}}}},
    {{{{{{{0xA8, 0x8E, 0x9A, 0xF9, 0x25, 0x12, 0x98, 0xE2, 0xC3, 0x61, 0x2E,
           0xE8, 0xD6, 0xA6, 0x77, 0x16, 0x49, 0x04, 0x75, 0x69, 0xD1, 0x83,
           0x2D, 0x3F, 0x2A, 0x79, 0xB6, 0x9B, 0xC9, 0x1D, 0x03, 0x90},
          {0x2A, 0xD8, 0x11, 0x9F, 0x26, 0x36, 0xE7, 0xE9, 0x3A, 0x05, 0x4C,
           0x15, 0x49, 0x93, 0xDA, 0xE9, 0xD0, 0x5A, 0xE4, 0x8D, 0x8A, 0xFA,
           0x04, 0xF1, 0x20, 0x84, 0x56, 0xEC, 0x3C, 0x27, 0x19, 0x5C}}},
        {{{0xF1, 0xAF, 0xBF, 0xF6, 0x0E, 0x58, 0x84, 0x2D, 0x94, 0x11, 0xF4,
           0xB5, 0xF4, 0x14, 0x51, 0xB0, 0x90, 0x46, 0x1A, 0x81, 0xED, 0xCF,
           0x91, 0x66, 0x58, 0xA6, 0x36, 0x3A, 0x52, 0x18, 0x5A, 0xC1},
          {0x08, 0x4C, 0x99, 0xD3, 0xDC, 0xCE, 0x7F, 0xCE, 0x78, 0xE0, 0x38,
           0x87, 0x32, 0xF1, 0x80, 0x3C, 0x7B, 0x67, 0xAA, 0x6F, 0xDD, 0xE0,
           0xFC, 0xCB, 0xD0, 0xB0, 0x3A, 0x59, 0x52, 0x2A, 0x84, 0xE4}}},
        {{{0xF8, 0x4A, 0xFF, 0x50, 0xA0, 0x65, 0xC4, 0xEE, 0xF4, 0x9C, 0xAA,
           0x34, 0x46, 0xF9, 0xD2, 0x6C, 0xA1, 0x61, 0x71, 0x49, 0x32, 0x25,
           0x84, 0x54, 0x90, 0x44, 0xBE, 0xA4, 0x0B, 0xF7, 0xFE, 0x26},
          {0x81, 0x63, 0x73, 0xF7, 0x2F, 0xF2, 0xFA, 0x24, 0x52, 0xA4, 0xD9,
           0x4C, 0xC1, 0xA7, 0xA5, 0xC3, 0x03, 0x36, 0x13, 0x9B, 0x16, 0x45,
           0x16, 0xCB, 0x4B, 0x99, 0x38, 0xF3, 0x6D, 0xC8, 0x7E, 0xAB}}}}},
      {{{{{0xB3, 0x53, 0xDF, 0xB6, 0x82, 0x60, 0x12, 0x11, 0x36, 0x69, 0x0E,
           0x05, 0x31, 0x8E, 0xCF, 0xD7, 0x3F, 0x32, 0xE7, 0x95, 0x84, 0x1D,
           0xC8, 0xB5, 0xBE, 0x49, 0x17, 0x9D, 0xCF, 0xA9, 0x5A, 0x2A},
          {0xC4, 0x11, 0x86, 0xE8, 0x6C, 0x02, 0x56, 0xB0, 0x25, 0x2F, 0xA0,
           0x06, 0xB3, 0x62, 0xB2, 0x11, 0xAF, 0xBE, 0xA4, 0xE8, 0x61, 0x64,
           0x85, 0xFB, 0xEB, 0x1C, 0xF1, 0xBC, 0x2C, 0xAE, 0x10, 0x51}}},
        {{{0x16, 0xA6, 0xC0, 0xB3, 0x86, 0x8E, 0x6D, 0x79, 0xB6, 0xBD, 0xDE,
           0x1E, 0x26, 0x06, 0x46, 0x65, 0x82, 0x84, 0x5A, 0x97, 0xD3, 0xB7,
           0x93, 0x78, 0x6B, 0x9D, 0x14, 0x33, 0x94, 0x43, 0x34, 0x04},
          {0x45, 0xD1, 0x47, 0xD4, 0x2F, 0x17, 0xCF, 0xF1, 0xDD, 0xEA, 0x11,
           0x52, 0xAE, 0x01, 0x88, 0x3A, 0x10, 0xEE, 0x5C, 0x16, 0xCD, 0xB5,
           0x48, 0xE9, 0x16, 0x2C, 0x70, 0xB4, 0x1E, 0x19, 0x38, 0xE0}}},
        {{{0x18, 0xE9, 0xAE, 0xC5, 0xDA, 0x74, 0x41, 0x2D, 0x70, 0x07, 0x60,
           0x37, 0x27, 0x66, 0xF7, 0x00, 0xBB, 0x79, 0x51, 0xF3, 0x7C, 0x8A,
           0x2B, 0xB5, 0x69, 0x6E, 0x10, 0x1F, 0xE0, 0x0A, 0x5E, 0xBE},
          {0xB4, 0x4E, 0x0E, 0x02, 0x59, 0xB5, 0xCB, 0x4A, 0x6A, 0x86, 0x8B,
           0xCC, 0xA2, 0x13, 0xA0, 0xE9, 0xF2, 0x5C, 0xB0, 0x23, 0xB2, 0x15,
           0xF9, 0xBB, 0x43, 0xC1, 0x54, 0xF4, 0xC8, 0xAB, 0x16, 0xA6}}}}}}},
};
const BigNumStr FfElementTest::fq12_multi_exp_exp_4[4] = {
    {
        0x14, 0x92, 0xD1, 0x1F, 0xAC, 0x90, 0x4D, 0xC3, 0x3E, 0xB8, 0xA7, 0xFE,
        0x35, 0x98, 0xDA, 0x94, 0xD6, 0xF3, 0x27, 0x29, 0x4B, 0x70, 0xCF, 0x0F,
        0xDA, 0x14, 0x97, 0xA1, 0x9B, 0x6B, 0x24, 0x08,
    },
    {
        0x76, 0x8D, 0xE5, 0xC2, 0xAB, 0x78, 0xD9, 0x76, 0x98, 0xFF, 0x92, 0xEA,
        0x95, 0x58, 0xC5, 0x0C, 0x6F, 0x1B, 0x35, 0xC4, 0xBF, 0x4A, 0x9E, 0xC2,
        0x6A, 0xEC, 0xE2, 0xF6, 0xAF, 0xEB, 0xAC, 0x06,
    },
    {
        0x50, 0x38, 0x60, 0x31, 0xAB, 0x05, 0xCC, 0xB1, 0xC2, 0x06, 0xA0, 0xD7,
        0x92, 0x12, 0xBD, 0x17, 0x81, 0xB9, 0x7E, 0x07, 0x9B, 0xD4, 0x3B, 0x2D,
        0x3C, 0x15, 0x3A, 0x5A, 0xF1, 0xC0, 0xC4, 0x75,
    },
    {
        0xA1, 0x3F, 0xEA, 0x99, 0x7E, 0xC7, 0x65, 0xF5, 0x41, 0xA6, 0xD6, 0xD3,
        0x77, 0xEC, 0x27, 0xF8, 0x6C, 0x18, 0x28, 0x69, 0x97, 0x08, 0x0E, 0x63,
        0x5A, 0xDA, 0xFE, 0x9F, 0xD1, 0x4A, 0x61, 0x4F,
    },
};
const Fq12ElemStr FfElementTest::fq12_multi_exp_res_4 = {
    {{{{{{0x3A, 0x30, 0x33, 0xA2, 0x14, 0xDF, 0xDC, 0x70, 0x48, 0xF3, 0xBA,
          0x3F, 0xCE, 0xFC, 0x69, 0x24, 0xAE, 0xA1, 0xF3, 0xCF, 0xD8, 0x77,
          0x69, 0x38, 0x38, 0xF4, 0x8E, 0xFB, 0x51, 0xFB, 0x10, 0x7C},
         {0x73, 0xB4, 0xEE, 0xF9, 0x76, 0xBB, 0x45, 0xEC, 0x07, 0x24, 0x23,
          0xA3, 0x38, 0x64, 0x39, 0x4C, 0x03, 0x94, 0xF5, 0xEE, 0x5F, 0xC9,
          0x83, 0x4F, 0xD1, 0xA6, 0x4A, 0x05, 0x25, 0x0C, 0x46, 0x33}}},
       {{{0xD4, 0x40, 0x47, 0xAE, 0xEC, 0xDA, 0x30, 0xF9, 0xE1, 0x28, 0xFB,
          0xB1, 0x4C, 0x62, 0xFB, 0x6C, 0x90, 0x0D, 0xB1, 0xEC, 0xAF, 0x2D,
          0x95, 0x64, 0x11, 0x93, 0xDA, 0x8E, 0xB8, 0x7D, 0xE4, 0xA3},
         {0x8E, 0xA6, 0x9B, 0xAA, 0x58, 0xD5, 0xDC, 0x59, 0x1A, 0x51, 0x53,
          0x47, 0x30, 0x1C, 0x2B, 0xB0, 0xBB, 0x57, 0x57, 0x0A, 0x8C, 0x5F,
          0x62, 0x9C, 0x52, 0x28, 0xC0, 0x25, 0x27, 0xAE, 0xCD, 0x36}}},
       {{{0xBF, 0x2D, 0x03, 0xB1, 0x33, 0xFD, 0x24, 0x81, 0x3C, 0x91, 0x43,
          0x90, 0x0C, 0x20, 0xC4, 0xE3, 0x69, 0x3F, 0xA9, 0xA2, 0x7C, 0xC2,
          0x48, 0x28, 0x1B, 0xF0, 0x81, 0x1F, 0x2B, 0x8F, 0x8D, 0x43},
         {0x38, 0x18, 0x12, 0xA3, 0x89, 0xF1, 0xD7, 0x60, 0x89, 0x68, 0x6A,
          0xC4, 0xCC, 0x5D, 0xF4, 0xCE, 0x43, 0x95, 0x84, 0xCD, 0x01, 0x55,
          0xB8, 0x5D, 0x24, 0x50, 0xCD, 0xE3, 0x68, 0x1C, 0xFF, 0x59}}}}},
     {{{{{0x0D, 0xAC, 0xCB, 0xE7, 0x9D, 0x68, 0x0F, 0x4A, 0xAF, 0xEB, 0xB5,
          0xFB, 0xF9, 0xB1, 0x58, 0x80, 0xD5, 0x71, 0x53, 0x26, 0x2E, 0x9C,
          0xCE, 0x10, 0xAC, 0xD2, 0x0A, 0xEB, 0xB4, 0x5C, 0xC8, 0xD7},
         {0x16, 0x26, 0x66, 0x71, 0xDD, 0x67, 0xBA, 0xDB, 0x35, 0x76, 0x64,
          0xC6, 0x0B, 0x0B, 0x07, 0x4B, 0x65, 0xA2, 0xF7, 0x68, 0x9E, 0xFE,
          0xE8, 0xE3, 0xA7, 0x09, 0x79, 0xC5, 0xDF, 0x5E, 0x9C, 0xEC}}},
       {{{0xEE, 0x83, 0x59, 0xB5, 0x89, 0x81, 0xA2, 0x87, 0xD7, 0x75, 0x65,
          0x90, 0xDE, 0x78, 0x37, 0x59, 0x04, 0x9B, 0x50, 0xC3, 0xBA, 0x90,
          0x09, 0x15, 0xAB, 0x17, 0xC5, 0xBF, 0x5B, 0xB9, 0xE4, 0x6C},
         {0xA9, 0xB1, 0x49, 0x76, 0x25, 0x74, 0x5D, 0x9C, 0x78, 0xC5, 0x09,
          0xEE, 0xEB, 0xEB, 0x9D, 0x1C, 0x6C, 0xC0, 0x27, 0x9D, 0x66, 0xE6,
          0x7F, 0x31, 0xCD, 0xB0, 0x8A, 0xE4, 0x9E, 0xBD, 0x70, 0x18}}},
       {{{0x88, 0xA1, 0x08, 0x39, 0xA2, 0x48, 0xA5, 0x98, 0xB6, 0xAD, 0x10,
          0x54, 0x07, 0xCD, 0xFC, 0x6D, 0xB1, 0x02, 0xFF, 0xE3, 0x92, 0xD7,
          0x9D, 0x48, 0xFB, 0xCE, 0x88, 0x46, 0x92, 0x07, 0x02, 0xBA},
         {0xEE, 0xEB, 0xAE, 0x88, 0xB1, 0x4E, 0xD0, 0xF2, 0xCE, 0xD7, 0x57,
          0x07, 0xD4, 0x39, 0xD2, 0x7D, 0x1A, 0x0C, 0xEF, 0xF2, 0x84, 0x84,
          0x22, 0x8A, 0xB1, 0x80, 0x0D, 0xDC, 0x64, 0x86, 0xFD, 0x70}}}}}}};
const FqElemStr FfElementTest::fq_multi_exp_base_5[5] = {
    {0x7B, 0x26, 0x96, 0x84, 0x04, 0x0D, 0x6F, 0x10, 0xAA, 0x7F, 0xD0, 0x0C,
     0x41, 0x3A, 0x68, 0x48, 0xBF, 0x3D, 0xB5, 0xCE, 0x3A, 0x9C, 0xA9, 0x10,
     0xA4, 0x67, 0x7C, 0xC0, 0x41, 0x52, 0xCA, 0xE7},
    {0x2E, 0xD9, 0xEF, 0x86, 0xB6, 0x32, 0x72, 0x89, 0x37, 0xCF, 0x16, 0xCE,
     0x27, 0x15, 0x7A, 0x95, 0xCF, 0x94, 0x1B, 0xF3, 0xCE, 0x49, 0x20, 0x29,
     0x9A, 0x61, 0x2E, 0x0A, 0xF5, 0xE1, 0xDC, 0x9F},
    {0xE0, 0x19, 0x37, 0x44, 0xA7, 0x45, 0x49, 0x7E, 0x19, 0x02, 0x09, 0x78,
     0xBE, 0xA4, 0x65, 0x60, 0x7A, 0xF5, 0xC8, 0xAF, 0x97, 0x5E, 0xDA, 0x3A,
     0xB4, 0x16, 0x70, 0x31, 0xE3, 0xB4, 0x18, 0xA8},
    {0xBC, 0x92, 0x29, 0x92, 0x14, 0xD3, 0x3F, 0xB8, 0xB8, 0x8C, 0x41, 0xDF,
     0xC5, 0xA1, 0xCA, 0x77, 0xE5, 0x73, 0xFE, 0xA7, 0xAC, 0x81, 0x66, 0x11,
     0x5A, 0x6D, 0x7D, 0x97, 0x13, 0x92, 0x8D, 0x1D},
    {0xE1, 0xA0, 0x0D, 0xDC, 0x8F, 0x20, 0xF5, 0x2D, 0x1D, 0x1F, 0xBD, 0x24,
     0x8C, 0xC2, 0x26, 0x06, 0x89, 0xE9, 0x46, 0xA9, 0xD2, 0x44, 0x8F, 0x1A,
     0x8D, 0xAF, 0x20, 0x73, 0x60, 0x0B, 0x66, 0x9C}};

const BigNumStr FfElementTest::fq_multi_exp_exp_5[5] = {
    {0x78, 0xE6, 0x3F, 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD7, 0x6E,
     0xE9, 0xFF, 0x4F, 0xFF, 0x23, 0xFF, 0x67, 0xB4, 0xED, 0xEE, 0xD7, 0xC6,
     0xFF, 0x4B, 0x0B, 0x6F, 0x1F, 0xD6, 0xFD, 0x7F},
    {0xA1, 0x87, 0xFF, 0x1B, 0xFF, 0x85, 0x68, 0xFF, 0x1C, 0xFF, 0xD5, 0xFF,
     0x95, 0x73, 0xFF, 0xFF, 0xFF, 0x9E, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0x5E,
     0x9E, 0x62, 0xFF, 0xFF, 0x97, 0xFF, 0xFF, 0xF3},
    {0x2E, 0xE8, 0x1E, 0x35, 0xFF, 0x82, 0x0B, 0x99, 0xEC, 0x30, 0x2B, 0xCE,
     0xEC, 0x83, 0x05, 0xFF, 0x9E, 0x3C, 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF,
     0x57, 0x26, 0x5B, 0x6C, 0xFF, 0xE6, 0x94, 0xFF},
    {0xFF, 0xFF, 0xFF, 0xFF, 0x94, 0xFF, 0xFF, 0x79, 0xFC, 0xFF, 0x83, 0xFF,
     0xFF, 0xFF, 0xFF, 0xFF, 0xA9, 0xFF, 0x2F, 0x6B, 0xD1, 0xE7, 0xFF, 0xFF,
     0xFF, 0x7C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
    {0x63, 0x53, 0x53, 0xFF, 0xFF, 0xFF, 0x4F, 0xFF, 0xFF, 0xFF, 0x09, 0xFF,
     0xC0, 0xD8, 0x17, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x45,
     0xFF, 0x3A, 0xFF, 0xFF, 0xFF, 0xFF, 0x60, 0x06}};

const FqElemStr FfElementTest::fq_multi_exp_res_5 = {
    0x8F, 0x6D, 0x54, 0xCA, 0x00, 0x85, 0xD8, 0x78, 0xA4, 0x45, 0x36,
    0x7C, 0x23, 0xD0, 0x3C, 0x2D, 0x20, 0x78, 0xD9, 0xD7, 0xF1, 0xC3,
    0x99, 0xD9, 0xD3, 0x0A, 0x0E, 0x86, 0x98, 0xC2, 0xA7, 0x97,
};
const FqElemStr FfElementTest::fq_multi_exp_base_6[6] = {
    {0x75, 0x18, 0x6A, 0x3D, 0xCC, 0x76, 0x33, 0x92, 0xD0, 0x57, 0xDA, 0xE0,
     0x37, 0x6F, 0x71, 0xD5, 0x9E, 0x7E, 0x65, 0xED, 0xD7, 0xFD, 0x82, 0xC0,
     0x6C, 0x83, 0x60, 0x30, 0xC1, 0xD3, 0x3D, 0x4D},
    {0xF5, 0x3A, 0x20, 0xAB, 0x22, 0x47, 0x07, 0xAE, 0x71, 0xC1, 0x91, 0x73,
     0xEF, 0x1F, 0x1D, 0x76, 0x2E, 0xEE, 0x0D, 0xDE, 0xD9, 0xF8, 0x5C, 0x85,
     0xC7, 0x5B, 0x93, 0x88, 0xF6, 0xFF, 0x4C, 0xA5},
    {0x21, 0xB3, 0x5E, 0xE8, 0xD2, 0xDA, 0x14, 0x1C, 0xB5, 0x2C, 0xFC, 0x61,
     0x9D, 0xEB, 0x65, 0x87, 0xBB, 0x5B, 0xBC, 0xFD, 0x37, 0x54, 0x6B, 0xDC,
     0xD9, 0xFA, 0x7A, 0xCD, 0x18, 0x7E, 0x8B, 0x89},
    {0x70, 0xB7, 0x19, 0x42, 0xB4, 0x41, 0x2C, 0x1B, 0xBD, 0x7B, 0x25, 0x06,
     0xA2, 0x95, 0xB5, 0xB6, 0x70, 0xDF, 0x58, 0x71, 0xCA, 0x09, 0x12, 0x66,
     0x5A, 0x7B, 0xF0, 0x5F, 0x43, 0x69, 0x32, 0xF6},
    {0x3D, 0x57, 0xE8, 0x3F, 0x1E, 0x39, 0x2B, 0xE5, 0xD0, 0xCF, 0xA9, 0xC8,
     0x72, 0x10, 0x7F, 0xC5, 0x4F, 0xAE, 0xE9, 0x73, 0x28, 0x4C, 0xFC, 0x3F,
     0xD5, 0xFF, 0xE8, 0xCF, 0x2C, 0xEB, 0x33, 0xD3},
    {0x51, 0x80, 0x15, 0x1C, 0xE6, 0x9C, 0x4B, 0x80, 0x40, 0xBA, 0x40, 0x29,
     0x3A, 0x86, 0xA8, 0xB2, 0x66, 0x08, 0x97, 0x8D, 0xEB, 0x8B, 0xA7, 0x93,
     0xE3, 0x49, 0xC6, 0xC0, 0x46, 0x93, 0xC1, 0x75}};
const BigNumStr FfElementTest::fq_multi_exp_exp_6[6] = {
    {0xFF, 0xFF, 0xFF, 0x49, 0x50, 0xFF, 0x19, 0xFF, 0xEB, 0xFF, 0xFF, 0xFF,
     0xFF, 0x28, 0x4A, 0x0E, 0xFF, 0x74, 0xFF, 0xC7, 0xFF, 0xD9, 0x81, 0xFF,
     0xFF, 0xFF, 0xD5, 0x2C, 0xFF, 0xFF, 0xFF, 0xAE},
    {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
     0xFF, 0x0C, 0x03, 0xFF, 0x95, 0xFF, 0x11, 0x9D, 0xFF, 0x9B, 0xFF, 0xFF,
     0x68, 0x44, 0xFF, 0xC9, 0xFF, 0x10, 0xC7, 0xBF},
    {0x64, 0xFF, 0x89, 0x4A, 0xFF, 0x20, 0xFF, 0xE7, 0xFF, 0x36, 0x23, 0xDD,
     0xFF, 0xFF, 0xFC, 0xFF, 0x6B, 0xFF, 0xFF, 0xFF, 0xFF, 0x48, 0xFF, 0xFF,
     0xFF, 0xFF, 0xFF, 0xFF, 0x94, 0xD3, 0x59, 0xBE},
    {0x0F, 0xFF, 0x76, 0xA5, 0x9E, 0x02, 0x9B, 0xFF, 0xA1, 0xFF, 0xC2, 0xFF,
     0x9D, 0xFF, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0x6B, 0x81, 0x2A, 0xFF, 0x98,
     0xFF, 0xFF, 0xB9, 0xFF, 0xB7, 0x78, 0xE6, 0xFF},
    {0xAF, 0xF3, 0xFF, 0x3C, 0xA8, 0xFF, 0xB9, 0x3A, 0xFF, 0xFF, 0xFF, 0x70,
     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x85, 0xFF, 0xFF, 0x52,
     0xFF, 0x41, 0x10, 0x62, 0xFF, 0x51, 0x35, 0xFF},
    {0xFF, 0xFF, 0xFF, 0xFF, 0xD3, 0xC3, 0xD9, 0xFF, 0xFF, 0x3A, 0x44, 0x88,
     0x04, 0xFF, 0x0B, 0xFF, 0xFF, 0xFF, 0x64, 0xFF, 0xFF, 0x52, 0xFF, 0x7D,
     0x6B, 0x24, 0x6E, 0xFF, 0xFF, 0xFF, 0xA7, 0x71}};
const FqElemStr FfElementTest::fq_multi_exp_res_6 = {
    0xFB, 0x89, 0x4F, 0xBB, 0x91, 0xEE, 0xD6, 0x57, 0x2D, 0x34, 0xF9,
    0x0B, 0xE3, 0xEB, 0x71, 0x1D, 0x63, 0x74, 0x96, 0x3B, 0xD4, 0x02,
    0x2F, 0x08, 0xDB, 0x95, 0x6A, 0x40, 0x68, 0xD4, 0x55, 0x76,
};

const Fq6ElemStr FfElementTest::epid11_GT_multi_exp_base_3[3] = {
    {0x02, 0x7C, 0xAC, 0xE1, 0x58, 0x08, 0x6A, 0x83, 0x50, 0xD8, 0xBA, 0xBA,
     0x4B, 0x60, 0x6C, 0xEB, 0x51, 0xCE, 0x7E, 0x6D, 0x8E, 0xA8, 0x56, 0x41,
     0x33, 0xF3, 0xB0, 0xA6, 0xFC, 0xCD, 0xC8, 0x41, 0x05, 0x9E, 0xCC, 0x4F,
     0x51, 0x77, 0xD9, 0xEC, 0x57, 0x34, 0x48, 0x47, 0x22, 0x7A, 0x7C, 0xA1,
     0x14, 0xB8, 0x2A, 0xC9, 0x16, 0x0A, 0xB4, 0xB3, 0x5D, 0x44, 0x28, 0x23,
     0x80, 0x7A, 0x3E, 0xDA, 0x02, 0x6D, 0x03, 0x47, 0xCD, 0x2A, 0xAB, 0xA4,
     0xCE, 0x63, 0x0B, 0x5E, 0x3A, 0xF2, 0x96, 0x86, 0xA9, 0x9F, 0x2A, 0x9A,
     0xFF, 0x8F, 0x94, 0x91, 0xC8, 0x3C, 0xF2, 0x5A, 0xAA, 0xDA, 0x6B, 0x8E,
     0x02, 0xFC, 0x42, 0x4B, 0xFE, 0xF3, 0x23, 0x0A, 0xF8, 0x1A, 0x5C, 0x9A,
     0x5C, 0x0D, 0x71, 0xEF, 0x85, 0x64, 0xA6, 0x4D, 0x6A, 0x8B, 0x82, 0x58,
     0x2E, 0xBC, 0xFB, 0xB9, 0xDF, 0xB8, 0xCE, 0x3D, 0x03, 0xF3, 0x07, 0x18,
     0x4A, 0x13, 0x82, 0x8A, 0xEA, 0x24, 0x57, 0x72, 0xE2, 0x33, 0x9D, 0xB3,
     0x0C, 0x57, 0xCF, 0xAB, 0xDD, 0xEE, 0xF8, 0xD7, 0x2A, 0x75, 0xF5, 0xD7,
     0x28, 0xED, 0x0F, 0xB7, 0x02, 0xEC, 0x5F, 0xED, 0x50, 0xAE, 0x6B, 0xF3,
     0x80, 0x29, 0x7B, 0xA2, 0x75, 0x61, 0xFD, 0x20, 0x01, 0x2B, 0xDF, 0x8B,
     0x3C, 0x2A, 0xB9, 0x1D, 0x92, 0xED, 0x0F, 0xAD, 0x73, 0x74, 0x1E, 0xD8},
    {0x06, 0xA6, 0x4A, 0x6B, 0x89, 0xD0, 0x07, 0x2A, 0xE6, 0x0B, 0x56, 0xD3,
     0x48, 0x17, 0xF6, 0x99, 0x31, 0x41, 0x21, 0x99, 0x51, 0xF6, 0xB1, 0x6C,
     0x02, 0xCD, 0x11, 0xE7, 0xCC, 0xD3, 0xC5, 0x6C, 0x06, 0xF4, 0x39, 0x62,
     0x37, 0x88, 0x37, 0xAD, 0x1F, 0x36, 0x81, 0xFA, 0xD7, 0x4B, 0x9F, 0x57,
     0x0F, 0x5B, 0xC3, 0x53, 0x14, 0x53, 0x41, 0x3A, 0x2B, 0xAB, 0x6E, 0xF4,
     0xD8, 0x7F, 0xC5, 0x67, 0x08, 0x70, 0xD7, 0x9B, 0x59, 0xE1, 0xE0, 0x57,
     0xE2, 0xF4, 0x04, 0x82, 0x06, 0x6A, 0xD5, 0xA2, 0x76, 0x64, 0x41, 0x7F,
     0x3B, 0xE6, 0x33, 0xB9, 0x39, 0x68, 0xDA, 0x0D, 0x13, 0x03, 0x63, 0xC8,
     0x07, 0x94, 0x70, 0xF9, 0xFB, 0xD8, 0x99, 0x31, 0xA1, 0x53, 0x1C, 0x20,
     0x43, 0x12, 0xEB, 0xFF, 0xA4, 0x5D, 0x64, 0x7C, 0x24, 0x9E, 0xE0, 0x03,
     0x80, 0x8E, 0xFB, 0xDC, 0xEE, 0xFD, 0x1F, 0xEF, 0x03, 0x43, 0x07, 0x44,
     0xEF, 0xB3, 0x71, 0x39, 0x77, 0x61, 0x5C, 0xA9, 0x32, 0x54, 0x33, 0x98,
     0xA2, 0x14, 0x6A, 0x13, 0x53, 0x22, 0x94, 0xA2, 0xCE, 0x15, 0xE7, 0xD0,
     0x30, 0xF2, 0x6B, 0x07, 0x02, 0x56, 0x28, 0xC3, 0xB1, 0x39, 0xF9, 0xC7,
     0xDA, 0xE2, 0xFD, 0xD0, 0xA8, 0x1B, 0xE8, 0xB2, 0xE3, 0x75, 0x02, 0xB8,
     0x90, 0xA4, 0xA5, 0x8F, 0x23, 0xA1, 0xCD, 0x75, 0xE7, 0x51, 0x37, 0xE5},
    {0x09, 0x27, 0x38, 0x30, 0x06, 0x44, 0x13, 0xEF, 0xFE, 0x70, 0x5C, 0x4A,
     0x21, 0xFF, 0xF8, 0xF5, 0xBB, 0xC9, 0x6E, 0xA8, 0x7E, 0x00, 0xB1, 0xD7,
     0x5E, 0x55, 0xCF, 0xC7, 0x34, 0x6B, 0x8D, 0xD5, 0x04, 0xCE, 0x6E, 0xCA,
     0x11, 0x5A, 0xB3, 0x0C, 0x33, 0x79, 0x5F, 0xDE, 0xD9, 0xDB, 0x8C, 0xFA,
     0x73, 0x4E, 0x1E, 0xFA, 0xA1, 0x21, 0x6D, 0xA3, 0x6D, 0xE8, 0x69, 0x02,
     0x9E, 0xCC, 0x4D, 0x14, 0x09, 0xB5, 0x7C, 0xBA, 0x98, 0xC2, 0xE3, 0xAA,
     0x82, 0x6A, 0x0F, 0x1E, 0x4C, 0x6C, 0x9E, 0xB8, 0xB6, 0xA3, 0x5D, 0x06,
     0xFE, 0x99, 0x5C, 0x62, 0xA9, 0x19, 0x4E, 0x84, 0x61, 0xC7, 0xF9, 0x78,
     0x04, 0x39, 0xDA, 0xB4, 0x79, 0x32, 0x63, 0x60, 0xA6, 0x69, 0x86, 0x5C,
     0xFF, 0xB0, 0x71, 0xD0, 0xF5, 0x5E, 0x3C, 0xB2, 0x5D, 0x81, 0x4F, 0x9F,
     0xE4, 0xF7, 0x3B, 0xC7, 0xC5, 0x80, 0x5E, 0x8E, 0x01, 0x23, 0xFA, 0xFC,
     0x09, 0xAE, 0x12, 0x55, 0xF2, 0xD0, 0x50, 0x5C, 0xED, 0xC6, 0xD6, 0x81,
     0x9A, 0xA7, 0x93, 0xA3, 0xF4, 0xAC, 0xE5, 0x3E, 0xDB, 0x5A, 0x05, 0xB7,
     0x0B, 0x80, 0xAD, 0xA9, 0x08, 0xF1, 0x5A, 0xB5, 0x09, 0x23, 0x52, 0x65,
     0x46, 0x64, 0x79, 0xF2, 0x47, 0x04, 0x72, 0x48, 0x4E, 0x01, 0x55, 0x4A,
     0x67, 0x8D, 0x1E, 0x07, 0xC7, 0x46, 0x87, 0xF6, 0x50, 0xC3, 0xA6, 0x6B}};

const std::vector<uint8_t> FfElementTest::epid11_GT_multi_exp_exp_3[3] = {
    {0x00, 0x00, 0xAF, 0x5B, 0x22, 0x71, 0x98, 0xB6, 0xEB, 0x67, 0x3D, 0x94,
     0x4A, 0xB6, 0x5E, 0x99, 0x81, 0xC5, 0x96, 0x91, 0x55, 0xBA, 0x2F, 0x16,
     0x01, 0x4E, 0xE1, 0x25, 0xAD, 0xCA, 0x94, 0x88, 0x60, 0x3B, 0xA2, 0x56,
     0x0A, 0x94, 0x0B, 0x2C, 0x3E, 0xD0, 0x8F, 0x15, 0x07, 0x3D, 0xD5, 0xBE,
     0x72, 0x3E, 0x2D, 0x06, 0x74, 0xFF, 0x06, 0xED, 0x47, 0x28, 0x08, 0x0C,
     0xA0, 0x6F, 0xDB, 0x75, 0x55, 0x32, 0xDC, 0x97, 0x47, 0x60, 0x4E, 0x6F,
     0xB4, 0x29, 0x89, 0x0C},

    {0x00, 0x00, 0x01, 0xB8, 0x40, 0xBB, 0xE1, 0x1C, 0x84, 0x8E, 0x02, 0xC0,
     0xEF, 0x69, 0x84, 0x90, 0xED, 0xEB, 0x99, 0x94, 0xBC, 0x79, 0x48, 0xC8,
     0x08, 0x3C, 0x25, 0xDA, 0xAC, 0xFF, 0x3A, 0xDD},

    {0x00, 0x00, 0x37, 0x1E, 0xCD, 0x0F, 0x66, 0x09, 0x7D, 0x33, 0x9A, 0xDC,
     0x47, 0x28, 0xF7, 0x91, 0xF3, 0xC2, 0xBC, 0x3A, 0xA9, 0x05, 0x62, 0xFC,
     0xDD, 0x8C, 0x65, 0xC2, 0xA8, 0x14, 0x55, 0x52},
};

const Fq6ElemStr FfElementTest::epid11_GT_multi_exp_res_3 = {
    0x09, 0xCF, 0x1D, 0xB6, 0x97, 0x14, 0x58, 0xAA, 0x29, 0x7E, 0x03, 0x96,
    0xD2, 0xDC, 0xD4, 0x2C, 0x1F, 0x2F, 0xB0, 0xC1, 0x5E, 0x71, 0xFB, 0x0C,
    0x8D, 0xDB, 0xBD, 0x1D, 0x20, 0xD9, 0x9A, 0xA5, 0x02, 0x69, 0x62, 0x1C,
    0x5C, 0xE8, 0x12, 0x11, 0xB1, 0x49, 0x93, 0x29, 0x23, 0xAF, 0xB4, 0xFF,
    0x77, 0x1E, 0xC9, 0xA6, 0xA0, 0x6D, 0xD9, 0x38, 0x89, 0x1A, 0xC7, 0xB9,
    0xF9, 0x66, 0x25, 0xD3, 0x00, 0x59, 0xE1, 0xAC, 0x0D, 0xDE, 0xCF, 0xC0,
    0xCF, 0x50, 0x48, 0x6B, 0xCE, 0x32, 0x15, 0x79, 0x13, 0x71, 0x12, 0x9B,
    0x63, 0x09, 0x4D, 0x20, 0xD9, 0x4A, 0xCD, 0x4F, 0x00, 0x7F, 0x8A, 0x19,
    0x06, 0x3F, 0x0F, 0x3E, 0x83, 0xA3, 0xEE, 0x0F, 0xAB, 0x72, 0xC9, 0x9A,
    0x5D, 0xD1, 0x67, 0xBF, 0xF1, 0x0E, 0xAB, 0x9C, 0xE8, 0x50, 0x04, 0xA7,
    0x20, 0xAA, 0xF6, 0xB9, 0x8E, 0x2F, 0x69, 0x44, 0x02, 0x68, 0x7A, 0x2E,
    0x70, 0xD4, 0x7E, 0x83, 0x8F, 0xAB, 0x58, 0x3E, 0xD2, 0x95, 0xA0, 0x1A,
    0x61, 0xC8, 0x93, 0xA0, 0xCC, 0xA4, 0x90, 0xFB, 0x73, 0xC2, 0xD2, 0x91,
    0x70, 0x34, 0x6A, 0x67, 0x03, 0x67, 0x49, 0x84, 0xEE, 0x3B, 0x9E, 0x8B,
    0x6D, 0x47, 0x95, 0xBD, 0x0E, 0x47, 0x97, 0x9E, 0x0A, 0x87, 0x61, 0x83,
    0x80, 0xEF, 0x4F, 0x91, 0xA8, 0xA6, 0xB7, 0xC0, 0x44, 0xE2, 0x21, 0x8D};

////////////////////////////////////////////////
// NewFfElement

TEST_F(FfElementTest, NewFailsGivenNullPointer) {
  FfElement* ff_elem = nullptr;
  EXPECT_EQ(kEpidBadArgErr, NewFfElement(nullptr, &ff_elem));
  EXPECT_EQ(kEpidBadArgErr, NewFfElement(this->fq, nullptr));
  DeleteFfElement(&ff_elem);
}

TEST_F(FfElementTest, NewSucceedsGiven256BitFiniteField) {
  FfElement* ff_elem = nullptr;
  EXPECT_EQ(kEpidNoErr, NewFfElement(this->fq, &ff_elem));
  DeleteFfElement(&ff_elem);
}

TEST_F(FfElementTest, Default256BitElementIsZero) {
  FfElement* ff_elem = nullptr;
  THROW_ON_EPIDERR(NewFfElement(this->fq, &ff_elem));
  FqElemStr ff_elem_str;
  EpidStatus sts =
      WriteFfElement(this->fq, ff_elem, &ff_elem_str, sizeof(ff_elem_str));
  DeleteFfElement(&ff_elem);
  THROW_ON_EPIDERR(sts);

  FqElemStr fq_zero_str = {0};
  EXPECT_EQ(fq_zero_str, ff_elem_str);
}

////////////////////////////////////////////////
// DeleteFfElement

TEST_F(FfElementTest, DeleteNullsPointer) {
  FfElement* ff_elem = nullptr;
  EpidStatus sts = NewFfElement(this->fq, &ff_elem);
  DeleteFfElement(&ff_elem);
  THROW_ON_EPIDERR(sts);
  EXPECT_EQ(nullptr, ff_elem);
}

TEST_F(FfElementTest, DeleteWorksGivenNullPointer) {
  EXPECT_NO_THROW(DeleteFfElement(nullptr));
  FfElement* ff_elem = nullptr;
  EXPECT_NO_THROW(DeleteFfElement(&ff_elem));
}

////////////////////////////////////////////////
// ReadFfElement

TEST_F(FfElementTest, ReadFailsGivenArgumentsMismatch) {
  uint8_t buf[sizeof(Fq12ElemStr)] = {0};
  EXPECT_EQ(kEpidBadArgErr,
            ReadFfElement(this->fq12, buf, sizeof(Fq12ElemStr), this->fq_a));
  EXPECT_EQ(kEpidBadArgErr,
            ReadFfElement(this->fq, buf, sizeof(FqElemStr), this->fq12_result));
}

TEST_F(FfElementTest, ReadFailsGivenNullPointer) {
  FqElemStr ff_elem_str;
  EXPECT_EQ(kEpidBadArgErr, ReadFfElement(nullptr, &ff_elem_str,
                                          sizeof(ff_elem_str), this->fq_a));
  EXPECT_EQ(kEpidBadArgErr,
            ReadFfElement(this->fq, nullptr, sizeof(ff_elem_str), this->fq_a));
  EXPECT_EQ(kEpidBadArgErr, ReadFfElement(this->fq, &ff_elem_str,
                                          sizeof(ff_elem_str), nullptr));
}

TEST_F(FfElementTest, ReadFailsGivenInvalidBufferSize) {
  FqElemStr ff_elem_str;
  EXPECT_EQ(kEpidBadArgErr,
            ReadFfElement(this->fq, &ff_elem_str, 0, this->fq_a));
  EXPECT_EQ(kEpidBadArgErr,
            ReadFfElement(this->fq, &ff_elem_str,
                          std::numeric_limits<size_t>::max(), this->fq_a));
}

TEST_F(FfElementTest, ReadFailsGivenElementDoesNotBelongToFF) {
  // q does not belong to Fq
  EXPECT_EQ(kEpidBadArgErr, ReadFfElement(this->fq, &this->bn_q_str,
                                          sizeof(this->bn_q_str), this->fq_a));
}

TEST_F(FfElementTest, Read256BitElementCorrectly) {
  // q-1 is valid element of Fq
  ASSERT_EQ(kEpidNoErr, ReadFfElement(this->fq, &this->fq_qm1_str,
                                      sizeof(this->fq_qm1_str), this->fq_a));

  FqElemStr buf;
  EXPECT_EQ(kEpidNoErr,
            WriteFfElement(this->fq, this->fq_a, &buf, sizeof(buf)));
  EXPECT_EQ(this->fq_qm1_str, buf);
}

TEST_F(FfElementTest, ReadIgnoreLeadingZerosForPrimeField) {
  // q-1 is valid element of Fq
  std::vector<uint8_t> ff_elem_str = {
      0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xCD, 0x46, 0xE5,
      0xF2, 0x5E, 0xEE, 0x71, 0xA4, 0x9F, 0x0C, 0xDC, 0x65, 0xFB, 0x12,
      0x98, 0x0A, 0x82, 0xD3, 0x29, 0x2D, 0xDB, 0xAE, 0xD3, 0x30, 0x12};
  ASSERT_EQ(kEpidNoErr, ReadFfElement(this->fq, ff_elem_str.data(),
                                      ff_elem_str.size(), this->fq_a));

  FqElemStr buf;
  EXPECT_EQ(kEpidNoErr,
            WriteFfElement(this->fq, this->fq_a, &buf, sizeof(buf)));
  EXPECT_EQ(this->fq_qm1_str, buf);
}

TEST_F(FfElementTest, ReadExpectExactSizeForFieldExtensions) {
  uint8_t buf[sizeof(Fq2ElemStr) + 1] = {0};
  EXPECT_EQ(kEpidBadArgErr,
            ReadFfElement(this->fq2, buf, sizeof(buf), this->fq2_a));
}

///////////////////////////////////////////////////////////////////////
// InitFfElementFromBn

TEST_F(FfElementTest, InitFromBnFailsGivenNonPrimeField) {
  BigNumStr str = {0x01};
  FfElementObj ffe(&this->fq2);
  BigNumObj bn(sizeof(str), str);
  EXPECT_EQ(kEpidBadArgErr, InitFfElementFromBn(this->fq2, bn, ffe));
}

TEST_F(FfElementTest, InitFromBnFailsGivenNullPointer) {
  BigNumStr str = {0x01};
  FfElementObj ffe(&this->fq);
  BigNumObj bn(sizeof(str), str);
  EXPECT_EQ(kEpidBadArgErr, InitFfElementFromBn(nullptr, bn, ffe));
  EXPECT_EQ(kEpidBadArgErr, InitFfElementFromBn(this->fq, nullptr, ffe));
  EXPECT_EQ(kEpidBadArgErr, InitFfElementFromBn(this->fq, bn, nullptr));
}

TEST_F(FfElementTest, InitFromBnInFieldElementCorrectly) {
  FfElementObj ffe(&this->fq);
  BigNumObj qm1_bn(this->bn_qm1_str);
  FqElemStr buf;

  EXPECT_EQ(kEpidNoErr, InitFfElementFromBn(this->fq, qm1_bn, ffe));
  EXPECT_EQ(kEpidNoErr, WriteFfElement(this->fq, ffe, &buf, sizeof(buf)));
  EXPECT_EQ(this->fq_qm1_str, buf);
}

TEST_F(FfElementTest, InitFromBnOutOfFieldElementCorrectly) {
  FfElementObj ffe(&this->fq);
  BigNumObj q_bn(this->bn_q_str);
  BigNumObj qp1_bn(this->bn_qp1_str);
  FqElemStr buf;

  EXPECT_EQ(kEpidNoErr, InitFfElementFromBn(this->fq, q_bn, ffe));
  EXPECT_EQ(kEpidNoErr, WriteFfElement(this->fq, ffe, &buf, sizeof(buf)));
  EXPECT_EQ(this->bn_0_str, buf);

  EXPECT_EQ(kEpidNoErr, InitFfElementFromBn(this->fq, qp1_bn, ffe));
  EXPECT_EQ(kEpidNoErr, WriteFfElement(this->fq, ffe, &buf, sizeof(buf)));
  EXPECT_EQ(this->bn_1_str, buf);
}

///////////////////////////////////////////////////////////////////////
// FfIsEqual

TEST_F(FfElementTest, FfIsEqualFailsGivenArgumentsMismatch) {
  bool result;
  EXPECT_EQ(kEpidBadArgErr,
            FfIsEqual(this->fq12, this->fq_a, this->fq_b, &result));
  EXPECT_EQ(kEpidBadArgErr,
            FfIsEqual(this->fq, this->fq12_g, this->fq_b, &result));
  EXPECT_EQ(kEpidBadArgErr,
            FfIsEqual(this->fq, this->fq_a, this->fq12_h, &result));
}

TEST_F(FfElementTest, FfIsEqualFailsGivenNullPointer) {
  bool result;
  EXPECT_EQ(kEpidBadArgErr,
            FfIsEqual(nullptr, this->fq_a, this->fq_a, &result));
  EXPECT_EQ(kEpidBadArgErr, FfIsEqual(this->fq, nullptr, this->fq_a, &result));
  EXPECT_EQ(kEpidBadArgErr, FfIsEqual(this->fq, this->fq_a, nullptr, &result));
  EXPECT_EQ(kEpidBadArgErr,
            FfIsEqual(this->fq, this->fq_a, this->fq_a, nullptr));
}

TEST_F(FfElementTest, FfIsEqualCanCompareElementWithItself) {
  bool result;
  EXPECT_EQ(kEpidNoErr, FfIsEqual(this->fq, this->fq_a, this->fq_a, &result));
  EXPECT_TRUE(result);
}

TEST_F(FfElementTest, Different256BitFiniteFieldElementsAreNotEqual) {
  bool result;
  EXPECT_EQ(kEpidNoErr, FfIsEqual(this->fq, this->fq_a, this->fq_b, &result));
  EXPECT_FALSE(result);
}

TEST_F(FfElementTest, Same256BitFiniteFieldElementsAreEqual) {
  FfElementObj fq_a_local(&this->fq, &this->fq_a_str, sizeof(this->fq_a_str));
  bool result;
  EXPECT_EQ(kEpidNoErr, FfIsEqual(this->fq, this->fq_a, fq_a_local, &result));
  EXPECT_TRUE(result);
}

TEST_F(FfElementTest, DifferentFq12ElementsAreNotEqual) {
  bool result;
  EXPECT_EQ(kEpidNoErr,
            FfIsEqual(this->fq12, this->fq12_g, this->fq12_h, &result));
  EXPECT_FALSE(result);
}

TEST_F(FfElementTest, SameFq12ElementsAreEqual) {
  FfElementObj fq12_g_local(&this->fq12, &this->fq12_g_str,
                            sizeof(this->fq12_g_str));
  bool result;
  EXPECT_EQ(kEpidNoErr,
            FfIsEqual(this->fq12, this->fq12_g, fq12_g_local, &result));
  EXPECT_TRUE(result);
}

////////////////////////////////////////////////
// WriteFfElement

TEST_F(FfElementTest, WriteFailsGivenArgumentsMismatch) {
  uint8_t buf[sizeof(Fq12ElemStr)] = {0};
  EXPECT_EQ(kEpidBadArgErr,
            WriteFfElement(this->fq12, this->fq_a, buf, sizeof(Fq12ElemStr)));
  EXPECT_EQ(kEpidBadArgErr,
            WriteFfElement(this->fq, this->fq12_g, buf, sizeof(Fq12ElemStr)));
}

TEST_F(FfElementTest, WriteFailsGivenNullPointer) {
  FqElemStr ff_elem_str;
  EXPECT_EQ(kEpidBadArgErr, WriteFfElement(nullptr, this->fq_a, &ff_elem_str,
                                           sizeof(ff_elem_str)));
  EXPECT_EQ(kEpidBadArgErr, WriteFfElement(this->fq, nullptr, &ff_elem_str,
                                           sizeof(ff_elem_str)));
  EXPECT_EQ(kEpidBadArgErr,
            WriteFfElement(this->fq, this->fq_a, nullptr, sizeof(ff_elem_str)));
}

TEST_F(FfElementTest, WriteFailsGivenInvalidBufferSize) {
  FqElemStr ff_elem_str;
  EXPECT_EQ(kEpidBadArgErr,
            WriteFfElement(this->fq, this->fq_a, &ff_elem_str, 0));
  EXPECT_EQ(kEpidBadArgErr, WriteFfElement(this->fq, this->fq_a, &ff_elem_str,
                                           sizeof(ff_elem_str) - 1));
  EXPECT_EQ(kEpidBadArgErr, WriteFfElement(this->fq, this->fq_a, &ff_elem_str,
                                           std::numeric_limits<size_t>::max()));
}

TEST_F(FfElementTest, WriteWorksGiven256BitElement) {
  FqElemStr ff_elem_str;
  EXPECT_EQ(kEpidNoErr, WriteFfElement(this->fq, this->fq_a, &ff_elem_str,
                                       sizeof(ff_elem_str)));
  EXPECT_EQ(this->fq_a_str, ff_elem_str);
}

TEST_F(FfElementTest, WritePadPrimeFieldElement) {
  FqElemStr ff_elem_str[2] = {0xcd};
  EXPECT_EQ(kEpidNoErr, WriteFfElement(this->fq, this->fq_a, &ff_elem_str[0],
                                       sizeof(ff_elem_str)));
  EXPECT_EQ(this->fq_0_str, ff_elem_str[0]);
  EXPECT_EQ(this->fq_a_str, ff_elem_str[1]);
}

TEST_F(FfElementTest, WriteExpectExactSizeForFieldExtensions) {
  uint8_t buf[sizeof(Fq12ElemStr) + 1] = {0};
  EXPECT_EQ(kEpidBadArgErr, WriteFfElement(this->fq12, this->fq12_g, buf,
                                           sizeof(Fq12ElemStr) + 1));
  EXPECT_EQ(kEpidBadArgErr, WriteFfElement(this->fq12, this->fq12_g, buf,
                                           sizeof(Fq12ElemStr) - 1));
  EXPECT_EQ(kEpidBadArgErr,
            WriteFfElement(this->fq12, this->fq12_g, buf, sizeof(FqElemStr)));
}

///////////////////////////////////////////////////////////////////////
// FfNeg

TEST_F(FfElementTest, FfNegFailsGivenArgumentsMismatch) {
  EXPECT_EQ(kEpidBadArgErr, FfNeg(this->fq12, this->fq_a, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr, FfNeg(this->fq, this->fq12_g, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr, FfNeg(this->fq, this->fq_a, this->fq12_result));
}

TEST_F(FfElementTest, FfNegFailsGivenNullPointer) {
  EXPECT_EQ(kEpidBadArgErr, FfNeg(nullptr, this->fq_a, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr, FfNeg(this->fq, nullptr, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr, FfNeg(this->fq, this->fq_a, nullptr));
}

TEST_F(FfElementTest, FfNegSucceedsGivenElementZero) {
  FqElemStr fq_r_str;
  EXPECT_EQ(kEpidNoErr, FfNeg(this->fq, this->fq_0, this->fq_result));
  THROW_ON_EPIDERR(
      WriteFfElement(this->fq, this->fq_result, &fq_r_str, sizeof(fq_r_str)));
  EXPECT_EQ(this->fq_0_str, fq_r_str)
      << "FfNeg: Negate element does not match to reference neg zero value";
}

TEST_F(FfElementTest, FfNegSucceedsGivenNonZeroElement) {
  FqElemStr fq_r_str;
  EXPECT_EQ(kEpidNoErr, FfNeg(this->fq, this->fq_a, this->fq_result));
  THROW_ON_EPIDERR(
      WriteFfElement(this->fq, this->fq_result, &fq_r_str, sizeof(fq_r_str)));
  EXPECT_EQ(this->fq_neg_a_str, fq_r_str)
      << "FfNeg: Negate element does not match to reference neg value";
}

////////////////////////////////////////////////
// FfIsZero

TEST_F(FfElementTest, FfIsZeroFailsGivenNullPointer) {
  bool result = false;
  EXPECT_EQ(kEpidBadArgErr, FfIsZero(nullptr, this->fq_0, &result));
  EXPECT_EQ(kEpidBadArgErr, FfIsZero(this->fq, nullptr, &result));
  EXPECT_EQ(kEpidBadArgErr, FfIsZero(this->fq, this->fq_0, nullptr));
}

TEST_F(FfElementTest, FfIsZeroFailsGivenArgumentsMismatch) {
  bool result;
  EXPECT_EQ(kEpidBadArgErr, FfIsZero(this->fq12, this->fq_a, &result));
  EXPECT_EQ(kEpidBadArgErr, FfIsZero(this->fq, this->fq12_g, &result));
}

TEST_F(FfElementTest, FfIsZeroSucceedsGivenZeroElement) {
  bool result = false;
  EXPECT_EQ(kEpidNoErr, FfIsZero(this->fq, this->fq_0, &result));
  EXPECT_TRUE(result);
}

TEST_F(FfElementTest, FfIsZeroSucceedsGivenNonZeroElement) {
  bool result = false;
  EXPECT_EQ(kEpidNoErr, FfIsZero(this->fq, this->fq_1, &result));
  EXPECT_FALSE(result);
}

////////////////////////////////////////////////
// FfMul

TEST_F(FfElementTest, FfMulFailsGivenNullPointer) {
  EXPECT_EQ(kEpidBadArgErr,
            FfMul(nullptr, this->fq_a, this->fq_b, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfMul(this->fq, nullptr, this->fq_b, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfMul(this->fq, this->fq_a, nullptr, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr, FfMul(this->fq, this->fq_a, this->fq_b, nullptr));
}

TEST_F(FfElementTest, FfMulFailsGivenArgumentsMismatch) {
  EXPECT_EQ(kEpidBadArgErr,
            FfMul(this->fq12, this->fq_a, this->fq_b, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfMul(this->fq, this->fq12_g, this->fq_b, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfMul(this->fq, this->fq_a, this->fq12_h, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfMul(this->fq, this->fq_a, this->fq_b, this->fq12_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfMul(this->fq2, this->fq_a, this->fq2_a, this->fq2_result));
}

TEST_F(FfElementTest, FfMulSucceedsGivenElementZero) {
  FqElemStr fq_r_str;

  EXPECT_EQ(kEpidNoErr,
            FfMul(this->fq, this->fq_0, this->fq_b, this->fq_result));
  THROW_ON_EPIDERR(
      WriteFfElement(this->fq, this->fq_result, &fq_r_str, sizeof(fq_r_str)));
  EXPECT_EQ(this->fq_0_str, fq_r_str);

  EXPECT_EQ(kEpidNoErr,
            FfMul(this->fq, this->fq_a, this->fq_0, this->fq_result));
  THROW_ON_EPIDERR(
      WriteFfElement(this->fq, this->fq_result, &fq_r_str, sizeof(fq_r_str)));
  EXPECT_EQ(this->fq_0_str, fq_r_str);
}

TEST_F(FfElementTest, FfMulSucceedsGivenElementOne) {
  FqElemStr fq_r_str;

  EXPECT_EQ(kEpidNoErr,
            FfMul(this->fq, this->fq_1, this->fq_b, this->fq_result));
  THROW_ON_EPIDERR(
      WriteFfElement(this->fq, this->fq_result, &fq_r_str, sizeof(fq_r_str)));
  EXPECT_EQ(this->fq_b_str, fq_r_str);

  EXPECT_EQ(kEpidNoErr,
            FfMul(this->fq, this->fq_a, this->fq_1, this->fq_result));
  THROW_ON_EPIDERR(
      WriteFfElement(this->fq, this->fq_result, &fq_r_str, sizeof(fq_r_str)));
  EXPECT_EQ(this->fq_a_str, fq_a_str);
}

TEST_F(FfElementTest, FfMulSucceedsGivenTwoElements) {
  FqElemStr fq_r_str;

  EXPECT_EQ(kEpidNoErr,
            FfMul(this->fq, this->fq_a, this->fq_b, this->fq_result));
  THROW_ON_EPIDERR(
      WriteFfElement(this->fq, this->fq_result, &fq_r_str, sizeof(fq_r_str)));
  EXPECT_EQ(this->fq_mul_ab_str, fq_r_str);

  Fq2ElemStr fq2_r_str;

  THROW_ON_EPIDERR(
      ReadFfElement(this->fq, &(fq_b_str), sizeof(fq_b_str), this->fq_b));
  EXPECT_EQ(kEpidNoErr,
            FfMul(this->fq2, this->fq2_a, this->fq_b, this->fq2_result));
  THROW_ON_EPIDERR(WriteFfElement(this->fq2, this->fq2_result, &fq2_r_str,
                                  sizeof(fq2_r_str)));
  EXPECT_EQ(this->fq2_mul_ab_str, fq2_r_str);

  Fq12ElemStr fq12_r_str;
  THROW_ON_EPIDERR(ReadFfElement(this->fq12, &(this->fq12_i_str),
                                 sizeof(this->fq12_i_str), this->fq12_i));
  THROW_ON_EPIDERR(ReadFfElement(this->fq12, &(fq12_j_str), sizeof(fq12_j_str),
                                 this->fq12_j));
  EXPECT_EQ(kEpidNoErr,
            FfMul(this->fq12, this->fq12_i, this->fq12_j, this->fq12_result));
  THROW_ON_EPIDERR(WriteFfElement(this->fq12, this->fq12_result, &fq12_r_str,
                                  sizeof(fq12_r_str)));
  EXPECT_EQ(fq12_mul_ij_str, fq12_r_str);
}

////////////////////////////////////////////////
// FfSub
TEST_F(FfElementTest, FfSubFailsGivenArgumentsMismatch) {
  EXPECT_EQ(kEpidBadArgErr,
            FfSub(this->fq12, this->fq_a, this->fq_b, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfSub(this->fq, this->fq12_g, this->fq_b, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfSub(this->fq, this->fq_a, this->fq12_h, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfSub(this->fq, this->fq_a, this->fq_b, this->fq12_result));
}

TEST_F(FfElementTest, FfSubFailsGivenNullPtr) {
  EXPECT_EQ(kEpidBadArgErr,
            FfSub(nullptr, this->fq_a, this->fq_b, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfSub(this->fq, nullptr, this->fq_b, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfSub(this->fq, this->fq_a, nullptr, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr, FfSub(this->fq, this->fq_a, this->fq_b, nullptr));
}

TEST_F(FfElementTest, FfSubSucceedsGivenElementZero) {
  FqElemStr fq_r_str = {0x0};

  // additive identity
  EXPECT_EQ(kEpidNoErr,
            FfSub(this->fq, this->fq_a, this->fq_0, this->fq_result));
  THROW_ON_EPIDERR(
      WriteFfElement(this->fq, this->fq_result, &fq_r_str, sizeof(fq_r_str)));
  EXPECT_EQ(this->fq_a_str, fq_r_str);

  EXPECT_EQ(kEpidNoErr,
            FfSub(this->fq, this->fq_0, this->fq_0, this->fq_result));
  THROW_ON_EPIDERR(
      WriteFfElement(this->fq, this->fq_result, &fq_r_str, sizeof(fq_r_str)));
  EXPECT_EQ(this->fq_0_str, fq_r_str);
}

TEST_F(FfElementTest, FfSubSucceedsGivenTwoEqualElements) {
  FqElemStr fq_r_str = {0x0};

  EXPECT_EQ(kEpidNoErr,
            FfSub(this->fq, this->fq_a, this->fq_a, this->fq_result));
  THROW_ON_EPIDERR(
      WriteFfElement(this->fq, this->fq_result, &fq_r_str, sizeof(fq_r_str)));
  EXPECT_EQ(this->fq_0_str, fq_r_str);
}

TEST_F(FfElementTest, FfSubSucceedsGivenTwoElements) {
  FqElemStr fq_r_str = {0x0};

  EXPECT_EQ(kEpidNoErr,
            FfSub(this->fq, this->fq_sum_ab, this->fq_b, this->fq_result));
  THROW_ON_EPIDERR(
      WriteFfElement(this->fq, this->fq_result, &fq_r_str, sizeof(fq_r_str)));
  EXPECT_EQ(this->fq_a_str, fq_r_str);
}

TEST_F(FfElementTest, FfSubSucceedsGivenTwoElementsFq2) {
  FfElementObj a(&this->fq2, &this->bn_a_str, sizeof(this->bn_a_str));
  FfElementObj b(&this->fq2, &this->bn_b_str, sizeof(this->bn_b_str));
  FfElementObj sum_ab(&this->fq2, this->fq2_sum_ab_str);
  FfElementObj r(&this->fq2);

  EXPECT_EQ(kEpidNoErr, FfSub(this->fq2, sum_ab, b, r));
  EXPECT_EQ(a, r);
}
TEST_F(FfElementTest, FfSubSucceedsGivenTwoElementsFq6) {
  FfElementObj a(&this->fq6, &this->bn_a_str, sizeof(this->bn_a_str));
  FfElementObj b(&this->fq6, &this->bn_b_str, sizeof(this->bn_b_str));
  FfElementObj sum_ab(&this->fq6, this->fq6_sum_ab_str);
  FfElementObj r(&this->fq6);

  EXPECT_EQ(kEpidNoErr, FfSub(this->fq6, sum_ab, b, r));
  EXPECT_EQ(a, r);
}
TEST_F(FfElementTest, FfSubSucceedsGivenTwoElementsFq12) {
  FfElementObj a(&this->fq12, &this->bn_a_str, sizeof(this->bn_a_str));
  FfElementObj b(&this->fq12, &this->bn_b_str, sizeof(this->bn_b_str));
  FfElementObj sum_ab(&this->fq12, this->fq12_sum_ab_str);
  FfElementObj r(&this->fq12);

  EXPECT_EQ(kEpidNoErr, FfSub(this->fq12, sum_ab, b, r));
  EXPECT_EQ(a, r);
}

////////////////////////////////////////////////
// FfAdd
TEST_F(FfElementTest, FfAddFailsGivenArgumentsMismatch) {
  EXPECT_EQ(kEpidBadArgErr,
            FfAdd(this->fq12, this->fq_a, this->fq_b, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfAdd(this->fq, this->fq12_g, this->fq_b, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfAdd(this->fq, this->fq_a, this->fq12_h, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfAdd(this->fq, this->fq_a, this->fq_b, this->fq12_result));
}

TEST_F(FfElementTest, FfAddFailsGivenNullPtr) {
  EXPECT_EQ(kEpidBadArgErr,
            FfAdd(nullptr, this->fq_a, this->fq_b, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfAdd(this->fq, nullptr, this->fq_b, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfAdd(this->fq, this->fq_a, nullptr, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr, FfAdd(this->fq, this->fq_a, this->fq_b, nullptr));
}

TEST_F(FfElementTest, FfAddSucceedsGivenElementZero) {
  FqElemStr fq_r_str = {0x0};

  // additive identity
  EXPECT_EQ(kEpidNoErr,
            FfAdd(this->fq, this->fq_a, this->fq_0, this->fq_result));
  THROW_ON_EPIDERR(
      WriteFfElement(this->fq, this->fq_result, &fq_r_str, sizeof(fq_r_str)));
  EXPECT_EQ(this->fq_a_str, fq_r_str);

  EXPECT_EQ(kEpidNoErr,
            FfAdd(this->fq, this->fq_0, this->fq_b, this->fq_result));
  THROW_ON_EPIDERR(
      WriteFfElement(this->fq, this->fq_result, &fq_r_str, sizeof(fq_r_str)));
  EXPECT_EQ(this->fq_b_str, fq_r_str);

  EXPECT_EQ(kEpidNoErr,
            FfAdd(this->fq, this->fq_0, this->fq_0, this->fq_result));
  THROW_ON_EPIDERR(
      WriteFfElement(this->fq, this->fq_result, &fq_r_str, sizeof(fq_r_str)));
  EXPECT_EQ(this->fq_0_str, fq_r_str);
}

TEST_F(FfElementTest, FfAddSucceedsGivenTwoElements) {
  FqElemStr fq_r_str = {0x0};

  EXPECT_EQ(kEpidNoErr,
            FfAdd(this->fq, this->fq_a, this->fq_b, this->fq_result));
  THROW_ON_EPIDERR(
      WriteFfElement(this->fq, this->fq_result, &fq_r_str, sizeof(fq_r_str)));
  EXPECT_EQ(this->fq_sum_ab_str, fq_r_str);
}

TEST_F(FfElementTest, FfAddSucceedsGivenTwoElementsFq2) {
  FfElementObj a(&this->fq2, &this->bn_a_str, sizeof(this->bn_a_str));
  FfElementObj b(&this->fq2, &this->bn_b_str, sizeof(this->bn_b_str));
  FfElementObj r(&this->fq2);

  EXPECT_EQ(kEpidNoErr, FfAdd(this->fq2, a, b, r));
  EXPECT_EQ(FfElementObj(&this->fq2, this->fq2_sum_ab_str), r);
}
TEST_F(FfElementTest, FfAddSucceedsGivenTwoElementsFq6) {
  FfElementObj a(&this->fq6, &this->bn_a_str, sizeof(this->bn_a_str));
  FfElementObj b(&this->fq6, &this->bn_b_str, sizeof(this->bn_b_str));
  FfElementObj r(&this->fq6);

  EXPECT_EQ(kEpidNoErr, FfAdd(this->fq6, a, b, r));
  EXPECT_EQ(FfElementObj(&this->fq6, this->fq6_sum_ab_str), r);
}
TEST_F(FfElementTest, FfAddSucceedsGivenTwoElementsFq12) {
  FfElementObj a(&this->fq12, &this->bn_a_str, sizeof(this->bn_a_str));
  FfElementObj b(&this->fq12, &this->bn_b_str, sizeof(this->bn_b_str));
  FfElementObj r(&this->fq12);

  EXPECT_EQ(kEpidNoErr, FfAdd(this->fq12, a, b, r));
  EXPECT_EQ(FfElementObj(&this->fq12, this->fq12_sum_ab_str), r);
}

////////////////////////////////////////////////
// FfInv

TEST_F(FfElementTest, FfInvFailsGivenNullPointer) {
  EXPECT_EQ(kEpidBadArgErr, FfInv(nullptr, (this->fq_a), this->fq_result));
  EXPECT_EQ(kEpidBadArgErr, FfInv(this->fq, nullptr, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr, FfInv(this->fq, this->fq_a, nullptr));
}

TEST_F(FfElementTest, FfInvFailsGivenArgumentsMismatch) {
  EXPECT_EQ(kEpidBadArgErr, FfInv(this->fq12, this->fq_a, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr, FfInv(this->fq, this->fq12_g, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr, FfInv(this->fq, this->fq_a, this->fq12_result));
}

TEST_F(FfElementTest, FfInvFailsGivenElementZero) {
  EXPECT_EQ(kEpidDivByZeroErr, FfInv(this->fq, this->fq_0, this->fq_result));
}

TEST_F(FfElementTest, FfInvSucceedsGivenElementOne) {
  FqElemStr fq_r_str;

  EXPECT_EQ(kEpidNoErr, FfInv(this->fq, this->fq_1, this->fq_result));
  THROW_ON_EPIDERR(
      WriteFfElement(this->fq, this->fq_result, &fq_r_str, sizeof(fq_r_str)));
  EXPECT_EQ(this->fq_1_str, fq_r_str);
}

TEST_F(FfElementTest, FfInvSucceedsGivenAnElement) {
  FqElemStr fq_r_str;

  EXPECT_EQ(kEpidNoErr, FfInv(this->fq, this->fq_a, this->fq_result));
  THROW_ON_EPIDERR(
      WriteFfElement(this->fq, this->fq_result, &fq_r_str, sizeof(fq_r_str)));
  EXPECT_EQ(this->fq_inv_a_str, fq_r_str);
}

////////////////////////////////////////////////
// FfExp

TEST_F(FfElementTest, FfExpFailsGivenNullPointer) {
  EXPECT_EQ(kEpidBadArgErr,
            FfExp(nullptr, this->fq_a, this->bn_a, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfExp(this->fq, nullptr, this->bn_a, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfExp(this->fq, this->fq_a, nullptr, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr, FfExp(this->fq, this->fq_a, this->bn_a, nullptr));
}

TEST_F(FfElementTest, FfExpFailsGivenArgumentsMismatch) {
  EXPECT_EQ(kEpidBadArgErr,
            FfExp(this->fq12, this->fq_a, this->bn_0, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfExp(this->fq, this->fq12_g, this->bn_0, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfExp(this->fq, this->fq_a, this->bn_0, this->fq12_result));
}

TEST_F(FfElementTest, FfExpSucceedsGivenElementZero) {
  FqElemStr fq_r_str;

  EXPECT_EQ(kEpidNoErr,
            FfExp(this->fq, this->fq_0, this->bn_a, this->fq_result));
  THROW_ON_EPIDERR(
      WriteFfElement(this->fq, this->fq_result, &fq_r_str, sizeof(fq_r_str)));
  EXPECT_EQ(this->fq_0_str, fq_r_str);
}

TEST_F(FfElementTest, FfExpSucceedsGivenExponentZero) {
  FqElemStr fq_r_str;

  EXPECT_EQ(kEpidNoErr,
            FfExp(this->fq, this->fq_a, this->bn_0, this->fq_result));
  THROW_ON_EPIDERR(
      WriteFfElement(this->fq, this->fq_result, &fq_r_str, sizeof(fq_r_str)));
  EXPECT_EQ(this->fq_1_str, fq_r_str);
}

TEST_F(FfElementTest, FfExpSucceedsGivenElementOne) {
  FqElemStr fq_r_str;

  EXPECT_EQ(kEpidNoErr,
            FfExp(this->fq, this->fq_1, this->bn_a, this->fq_result));
  THROW_ON_EPIDERR(
      WriteFfElement(this->fq, this->fq_result, &fq_r_str, sizeof(fq_r_str)));
  EXPECT_EQ(this->fq_1_str, fq_r_str);
}

TEST_F(FfElementTest, FfExpSucceedsGivenExponentOne) {
  FqElemStr fq_r_str;

  EXPECT_EQ(kEpidNoErr,
            FfExp(this->fq, this->fq_a, this->bn_1, this->fq_result));
  THROW_ON_EPIDERR(
      WriteFfElement(this->fq, this->fq_result, &fq_r_str, sizeof(fq_r_str)));
  EXPECT_EQ(this->fq_a_str, fq_r_str);
}

TEST_F(FfElementTest, FfExpSucceedsGivenAnElement) {
  FqElemStr fq_r_str;

  EXPECT_EQ(kEpidNoErr,
            FfExp(this->fq, this->fq_a, this->bn_a, this->fq_result));
  THROW_ON_EPIDERR(
      WriteFfElement(this->fq, this->fq_result, &fq_r_str, sizeof(fq_r_str)));
  EXPECT_EQ(this->fq_exp_ab_str, fq_r_str);

  Fq12ElemStr fq12_r_str;

  BigNumObj bn_pm1(sizeof(this->fp_pm1_str), this->fp_pm1_str);

  EXPECT_EQ(kEpidNoErr,
            FfExp(this->fq12, this->fq12_k, bn_pm1, this->fq12_result));
  THROW_ON_EPIDERR(WriteFfElement(this->fq12, this->fq12_result, &fq12_r_str,
                                  sizeof(fq12_r_str)));
  EXPECT_EQ(this->fq12_mul_gb_str, fq12_r_str);
}

////////////////////////////////////////////////
// FfHash

TEST_F(FfElementTest, FfHashFailsGivenArgumentsMismatch) {
  EXPECT_EQ(kEpidBadArgErr,
            FfHash(this->fq12, this->sha_msg, sizeof(this->sha_msg), kSha256,
                   this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfHash(this->fq, this->sha_msg, sizeof(this->sha_msg), kSha256,
                   this->fq12_result));
}

TEST_F(FfElementTest, FfHashFailsGivenNullPointer) {
  uint8_t const msg[] = {0};
  EXPECT_EQ(kEpidBadArgErr,
            FfHash(nullptr, msg, sizeof(msg), kSha256, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfHash(this->fq, nullptr, sizeof(msg), kSha256, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfHash(this->fq, msg, sizeof(msg), kSha256, nullptr));
}

TEST_F(FfElementTest, FfHashFailsGivenUnsupportedHashAlg) {
  uint8_t const msg[] = {0};
  EXPECT_EQ(kEpidHashAlgorithmNotSupported,
            FfHash(this->fq, msg, sizeof(msg), kSha512_256, this->fq_result));
  EXPECT_EQ(kEpidHashAlgorithmNotSupported,
            FfHash(this->fq, msg, sizeof(msg), kSha3_256, this->fq_result));
  EXPECT_EQ(kEpidHashAlgorithmNotSupported,
            FfHash(this->fq, msg, sizeof(msg), kSha3_384, this->fq_result));
  EXPECT_EQ(kEpidHashAlgorithmNotSupported,
            FfHash(this->fq, msg, sizeof(msg), kSha3_512, this->fq_result));
}

TEST_F(FfElementTest, FfHashFailsGivenIncorrectMsgLen) {
  uint8_t const msg[] = {0};
  size_t len_greater_int_max = (size_t)INT_MAX + 1;
  EXPECT_EQ(kEpidBadArgErr, FfHash(this->fq, msg, 0, kSha256, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfHash(this->fq, msg, std::numeric_limits<size_t>::max(), kSha256,
                   this->fq_result));
  EXPECT_EQ(kEpidBadArgErr, FfHash(this->fq, msg, len_greater_int_max, kSha256,
                                   this->fq_result));
}

TEST_F(FfElementTest, FfHashWorksGivenSHA256HashAlg) {
  FqElemStr fq_r_str;
  EXPECT_EQ(kEpidNoErr, FfHash(this->fq, sha_msg, sizeof(sha_msg), kSha256,
                               this->fq_result));
  THROW_ON_EPIDERR(
      WriteFfElement(this->fq, this->fq_result, &fq_r_str, sizeof(fq_r_str)));
  EXPECT_EQ(this->fq_abc_sha256_str, fq_r_str)
      << "FfHash: Hash element does not match to reference value";
}

TEST_F(FfElementTest, FfHashWorksGivenSHA384HashAlg) {
  FqElemStr fq_r_str;
  EXPECT_EQ(kEpidNoErr, FfHash(this->fq, sha_msg, sizeof(sha_msg), kSha384,
                               this->fq_result));
  THROW_ON_EPIDERR(
      WriteFfElement(this->fq, this->fq_result, &fq_r_str, sizeof(fq_r_str)));
  EXPECT_EQ(this->fq_abc_sha384_str, fq_r_str)
      << "FfHash: Hash element does not match to reference value";
}

TEST_F(FfElementTest, FfHashWorksGivenSHA512HashAlg) {
  FqElemStr fq_r_str;
  EXPECT_EQ(kEpidNoErr, FfHash(this->fq, sha_msg, sizeof(sha_msg), kSha512,
                               this->fq_result));
  THROW_ON_EPIDERR(
      WriteFfElement(this->fq, this->fq_result, &fq_r_str, sizeof(fq_r_str)));
  EXPECT_EQ(this->fq_abc_sha512_str, fq_r_str)
      << "FfHash: Hash element does not match to reference value";
}

////////////////////////////////////////////////
// FfMultiExp

TEST_F(FfElementTest, FfMultiExpFailsGivenArgumentsMismatch) {
  FfElement const* p[] = {this->fq_a, this->fq_b};
  FfElement const* p12[] = {this->fq12_g, this->fq12_h};
  BigNumStr const* b[] = {&this->bn_0_str, &this->bn_0_str};
  EXPECT_EQ(kEpidBadArgErr, FfMultiExp(this->fq12, p, b, 2, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr, FfMultiExp(this->fq, p12, b, 2, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr, FfMultiExp(this->fq, p, b, 2, this->fq12_result));
}

TEST_F(FfElementTest, FfMultiExpFailsGivenNullPointer) {
  FfElement const* p[] = {this->fq_a, this->fq_b};
  FfElement const* p_withnull[] = {nullptr, this->fq_b};
  BigNumStr const* b[] = {&fq_multi_exp_exp_2[0], &this->fq_multi_exp_exp_2[1]};
  BigNumStr const* b_withnull[] = {nullptr, &this->fq_multi_exp_exp_2[1]};
  size_t m = 2;
  EXPECT_EQ(kEpidBadArgErr, FfMultiExp(nullptr, p, b, m, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfMultiExp(this->fq, nullptr, b, m, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfMultiExp(this->fq, p, nullptr, m, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr, FfMultiExp(this->fq, p, b, m, nullptr));
  EXPECT_EQ(kEpidBadArgErr,
            FfMultiExp(this->fq, p_withnull, b, m, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfMultiExp(this->fq, p, b_withnull, m, this->fq_result));
}

TEST_F(FfElementTest, FfMultiExpFailsGivenIncorrectMLen) {
  FfElement const* p[] = {this->fq_a, this->fq_b};
  BigNumStr const* b[] = {&this->fq_multi_exp_exp_2[0],
                          &this->fq_multi_exp_exp_2[1]};
  size_t len_greater_int_max = (size_t)INT_MAX + 1;
  EXPECT_EQ(kEpidBadArgErr, FfMultiExp(this->fq, p, b, 0, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfMultiExp(this->fq, p, b, std::numeric_limits<size_t>::max(),
                       this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfMultiExp(this->fq, p, b, len_greater_int_max, this->fq_result));
}

TEST_F(FfElementTest, FfMultiExpWorksGivenOneExponent) {
  FfElementObj r(&this->fq);
  FfElementObj fq_exp[1];
  FfElement const* p[1];
  BigNumStr const* b[1];
  int m = 0;
  // prepare data for test
  for (m = 0; m < 1; m++) {
    fq_exp[m] = FfElementObj(&this->fq, this->fq_multi_exp_base_1[m]);
    // initialize data for test
    p[m] = fq_exp[m];
    b[m] = &this->fq_multi_exp_exp_1[m];
  }
  // do test
  EXPECT_EQ(kEpidNoErr, FfMultiExp(this->fq, p, b, 1, r));
  // verify calculation is correct
  EXPECT_EQ(FfElementObj(&this->fq, this->fq_multi_exp_res_1), r)
      << "FfMultiExp: Finite field element does not match with reference value";
}

TEST_F(FfElementTest, FfMultiExpWorksGivenTwoExponents) {
  FfElementObj r(&this->fq);
  FfElementObj fq_exp[2];
  FfElement const* p[2];
  BigNumStr const* b[2];
  int m = 0;
  // prepare data for test
  for (m = 0; m < 2; m++) {
    fq_exp[m] = FfElementObj(&this->fq, this->fq_multi_exp_base_2[m]);
    // initialize data for test
    p[m] = fq_exp[m];
    b[m] = &this->fq_multi_exp_exp_2[m];
  }
  // do test
  EXPECT_EQ(kEpidNoErr, FfMultiExp(this->fq, p, b, 2, r));
  EXPECT_EQ(FfElementObj(&this->fq, this->fq_multi_exp_res_2), r)
      << "FfMultiExp: Finite field element does not match with reference value";
}

TEST_F(FfElementTest, FfMultiExpWorksGivenThreeExponents) {
  FfElementObj r(&this->fq);
  FfElementObj fq_exp[3];
  FfElement const* p[3];
  BigNumStr const* b[3];
  int m = 0;
  // prepare data for test
  for (m = 0; m < 3; m++) {
    fq_exp[m] = FfElementObj(&this->fq, this->fq_multi_exp_base_3[m]);
    // initialize data for test
    p[m] = fq_exp[m];
    b[m] = &this->fq_multi_exp_exp_3[m];
  }
  // do test
  EXPECT_EQ(kEpidNoErr, FfMultiExp(this->fq, p, b, 3, r));
  EXPECT_EQ(FfElementObj(&this->fq, this->fq_multi_exp_res_3), r)
      << "FfMultiExp: Finite field element does not match with reference value";
}

TEST_F(FfElementTest, FfMultiExpWorksGivenFourExponents) {
  FfElementObj r(&this->fq);
  FfElementObj fq_exp[4];
  FfElement const* p[4];
  BigNumStr const* b[4];
  int m = 0;
  // prepare data for test
  for (m = 0; m < 4; m++) {
    fq_exp[m] = FfElementObj(&this->fq, this->fq_multi_exp_base_4[m]);
    // initialize data for test
    p[m] = fq_exp[m];
    b[m] = &this->fq_multi_exp_exp_4[m];
  }
  // do test
  EXPECT_EQ(kEpidNoErr, FfMultiExp(this->fq, p, b, 4, r));
  EXPECT_EQ(FfElementObj(&this->fq, this->fq_multi_exp_res_4), r)
      << "FfMultiExp: Finite field element does not match with reference value";
}

TEST_F(FfElementTest, FfMultiExpWorksGivenFourFq12Exponents) {
  FfElementObj r12(&this->fq12);
  FfElementObj fq12_exp[4];
  FfElement const* p[4];
  BigNumStr const* b[4];
  int m = 0;
  // prepare data for test
  for (m = 0; m < 4; m++) {
    fq12_exp[m] = FfElementObj(&this->fq12, this->fq12_multi_exp_base_4[m]);
    // initialize data for test
    p[m] = fq12_exp[m];
    b[m] = &this->fq12_multi_exp_exp_4[m];
  }
  // do test
  EXPECT_EQ(kEpidNoErr, FfMultiExp(this->fq12, p, b, 4, r12));
  EXPECT_EQ(FfElementObj(&this->fq12, this->fq12_multi_exp_res_4), r12)
      << "FfMultiExp: Finite field element does not match with reference value";
}

TEST_F(FfElementTest, FfMultiExpWorksGivenFiveExponents) {
  FfElementObj r(&this->fq);
  FfElementObj fq_exp[5];
  FfElement const* p[5];
  BigNumStr const* b[5];
  int m = 0;
  // prepare data for test
  for (m = 0; m < 5; m++) {
    fq_exp[m] = FfElementObj(&this->fq, this->fq_multi_exp_base_5[m]);
    // initialize data for test
    p[m] = fq_exp[m];
    b[m] = &this->fq_multi_exp_exp_5[m];
  }
  // do test
  EXPECT_EQ(kEpidNoErr, FfMultiExp(this->fq, p, b, 5, r));
  EXPECT_EQ(FfElementObj(&this->fq, this->fq_multi_exp_res_5), r)
      << "FfMultiExp: Finite field element does not match with reference value";
}

TEST_F(FfElementTest, FfMultiExpWorksGivenSixExponents) {
  FfElementObj r(&this->fq);
  FfElementObj fq_exp[6];
  FfElement const* p[6];
  BigNumStr const* b[6];
  int m = 0;
  // prepare data for test
  for (m = 0; m < 6; m++) {
    fq_exp[m] = FfElementObj(&this->fq, this->fq_multi_exp_base_6[m]);
    // initialize data for test
    p[m] = fq_exp[m];
    b[m] = &this->fq_multi_exp_exp_6[m];
  }
  // do test
  EXPECT_EQ(kEpidNoErr, FfMultiExp(this->fq, p, b, 6, r));
  EXPECT_EQ(FfElementObj(&this->fq, this->fq_multi_exp_res_6), r)
      << "FfMultiExp: Finite field element does not match with reference value";
}

///////////////////////////////////////////////////////////////////////
// FfMultiExpBn

TEST_F(FfElementTest, FfMultiExpBnFailsGivenArgumentsMismatch) {
  FfElement const* p[] = {this->fq_a, this->fq_b};
  FfElement const* p12[] = {this->fq12_g, this->fq12_h};
  BigNum const* b[] = {bn_0, bn_0};
  EXPECT_EQ(kEpidBadArgErr, FfMultiExpBn(this->fq12, p, b, 2, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr, FfMultiExpBn(this->fq, p12, b, 2, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr, FfMultiExpBn(this->fq, p, b, 2, this->fq12_result));
}

TEST_F(FfElementTest, FfMultiExpBnFailsGivenNullPointer) {
  FfElement const* p[] = {this->fq_a, this->fq_b};
  FfElement const* p_withnull[] = {nullptr, this->fq_b};
  BigNumObj bn_exp_0(this->fq_multi_exp_exp_2[0]);
  BigNumObj bn_exp_1(this->fq_multi_exp_exp_2[1]);
  BigNum const* b[] = {bn_exp_0, bn_exp_1};
  BigNum const* b_withnull[] = {nullptr, bn_exp_1};
  size_t m = 2;
  EXPECT_EQ(kEpidBadArgErr, FfMultiExpBn(nullptr, p, b, m, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfMultiExpBn(this->fq, nullptr, b, m, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfMultiExpBn(this->fq, p, nullptr, m, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr, FfMultiExpBn(this->fq, p, b, m, nullptr));
  EXPECT_EQ(kEpidBadArgErr,
            FfMultiExpBn(this->fq, p_withnull, b, m, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfMultiExpBn(this->fq, p, b_withnull, m, this->fq_result));
}

TEST_F(FfElementTest, FfMultiExpBnFailsGivenIncorrectMLen) {
  FfElement const* p[] = {this->fq_a, this->fq_b};
  BigNumObj bn_exp_0(this->fq_multi_exp_exp_2[0]);
  BigNumObj bn_exp_1(this->fq_multi_exp_exp_2[1]);
  BigNum const* b[] = {bn_exp_0, bn_exp_1};
  size_t len_greater_int_max = (size_t)INT_MAX + 1;
  EXPECT_EQ(kEpidBadArgErr, FfMultiExpBn(this->fq, p, b, 0, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfMultiExpBn(this->fq, p, b, std::numeric_limits<size_t>::max(),
                         this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfMultiExpBn(this->fq, p, b, len_greater_int_max, this->fq_result));
}

TEST_F(FfElementTest, FfMultiExpBnWorksGivenOneExponent) {
  const int items = 1;
  FfElementObj r(&this->fq);
  FfElementObj fq_base[1];
  BigNumObj bn_exp[1];
  FfElement const* p[1];
  BigNum const* b[1];
  int m = 0;
  // prepare data for test
  for (m = 0; m < items; m++) {
    fq_base[m] = FfElementObj(&this->fq, this->fq_multi_exp_base_1[m]);
    bn_exp[m] = BigNumObj(this->fq_multi_exp_exp_1[m]);
    // initialize data for test
    p[m] = fq_base[m];
    b[m] = bn_exp[m];
  }
  // do test
  EXPECT_EQ(kEpidNoErr, FfMultiExpBn(this->fq, p, b, items, r));
  EXPECT_EQ(FfElementObj(&this->fq, this->fq_multi_exp_res_1), r)
      << "FfMultiExpBn: Finite field element does not "
         "match with reference value";
}

TEST_F(FfElementTest, FfMultiExpBnWorksGivenTwoExponents) {
  const int items = 2;
  FfElementObj r(&this->fq);
  FfElementObj fq_base[2];
  BigNumObj bn_exp[2];
  FfElement const* p[2];
  BigNum const* b[2];
  int m = 0;
  // prepare data for test
  for (m = 0; m < items; m++) {
    fq_base[m] = FfElementObj(&this->fq, this->fq_multi_exp_base_2[m]);
    bn_exp[m] = BigNumObj(this->fq_multi_exp_exp_2[m]);
    // initialize data for test
    p[m] = fq_base[m];
    b[m] = bn_exp[m];
  }
  // do test
  EXPECT_EQ(kEpidNoErr, FfMultiExpBn(this->fq, p, b, items, r));
  EXPECT_EQ(FfElementObj(&this->fq, this->fq_multi_exp_res_2), r)
      << "FfMultiExpBn: Finite field element does not "
         "match with reference value";
}
TEST_F(FfElementTest, FfMultiExpBnWorksGivenThreeExponents) {
  const int items = 3;
  FfElementObj r(&this->fq);
  FfElementObj fq_base[3];
  BigNumObj bn_exp[3];
  FfElement const* p[3];
  BigNum const* b[3];
  int m = 0;
  // prepare data for test
  for (m = 0; m < items; m++) {
    fq_base[m] = FfElementObj(&this->fq, this->fq_multi_exp_base_3[m]);
    bn_exp[m] = BigNumObj(this->fq_multi_exp_exp_3[m]);
    // initialize data for test
    p[m] = fq_base[m];
    b[m] = bn_exp[m];
  }
  // do test
  EXPECT_EQ(kEpidNoErr, FfMultiExpBn(this->fq, p, b, items, r));
  EXPECT_EQ(FfElementObj(&this->fq, this->fq_multi_exp_res_3), r)
      << "FfMultiExpBn: Finite field element does not "
         "match with reference value";
}

TEST_F(FfElementTest, FfMultiExpBnWorksGivenFourExponents) {
  const int items = 4;
  FfElementObj r(&this->fq);
  FfElementObj fq_base[4];
  BigNumObj bn_exp[4];
  FfElement const* p[4];
  BigNum const* b[4];
  int m = 0;
  // prepare data for test
  for (m = 0; m < items; m++) {
    fq_base[m] = FfElementObj(&this->fq, this->fq_multi_exp_base_4[m]);
    bn_exp[m] = BigNumObj(this->fq_multi_exp_exp_4[m]);
    // initialize data for test
    p[m] = fq_base[m];
    b[m] = bn_exp[m];
  }
  // do test
  EXPECT_EQ(kEpidNoErr, FfMultiExpBn(this->fq, p, b, items, r));
  EXPECT_EQ(FfElementObj(&this->fq, this->fq_multi_exp_res_4), r)
      << "FfMultiExpBn: Finite field element does not "
         "match with reference value";
}

TEST_F(FfElementTest, DISABLED_FfMultiExpBnWorksGivenFourFq12Exponents) {
  const int items = 4;
  FfElementObj fq12_r(&this->fq12);
  FfElementObj fq12_base[4];
  BigNumObj fq12_bn_exp[4];
  FfElement const* fq12_p[4];
  BigNum const* fq12_b[4];
  int m = 0;
  // prepare data for test
  for (m = 0; m < items; m++) {
    fq12_base[m] = FfElementObj(&this->fq12, this->fq12_multi_exp_base_4[m]);
    fq12_bn_exp[m] = BigNumObj(this->fq12_multi_exp_exp_4[m]);
    // initialize data for test
    fq12_p[m] = fq12_base[m];
    fq12_b[m] = fq12_bn_exp[m];
  }
  // do test
  EXPECT_EQ(kEpidNoErr,
            FfMultiExpBn(this->fq12, fq12_p, fq12_b, items, fq12_r));
  EXPECT_EQ(FfElementObj(&this->fq12, this->fq_multi_exp_res_4), fq12_r)
      << "FfMultiExpBn: Finite field element does not "
         "match with reference value";
}

TEST_F(FfElementTest, FfMultiExpBnWorksGivenFiveExponents) {
  const int items = 5;
  FfElementObj r(&this->fq);
  FfElementObj fq_base[5];
  BigNumObj bn_exp[5];
  FfElement const* p[5];
  BigNum const* b[5];
  int m = 0;
  // prepare data for test
  for (m = 0; m < items; m++) {
    fq_base[m] = FfElementObj(&this->fq, this->fq_multi_exp_base_5[m]);
    bn_exp[m] = BigNumObj(this->fq_multi_exp_exp_5[m]);
    // initialize data for test
    p[m] = fq_base[m];
    b[m] = bn_exp[m];
  }
  // do test
  EXPECT_EQ(kEpidNoErr, FfMultiExpBn(this->fq, p, b, items, r));
  EXPECT_EQ(FfElementObj(&this->fq, this->fq_multi_exp_res_5), r)
      << "FfSscmMultiExp: Finite field element does not "
         "match with reference value";
}

TEST_F(FfElementTest, FfMultiExpBnWorksGivenSixExponents) {
  const int items = 6;
  FfElementObj r(&this->fq);
  FfElementObj fq_base[6];
  BigNumObj bn_exp[6];
  FfElement const* p[6];
  BigNum const* b[6];
  int m = 0;
  // prepare data for test
  for (m = 0; m < items; m++) {
    fq_base[m] = FfElementObj(&this->fq, this->fq_multi_exp_base_6[m]);
    bn_exp[m] = BigNumObj(this->fq_multi_exp_exp_6[m]);
    // initialize data for test
    p[m] = fq_base[m];
    b[m] = bn_exp[m];
  }
  // do test
  EXPECT_EQ(kEpidNoErr, FfMultiExpBn(this->fq, p, b, items, r));
  EXPECT_EQ(FfElementObj(&this->fq, this->fq_multi_exp_res_6), r)
      << "FfSscmMultiExp: Finite field element does not "
         "match with reference value";
}

TEST_F(FfElementTest, FfMultiExpBnWorksOverEpid11GT) {
  const int items = 3;
  FfElementObj r(&this->epid11_GT);
  FfElementObj ff_base[3];
  BigNumObj bn_exp[3];
  FfElement const* p[3];
  BigNum const* b[3];
  int m = 0;
  // prepare data for test
  for (m = 0; m < items; m++) {
    ff_base[m] =
        FfElementObj(&this->epid11_GT, this->epid11_GT_multi_exp_base_3[m]);
    bn_exp[m] = BigNumObj(this->epid11_GT_multi_exp_exp_3[m]);
    // initialize data for test
    p[m] = ff_base[m];
    b[m] = bn_exp[m];
  }
  // do test
  EXPECT_EQ(kEpidNoErr, FfMultiExpBn(this->epid11_GT, p, b, items, r));
  EXPECT_EQ(FfElementObj(&this->epid11_GT, this->epid11_GT_multi_exp_res_3), r)
      << "FfSscmMultiExp: Finite field element does not "
         "match with reference value";
}

///////////////////////////////////////////////////////////////////////
// FfSscmMultiExp

TEST_F(FfElementTest, SscmFfMultiExpFailsGivenArgumentsMismatch) {
  FfElement const* p[] = {this->fq_a, this->fq_b};
  FfElement const* p12[] = {this->fq12_g, this->fq12_h};
  BigNumStr const* b[] = {&this->bn_0_str, &this->bn_0_str};
  EXPECT_EQ(kEpidBadArgErr,
            FfSscmMultiExp(this->fq12, p, b, 2, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfSscmMultiExp(this->fq, p12, b, 2, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfSscmMultiExp(this->fq, p, b, 2, this->fq12_result));
}

TEST_F(FfElementTest, SscmFfMultiExpFailsGivenNullPointer) {
  FfElement const* p[] = {this->fq_a, this->fq_b};
  FfElement const* p_withnull[] = {nullptr, this->fq_b};
  BigNumStr const* b[] = {&this->fq_multi_exp_exp_2[0],
                          &this->fq_multi_exp_exp_2[1]};
  BigNumStr const* b_withnull[] = {nullptr, &this->fq_multi_exp_exp_2[1]};
  size_t m = 2;
  EXPECT_EQ(kEpidBadArgErr, FfSscmMultiExp(nullptr, p, b, m, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfSscmMultiExp(this->fq, nullptr, b, m, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfSscmMultiExp(this->fq, p, nullptr, m, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr, FfSscmMultiExp(this->fq, p, b, m, nullptr));
  EXPECT_EQ(kEpidBadArgErr,
            FfSscmMultiExp(this->fq, p_withnull, b, m, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfSscmMultiExp(this->fq, p, b_withnull, m, this->fq_result));
}

TEST_F(FfElementTest, SscmFfMultiExpFailsGivenIncorrectMLen) {
  FfElement const* p[] = {this->fq_a, this->fq_b};
  BigNumStr const* b[] = {&this->fq_multi_exp_exp_2[0],
                          &this->fq_multi_exp_exp_2[1]};
  size_t len_greater_int_max = (size_t)INT_MAX + 1;
  EXPECT_EQ(kEpidBadArgErr, FfSscmMultiExp(this->fq, p, b, 0, this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfSscmMultiExp(this->fq, p, b, std::numeric_limits<size_t>::max(),
                           this->fq_result));
  EXPECT_EQ(kEpidBadArgErr, FfSscmMultiExp(this->fq, p, b, len_greater_int_max,
                                           this->fq_result));
}

TEST_F(FfElementTest, SscmFfMultiExpWorksGivenOneExponent) {
  FfElementObj r(&this->fq);
  FfElementObj fq_exp[1];
  FfElement const* p[1];
  BigNumStr const* b[1];
  int m = 0;
  // prepare data for test
  for (m = 0; m < 1; m++) {
    fq_exp[m] = FfElementObj(&this->fq, this->fq_multi_exp_base_1[m]);
    // initialize data for test
    p[m] = fq_exp[m];
    b[m] = &this->fq_multi_exp_exp_1[m];
  }
  // do test
  EXPECT_EQ(kEpidNoErr, FfSscmMultiExp(this->fq, p, b, 1, r));
  EXPECT_EQ(FfElementObj(&this->fq, this->fq_multi_exp_res_1), r)
      << "FfSscmMultiExp: Finite field element does not "
         "match with reference value";
}

TEST_F(FfElementTest, SscmFfMultiExpWorksGivenTwoExponents) {
  FfElementObj r(&this->fq);
  FfElementObj fq_exp[2];
  FfElement const* p[2];
  BigNumStr const* b[2];
  int m = 0;
  // prepare data for test
  for (m = 0; m < 2; m++) {
    fq_exp[m] = FfElementObj(&this->fq, this->fq_multi_exp_base_2[m]);
    // initialize data for test
    p[m] = fq_exp[m];
    b[m] = &this->fq_multi_exp_exp_2[m];
  }
  // do test
  EXPECT_EQ(kEpidNoErr, FfSscmMultiExp(this->fq, p, b, 2, r));
  EXPECT_EQ(FfElementObj(&this->fq, this->fq_multi_exp_res_2), r)
      << "FfSscmMultiExp: Finite field element does not "
         "match with reference value";
}

TEST_F(FfElementTest, SscmFfMultiExpWorksGivenThreeExponents) {
  FfElementObj r(&this->fq);
  FfElementObj fq_exp[3];
  FfElement const* p[3];
  BigNumStr const* b[3];
  int m = 0;
  // prepare data for test
  for (m = 0; m < 3; m++) {
    fq_exp[m] = FfElementObj(&this->fq, this->fq_multi_exp_base_3[m]);
    // initialize data for test
    p[m] = fq_exp[m];
    b[m] = &this->fq_multi_exp_exp_3[m];
  }
  // do test
  EXPECT_EQ(kEpidNoErr, FfSscmMultiExp(this->fq, p, b, 3, r));
  EXPECT_EQ(FfElementObj(&this->fq, this->fq_multi_exp_res_3), r)
      << "FfSscmMultiExp: Finite field element does not "
         "match with reference value";
}

TEST_F(FfElementTest, SscmFfMultiExpWorksGivenFourExponents) {
  FfElementObj r(&this->fq);
  FfElementObj fq_exp[4];
  FfElement const* p[4];
  BigNumStr const* b[4];
  int m = 0;
  // prepare data for test
  for (m = 0; m < 4; m++) {
    fq_exp[m] = FfElementObj(&this->fq, this->fq_multi_exp_base_4[m]);
    // initialize data for test
    p[m] = fq_exp[m];
    b[m] = &this->fq_multi_exp_exp_4[m];
  }
  // do test
  EXPECT_EQ(kEpidNoErr, FfSscmMultiExp(this->fq, p, b, 4, r));
  EXPECT_EQ(FfElementObj(&this->fq, this->fq_multi_exp_res_4), r)
      << "FfSscmMultiExp: Finite field element does not "
         "match with reference value";
}

TEST_F(FfElementTest, SscmFfMultiExpWorksGivenFourFq12Exponents) {
  FfElementObj r12(&this->fq12);
  FfElementObj fq12_exp[4];
  FfElement const* p[4];
  BigNumStr const* b[4];
  int m = 0;
  // prepare data for test
  for (m = 0; m < 4; m++) {
    fq12_exp[m] = FfElementObj(&this->fq12, this->fq12_multi_exp_base_4[m]);
    // initialize data for test
    p[m] = fq12_exp[m];
    b[m] = &this->fq12_multi_exp_exp_4[m];
  }
  // do test
  EXPECT_EQ(kEpidNoErr, FfSscmMultiExp(this->fq12, p, b, 4, r12));
  EXPECT_EQ(FfElementObj(&this->fq12, this->fq12_multi_exp_res_4), r12)
      << "FfSscmMultiExp: Finite field element does not match with reference "
         "value";
}

TEST_F(FfElementTest, SscmFfMultiExpWorksGivenFiveExponents) {
  FfElementObj r(&this->fq);
  FfElementObj fq_exp[5];
  FfElement const* p[5];
  BigNumStr const* b[5];
  int m = 0;
  // prepare data for test
  for (m = 0; m < 5; m++) {
    fq_exp[m] = FfElementObj(&this->fq, this->fq_multi_exp_base_5[m]);
    // initialize data for test
    p[m] = fq_exp[m];
    b[m] = &this->fq_multi_exp_exp_5[m];
  }
  // do test
  EXPECT_EQ(kEpidNoErr, FfSscmMultiExp(this->fq, p, b, 5, r));
  EXPECT_EQ(FfElementObj(&this->fq, this->fq_multi_exp_res_5), r)
      << "FfSscmMultiExp: Finite field element does not "
         "match with reference value";
}

TEST_F(FfElementTest, SscmFfMultiExpWorksGivenSixExponents) {
  FfElementObj r(&this->fq);
  FfElementObj fq_exp[6];
  FfElement const* p[6];
  BigNumStr const* b[6];
  int m = 0;
  // prepare data for test
  for (m = 0; m < 6; m++) {
    fq_exp[m] = FfElementObj(&this->fq, this->fq_multi_exp_base_6[m]);
    // initialize data for test
    p[m] = fq_exp[m];
    b[m] = &this->fq_multi_exp_exp_6[m];
  }
  // do test
  EXPECT_EQ(kEpidNoErr, FfSscmMultiExp(this->fq, p, b, 6, r));
  EXPECT_EQ(FfElementObj(&this->fq, this->fq_multi_exp_res_6), r)
      << "FfSscmMultiExp: Finite field element does not "
         "match with reference value";
}
////////////////////////////////////////////////
// FfGetRandom

TEST_F(FfElementTest, FfGetRandomFailsGivenArgumentsMismatch) {
  Prng my_prng;
  EXPECT_EQ(kEpidBadArgErr,
            FfGetRandom(this->fq12, &this->bn_1_str, &Prng::Generate, &my_prng,
                        this->fq_result));
  EXPECT_EQ(kEpidBadArgErr,
            FfGetRandom(this->fq, &this->bn_1_str, &Prng::Generate, &my_prng,
                        this->fq12_result));
}

TEST_F(FfElementTest, FfGetRandomFailsGivenNullPtr) {
  Prng my_prng;
  FfElementObj r(&this->fq);
  EXPECT_EQ(kEpidBadArgErr, FfGetRandom(nullptr, &this->bn_1_str,
                                        &Prng::Generate, &my_prng, r));
  EXPECT_EQ(kEpidBadArgErr,
            FfGetRandom(this->fq, nullptr, &Prng::Generate, &my_prng, r));
  EXPECT_EQ(kEpidBadArgErr,
            FfGetRandom(this->fq, &this->bn_1_str, nullptr, &my_prng, r));
  EXPECT_EQ(kEpidBadArgErr, FfGetRandom(this->fq, &this->bn_1_str,
                                        &Prng::Generate, &my_prng, nullptr));
}
TEST_F(FfElementTest, FfGetRandomSucceedsGivenFq2) {
  Prng my_prng;
  FfElementObj r(&this->fq2);
  EXPECT_EQ(kEpidNoErr, FfGetRandom(this->fq2, &this->bn_1_str, &Prng::Generate,
                                    &my_prng, r));
}
TEST_F(FfElementTest, FfGetRandomSucceedsGivenFq6) {
  Prng my_prng;
  FfElementObj r(&this->fq6);
  EXPECT_EQ(kEpidNoErr, FfGetRandom(this->fq6, &this->bn_1_str, &Prng::Generate,
                                    &my_prng, r));
}
TEST_F(FfElementTest, FfGetRandomSucceedsGivenFq12) {
  Prng my_prng;
  FfElementObj r(&this->fq12);
  EXPECT_EQ(kEpidNoErr, FfGetRandom(this->fq12, &this->bn_1_str,
                                    &Prng::Generate, &my_prng, r));
}

TEST_F(FfElementTest, FfGetRandomSuccedsGivenLowBound) {
  Prng my_prng;
  FfElementObj r(&this->fq);
  FqElemStr buf;
  unsigned int result;
  EXPECT_EQ(kEpidNoErr, FfGetRandom(this->fq, &this->bn_1_str, &Prng::Generate,
                                    &my_prng, r));
  THROW_ON_EPIDERR(WriteFfElement(this->fq, r, &buf, sizeof(buf)));
  THROW_ON_EPIDERR(Cmp_OctStr256(&this->bn_1_str.data, &buf.data, &result));
  EXPECT_EQ(result, (unsigned int)2);
  EXPECT_EQ(kEpidNoErr, FfGetRandom(this->fq, &this->bn_2_str, &Prng::Generate,
                                    &my_prng, r));
  THROW_ON_EPIDERR(WriteFfElement(this->fq, r, &buf, sizeof(buf)));
  THROW_ON_EPIDERR(Cmp_OctStr256(&this->bn_2_str.data, &buf.data, &result));
  EXPECT_EQ(result, (unsigned int)2);
  EXPECT_EQ(kEpidNoErr, FfGetRandom(this->fq, &this->bn_0xffff_str,
                                    &Prng::Generate, &my_prng, r));
  THROW_ON_EPIDERR(WriteFfElement(this->fq, r, &buf, sizeof(buf)));
  THROW_ON_EPIDERR(
      Cmp_OctStr256(&this->bn_0xffff_str.data, &buf.data, &result));
  EXPECT_EQ(result, (unsigned int)2);
  EXPECT_EQ(kEpidNoErr, FfGetRandom(this->fq, &this->bn_0xffff_str,
                                    &Prng::Generate, &my_prng, r));
  THROW_ON_EPIDERR(WriteFfElement(this->fq, r, &buf, sizeof(buf)));
  THROW_ON_EPIDERR(
      Cmp_OctStr256(&this->bn_0xffff_str.data, &buf.data, &result));
  EXPECT_EQ(result, (unsigned int)2);
}

TEST_F(FfElementTest, FfGetRandomGeneratesDifferentNumbers) {
  Prng my_prng;
  FfElementObj r1(&this->fq);
  FfElementObj r2(&this->fq);
  bool result;
  EXPECT_EQ(kEpidNoErr, FfGetRandom(this->fq, &this->bn_1_str, &Prng::Generate,
                                    &my_prng, r1));
  EXPECT_EQ(kEpidNoErr, FfGetRandom(this->fq, &this->bn_1_str, &Prng::Generate,
                                    &my_prng, r2));
  THROW_ON_EPIDERR(FfIsEqual(this->fq, r1, r2, &result));
  EXPECT_FALSE(result);
}
TEST_F(FfElementTest, FfGetRandomFailsOnMaxIterGivenLargeLowBound) {
  Prng my_prng;
  FfElementObj r(&this->fq);
  // FfGetRandom generates random data between [low_bound, modulus-1]
  // modulus in this case is Intel(R) EPID 2.0 parameter q
  // giving low_bound = modulus - {0x30, 0x13} should get kEpidRandMaxIterErr
  EXPECT_EQ(kEpidRandMaxIterErr, FfGetRandom(this->fq, &this->fq_qm0x3013_str,
                                             &Prng::Generate, &my_prng, r));
}

////////////////////////////////////////////////
// FfSqrt
TEST_F(FfElementTest, FfSqrtFailsGivenNullPtr) {
  FfElementObj r(&this->fq);
  EXPECT_EQ(kEpidBadArgErr, FfSqrt(nullptr, this->fq_4, r));
  EXPECT_EQ(kEpidBadArgErr, FfSqrt(this->fq, nullptr, r));
  EXPECT_EQ(kEpidBadArgErr, FfSqrt(this->fq, this->fq_4, nullptr));
}

TEST_F(FfElementTest, FfSqrtWorksForOne) {
  FfElementObj r(&this->fq);
  FfElementObj s(&this->fq);
  EXPECT_EQ(kEpidNoErr, FfSqrt(this->fq, this->fq_1, r));
  EXPECT_EQ(this->fq_1, r);
}

TEST_F(FfElementTest, FfSqrtFailsForTwo) {
  FfElementObj r(&this->fq);
  EXPECT_EQ(kEpidMathQuadraticNonResidueError, FfSqrt(this->fq, this->fq_2, r));
}

TEST_F(FfElementTest, FfSqrtFailsForThree) {
  FfElementObj r(&this->fq);
  EXPECT_EQ(kEpidMathQuadraticNonResidueError, FfSqrt(this->fq, this->fq_3, r));
}

TEST_F(FfElementTest, FfSqrtWorksForFour) {
  FfElementObj r(&this->fq);
  EXPECT_EQ(kEpidNoErr, FfSqrt(this->fq, this->fq_4, r));
  EXPECT_EQ(this->fq_qm2, r);
}

TEST_F(FfElementTest, FfSqrtFailsForFive) {
  FfElementObj r(&this->fq);
  EXPECT_EQ(kEpidMathQuadraticNonResidueError, FfSqrt(this->fq, this->fq_5, r));
}

TEST_F(FfElementTest, FfSqrtWorksForEpid11Prime) {
  // given b_str value ensure sqrt algorithm step 7 if clause is triggered
  const BigNumStr b_str = {0x06, 0xc1, 0x26, 0xe8, 0xa5, 0xa5, 0x21, 0x19,
                           0x07, 0x42, 0x49, 0x77, 0x7c, 0x5c, 0x98, 0x7f,
                           0xd4, 0x0c, 0x42, 0xf5, 0x25, 0x2c, 0xac, 0xb9,
                           0x7e, 0x09, 0x70, 0xf0, 0x84, 0x3b, 0x81, 0x46};
  FfElementObj b(&this->epid11_fq, &b_str, sizeof((b_str)));

  FfElementObj r(&this->epid11_fq);
  FfElementObj s(&this->epid11_fq);
  FfElementObj r2(&this->epid11_fq);

  EXPECT_EQ(kEpidNoErr, FfMul(this->epid11_fq, b, b, s));
  EXPECT_EQ(kEpidNoErr, FfSqrt(this->epid11_fq, s, r));
  EXPECT_EQ(kEpidNoErr, FfMul(this->epid11_fq, r, r, r2));
  EXPECT_EQ(s, r2);
}

TEST_F(FfElementTest, FfSqrtReturnsARoot) {
  Prng my_prng;
  FfElementObj r(&this->fq);
  FfElementObj b(&this->fq);
  FfElementObj s(&this->fq);
  FfElementObj r2(&this->fq);
  unsigned int i;
  for (i = 0; i < 1000; i++) {
    ASSERT_EQ(kEpidNoErr, FfGetRandom(this->fq, &this->bn_2_str,
                                      &Prng::Generate, &my_prng, b));
    ASSERT_EQ(kEpidNoErr, FfMul(this->fq, b, b, s));
    ASSERT_EQ(kEpidNoErr, FfSqrt(this->fq, s, r));
    ASSERT_EQ(kEpidNoErr, FfMul(this->fq, r, r, r2));
    ASSERT_EQ(s, r2);
  }
}

TEST_F(FfElementTest, FfSqrtReturnsARootInEpid11) {
  Prng my_prng;
  FfElementObj r(&this->epid11_fq);
  FfElementObj b(&this->epid11_fq);
  FfElementObj s(&this->epid11_fq);
  FfElementObj r2(&this->epid11_fq);
  unsigned int i;
  for (i = 0; i < 1000; i++) {
    ASSERT_EQ(kEpidNoErr, FfGetRandom(this->epid11_fq, &this->bn_2_str,
                                      &Prng::Generate, &my_prng, b));
    ASSERT_EQ(kEpidNoErr, FfMul(this->epid11_fq, b, b, s));
    ASSERT_EQ(kEpidNoErr, FfSqrt(this->epid11_fq, s, r));
    ASSERT_EQ(kEpidNoErr, FfMul(this->epid11_fq, r, r, r2));
    ASSERT_EQ(s, r2);
  }
}

TEST_F(FfElementTest, FfSqrtReturnsARoot224Prime) {
  const BigNumStr prime_224r1 = {
      0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
  FiniteFieldObj f_q(prime_224r1);

  Prng my_prng;
  FfElementObj r(&f_q);
  FfElementObj b(&f_q);
  FfElementObj s(&f_q);
  FfElementObj r2(&f_q);
  unsigned int i;
  for (i = 0; i < 100; i++) {
    EXPECT_EQ(kEpidNoErr,
              FfGetRandom(f_q, &this->bn_2_str, &Prng::Generate, &my_prng, b));
    EXPECT_EQ(kEpidNoErr, FfMul(f_q, b, b, s));
    EXPECT_EQ(kEpidNoErr, FfSqrt(f_q, s, r));
    EXPECT_EQ(kEpidNoErr, FfMul(f_q, r, r, r2));
    EXPECT_EQ(s, r2);
  }
}

}  // namespace
