@@ -1348,6 +1348,121 @@ int CoToRat(UBYTE *s)
13481348
13491349/*
13501350 #] CoToRat :
1351+ #[ CoChop :
1352+
1353+ LHS notation of the chop statement:
1354+ TYPECHOP, length, FLOATFUN, ...
1355+ where FLOATFUN, ... represents the threshold of the chop statement in
1356+ the notation of a float_ function with its arguments.
1357+
1358+ */
1359+
1360+ int CoChop (UBYTE * s )
1361+ {
1362+ GETIDENTITY
1363+ UBYTE * ss , c ;
1364+ WORD * w , * OldWork ;
1365+ int spec , pow = 1 ;
1366+ unsigned long x ;
1367+ if ( AT .aux_ == 0 ) {
1368+ MesPrint ("&Illegal attempt to chop a float_ without activating floating point numbers." );
1369+ MesPrint ("&Forgotten %#startfloat instruction?" );
1370+ return (1 );
1371+ }
1372+ if ( * s == 0 ) {
1373+ MesPrint ("&Chop needs a number (float or rational) as an argument." );
1374+ return (1 );
1375+ }
1376+ /* Create TYPECHOP header */
1377+ w = OldWork = AT .WorkPointer ;
1378+ * w ++ = TYPECHOP ;
1379+ w ++ ;
1380+
1381+ while ( * s == ' ' || * s == ',' || * s == '\t' ) s ++ ;
1382+
1383+ /*
1384+ The argument of chop can be
1385+ 1: a floating-point number
1386+ 2: an integer, rational number or power
1387+ */
1388+ if ( FG .cTable [* s ] == 1 || * s == '.' ) {
1389+ /* 1: Attempt to parse as floating-point number */
1390+ ss = CheckFloat (s , & spec );
1391+ if ( ss > s ) {
1392+ /* CheckFloat found a valid float */
1393+ if ( spec == 1 ) { /* Zero */
1394+ MesPrint ("&The argument in Chop needs to be larger than 0." );
1395+ return (1 );
1396+ }
1397+ else if ( spec == -1 ) {
1398+ MesPrint ("&The floating point system has not been started." );
1399+ return (1 );
1400+ }
1401+ else {
1402+ AT .WorkPointer = w ;
1403+ /*
1404+ Reads the floating point number and outputs it at AT.WorkPointer as if it were a float_
1405+ function with its arguments.
1406+ */
1407+ ReadFloat ((SBYTE * )s );
1408+ s = ss ;
1409+ w += w [1 ];
1410+ }
1411+ }
1412+ else {
1413+ /* 2: CheckFloat didn't find a float, we now try for integers and rationals */
1414+ /* Parse the integer part (numerator for rationals) */
1415+ ss = s ;
1416+ while ( FG .cTable [* s ] == 1 ) s ++ ; /* Skip over digits */
1417+ c = * s ; * s = 0 ;
1418+ gmp_sscanf ((char * )ss , "%Ff" , aux1 ); /* Parse into GMP float */
1419+ if ( mpf_sgn (aux1 ) == 0 ) {
1420+ MesPrint ("&The argument in Chop needs to be larger than 0." );
1421+ return (1 );
1422+ }
1423+ * s = c ;
1424+ while ( * s == ' ' || * s == '\t' ) s ++ ;
1425+ /* Check for rational number or power*/
1426+ if ( * s == '/' || * s == '^' ) {
1427+ c = * s ; s ++ ;
1428+ while ( * s == ' ' || * s == '\t' ) s ++ ;
1429+ if ( * s == '-' ) { s ++ ; pow = -1 ; } /* negative power */
1430+ /* Parse the denominator or power */
1431+ if ( FG .cTable [* s ] == 1 ) {
1432+ ParseNumber (x ,s )
1433+ if ( c == '/' ) { /* rational */
1434+ if ( x == 0 ) {
1435+ MesPrint ("&Division by zero in chop statement." );
1436+ return (1 );
1437+ }
1438+ /* Perform the division */
1439+ mpf_div_ui (aux1 , aux1 ,x );
1440+ }
1441+ else { /* Power */
1442+ mpf_pow_ui (aux1 ,aux1 ,x );
1443+ if ( pow == -1 ) {
1444+ mpf_ui_div (aux1 ,(unsigned long ) 1 , aux1 );
1445+ }
1446+ }
1447+ }
1448+ }
1449+ /* Put aux1 in the notation of a float_ function */
1450+ PackFloat (w , aux1 );
1451+ w += w [1 ];
1452+ }
1453+ }
1454+ if ( * s ) {
1455+ MesPrint ("&Illegal argument(s) in Chop statement: '%s'" ,s );
1456+ return (1 );
1457+ }
1458+ AT .WorkPointer = OldWork ;
1459+ AT .WorkPointer [1 ] = w - AT .WorkPointer ; /* Set total length */
1460+ AddNtoL (AT .WorkPointer [1 ],AT .WorkPointer ); /* Add the LHS to the compiler buffer */
1461+ return (0 );
1462+ }
1463+
1464+ /*
1465+ #] CoChop :
13511466 #[ ToFloat :
13521467
13531468 Converts the coefficient to floating point if it is still a rat.
@@ -1416,6 +1531,46 @@ int ToRat(PHEAD WORD *term, WORD level)
14161531
14171532/*
14181533 #] ToRat :
1534+ #[ Chop :
1535+
1536+ Removes terms with a floating point number smaller than a given threshold.
1537+
1538+ Search for a FLOATFUN and compares its absolute value against the threshold
1539+ specified in the chop statement. This threshold can be obtained from the
1540+ LHS of the chop statement in the compiler buffer.
1541+
1542+ */
1543+ int Chop (PHEAD WORD * term , WORD level )
1544+ {
1545+ WORD * tstop , * t , nsize , * threshold ;
1546+ CBUF * C = cbuf + AM .rbufnum ;
1547+ /* Find the float which should be at the end. */
1548+ tstop = term + * term ;
1549+ nsize = ABS (tstop [-1 ]); tstop -= nsize ;
1550+ t = term + 1 ;
1551+ while ( t < tstop ) {
1552+ if ( * t == FLOATFUN && t + t [1 ] == tstop && TestFloat (t ) &&
1553+ nsize == 3 && tstop [0 ] == 1 && tstop [1 ] == 1 ) break ;
1554+ t += t [1 ];
1555+ }
1556+ if ( t < tstop ) {
1557+ /* Get threshold value from compiler buffer */
1558+ threshold = C -> lhs [level ];
1559+ threshold += 2 ; /* Skip TYPECHOP header */
1560+ UnpackFloat (aux5 , threshold );
1561+
1562+ /* Extract float and compute its absolute value */
1563+ UnpackFloat (aux4 , t );
1564+ mpf_abs (aux4 , aux4 );
1565+
1566+ /* Remove if < threshold */
1567+ if ( mpf_cmp (aux4 , aux5 ) < 0 ) return (0 );
1568+ }
1569+ return (Generator (BHEAD term ,level )) ;
1570+ }
1571+
1572+ /*
1573+ #] Chop :
14191574 #] Float Routines :
14201575 #[ Sorting :
14211576
0 commit comments