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