int fp_exptmod_ex(fp_int * G, fp_int * X, int digits, fp_int * P, fp_int * Y)
{

#if defined(WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) && \
   !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI)
   int x = fp_count_bits (X);
#endif

   if (fp_iszero(G)) {
      fp_set(G, 0);
      return FP_OKAY;
   }

   /* prevent overflows */
   if (P->used > (FP_SIZE/2)) {
      return FP_VAL;
   }

#if defined(WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) && \
   !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI)
   if(x > EPS_RSA_EXPT_XBTIS) {
      return esp_mp_exptmod(G, X, x, P, Y);
   }
#endif

   if (X->sign == FP_NEG) {
#ifndef POSITIVE_EXP_ONLY  /* reduce stack if assume no negatives */
      int    err;
   #ifndef WOLFSSL_SMALL_STACK
      fp_int tmp[2];
   #else
      fp_int *tmp;
   #endif

   #ifdef WOLFSSL_SMALL_STACK
      tmp = (fp_int*)XMALLOC(sizeof(fp_int) * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER);
      if (tmp == NULL)
          return FP_MEM;
   #endif

      /* yes, copy G and invmod it */
      fp_init_copy(&tmp[0], G);
      fp_init_copy(&tmp[1], P);
      tmp[1].sign = FP_ZPOS;
      err = fp_invmod(&tmp[0], &tmp[1], &tmp[0]);
      if (err == FP_OKAY) {
         X->sign = FP_ZPOS;
         err =  _fp_exptmod(&tmp[0], X, digits, P, Y);
         if (X != Y) {
            X->sign = FP_NEG;
         }
         if (P->sign == FP_NEG) {
            fp_add(Y, P, Y);
         }
      }
   #ifdef WOLFSSL_SMALL_STACK
      XFREE(tmp, NULL, DYNAMIC_TYPE_BIGINT);
   #endif
      return err;
#else
      return FP_VAL;
#endif
   }
   else {
      /* Positive exponent so just exptmod */
      return _fp_exptmod(G, X, digits, P, Y);
   }
}
int fp_exptmod_ex(fp_int * G, fp_int * X, int digits, fp_int * P, fp_int * Y)
{

#if defined(WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) && \
   !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI)
   int x = fp_count_bits (X);
#endif

   if (fp_iszero(G)) {
      fp_set(G, 0);
      return FP_OKAY;
   }

    
   if (P->used > (FP_SIZE/2)) {
      return FP_VAL;
   }

#if defined(WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) && \
   !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI)
   if(x > EPS_RSA_EXPT_XBTIS) {
      return esp_mp_exptmod(G, X, x, P, Y);
   }
#endif

   if (X->sign == FP_NEG) {
#ifndef POSITIVE_EXP_ONLY   
      int    err;
   #ifndef WOLFSSL_SMALL_STACK
      fp_int tmp[2];
   #else
      fp_int *tmp;
   #endif

   #ifdef WOLFSSL_SMALL_STACK
      tmp = (fp_int*)XMALLOC(sizeof(fp_int) * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER);
      if (tmp == NULL)
          return FP_MEM;
   #endif

       
      fp_init_copy(&tmp[0], G);
      fp_init_copy(&tmp[1], P);
      tmp[1].sign = FP_ZPOS;
      err = fp_invmod(&tmp[0], &tmp[1], &tmp[0]);
      if (err == FP_OKAY) {
         X->sign = FP_ZPOS;
         err =  _fp_exptmod(&tmp[0], X, digits, P, Y);
         if (X != Y) {
            X->sign = FP_NEG;
         }
         if (P->sign == FP_NEG) {
            fp_add(Y, P, Y);
         }
      }
   #ifdef WOLFSSL_SMALL_STACK
      XFREE(tmp, NULL, DYNAMIC_TYPE_BIGINT);
   #endif
      return err;
#else
      return FP_VAL;
#endif
   }
   else {
       
      return _fp_exptmod(G, X, digits, P, Y);
   }
}