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

  1. /* complex.c -- UMB Scheme, complex number package.
  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. #define A (Get_Number_Complex_Real_Part(Top(2)))
  53. #define B (Get_Number_Complex_Imaginary_Part(Top(2)))
  54. #define C (Get_Number_Complex_Real_Part(Top(1)))
  55. #define D (Get_Number_Complex_Imaginary_Part(Top(1)))
  56.  
  57. #define PI    3.14159265358979323846
  58. #define HALF_PI    1.57079632679489661923
  59.  
  60.  
  61. /* Predicates. */
  62.  
  63. Public Boolean Is_Complex_Zero()
  64. {
  65.     return ( (C == 0.0) && (D == 0.0) );
  66. }
  67.  
  68.  
  69. Public Boolean Is_Complex_Positive()
  70. {
  71.         Error("No Positive/Negative Concept about Complex!");
  72.         return FALSE;
  73. }
  74.  
  75.  
  76. Public Boolean Is_Complex_Negative()
  77. {
  78.         Error("No Positive/Negative Concept about Complex!");
  79.         return FALSE;
  80. }
  81.  
  82.  
  83.  
  84. Public Boolean Is_Complex_Odd()
  85. {
  86.         Error("No Odd/Even Concept about Complex!");
  87.         return FALSE;
  88. }
  89.  
  90.  
  91.  
  92. Public Boolean Is_Complex_Even()
  93. {
  94.         Error("No Odd/Even Concept about Complex!");
  95.         return FALSE;
  96. }
  97.  
  98.  
  99.  
  100. Public Boolean Is_Complex_Exact()
  101. {
  102.     return FALSE;    /* Complex numbers are always inexact */
  103. }
  104.  
  105.  
  106. Public Boolean Is_Complex_Inexact()
  107. {
  108.         return TRUE;    /* Complex numbers are always inexact */
  109. }
  110.  
  111. /* Comparisons. */
  112.  
  113.  
  114. Public Boolean Complex_Less_Than()
  115. {
  116.         Error("No Inequality about Complex!");
  117.     return FALSE;
  118. }
  119.  
  120.  
  121.  
  122. Public Boolean Complex_Greater_Than()
  123. {
  124.         Error("No Inequality about Complex!");
  125.     return FALSE;
  126. }
  127.  
  128.  
  129.  
  130. Public Boolean Complex_Equal()
  131. {
  132.     return ( (A == C) && (B == D) );
  133. }
  134.  
  135.  
  136. Public Boolean Complex_Less_Than_Or_Equal()
  137. {
  138.         Error("No Inequality about Complex!");
  139.     return FALSE;
  140. }
  141.  
  142.  
  143. Public Boolean Complex_Greater_Than_Or_Equal()
  144. {
  145.         Error("No Inequality about Complex!");
  146.         return FALSE;
  147. }
  148.  
  149.  
  150. /* Arithmetic. */
  151.  
  152.  
  153. Public void Complex_Add()
  154. {
  155.     Make_Complex_Number( A + C, B + D );
  156. }
  157.  
  158.  
  159.  
  160. Public void Complex_Subtract()
  161. {
  162.     Make_Complex_Number( A - C, B - D );
  163. }
  164.  
  165.  
  166.  
  167. Public void Complex_Multiply()
  168. {
  169.     Make_Complex_Number( ( (A*C) - (B*D) ), ( (A*D) + (B*C) ) );
  170. }
  171.  
  172.  
  173.  
  174. Public void Complex_Divide()
  175. {
  176.     if (Is_Complex_Zero())           /* C+Di = 0+0i, it's on top(1) */
  177.         Error("Complex division by ZERO !!!!");
  178.     else
  179.         Make_Complex_Number(     ( (A*C)+(B*D) ) / ( (C*C)+(D*D) ),
  180.                          ( (B*C)-(A*D) ) / ( (C*C)+(D*D) ) );
  181. }
  182.  
  183.  
  184.  
  185. Public void Complex_Quotient()
  186. {
  187.         Error("No Quotient Operation on Complex!");
  188. }
  189.  
  190.  
  191.  
  192. Public void Complex_Remainder()
  193. {
  194.         Error("No Remainder Operation on Complex!");
  195. }
  196.  
  197.  
  198.  
  199. Public void Complex_Modulo()
  200. {
  201.     Error("No Modulo Operation on Complex!");
  202.  
  203.  
  204.  
  205.  
  206. Public void Complex_Negate()
  207. {
  208.     Value_Register = Copy_Object(Top(1), Complex_Size);
  209.  
  210.     Get_Number_Complex_Real_Part(Value_Register) =
  211.         - Get_Number_Complex_Real_Part(Value_Register);
  212.  
  213.  
  214.     Get_Number_Complex_Imaginary_Part(Value_Register) =
  215.         - Get_Number_Complex_Imaginary_Part(Value_Register); 
  216.  
  217. }
  218.  
  219.  
  220.  
  221. Public void Complex_Abs()
  222. {
  223.         Make_Real_Number(sqrt( (C*C) + (D*D) ));
  224. }
  225.  
  226.  
  227.  
  228. Public void Complex_Numerator()
  229. {
  230.     Error("No Numerator Operation on Complex!");
  231. }
  232.  
  233.  
  234.  
  235. Public void Complex_Denominator()
  236. {
  237.     Error("No Denominator Operation on Complex!");
  238. }
  239.  
  240.  
  241.  
  242. Public void Complex_Rationalize()
  243. {
  244.     Error("No Rationalize Operation on Complex!");
  245. }
  246.  
  247.  
  248.  
  249. Public void Complex_Max()
  250. {
  251.         Error("No Max Operation on Complex!");
  252. }
  253.  
  254.  
  255.  
  256. Public void Complex_Min()
  257. {
  258.         Error("No Min Operation on Complex!");
  259. }
  260.  
  261.  
  262.  
  263. Public void Complex_GCD()
  264. {
  265.     Error("No GCD Operation on Complex!");
  266. }
  267.  
  268.  
  269.  
  270. Public void Complex_LCM()
  271. {
  272.     Error("No LCM Operation on Complex!");
  273. }
  274.  
  275.  
  276.  
  277. Public void Complex_Floor()
  278. {
  279.     Error("No Floor Operation on Complex!");
  280. }
  281.  
  282.  
  283.  
  284. Public void Complex_Ceiling()
  285. {
  286.     Error("No Ceiling Operation on Complex!");
  287. }
  288.  
  289.  
  290.  
  291. Public void Complex_Truncate()
  292. {
  293.     Error("No Truncate Operation on Complex!");
  294. }
  295.  
  296.  
  297.  
  298. Public void Complex_Round()
  299. {
  300.     Error("No Round Operation on Complex!");
  301. }
  302.  
  303.  
  304.  
  305.  
  306. Public void Complex_Sqrt()
  307.     /* sqrtz = sqrt(|z|)*( cos((angle+2kPi)/2) + isin((angle+2kPi)/2) ) */
  308. {
  309.         Double mag_sqrt = sqrt(sqrt( (C*C) + (D*D) ));
  310.     Double ang = ( C == 0.0 && D > 0.0 ) ? HALF_PI :
  311.              ( ( C == 0.0 && D < 0.0 ) ? -HALF_PI : atan2(D,C) );
  312.  
  313.     /* select a proper angle so that 
  314.                 the real part of the result is non-negative */
  315.  
  316.         if (cos(ang/2.0) >= 0.0) ang /= 2.0;
  317.         else ang = (ang/2.0) + PI;
  318.  
  319.         Make_Complex_Number(mag_sqrt * cos(ang), mag_sqrt * sin(ang));
  320. }
  321.  
  322.  
  323.  
  324. Public void Complex_Exp()
  325. {
  326.         Make_Complex_Number( exp(C) * cos(D) , exp(C) * sin(D) );
  327. }
  328.  
  329.  
  330.  
  331. Public void Complex_Log()
  332.     /* logz = log(magnitude(z)) + angle(z)i */
  333. {
  334.     Double ang = ( C == 0.0 && D > 0.0 ) ? HALF_PI :
  335.              ( ( C == 0.0 && D < 0.0 ) ? -HALF_PI : atan2(D,C) );
  336.  
  337.     if (Is_Complex_Zero()) Display_Error("Bad arg to Log : ", Top(1) );
  338.     else  Make_Complex_Number( log(sqrt(C*C + D*D)), ang ); 
  339. }
  340.  
  341.  
  342.  
  343. Public void Complex_Expt()
  344.         /* z1**z2 = e**z2log(z1)   ;  0**0 is defined to be 1 */
  345. {
  346.  
  347. #define Z1_and_Z2_are_Zeros (A == 0.0 && B == 0.0) && (C == 0.0 && D == 0.0)
  348. #define Z1_is_Zero  A == 0.0 && B == 0.0
  349.  
  350.     Promote( 2 , COMPLEX_LEVEL );
  351.     if ( Z1_and_Z2_are_Zeros )  Make_Complex_Number(1.0, 0.0);
  352.     else if ( Z1_is_Zero )    Display_Error("Bad arg to Expt:", Top(2));
  353.     else 
  354.     {
  355.             Push(Top(2));         /* push z1 */
  356.             Complex_Log();      /* compute logz1 */
  357.             Pop(1);            /* remove z1 */
  358.             Push(Value_Register);    /* push logz1 */
  359.             Complex_Multiply();     /* compute z2logz1 */
  360.             Pop(1);            /* remove logz1 */
  361.             Push(Value_Register);    /* push z2logz1 */
  362.             Complex_Exp();        /* compute e**z2logz1 */
  363.             Pop(1);            /* remove z2logz1 */
  364.          }
  365. #undef Z1_and_Z2_are_Zeros
  366. #undef Z1_is_Zero 
  367. }
  368.  
  369.  
  370.  
  371. Public void Complex_Sin()
  372.     /* sinz = (e**iz - e**-iz) / 2i */
  373. {
  374.         Make_Complex_Number( ((exp(-D) * sin(C)) - (exp(D) * sin(-C))) / 2.0 , 
  375.                  ((exp(D) * cos(-C)) - (exp(-D) * cos(C))) / 2.0 );
  376. }
  377.  
  378.  
  379.  
  380. Public void Complex_Cos()
  381.     /* cosz = (e**iz + e**-iz) / 2 */
  382. {
  383.         Make_Complex_Number(((exp(-D) * cos(C)) + (exp(D) * cos(-C))) / 2.0 ,
  384.                             ((exp(-D) * sin(C)) + (exp(D) * sin(-C))) / 2.0 );
  385. }
  386.  
  387.  
  388.  
  389. Public void Complex_Tan()
  390.     /* tanz = sinz / cosz */
  391. {
  392.         Complex_Sin();          /* compute sin(z) */
  393.         Push( Value_Register ); /* push sin(z) onto stack */
  394.         Push( Top(2) );         /* swap z upto top to compute cos(z) */
  395.         Complex_Cos();          /* compute cos(z) */
  396.         Pop(1);                 /* remove the temp z */
  397.         Push( Value_Register ); /* push cos(z) onto stack */
  398.         Complex_Divide();       /* compute tan(z) = sin(z) / cos(z) */
  399.         Pop(2);                 /* remove sin(z) and cos(z) off the stack */
  400. }
  401.  
  402.  
  403.  
  404. Public void Complex_Asin()
  405.     /* asinz = -ilog(iz + sqrt(1-z**2)) */
  406. {
  407.         Make_Complex_Number( 1.0 - (C*C) + (D*D), -(2.0*(C*D)) ); 
  408.                         /* Make 1-z**2 */
  409.     Push( Value_Register );     /* push 1-z**2 onto stack */
  410.         Complex_Sqrt();             /* compute sqrt (1-z**2) */
  411.         Pop(1);                /* remove 1-z**2 */
  412.         Push( Value_Register );     /* push sqrt(1-z**2) */
  413.         Make_Complex_Number( -B, A);    /* make iz */
  414.         Push( Value_Register );     /* push iz */
  415.         Complex_Add();            /* compute iz + sqrt(1-z**2) */
  416.         Pop(2);                /* remove iz and sqrt(1-z**2) */
  417.         Push( Value_Register );     /* push iz + sqrt(1-z**2) */
  418.         Complex_Log();            /* compute log(iz + sqrt(1-z**2)) */
  419.         Pop(1);                /* remove iz + sqrt(1-z**2) */
  420.         Push( Value_Register );        /* push log(iz + sqrt(1-z**2)) */
  421.         Make_Complex_Number( D, -C);    /* compute -ilog(iz + sqrt(1-z**2)) */
  422.         Pop(1);                /* remove log(iz + sqrt(1-z**2)) */
  423.  
  424. }
  425.  
  426.  
  427.  
  428.  
  429. Public void Complex_Acos()
  430.     /* acosz = -ilog(z + i*sqrt(1-z**2)) */
  431. {
  432.         Make_Complex_Number(1.0-(C*C)+(D*D), -(2.0*(C*D)) ); /* make 1-z**2 */
  433.         Push( Value_Register );     /* push 1-z**2 */
  434.         Complex_Sqrt();             /* compute sqrt (1-z**2) */
  435.         Pop(1);                /* remove 1-z*2 */
  436.         Push( Value_Register );        /* push sqrt(1-z**2) */
  437.         Make_Complex_Number( 0.0,1.0);  /* make i */
  438.         Push( Value_Register );     /* push i */
  439.         Complex_Multiply();        /* compute i*sqrt(1-z**2) */
  440.         Pop(2);                /* remove i and sqrt(1-z**2) */
  441.         Push( Value_Register );     /* push i*sqrt(1-z**2) */
  442.         Complex_Add();            /* compute z + i*sqrt(1-z**2) */
  443.         Pop(1);                /* remove i*sqrt(1-z**2) */
  444.         Push( Value_Register );        /* push z + i*sqrt(1-z**2) */
  445.         Complex_Log();            /* compute log(z + i*sqrt(1-z**2)) */
  446.         Pop(1);                /* remove z + i*sqrt(1-z**2) */
  447.         Push( Value_Register );        /* push log(z + i*sqrt(1-z**2)) */
  448.         Make_Complex_Number( D, -C);    /* compute -ilog(z + i*sqrt(1-z**2)) */
  449.         Pop(1);                /* remove log(z + i*sqrt(1-z**2)) */
  450.  
  451. }
  452.  
  453.  
  454.  
  455. Public void Complex_Atan()
  456.     /* atanz = -ilog((1+iz)*sqrt(1/(1+z**2))) */
  457. {
  458.         Make_Complex_Number(1.0,0.0);    /* make 1 */
  459.         Push(Value_Register);        /* push 1 */
  460.         Make_Complex_Number(1.0+(A*A)-(B*B), 2.0*(A*B)); /* make 1+z**2 */
  461.         Push( Value_Register );     /* push 1+z**2 */
  462.         Complex_Divide();        /* compute 1 / (1+z**2) */
  463.         Pop(2);                /* remove 1 and 1+z**2 */
  464.         Push(Value_Register);        /* push 1/(1+z**2) */
  465.         Complex_Sqrt();             /* compute sqrt(1/(1+z**2)) */
  466.         Pop(1);                /* remove 1/(1+z**2) */
  467.         Push( Value_Register );        /* push sqrt(1/(1+z**2)) */
  468.         Make_Complex_Number( 1.0 - B, A); /* make 1+iz */
  469.         Push( Value_Register );        /* push 1+iz */
  470.     Complex_Multiply();         /* compute (1+iz)(sqrt(1/(1+z**2))) */
  471.         Pop(2);             /* remove 1+iz and sqrt(1/(1+z**2)) */
  472.         Push( Value_Register );     /* push (1+iz)(sqrt(1/(1+z**2))) */
  473.         Complex_Log();         /* compute log((1+iz)(sqrt(1/(1+z**2))) */
  474.         Pop(1);                /* remove (1+iz)(sqrt(1/(1+z**2))) */
  475.         Push( Value_Register );     /* push log((1+iz)(sqrt(1/(1+z**2))) */
  476.         Make_Complex_Number( D, -C);/* compute -ilog((1+iz)(sqrt(1/(1+z**2))) */
  477.         Pop(1);            /* remove log((1+iz)(sqrt(1/(1+z**2))) */
  478.  
  479. }
  480.  
  481.  
  482.  
  483. Public void Complex_Atan2()
  484. {
  485.     Error("No Atan2 Operation on Complex!");
  486. }
  487.  
  488.  
  489.  
  490.  
  491. Public void Complex_Exact_To_Inexact()
  492. {
  493.     Value_Register = Top( 1 );
  494. }
  495.  
  496.  
  497.  
  498. Public void Complex_Inexact_To_Exact()
  499. {
  500.         Error("inexact->to->exact is not applicable to complex numbers");
  501. }
  502.  
  503.  
  504.  
  505.  
  506. Public void Complex_To_String()
  507. {
  508.     Import    void    String_Append();
  509.     Integer    radix = Number_To_Integer( Top(1) );
  510.  
  511.     if ( A == 0.0 )
  512.     {
  513.         Make_Constant_String(     radix == 2 ? "#b" :
  514.                     radix == 8 ? "#o" :
  515.                     radix == 10 ? "" : "#x" );
  516.         Push( Value_Register );
  517.     }
  518.     else
  519.     {
  520.         Make_Real_Number( A );
  521.         Push( Value_Register );
  522.         Push( Top(2) );
  523.         Number_To_String(); Pop(2);
  524.         Push( Value_Register );
  525.     }
  526.  
  527.     if ( Get_Number_Complex_Imaginary_Part( Top(3) ) >= 0 )
  528.     {
  529.         Make_Constant_String( "+" );
  530.         Push( Value_Register );
  531.         String_Append(); Pop(2);
  532.         Push( Value_Register );
  533.     }
  534.  
  535.     Make_Real_Number( Get_Number_Complex_Imaginary_Part( Top(3) ) );
  536.     Push( Value_Register );
  537.     Push( Top(3) );
  538.     Number_To_String(); Pop(2);
  539.     Push( Value_Register );
  540.     if ( radix != 10 )
  541.     {
  542.         /* remove radix prefix from imaginary part */
  543.  
  544.         Make_Constant_String( Get_String_Value( Top(1) ) + 2 ); Pop(1);
  545.         Push( Value_Register );
  546.     }
  547.     String_Append(); Pop(2);
  548.     Push( Value_Register );
  549.  
  550.     Make_Constant_String( "i" );
  551.     Push( Value_Register );
  552.     String_Append(); Pop(2);
  553. }
  554.  
  555. Public void Complex_Make_Rectangular()
  556.         /* Make a Complex in rectangular form; z = x + yi */
  557. {
  558.         Tower_Position argtypeX = Get_Number_Tower_Position(Top(2));
  559.         Tower_Position argtypeY = Get_Number_Tower_Position(Top(1));
  560.  
  561.         if (argtypeX == COMPLEX_LEVEL || argtypeY == COMPLEX_LEVEL)
  562.         {
  563.                 Error("Bad arguments to Make-Rectangular.");
  564.         }
  565.  
  566. }
  567.  
  568.  
  569.  
  570. Public void Complex_Make_Polar()
  571. {
  572.         Tower_Position argtypeX = Get_Number_Tower_Position(Top(2));
  573.         Tower_Position argtypeY = Get_Number_Tower_Position(Top(1));
  574.  
  575.         if (argtypeX == COMPLEX_LEVEL || argtypeY == COMPLEX_LEVEL)
  576.         {
  577.                 Error("Bad arguments to Make-Rectangular.");
  578.         }
  579. }
  580.  
  581.  
  582.  
  583. Public void Complex_Real_Part()
  584.         /* Return the real part of a complex in rectangular form */
  585. {
  586.         Make_Real_Number( C );
  587. }
  588.  
  589.  
  590.  
  591.  
  592. Public void Complex_Imaginary_Part()
  593.         /* Return the imaginary part of a complex in rectangular form */
  594. {
  595.         Make_Real_Number( D );
  596. }
  597.  
  598.  
  599.  
  600.  
  601. Public void Complex_Magnitude()
  602.         /* Return the Magnitude of a complex, */
  603. {
  604.         Make_Real_Number( sqrt( (C*C) + (D*D) ) );
  605. }
  606.  
  607.  
  608.  
  609.  
  610. Public void Complex_Angle()
  611.         /* Return the angle of a complex */
  612. {
  613.     Double ang;
  614.     
  615.     ang = ( C == 0.0 && D > 0.0 ) ? HALF_PI :
  616.              ( ( C == 0.0 && D < 0.0 ) ? -HALF_PI : atan2(D,C) );
  617.  
  618.     if (Is_Complex_Zero()) Make_Real_Number( 0.0 );
  619.         else Make_Real_Number( ang );
  620.  
  621. }
  622.  
  623.  
  624. #undef A
  625. #undef B
  626. #undef C
  627. #undef D
  628.