home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD2.bin / bbs / dev / umbscheme-2.12.lha / UMBScheme / src / complex.c < prev    next >
C/C++ Source or Header  |  1993-11-29  |  14KB  |  629 lines

  1. /* complex.c -- UMB Scheme, complex number package.
  2.  
  3. UMB Scheme Interpreter                  $Revision: 2.12 $
  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**