home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / oct93 / develop / umbscheme.lha / UMBScheme / src / rational.c < prev    next >
C/C++ Source or Header  |  1992-08-04  |  15KB  |  812 lines

  1. /* rational.c -- UMB Scheme, specific rational number procedures.
  2.  
  3. UMB Scheme Interpreter                  $Revision: 2.5 $
  4. Copyright (C) 1988, 1991 William R Campbell
  5.  
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  
  20. UMB Scheme was written by Bill Campbell with help from Karl Berry,
  21. Barbara Dixey, Ira Gerstein, Mary Glaser, Kathy Hargreaves, Bill McCabe,
  22. Long Nguyen, Susan Quina, Jeyashree Sivasubram, Bela Sohoni and Thang Quoc Tran.
  23.  
  24. For additional information about UMB Scheme, contact the author:
  25.  
  26.     Bill Campbell
  27.     Department of Mathematics and Computer Science
  28.     University of Massachusetts at Boston
  29.     Harbor Campus
  30.     Boston, MA 02125
  31.  
  32.     Telephone: 617-287-6449        Internet: bill@cs.umb.edu
  33.  
  34. */
  35.  
  36.  
  37. #include "portable.h"
  38. #include "eval.h"
  39. #include "object.h"
  40. #include "architecture.h"
  41. #include "number.h"
  42. #include "fixnum.h"
  43. #include "bignum.h"
  44. #include "rational.h"
  45. #include "real.h"
  46. #include "complex.h"
  47. #include "steering.h"
  48. #include "io.h"
  49. #include <math.h>
  50. #include <errno.h>
  51.  
  52. Private Short Rational_Compare();
  53.  
  54.  
  55.  
  56. /* Predicates. */
  57.  
  58. Public Boolean Is_Rational_Zero()
  59. {
  60.       return (Number_Sign(Get_Number_Rational_Numerator(Top(1))) == 0);;
  61. }
  62.  
  63. Public Boolean Is_Rational_Positive()
  64. {
  65.     return (Number_Sign(Get_Number_Rational_Numerator(Top(1))) > 0);
  66. }
  67.  
  68. Public Boolean Is_Rational_Negative()
  69. {
  70.     return(Number_Sign(Get_Number_Rational_Numerator(Top(1))) < 0);
  71. }
  72.  
  73. Public Boolean Is_Rational_Odd()
  74. {
  75.     Error("Rationals aren't odd or even");
  76.     return FALSE;
  77. }
  78.  
  79. Public Boolean Is_Rational_Even()
  80. {
  81.     Error("Rationals aren't odd or even");
  82.     return FALSE;
  83. }
  84.  
  85. Public Boolean Is_Rational_Exact()
  86. {
  87.     return (Is_Exact_Number(Top(1)));
  88. }
  89.  
  90. Public Boolean Is_Rational_Inexact()
  91. {
  92.     return (! Is_Exact_Number(Top(1)));
  93. }
  94.  
  95.  
  96.  
  97. /* Comparisons. */
  98.  
  99. Public Boolean Rational_Less_Than()
  100. {
  101.     return Rational_Compare() < 0;
  102. }
  103.  
  104. Public Boolean Rational_Greater_Than()
  105. {
  106.     return Rational_Compare() > 0;
  107. }
  108.  
  109. Public Boolean Rational_Equal()
  110. {
  111.     return Rational_Compare() == 0;
  112. }
  113.  
  114. Public Boolean Rational_Less_Than_Or_Equal()
  115. {
  116.     return Rational_Compare() <= 0;
  117. }
  118.  
  119. Public Boolean Rational_Greater_Than_Or_Equal()
  120. {
  121.     return Rational_Compare() >= 0;
  122. }
  123.  
  124. Private Short Rational_Compare()
  125. {
  126.     Rational_Subtract();
  127.     return Number_Sign( Get_Number_Rational_Numerator( Value_Register ));
  128. }
  129.  
  130.  
  131.  
  132.  
  133. /* Arithmetic. */
  134.  
  135. Public void Rational_Add()
  136. {
  137.     /* rat 1 = a/b, rat 2 = c/d, result = (a*d + b*c)/b*d     */
  138.  
  139.     Push(Get_Number_Rational_Numerator(Top( 2 )));    /* numer rat 1 */
  140.     Push(Get_Number_Rational_Denominator(Top( 2 )));  /* denom rat 2 */
  141.     Number_Multiply();
  142.     Pop( 2 );
  143.     Push( Value_Register );
  144.  
  145.     Push(Get_Number_Rational_Denominator(Top( 3 )));  /* denom rat 1 */
  146.     Push(Get_Number_Rational_Numerator(Top( 3 )));    /* numer rat 2 */
  147.     Number_Multiply();
  148.     Pop( 2 );
  149.     Push( Value_Register );
  150.  
  151.     /* add 2 new numerators */
  152.     Number_Add();
  153.     Pop( 2 );
  154.     Push( Value_Register );
  155.  
  156.     Push(Get_Number_Rational_Denominator(Top( 3 )));  /* denom rat 1 */
  157.     Push(Get_Number_Rational_Denominator(Top( 3 ))); /* denom rat 2 */
  158.     Number_Multiply();
  159.     Pop( 2 );
  160.     Push( Value_Register );    /* denominator */
  161.  
  162.     Make_Rational_Number();
  163.     Pop( 2 );
  164.  
  165.     if ( ! Is_Exact_Number( Top(1) ) || ! Is_Exact_Number( Top(2) ) )
  166.     {
  167.         Push( Value_Register );
  168.         Number_Exact_To_Inexact(); Pop(1);
  169.     }
  170. }
  171.  
  172.  
  173.  
  174. Public void Rational_Subtract()
  175. {
  176.     /* rat 1 = a/b, rat 2 = c/d, result = (a*d - b*c)/b*d     */
  177.  
  178.     Push(Get_Number_Rational_Numerator(Top( 2 )));    /* numer rat 1 */
  179.     Push(Get_Number_Rational_Denominator(Top( 2 )));  /* denom rat 2 */
  180.     Number_Multiply();
  181.     Pop( 2 );
  182.     Push( Value_Register );
  183.  
  184.     Push(Get_Number_Rational_Denominator(Top( 3 )));  /* denom rat 1 */
  185.     Push(Get_Number_Rational_Numerator(Top( 3 )));    /* numer rat 2 */
  186.     Number_Multiply();
  187.     Pop( 2 );
  188.     Push( Value_Register );
  189.  
  190.     /* subtract 2 new numerators */
  191.     Number_Subtract();
  192.     Pop( 2 );
  193.     Push( Value_Register );
  194.  
  195.     Push(Get_Number_Rational_Denominator(Top( 3 )));  /* denom rat 1 */
  196.     Push(Get_Number_Rational_Denominator(Top( 3 ))); /* denom rat 2 */
  197.     Number_Multiply();
  198.     Pop( 2 );
  199.     Push( Value_Register );    /* denominator */
  200.  
  201.     Make_Rational_Number();
  202.     Pop( 2 );
  203.  
  204.     if ( ! Is_Exact_Number( Top(1) ) || ! Is_Exact_Number( Top(2) ) )
  205.     {
  206.         Push( Value_Register );
  207.         Number_Exact_To_Inexact(); Pop(1);
  208.     }
  209. }
  210.  
  211.  
  212.  
  213. Public void Rational_Multiply()
  214. {
  215.     /* rat 1 = a/b, rat 2 = c/d, result = a*c/b*d    */
  216.  
  217.     Push(Get_Number_Rational_Numerator(Top( 2 )));    /* numer rat 1 */
  218.     Push(Get_Number_Rational_Numerator(Top( 2 )));    /* numer rat 2 */
  219.     Number_Multiply();
  220.     Pop( 2 );
  221.     Push( Value_Register );    /* new numer of result rat */
  222.  
  223.     Push(Get_Number_Rational_Denominator(Top( 2 ))); /* denom rat 2 */
  224.     Push(Get_Number_Rational_Denominator(Top( 4 ))); /* denom rat 1 */
  225.     Number_Multiply();
  226.     Pop( 2 );
  227.     Push( Value_Register );    /* new denom of result rat */
  228.  
  229.     Make_Rational_Number();
  230.     Pop( 2 );
  231.  
  232.     if ( ! Is_Exact_Number( Top(1) ) || ! Is_Exact_Number( Top(2) ) )
  233.     {
  234.         Push( Value_Register );
  235.         Number_Exact_To_Inexact(); Pop(1);
  236.     }
  237. }
  238.  
  239.  
  240. Public void Rational_Divide()
  241. {
  242.     /* rat 1 = a/b, rat 2 = c/d, result = a*d/c*b    */
  243.  
  244.     Push(Get_Number_Rational_Numerator(Top( 2 )));    /* numer rat 1 */
  245.     Push(Get_Number_Rational_Denominator(Top( 2 ))); /* denom rat 2 */
  246.     Number_Multiply();
  247.     Pop( 2 );
  248.     Push( Value_Register );    /* new numer of result rat */
  249.  
  250.     Push(Get_Number_Rational_Denominator(Top( 3 ))); /* denom rat 1 */
  251.     Push(Get_Number_Rational_Numerator(Top( 3 )));    /* numer rat 2 */
  252.     Number_Multiply();
  253.     Pop( 2 );
  254.     Push( Value_Register );    /* new denom of result rat */
  255.  
  256.     Make_Rational_Number();
  257.     Pop( 2 );
  258.  
  259.     if ( ! Is_Exact_Number( Top(1) ) || ! Is_Exact_Number( Top(2) ) )
  260.     {
  261.         Push( Value_Register );
  262.         Number_Exact_To_Inexact(); Pop(1);
  263.     }
  264. }
  265.  
  266.  
  267. Public void Rational_Quotient()
  268. {
  269.     Error("Quotient makes no sense on rationals");
  270. }
  271.  
  272. Public void Rational_Remainder()
  273. {
  274.     Error("Remainder makes no sense on rationals");
  275. }
  276.  
  277.  
  278. Public void Rational_Modulo()
  279. {
  280.     Error("Modulo makes no sense on rationals");
  281. }
  282.  
  283.  
  284. Public void Rational_Negate()
  285. {
  286.     Push(Get_Number_Rational_Numerator(Top(1)));
  287.     Number_Negate();
  288.     Replace(1, Value_Register);
  289.     Push(Get_Number_Rational_Denominator(Top(2)));
  290.     Make_Rational_Number();
  291.     Pop(2);    
  292.  
  293.     if ( ! Is_Exact_Number( Top(1) ) || ! Is_Exact_Number( Top(2) ) )
  294.     {
  295.         Push( Value_Register );
  296.         Number_Exact_To_Inexact(); Pop(1);
  297.     }
  298. }
  299.  
  300.  
  301. Public void Rational_Abs()
  302. {
  303.     if (Is_Rational_Negative())
  304.     {
  305.         Rational_Negate();
  306.     }
  307.     else
  308.     {
  309.         Value_Register = Top(1);
  310.     }
  311.  
  312.     if ( ! Is_Exact_Number( Top(1) ) || ! Is_Exact_Number( Top(2) ) )
  313.     {
  314.         Push( Value_Register );
  315.         Number_Exact_To_Inexact(); Pop(1);
  316.     }
  317. }
  318.  
  319. Public void Rational_Numerator()
  320. {
  321.     
  322.     Value_Register = Get_Number_Rational_Numerator(Top( 1 ));
  323.  
  324.     if ( ! Is_Exact_Number( Top(1) ) )
  325.     {
  326.         Push( Value_Register );
  327.         Number_Exact_To_Inexact(); Pop(1);
  328.     }
  329. }
  330.  
  331.  
  332. Public void Rational_Denominator()
  333. {
  334.     
  335.     Value_Register = Get_Number_Rational_Denominator(Top( 1 ));
  336.  
  337.     if ( ! Is_Exact_Number( Top(1) ) )
  338.     {
  339.         Push( Value_Register );
  340.         Number_Exact_To_Inexact(); Pop(1);
  341.     }
  342. }
  343.  
  344.  
  345. Public void Rational_Rationalize()
  346. {
  347.     Error("Rational_Rationalize is not yet implemented");
  348. }
  349.  
  350.  
  351.  
  352. Public void Rational_Max()
  353. {
  354.     Value_Register = Rational_Greater_Than() ? Top(2) : Top(1);
  355.  
  356.     if ( ! Is_Exact_Number( Top(1) ) || ! Is_Exact_Number( Top(2) ) )
  357.     {
  358.         Push( Value_Register );
  359.         Number_Exact_To_Inexact(); Pop(1);
  360.     }
  361. }
  362.  
  363. Public void Rational_Min()
  364. {
  365.     Value_Register = Rational_Less_Than() ? Top(2) : Top(1);
  366.  
  367.     if ( ! Is_Exact_Number( Top(1) ) || ! Is_Exact_Number( Top(2) ) )
  368.     {
  369.         Push( Value_Register );
  370.         Number_Exact_To_Inexact(); Pop(1);
  371.     }
  372. }
  373.  
  374. Public void Rational_GCD()
  375. {
  376.     Error("GCD makes no sense on rationals");
  377. }
  378.  
  379.  
  380. Public void Rational_LCM()
  381. {
  382.     Error("LCM makes no sense on rationals");
  383. }
  384.  
  385. Public void Rational_Floor()
  386. {
  387.     Value_Register = Copy_Object(Top(1), Rational_Size);
  388.  
  389.     Push(Get_Number_Rational_Numerator(Value_Register));
  390.     Push(Get_Number_Rational_Denominator(Value_Register));
  391.     Push(Top(2));
  392.  
  393.     Is_Number_Negative();
  394.     Pop(1);
  395.  
  396.     if (Value_Register == The_True_Object )
  397.     {
  398.         Number_Quotient();
  399.         Push(Value_Register);
  400.         Make_Fixnum_Number(1);
  401.         Push(Value_Register);
  402.         Number_Subtract();
  403.         Pop(4);
  404.     }
  405.     else
  406.     {
  407.         Number_Quotient();
  408.         Pop(2);
  409.     }
  410.  
  411.     if ( ! Is_Exact_Number( Top(1) ) )
  412.     {
  413.         Push( Value_Register );
  414.         Number_Exact_To_Inexact(); Pop(1);
  415.     }
  416. }
  417.  
  418. Public void Rational_Ceiling()
  419. {
  420.     Value_Register = Copy_Object(Top(1), Rational_Size);
  421.  
  422.     Push(Get_Number_Rational_Numerator(Value_Register));
  423.     Push(Get_Number_Rational_Denominator(Value_Register));
  424.  
  425.     Number_Remainder();
  426.     Push(Value_Register);
  427.     Is_Number_Zero();
  428.     Pop(1);
  429.  
  430.     if (Value_Register == The_True_Object)
  431.     {
  432.         Push(Top(3));
  433.         Rational_Floor();    
  434.         Pop(3);
  435.     }
  436.     else
  437.     {
  438.         Push(Top(3));
  439.         Rational_Floor();
  440.         Push(Value_Register);
  441.         Make_Fixnum_Number(1);
  442.         Push(Value_Register);
  443.         Number_Add();
  444.         Pop(5);
  445.     }
  446.  
  447.     if ( ! Is_Exact_Number( Top(1) ) )
  448.     {
  449.         Push( Value_Register );
  450.         Number_Exact_To_Inexact(); Pop(1);
  451.     }
  452. }
  453.  
  454.  
  455.  
  456. Public void Rational_Truncate()
  457. {
  458.     if (Number_Sign(Get_Number_Rational_Numerator(Top(1))) > 0)
  459.     {
  460.         Rational_Floor();
  461.     }
  462.     else
  463.     {
  464.         Rational_Ceiling();
  465.     }
  466.  
  467.     if ( ! Is_Exact_Number( Top(1) ) )
  468.     {
  469.         Push( Value_Register );
  470.         Number_Exact_To_Inexact(); Pop(1);
  471.     }
  472. }
  473.  
  474.  
  475.  
  476. Public void Rational_Round()
  477. {
  478.     /* Compare the given rat to average of floor and ceiling and choose
  479.        either floor or ceiling depending on result and sign of the rat;
  480.        Numbers halfway between two integers round to even. */
  481.  
  482.     
  483.     Rational_Floor();
  484.     Push(Value_Register);
  485.     Push(Top(2));
  486.     Rational_Ceiling();
  487.     Push(Value_Register);
  488.     Push(Top(3));
  489.     Number_Add();
  490.     Push(Value_Register);
  491.     Make_Fixnum_Number(2);
  492.     Push(Value_Register);
  493.     Number_Divide();
  494.     Push(Value_Register);
  495.     Push(Top(6));
  496.     Number_Less_Than();
  497.  
  498.     if (Value_Register == The_True_Object)
  499.     {
  500.         Push(Top(7));
  501.         Rational_Ceiling();
  502.         Pop(9);
  503.     }
  504.     else 
  505.     {
  506.         Number_Greater_Than();
  507.         if(Value_Register == The_True_Object)
  508.         {
  509.             Push(Top(7));
  510.             Rational_Floor();
  511.             Pop(9);
  512.         }
  513.         else
  514.         {
  515.             Push(Top(7));
  516.             Rational_Floor();
  517.             Push(Value_Register);
  518.             Is_Number_Even();
  519.             if(Value_Register == The_True_Object)
  520.             {
  521.                 Value_Register = Top(1);
  522.                 Pop(10);
  523.             }
  524.             else
  525.             {
  526.                 Pop(1);
  527.                 Rational_Ceiling();
  528.                 Pop(9);
  529.             }
  530.         }
  531.     }
  532.  
  533.     if ( ! Is_Exact_Number( Top(1) ) )
  534.     {
  535.         Push( Value_Register );
  536.         Number_Exact_To_Inexact(); Pop(1);
  537.     }
  538. }
  539.  
  540.  
  541.  
  542.  
  543. Public void Rational_Sqrt()
  544. {
  545.     if(Number_Sign(Get_Number_Rational_Numerator(Top(1))) < 0)
  546.     {
  547.         Error("Argument of sqrt must be nonnegative");
  548.     }
  549.  
  550.     Promote(1, REAL_LEVEL);
  551.  
  552.     Make_Real_Number( sqrt(Get_Number_Real_Value(Top(1))) );
  553. }
  554.  
  555.  
  556.  
  557. Public void Rational_Exp()
  558. {
  559.     Promote(1, REAL_LEVEL);
  560.  
  561.     Make_Real_Number( exp (Get_Number_Real_Value(Top(1))) );
  562. }
  563.  
  564.  
  565.  
  566. Public void Rational_Log()
  567. {
  568.     if(Number_Sign(Get_Number_Rational_Numerator(Top(1))) < 0)
  569.     {
  570.         Error("Argument of log must be nonnegative");
  571.     }
  572.  
  573.     Promote(1, REAL_LEVEL);
  574.  
  575.     Make_Real_Number( log (Get_Number_Real_Value(Top(1))) );
  576. }
  577.  
  578.  
  579.  
  580. Public void Rational_Expt()
  581. {
  582.     Promote(1, REAL_LEVEL);
  583.     Promote(2, REAL_LEVEL);
  584.  
  585.     Make_Real_Number( pow ((Get_Number_Real_Value(Top(2))),
  586.                 (Get_Number_Real_Value(Top(1))) ) );
  587. }
  588.  
  589.  
  590.  
  591.  
  592. Public void Rational_Sin()
  593. {
  594.     Promote(1, REAL_LEVEL);
  595.  
  596.     Make_Real_Number( sin (Get_Number_Real_Value(Top(1))) );
  597. }
  598.  
  599.  
  600.  
  601. Public void Rational_Cos()
  602. {
  603.     Promote(1, REAL_LEVEL);
  604.  
  605.     Make_Real_Number( cos (Get_Number_Real_Value(Top(1))) );
  606. }
  607.  
  608.  
  609.  
  610. Public void Rational_Tan()
  611. {
  612.     Promote(1, REAL_LEVEL);
  613.  
  614.     Make_Real_Number( tan (Get_Number_Real_Value(Top(1))) );
  615. }
  616.  
  617.  
  618.  
  619. Public void Rational_Asin()
  620. {
  621.     Promote(1, REAL_LEVEL);
  622.  
  623.     if(((Get_Number_Real_Value(Top(1))) < -1) ||
  624.         ((Get_Number_Real_Value(Top(1))) > 1))
  625.     {
  626.         Error("Argument of asin must lie between -1 and 1, inclusive");
  627.     }
  628.  
  629.     Make_Real_Number( asin (Get_Number_Real_Value(Top(1))) );
  630. }
  631.  
  632.  
  633.  
  634. Public void Rational_Acos()
  635. {
  636.     Promote(1, REAL_LEVEL);
  637.  
  638.     if(((Get_Number_Real_Value(Top(1))) < -1) ||
  639.         ((Get_Number_Real_Value(Top(1))) > 1))
  640.     {
  641.         Error("Argument of acos must lie between -1 and 1, inclusive");
  642.     }
  643.  
  644.     Make_Real_Number( acos (Get_Number_Real_Value(Top(1))) );
  645. }
  646.  
  647.  
  648.  
  649. Public void Rational_Atan()
  650. {
  651.     Promote(1, REAL_LEVEL);
  652.  
  653.     Make_Real_Number( atan (Get_Number_Real_Value(Top(1))) );
  654. }
  655.  
  656.  
  657.  
  658. Public void Rational_Atan2()
  659. {
  660.     Promote(1, REAL_LEVEL);
  661.     Promote(2, REAL_LEVEL);
  662.  
  663.     Make_Real_Number( atan2 (Get_Number_Real_Value(Top(2)),   
  664.                 Get_Number_Real_Value(Top(1))) );
  665.  
  666. }
  667.  
  668.  
  669.  
  670.  
  671. /* Transfer functions */
  672.  
  673.  
  674. Public void Rational_Exact_To_Inexact()
  675. {
  676.     Value_Register = Copy_Object(Top(1), Rational_Size);
  677.     Is_Exact_Number( Value_Register ) = FALSE;
  678. }
  679.  
  680.  
  681.  
  682. Public void Rational_Inexact_To_Exact()
  683. {
  684.     Value_Register = Copy_Object(Top(1), Rational_Size);
  685.     Is_Exact_Number( Value_Register ) = TRUE;
  686. }
  687.  
  688.  
  689. Public void Rational_To_String()
  690. {
  691.     Import    void String_Append();
  692.  
  693.     Integer radix = Number_To_Integer( Top(1) );
  694.  
  695.     Make_Constant_String( Is_Exact_Number( Top(2) ) ? "" : "#i" );
  696.     Push( Value_Register );
  697.  
  698.     Push(Get_Number_Rational_Numerator(Top(3)));
  699.     Push( Top(3) );
  700.     Number_To_String(); Pop(2);
  701.     Push( Value_Register );
  702.     String_Append(); Pop(2);
  703.     Push( Value_Register );
  704.  
  705.     Make_Constant_String( "/" );
  706.     Push( Value_Register );
  707.     String_Append(); Pop(2);
  708.     Push( Value_Register );
  709.  
  710.     Push(Get_Number_Rational_Denominator(Top(3)));
  711.     Push( Top(3) );
  712.     Number_To_String(); Pop(2);
  713.     Push( Value_Register );
  714.     if ( radix != 10)
  715.     {
  716.         /* Remove radix prefix from denominator */
  717.  
  718.         Make_Constant_String( Get_String_Value( Top(1) ) + 2 ); Pop(1);
  719.         Push( Value_Register );
  720.     }
  721.     String_Append(); Pop(2);
  722. }
  723.  
  724. Public void Rational_Make_Rectangular()
  725. {
  726.     Promote(1, REAL_LEVEL);
  727.     Promote(2, REAL_LEVEL);
  728.  
  729.     Make_Complex_Number( Get_Number_Real_Value(Top(2)),
  730.                 Get_Number_Real_Value(Top(1)));
  731. }
  732.  
  733.  
  734.  
  735. Public void Rational_Make_Polar()
  736.  
  737. #define MAG Get_Number_Real_Value(Top(2))
  738. #define ANG Get_Number_Real_Value(Top(1))
  739.  
  740. {
  741.     Promote( 2, REAL_LEVEL);
  742.     Promote( 1, REAL_LEVEL);
  743.  
  744.     Make_Complex_Number( (MAG) * cos(ANG) , (MAG) * sin(ANG) );
  745.  
  746. }
  747.  
  748. #undef MAG
  749. #undef ANG
  750.  
  751.  
  752.  
  753.  
  754. Public void Rational_Real_Part()
  755. {
  756.     Promote(1, REAL_LEVEL);
  757.     Value_Register = Top(1);
  758. }
  759.  
  760.  
  761.  
  762. Public void Rational_Imaginary_Part()
  763. {
  764.     Make_Real_Number(0.0);
  765. }
  766.  
  767.  
  768.  
  769. Public void Rational_Magnitude()
  770. {
  771.     Rational_Abs();
  772. }
  773.  
  774.  
  775.  
  776. Public void Rational_Angle()
  777. {
  778.     Make_Real_Number(0.0);
  779. }
  780.  
  781.  
  782.  
  783. Public    void Reduce_Rational()
  784. {
  785.     /* To reduce a rational you divide the numerator and
  786.        denominator by their GCD */
  787.  
  788.  
  789.     Push( Value_Register ); /* The rational */
  790.  
  791.     Push(Get_Number_Rational_Numerator(Value_Register));
  792.     Push(Get_Number_Rational_Denominator(Value_Register));
  793.     Number_GCD(); 
  794.     Pop(2);
  795.     Push( Value_Register );    /* The gcd */
  796.  
  797.     Push( Get_Number_Rational_Numerator(Top(2)) )
  798.     Push(Top(2));
  799.     Number_Quotient();
  800.     Pop(2);
  801.     Get_Number_Rational_Numerator(Top(2)) = Value_Register;
  802.  
  803.     Push( Get_Number_Rational_Denominator( Top(2) ) );
  804.     Push(Top(2));
  805.     Number_Quotient();
  806.     Pop(2);
  807.     Get_Number_Rational_Denominator(Top(2)) = Value_Register;
  808.  
  809.     Value_Register = Top(2);
  810.     Pop(2);
  811. }    
  812.