@@ -591,7 +591,7 @@ long FloatToInteger(UWORD *out, mpf_t floatin, long *bitsused)
591591 mpz_set_f (z ,floatin );
592592 ZtoForm (out ,& nout ,z );
593593 mpz_clear (z );
594- x = out [0 ]; nx = 0 ;
594+ x = out [nout - 1 ]; nx = 0 ;
595595 while ( x ) { nx ++ ; x >>= 1 ; }
596596 * bitsused = (nout - 1 )* BITSINWORD + nx ;
597597 return (nout );
@@ -678,7 +678,7 @@ int FloatToRat(UWORD *ratout, WORD *nratout, mpf_t floatin)
678678 WORD na , nb , nc , nd , i ;
679679 int nout ;
680680 LONG oldpWorkPointer = AT .pWorkPointer ;
681- long bitsused = 0 , totalbitsused = 0 , totalbits = AC .DefaultPrecision ;
681+ long bitsused = 0 , totalbitsused = 0 , totalbits = AC .DefaultPrecision - AC . MaxWeight - 1 ;
682682 int retval = 0 , startnul ;
683683 WantAddPointers (AC .DefaultPrecision ); /* Horrible overkill */
684684 AT .pWorkSpace [AT .pWorkPointer ++ ] = out ;
@@ -710,15 +710,24 @@ int FloatToRat(UWORD *ratout, WORD *nratout, mpf_t floatin)
710710 else {
711711 nout = FloatToInteger ((UWORD * )out ,aux1 ,& bitsused );
712712 out += nout ;
713- totalbitsused += bitsused ;
714713 }
715714 if ( bitsused > (totalbits - totalbitsused )/2 ) { break ; }
716715 if ( mpf_sgn (aux2 ) == 0 ) {
717716 /*if ( startnul == 1 )*/ AT .pWorkSpace [AT .pWorkPointer ++ ] = out ;
718717 break ;
719718 }
719+ totalbitsused += bitsused ;
720720 AT .pWorkSpace [AT .pWorkPointer ++ ] = out ;
721721 }
722+ /*
723+ For |floatin| << 1, we have startnul = 1 and hit the precision guard
724+ already on the first continued-fraction step. The resulting float is
725+ therefore close to the rational 0/1 and we can immediately return.
726+ */
727+ if ( startnul == 1 && AT .pWorkPointer == oldpWorkPointer + 2 ) {
728+ * ratout ++ = 0 ; * ratout ++ = 1 ; * ratout = * nratout = 3 ;
729+ goto ret ;
730+ }
722731/*
723732 At this point we have the function with the repeated fraction.
724733 Now we should work out the fraction. Form code would be:
@@ -734,11 +743,6 @@ int FloatToRat(UWORD *ratout, WORD *nratout, mpf_t floatin)
734743 na = 1 ; a [0 ] = 1 ;
735744 c = (UWORD * )(AT .pWorkSpace [-- AT .pWorkPointer ]);
736745 nc = nb = ((UWORD * )out )- c ;
737- if ( nc > 10 ) {
738- mc = c ;
739- c = (UWORD * )(AT .pWorkSpace [-- AT .pWorkPointer ]);
740- nc = nb = ((UWORD * )mc )- c ;
741- }
742746 for ( i = 0 ; i < nb ; i ++ ) b [i ] = c [i ];
743747 mc = c = NumberMalloc ("FloatToRat" );
744748 while ( AT .pWorkPointer > oldpWorkPointer ) {
@@ -791,12 +795,13 @@ int FloatToRat(UWORD *ratout, WORD *nratout, mpf_t floatin)
791795 if ( s < 0 ) mpf_neg (floatin ,floatin );
792796/*
793797 {
794- WORD n = *ratout ;
798+ WORD n = *nratout ;
795799 RatToFloat(aux1,ratout,n);
796800 mpf_sub(aux2,floatin,aux1);
797801 gmp_printf("Diff is %.*Fe\n",40,aux2);
798802 }
799803*/
804+ ret :
800805 return (retval );
801806}
802807
@@ -1492,7 +1497,11 @@ int ToRat(PHEAD WORD *term, WORD level)
14921497 The result can go straight over the float_ function.
14931498*/
14941499 UnpackFloat (aux4 ,t );
1500+ // If aux4 is zero, the term vanishes
1501+ if ( mpf_sgn (aux4 ) == 0 ) return (0 );
14951502 if ( FloatToRat ((UWORD * )t ,& ncoef ,aux4 ) == 0 ) {
1503+ // Check if the resulting rational is zero
1504+ if ( t [0 ] == 0 && t [1 ] == 1 && ncoef == 3 ) return (0 );
14961505 t += ABS (ncoef );
14971506 t [-1 ] = ncoef * nsign ;
14981507 * term = t - term ;
0 commit comments