@@ -3781,6 +3781,43 @@ mpd_qdiv(mpd_t *q, const mpd_t *a, const mpd_t *b,
37813781 const mpd_context_t * ctx , uint32_t * status )
37823782{
37833783 _mpd_qdiv (SET_IDEAL_EXP , q , a , b , ctx , status );
3784+
3785+ if (* status & MPD_Malloc_error ) {
3786+ /* Inexact quotients (the usual case) fill the entire context precision,
3787+ * which can lead to malloc() failures for very high precisions. Retry
3788+ * the operation with a lower precision in case the result is exact.
3789+ *
3790+ * We need an upper bound for the number of digits of a_coeff / b_coeff
3791+ * when the result is exact. If a_coeff' * 1 / b_coeff' is in lowest
3792+ * terms, then maxdigits(a_coeff') + maxdigits(1 / b_coeff') is a suitable
3793+ * bound.
3794+ *
3795+ * 1 / b_coeff' is exact iff b_coeff' exclusively has prime factors 2 or 5.
3796+ * The largest amount of digits is generated if b_coeff' is a power of 2 or
3797+ * a power of 5 and is less than or equal to log5(b_coeff') <= log2(b_coeff').
3798+ *
3799+ * We arrive at a total upper bound:
3800+ *
3801+ * maxdigits(a_coeff') + maxdigits(1 / b_coeff') <=
3802+ * a->digits + log2(b_coeff) =
3803+ * a->digits + log10(b_coeff) / log10(2) <=
3804+ * a->digits + b->digits * 4;
3805+ */
3806+ uint32_t workstatus = 0 ;
3807+ mpd_context_t workctx = * ctx ;
3808+ workctx .prec = a -> digits + b -> digits * 4 ;
3809+ if (workctx .prec >= ctx -> prec ) {
3810+ return ; /* No point in retrying, keep the original error. */
3811+ }
3812+
3813+ _mpd_qdiv (SET_IDEAL_EXP , q , a , b , & workctx , & workstatus );
3814+ if (workstatus == 0 ) { /* The result is exact, unrounded, normal etc. */
3815+ * status = 0 ;
3816+ return ;
3817+ }
3818+
3819+ mpd_seterror (q , * status , status );
3820+ }
37843821}
37853822
37863823/* Internal function. */
@@ -7702,9 +7739,9 @@ mpd_qinvroot(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
77027739/* END LIBMPDEC_ONLY */
77037740
77047741/* Algorithm from decimal.py */
7705- void
7706- mpd_qsqrt (mpd_t * result , const mpd_t * a , const mpd_context_t * ctx ,
7707- uint32_t * status )
7742+ static void
7743+ _mpd_qsqrt (mpd_t * result , const mpd_t * a , const mpd_context_t * ctx ,
7744+ uint32_t * status )
77087745{
77097746 mpd_context_t maxcontext ;
77107747 MPD_NEW_STATIC (c ,0 ,0 ,0 ,0 );
@@ -7836,6 +7873,40 @@ mpd_qsqrt(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
78367873 goto out ;
78377874}
78387875
7876+ void
7877+ mpd_qsqrt (mpd_t * result , const mpd_t * a , const mpd_context_t * ctx ,
7878+ uint32_t * status )
7879+ {
7880+ _mpd_qsqrt (result , a , ctx , status );
7881+
7882+ if (* status & (MPD_Malloc_error |MPD_Division_impossible )) {
7883+ /* The above conditions can occur at very high context precisions
7884+ * if intermediate values get too large. Retry the operation with
7885+ * a lower context precision in case the result is exact.
7886+ *
7887+ * If the result is exact, an upper bound for the number of digits
7888+ * is the number of digits in the input.
7889+ *
7890+ * NOTE: sqrt(40e9) = 2.0e+5 /\ digits(40e9) = digits(2.0e+5) = 2
7891+ */
7892+ uint32_t workstatus = 0 ;
7893+ mpd_context_t workctx = * ctx ;
7894+ workctx .prec = a -> digits ;
7895+
7896+ if (workctx .prec >= ctx -> prec ) {
7897+ return ; /* No point in repeating this, keep the original error. */
7898+ }
7899+
7900+ _mpd_qsqrt (result , a , & workctx , & workstatus );
7901+ if (workstatus == 0 ) {
7902+ * status = 0 ;
7903+ return ;
7904+ }
7905+
7906+ mpd_seterror (result , * status , status );
7907+ }
7908+ }
7909+
78397910
78407911/******************************************************************************/
78417912/* Base conversions */
0 commit comments