ecma_bigint_pow (ecma_value_t left_value, /**< left BigInt value */
                 ecma_value_t right_value) /**< right BigInt value */
{
  JERRY_ASSERT (ecma_is_value_bigint (left_value) && ecma_is_value_bigint (right_value));

  if (right_value == ECMA_BIGINT_ZERO)
  {
    return ecma_bigint_create_from_digit (1, false);
  }

  ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value);

  if (right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)
  {
    return ecma_raise_range_error (ECMA_ERR_MSG ("Negative exponent is not allowed for BigInts"));
  }

  if (left_value == ECMA_BIGINT_ZERO)
  {
    return ECMA_BIGINT_ZERO;
  }

  ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value);
  ecma_bigint_digit_t base = 0;

  if (ECMA_BIGINT_GET_SIZE (left_p) == sizeof (ecma_bigint_digit_t))
  {
    base = *ECMA_BIGINT_GET_DIGITS (left_p, 0);

    JERRY_ASSERT (base != 0);

    if (base == 1)
    {
      if (!(left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)
          || ECMA_BIGINT_NUMBER_IS_ODD (*ECMA_BIGINT_GET_DIGITS (right_p, 0)))
      {
        ecma_ref_extended_primitive (left_p);
        return left_value;
      }

      return ecma_bigint_create_from_digit (1, false);
    }
  }

  if (JERRY_UNLIKELY (ECMA_BIGINT_GET_SIZE (right_p) > sizeof (ecma_bigint_digit_t)))
  {
    return ecma_bigint_raise_memory_error ();
  }

  ecma_bigint_digit_t power = *ECMA_BIGINT_GET_DIGITS (right_p, 0);

  if (power == 1)
  {
    ecma_ref_extended_primitive (left_p);
    return left_value;
  }

  ecma_extended_primitive_t *result_p;

  if (base == 2)
  {
    result_p = ecma_big_uint_shift_left (left_p, power - 1);
  }
  else
  {
    result_p = ecma_big_uint_pow (left_p, power);
  }

  if (JERRY_UNLIKELY (result_p == NULL))
  {
    return ecma_bigint_raise_memory_error ();
  }

  if ((left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) && ECMA_BIGINT_NUMBER_IS_ODD (power))
  {
    result_p->u.bigint_sign_and_size |= ECMA_BIGINT_SIGN;
  }

  return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT);
} /* ecma_bigint_pow */
ecma_bigint_pow (ecma_value_t left_value,  
                 ecma_value_t right_value)  
{
  JERRY_ASSERT (ecma_is_value_bigint (left_value) && ecma_is_value_bigint (right_value));

  if (right_value == ECMA_BIGINT_ZERO)
  {
    return ecma_bigint_create_from_digit (1, false);
  }

  ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value);

  if (right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)
  {
    return ecma_raise_range_error (ECMA_ERR_MSG ("Negative exponent is not allowed for BigInts"));
  }

  if (left_value == ECMA_BIGINT_ZERO)
  {
    return ECMA_BIGINT_ZERO;
  }

  ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value);
  ecma_bigint_digit_t base = 0;

  if (ECMA_BIGINT_GET_SIZE (left_p) == sizeof (ecma_bigint_digit_t))
  {
    base = *ECMA_BIGINT_GET_DIGITS (left_p, 0);

    JERRY_ASSERT (base != 0);

    if (base == 1)
    {
      if (!(left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)
          || ECMA_BIGINT_NUMBER_IS_ODD (*ECMA_BIGINT_GET_DIGITS (right_p, 0)))
      {
        ecma_ref_extended_primitive (left_p);
        return left_value;
      }

      return ecma_bigint_create_from_digit (1, false);
    }
  }

  if (JERRY_UNLIKELY (ECMA_BIGINT_GET_SIZE (right_p) > sizeof (ecma_bigint_digit_t)))
  {
    return ecma_bigint_raise_memory_error ();
  }

  ecma_bigint_digit_t power = *ECMA_BIGINT_GET_DIGITS (right_p, 0);

  if (power == 1)
  {
    ecma_ref_extended_primitive (left_p);
    return left_value;
  }

  ecma_extended_primitive_t *result_p;

  if (base == 2)
  {
    result_p = ecma_big_uint_shift_left (left_p, power - 1);
  }
  else
  {
    result_p = ecma_big_uint_pow (left_p, power);
  }

  if (JERRY_UNLIKELY (result_p == NULL))
  {
    return ecma_bigint_raise_memory_error ();
  }

  if ((left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) && ECMA_BIGINT_NUMBER_IS_ODD (power))
  {
    result_p->u.bigint_sign_and_size |= ECMA_BIGINT_SIGN;
  }

  return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT);
}  