@@ -1395,6 +1395,120 @@ int CoStrictRounding(UBYTE *s)
13951395}
13961396/*
13971397 #] CoStrictRounding :
1398+ #[ CoChop :
1399+
1400+ LHS notation of the chop statement:
1401+ TYPECHOP, length, FLOATFUN, ...
1402+ where FLOATFUN, ... represents the threshold of the chop statement in
1403+ the notation of a float_ function with its arguments.
1404+
1405+ */
1406+
1407+ int CoChop (UBYTE * s )
1408+ {
1409+ GETIDENTITY
1410+ UBYTE * ss , c ;
1411+ WORD * w , * OldWork ;
1412+ int spec , pow = 1 ;
1413+ unsigned long x ;
1414+ if ( AT .aux_ == 0 ) {
1415+ MesPrint ("&Illegal attempt to chop a float_ without activating floating point numbers." );
1416+ MesPrint ("&Forgotten %#startfloat instruction?" );
1417+ return (1 );
1418+ }
1419+ if ( * s == 0 ) {
1420+ MesPrint ("&Chop needs a number (float or rational) as an argument." );
1421+ return (1 );
1422+ }
1423+ /* Create TYPECHOP header */
1424+ w = OldWork = AT .WorkPointer ;
1425+ * w ++ = TYPECHOP ;
1426+ w ++ ;
1427+
1428+ while ( * s == ' ' || * s == ',' || * s == '\t' ) s ++ ;
1429+
1430+ /*
1431+ The argument of chop can be
1432+ 1: a floating-point number
1433+ 2: an integer, rational number or power
1434+ */
1435+ if ( FG .cTable [* s ] == 1 || * s == '.' ) {
1436+ /* 1: Attempt to parse as floating-point number */
1437+ ss = CheckFloat (s , & spec );
1438+ if ( ss > s ) {
1439+ /* CheckFloat found a valid float */
1440+ if ( spec == 1 ) { /* Zero */
1441+ MesPrint ("&The argument in Chop needs to be larger than 0." );
1442+ return (1 );
1443+ }
1444+ else if ( spec == -1 ) {
1445+ MesPrint ("&The floating point system has not been started." );
1446+ return (1 );
1447+ }
1448+ else {
1449+ AT .WorkPointer = w ;
1450+ /*
1451+ Reads the floating point number and outputs it at AT.WorkPointer as if it were a float_
1452+ function with its arguments.
1453+ */
1454+ ReadFloat ((SBYTE * )s );
1455+ s = ss ;
1456+ w += w [1 ];
1457+ }
1458+ }
1459+ else {
1460+ /* 2: CheckFloat didn't find a float, we now try for rationals and powers */
1461+ /* Parse the integer part (numerator for rationals) */
1462+ if ( FG .cTable [* s ] == 1 ) {
1463+ ParseNumber (x ,s )
1464+ mpf_set_ui (aux1 ,x );
1465+ }
1466+ if ( mpf_sgn (aux1 ) == 0 ) {
1467+ MesPrint ("&The argument in Chop needs to be larger than 0." );
1468+ return (1 );
1469+ }
1470+ while ( * s == ' ' || * s == '\t' ) s ++ ;
1471+ /* Check for rational number or power*/
1472+ if ( * s == '/' || * s == '^' ) {
1473+ c = * s ; s ++ ;
1474+ while ( * s == ' ' || * s == '\t' ) s ++ ;
1475+ if ( * s == '-' ) { s ++ ; pow = -1 ; } /* negative power */
1476+ /* Parse the denominator or power */
1477+ if ( FG .cTable [* s ] == 1 ) {
1478+ ParseNumber (x ,s )
1479+ if ( c == '/' ) { /* rational */
1480+ if ( x == 0 ) {
1481+ MesPrint ("&Division by zero in chop statement." );
1482+ return (1 );
1483+ }
1484+ /* Perform the division */
1485+ mpf_div_ui (aux1 , aux1 ,x );
1486+ }
1487+ else { /* Power */
1488+ mpf_pow_ui (aux1 ,aux1 ,x );
1489+ if ( pow == -1 ) {
1490+ mpf_ui_div (aux1 ,(unsigned long ) 1 , aux1 );
1491+ }
1492+ }
1493+ }
1494+ }
1495+ /* Put aux1 in the notation of a float_ function */
1496+ PackFloat (w , aux1 );
1497+ w += w [1 ];
1498+ }
1499+ }
1500+ if ( * s ) {
1501+ MesPrint ("&Illegal argument(s) in Chop statement: '%s'" ,s );
1502+ return (1 );
1503+ }
1504+ AT .WorkPointer = OldWork ;
1505+ AT .WorkPointer [1 ] = w - AT .WorkPointer ; /* Set total length */
1506+ AddNtoL (AT .WorkPointer [1 ],AT .WorkPointer ); /* Add the LHS to the compiler buffer */
1507+ return (0 );
1508+ }
1509+
1510+ /*
1511+ #] CoChop :
13981512 #[ ToFloat :
13991513
14001514 Converts the coefficient to floating point if it is still a rat.
@@ -1521,6 +1635,46 @@ int StrictRounding(PHEAD WORD *term, WORD level, WORD prec, WORD base) {
15211635}
15221636/*
15231637 #] StrictRounding :
1638+ #[ Chop :
1639+
1640+ Removes terms with a floating point number smaller than a given threshold.
1641+
1642+ Search for a FLOATFUN and compares its absolute value against the threshold
1643+ specified in the chop statement. This threshold can be obtained from the
1644+ LHS of the chop statement in the compiler buffer.
1645+
1646+ */
1647+ int Chop (PHEAD WORD * term , WORD level )
1648+ {
1649+ WORD * tstop , * t , nsize , * threshold ;
1650+ CBUF * C = cbuf + AM .rbufnum ;
1651+ /* Find the float which should be at the end. */
1652+ tstop = term + * term ;
1653+ nsize = ABS (tstop [-1 ]); tstop -= nsize ;
1654+ t = term + 1 ;
1655+ while ( t < tstop ) {
1656+ if ( * t == FLOATFUN && t + t [1 ] == tstop && TestFloat (t ) &&
1657+ nsize == 3 && tstop [0 ] == 1 && tstop [1 ] == 1 ) break ;
1658+ t += t [1 ];
1659+ }
1660+ if ( t < tstop ) {
1661+ /* Get threshold value from compiler buffer */
1662+ threshold = C -> lhs [level ];
1663+ threshold += 2 ; /* Skip TYPECHOP header */
1664+ UnpackFloat (aux5 , threshold );
1665+
1666+ /* Extract float and compute its absolute value */
1667+ UnpackFloat (aux4 , t );
1668+ mpf_abs (aux4 , aux4 );
1669+
1670+ /* Remove if < threshold */
1671+ if ( mpf_cmp (aux4 , aux5 ) < 0 ) return (0 );
1672+ }
1673+ return (Generator (BHEAD term ,level )) ;
1674+ }
1675+
1676+ /*
1677+ #] Chop :
15241678 #] Float Routines :
15251679 #[ Sorting :
15261680
0 commit comments