@@ -917,7 +917,7 @@ int SetFloatPrecision(WORD prec)
917917 else {
918918 AC .DefaultPrecision = prec ;
919919 if ( AO .floatspace != 0 ) M_free (AO .floatspace ,"floatspace" );
920- AO .floatsize = (( 10 * prec )/ 33 + 20 )* sizeof (char );
920+ AO .floatsize = (prec + 64 )* sizeof (char );
921921 AO .floatspace = (UBYTE * )Malloc1 (AO .floatsize ,"floatspace" );
922922 mpf_set_default_prec (prec );
923923 return (0 );
@@ -1348,6 +1348,50 @@ int CoToRat(UBYTE *s)
13481348
13491349/*
13501350 #] CoToRat :
1351+ #[ CoStrictRounding :
1352+
1353+ Syntax: StrictRounding [precision][base]
1354+ - precision: number of digits to round to (optional)
1355+ - base: 'd' for decimal (base 10) or 'b' for binary (base 2)
1356+
1357+ If no arguments are provided, uses default precision with binary base.
1358+ */
1359+ int CoStrictRounding (UBYTE * s )
1360+ {
1361+ GETIDENTITY
1362+ WORD x ;
1363+ int base ;
1364+ if ( AT .aux_ == 0 ) {
1365+ MesPrint ("&Illegal attempt for strict rounding without activating floating point numbers." );
1366+ MesPrint ("&Forgotten %#startfloat instruction?" );
1367+ return (1 );
1368+ }
1369+ while ( * s == ' ' || * s == ',' || * s == '\t' ) s ++ ;
1370+ if ( * s == 0 ) {
1371+ /* No subkey, which means round to default precision */
1372+ x = AC .DefaultPrecision - AC .MaxWeight - 1 ;
1373+ Add4Com (TYPESTRICTROUNDING ,x ,2 );
1374+ return (0 );
1375+ }
1376+ if ( FG .cTable [* s ] == 1 ) { /* number */
1377+ ParseNumber (x ,s )
1378+ if ( tolower (* s ) == 'd' ) { base = 10 ; s ++ ; } /* decimal base */
1379+ else if ( tolower (* s ) == 'b' ){ base = 2 ; s ++ ; } /* binary base */
1380+ else goto IllPar ; /* invalid base specification */
1381+ }
1382+ while ( * s == ' ' || * s == ',' || * s == '\t' ) s ++ ;
1383+
1384+ /* Check for invalid arguments */
1385+ if ( * s ) {
1386+ IllPar :
1387+ MesPrint ("&Illegal argument(s) in StrictRounding statement: '%s'" ,s );
1388+ return (1 );
1389+ }
1390+ Add4Com (TYPESTRICTROUNDING ,x ,base );
1391+ return (0 );
1392+ }
1393+ /*
1394+ #] CoStrictRounding :
13511395 #[ ToFloat :
13521396
13531397 Converts the coefficient to floating point if it is still a rat.
@@ -1416,6 +1460,52 @@ int ToRat(PHEAD WORD *term, WORD level)
14161460
14171461/*
14181462 #] ToRat :
1463+ #[ StrictRounding :
1464+
1465+ Rounds floating point numbers to a specified precision
1466+ in a given base (decimal or binary).
1467+ */
1468+ int StrictRounding (PHEAD WORD * term , WORD level , WORD prec , WORD base ) {
1469+ WORD * tstop , * t , * oldworkpointer = AT .WorkPointer ;
1470+ int retval ,sign ;
1471+
1472+ tstop = term + * term ; tstop -= ABS (tstop [-1 ]);
1473+ t = term + 1 ;
1474+ while ( t < tstop ) {
1475+ if ( * t == FLOATFUN && t + t [1 ] == tstop ) {
1476+ char * s ;
1477+ mp_exp_t exp ;
1478+ /* Extract the floating point value */
1479+ UnpackFloat (aux4 ,t );
1480+ /* Convert to string: the generated string is a fraction with an implicit
1481+ radix point immediately to the left of the first digit.
1482+ The applicable exponent is written in exp. */
1483+ s = mpf_get_str (0 ,& exp , base , prec , aux4 );
1484+ /* Format as MeN with M the mantissa and N the exponent */
1485+ snprintf ((char * )AO .floatspace ,AO .floatsize ,".%se%ld" ,s ,exp );
1486+ /* Negative base values are used to specify that the exponent is in decimal */
1487+ mpf_set_str (aux4 ,(char * )AO .floatspace ,- base );
1488+ free (s );
1489+ break ;
1490+ }
1491+ t += t [1 ];
1492+ }
1493+ if ( t < tstop ) {
1494+ /* Pack the rounded floating point value back into the term */
1495+ PackFloat (t ,aux4 );
1496+ t += t [1 ];
1497+ if ( term [* term - 1 ] < 0 ) sign = -1 ;
1498+ else sign = 1 ;
1499+ * t ++ = 1 ; * t ++ = 1 ; * t ++ = 3 * sign ;
1500+ * term = t - term ;
1501+ }
1502+ AT .WorkPointer = t ;
1503+ retval = Generator (BHEAD term ,level );
1504+ AT .WorkPointer = oldworkpointer ;
1505+ return (retval );
1506+ }
1507+ /*
1508+ #] StrictRounding :
14191509 #] Float Routines :
14201510 #[ Sorting :
14211511
0 commit comments