diff src/DLD-FUNCTIONS/besselj.cc @ 3220:3deb1105fbc1

[project @ 1998-11-19 00:06:30 by jwe]
author jwe
date Thu, 19 Nov 1998 00:06:34 +0000
parents 3d3eca53ecca
children 511caaa5e98e
line wrap: on
line diff
--- a/src/DLD-FUNCTIONS/besselj.cc	Fri Nov 13 03:44:36 1998 +0000
+++ b/src/DLD-FUNCTIONS/besselj.cc	Thu Nov 19 00:06:34 1998 +0000
@@ -32,25 +32,43 @@
 #include "oct-obj.h"
 #include "utils.h"
 
-#define DO_BESSEL(type, alpha, x) \
+enum bessel_type
+{
+  BESSEL_J,
+  BESSEL_Y,
+  BESSEL_I,
+  BESSEL_K,
+  BESSEL_H1,
+  BESSEL_H2
+};
+
+#define DO_BESSEL(type, alpha, x, scaled, ierr, result) \
   do \
     { \
       switch (type) \
 	{ \
-	  case 'j': \
-	    retval = besselj (alpha, x); \
+	  case BESSEL_J: \
+	    result = besselj (alpha, x, scaled, ierr); \
+	    break; \
+ \
+	  case BESSEL_Y: \
+	    result = bessely (alpha, x, scaled, ierr); \
 	    break; \
  \
-	  case 'y': \
-	    retval = bessely (alpha, x); \
+	  case BESSEL_I: \
+	    result = besseli (alpha, x, scaled, ierr); \
 	    break; \
  \
-	  case 'i': \
-	    retval = besseli (alpha, x); \
+	  case BESSEL_K: \
+	    result = besselk (alpha, x, scaled, ierr); \
 	    break; \
  \
-	  case 'k': \
-	    retval = besselk (alpha, x); \
+	  case BESSEL_H1: \
+	    result = besselh1 (alpha, x, scaled, ierr); \
+	    break; \
+ \
+	  case BESSEL_H2: \
+	    result = besselh2 (alpha, x, scaled, ierr); \
 	    break; \
  \
 	  default: \
@@ -59,78 +77,155 @@
     } \
   while (0)
 
+static inline Matrix
+int_array2_to_matrix (const Array2<int>& a)
+{
+  int nr = a.rows ();
+  int nc = a.cols ();
+
+  Matrix retval (nr, nc);
+
+  for (int j = 0; j < nc; j++)
+    for (int i = 0; i < nr; i++)
+      retval(i,j) = (double) (a(i,j));
+
+  return retval;
+}
+
 static void
-gripe_bessel_arg_1 (const char *fn)
+gripe_bessel_arg (const char *fn, const char *arg)
 {
-  error ("%s: alpha must be scalar or range with increment equal to 1", fn);
+  error ("%s: expecting scalar or matrix as %s argument", fn, arg);
 }
 
 octave_value_list
-do_bessel (char type, const char *fn, const octave_value_list& args)
+do_bessel (enum bessel_type type, const char *fn,
+	   const octave_value_list& args, int nargout)
 {
-  octave_value retval;
+  octave_value_list retval;
 
   int nargin = args.length ();
 
-  if (nargin == 2)
+  if (nargin == 2 || nargin == 3)
     {
+      bool scaled = (nargin == 3);
+
       octave_value alpha_arg = args(0);
+      octave_value x_arg = args(1);
 
       if (alpha_arg.is_scalar_type ())
 	{
-	  double alpha = alpha_arg.double_value ();
+	  double alpha = args(0).double_value ();
 
 	  if (! error_state)
 	    {
-	      Matrix x = args(1).matrix_value ();
+	      if (x_arg.is_scalar_type ())
+		{
+		  Complex x = x_arg.complex_value ();
+
+		  if (! error_state)
+		    {
+		      int ierr;
+		      octave_value result;
+
+		      DO_BESSEL (type, alpha, x, scaled, ierr, result);
+
+		      if (nargout > 1)
+			retval(1) = (double) ierr;
 
-	      if (! error_state)
-		DO_BESSEL (type, alpha, x);
+		      retval(0) = result;
+		    }
+		  else
+		    gripe_bessel_arg (fn, "second");
+		}
 	      else
-		error ("%s: expecting matrix as second argument", fn);
+		{
+		  ComplexMatrix x = x_arg.complex_matrix_value ();
+
+		  if (! error_state)
+		    {
+		      Array2<int> ierr;
+		      octave_value result;
+
+		      DO_BESSEL (type, alpha, x, scaled, ierr, result);
+
+		      if (nargout > 1)
+			retval(1) = int_array2_to_matrix (ierr);
+
+		      retval(0) = result;
+		    }
+		  else
+		    gripe_bessel_arg (fn, "second");
+		}
 	    }
 	  else
-	    gripe_bessel_arg_1 (fn);
+	    gripe_bessel_arg (fn, "first");
 	}
       else
 	{
-	  Range alpha;
+	  Matrix alpha = args(0).matrix_value ();
 
-	  if (! alpha_arg.is_range ())
+	  if (! error_state)
 	    {
-	      ColumnVector tmp = alpha_arg.vector_value ();
+	      if (x_arg.is_scalar_type ())
+		{
+		  Complex x = x_arg.complex_value ();
+
+		  if (! error_state)
+		    {
+		      Array2<int> ierr;
+		      octave_value result;
 
-	      if (! error_state)
+		      DO_BESSEL (type, alpha, x, scaled, ierr, result);
+
+		      if (nargout > 1)
+			retval(1) = int_array2_to_matrix (ierr);
+
+		      retval(0) = result;
+		    }
+		  else
+		    gripe_bessel_arg (fn, "second");
+		}
+	      else
 		{
-		  int len = tmp.length ();
+		  ComplexMatrix x = x_arg.complex_matrix_value ();
 
-		  double base = tmp(0);
+		  if (! error_state)
+		    {
+		      if (alpha.rows () == 1 && x.columns () == 1)
+			{
+			  RowVector ralpha = alpha.row (0);
+			  ComplexColumnVector cx = x.column (0);
+
+			  Array2<int> ierr;
+			  octave_value result;
+
+			  DO_BESSEL (type, ralpha, cx, scaled, ierr, result);
 
-		  for (int i = 1; i < len; i++)
-		    {
-		      if (tmp(i) != base + i)
+			  if (nargout > 1)
+			    retval(1) = int_array2_to_matrix (ierr);
+
+			  retval(0) = result;
+			}
+		      else
 			{
-			  gripe_bessel_arg_1 (fn);
-			  break;
+			  Array2<int> ierr;
+			  octave_value result;
+
+			  DO_BESSEL (type, alpha, x, scaled, ierr, result);
+
+			  if (nargout > 1)
+			    retval(1) = int_array2_to_matrix (ierr);
+
+			  retval(0) = result;
 			}
 		    }
-
-		  if (! error_state)
-		    alpha = Range (tmp(0), tmp(len-1));
+		  else
+		    gripe_bessel_arg (fn, "second");
 		}
 	    }
 	  else
-	    alpha = alpha_arg.range_value ();
-
-	  if (! error_state)
-	    {
-	      ColumnVector x = args(1).vector_value ();
-
-	      if (! error_state)
-		DO_BESSEL (type, alpha, x);
-	      else
-		error ("%s: expecting vector as second argument", fn);
-	    }
+	    gripe_bessel_arg (fn, "first");
 	}
     }
   else
@@ -139,72 +234,281 @@
   return retval;
 }
 
-DEFUN_DLD (besselj, args, ,
-  "besselj (alpha, x)\n\
+DEFUN_DLD (besselj, args, nargout,
+  "[J, IERR] = BESSELJ (ALPHA, X [, 1])\n\
 \n\
 Compute Bessel functions of the first kind.\n\
 \n\
-X must be a real matrix, vector or scalar.\n\
+If a third argument is supplied, scale the result by exp(-I*Z) for\n\
+K = 1 or exp(I*Z) for K = 2.\n\
+\n\
+If ALPHA is a scalar, the result is the same size as X.  If X is a\n\
+scalar, the result is the same size as ALPHA.  If ALPHA is a row\n\
+vector and X is a column vector, the result is a matrix with\n\
+length(X) rows and length(ALPHA) columns.  Otherwise, ALPHA and X must\n\
+conform and the result will be the same size.\n\
+\n\
+ALPHA must be real.  X may be complex.\n\
 \n\
-If ALPHA is a scalar, the result is the same size as X.  If ALPHA is a\n\
-range, X must be a vector or scalar, and the result is a matrix with\n\
-length(X) rows and length(ALPHA) columns.\n\
-\n\
-ALPHA must be greater than or equal to zero.  If ALPHA is a range, it\n\
-must have an increment equal to one.")
+If requested, IERR contains the following status information and is\n\
+the same size as the result.\n\
+\n
+  0  normal return\n\
+  1  input error, return NaN\n\
+  2  overflow, return Inf\n\
+  3  loss of significance by argument reduction results in less than\n\
+     half of machine accuracy\n\
+  4  complete loss of significance by argument reduction, return NaN\n\
+  5  error -- no computation, algorithm termination condition not met,\n\
+     return NaN")
 {
-  return do_bessel ('j', "besselj", args);
+  return do_bessel (BESSEL_J, "besselj", args, nargout);
 }
 
-DEFUN_DLD (bessely, args, ,
-  "bessely (alpha, x)\n\
+DEFUN_DLD (bessely, args, nargout,
+  "[Y, IERR] = BESSELY (ALPHA, X [, 1])\n\
 \n\
 Compute Bessel functions of the second kind.\n\
 \n\
-X must be a real matrix, vector or scalar.\n\
+If a third argument is supplied, scale the result by exp(-I*Z) for\n\
+K = 1 or exp(I*Z) for K = 2.\n\
+\n\
+If ALPHA is a scalar, the result is the same size as X.  If X is a\n\
+scalar, the result is the same size as ALPHA.  If ALPHA is a row\n\
+vector and X is a column vector, the result is a matrix with\n\
+length(X) rows and length(ALPHA) columns.  Otherwise, ALPHA and X must\n\
+conform and the result will be the same size.\n\
+\n\
+ALPHA must be real.  X may be complex.\n\
 \n\
-If ALPHA is a scalar, the result is the same size as X.  If ALPHA is a\n\
-range, X must be a vector or scalar, and the result is a matrix with\n\
-length(X) rows and length(ALPHA) columns.\n\
-\n\
-ALPHA must be greater than or equal to zero.  If ALPHA is a range, it\n\
-must have an increment equal to one.")
+If requested, IERR contains the following status information and is\n\
+the same size as the result.\n\
+\n
+  0  normal return\n\
+  1  input error, return NaN\n\
+  2  overflow, return Inf\n\
+  3  loss of significance by argument reduction results in less than\n\
+     half of machine accuracy\n\
+  4  complete loss of significance by argument reduction, return NaN\n\
+  5  error -- no computation, algorithm termination condition not met,\n\
+     return NaN")
 {
-  return do_bessel ('y', "bessely", args);
+  return do_bessel (BESSEL_Y, "bessely", args, nargout);
 }
 
-DEFUN_DLD (besseli, args, ,
-  "besseli (alpha, x)\n\
+DEFUN_DLD (besseli, args, nargout,
+  "[I, IERR] = BESSELI (ALPHA, X [, 1])\n\
 \n\
 Compute modified Bessel functions of the first kind.\n\
 \n\
-X must be a real matrix, vector or scalar.\n\
+If a third argument is supplied, scale the result by exp(-I*Z) for\n\
+K = 1 or exp(I*Z) for K = 2.\n\
+\n\
+If ALPHA is a scalar, the result is the same size as X.  If X is a\n\
+scalar, the result is the same size as ALPHA.  If ALPHA is a row\n\
+vector and X is a column vector, the result is a matrix with\n\
+length(X) rows and length(ALPHA) columns.  Otherwise, ALPHA and X must\n\
+conform and the result will be the same size.\n\
+\n\
+ALPHA must be real.  X may be complex.\n\
 \n\
-If ALPHA is a scalar, the result is the same size as X.  If ALPHA is a\n\
-range, X must be a vector or scalar, and the result is a matrix with\n\
-length(X) rows and length(ALPHA) columns.\n\
-\n\
-ALPHA must be greater than or equal to zero.  If ALPHA is a range, it\n\
-must have an increment equal to one.")
+If requested, IERR contains the following status information and is\n\
+the same size as the result.\n\
+\n
+  0  normal return\n\
+  1  input error, return NaN\n\
+  2  overflow, return Inf\n\
+  3  loss of significance by argument reduction results in less than\n\
+     half of machine accuracy\n\
+  4  complete loss of significance by argument reduction, return NaN\n\
+  5  error -- no computation, algorithm termination condition not met,\n\
+     return NaN")
 {
-  return do_bessel ('i', "besseli", args);
+  return do_bessel (BESSEL_I, "besseli", args, nargout);
 }
 
-DEFUN_DLD (besselk, args, ,
-  "besselk (alpha, x)\n\
+DEFUN_DLD (besselk, args, nargout,
+  "[K, IERR] = BESSELK (ALPHA, X [, 1])\n\
 \n\
 Compute modified Bessel functions of the second kind.\n\
 \n\
-X must be a real matrix, vector or scalar.\n\
+If a third argument is supplied, scale the result by exp(-I*Z) for\n\
+K = 1 or exp(I*Z) for K = 2.\n\
+\n\
+If ALPHA is a scalar, the result is the same size as X.  If X is a\n\
+scalar, the result is the same size as ALPHA.  If ALPHA is a row\n\
+vector and X is a column vector, the result is a matrix with\n\
+length(X) rows and length(ALPHA) columns.  Otherwise, ALPHA and X must\n\
+conform and the result will be the same size.\n\
+\n\
+ALPHA must be real.  X may be complex.\n\
+\n\
+If requested, IERR contains the following status information and is\n\
+the same size as the result.\n\
+\n
+  0  normal return\n\
+  1  input error, return NaN\n\
+  2  overflow, return Inf\n\
+  3  loss of significance by argument reduction results in less than\n\
+     half of machine accuracy\n\
+  4  complete loss of significance by argument reduction, return NaN\n\
+  5  error -- no computation, algorithm termination condition not met,\n\
+     return NaN")
+{
+  return do_bessel (BESSEL_K, "besselk", args, nargout);
+}
+
+DEFUN_DLD (besselh, args, nargout,
+  "[H, IERR] = besselh (ALPHA, K, X [, 1])\n\
+\n\
+Compute Hankel functions of the first (K = 1) or second (K = 2) kind.\n\
+\n\
+If a fourth argument is supplied, scale the result by exp(-I*Z) for\n\
+K = 1 or exp(I*Z) for K = 2.\n\
+\n\
+If ALPHA is a scalar, the result is the same size as X.  If X is a\n\
+scalar, the result is the same size as ALPHA.  If ALPHA is a row\n\
+vector and X is a column vector, the result is a matrix with\n\
+length(X) rows and length(ALPHA) columns.  Otherwise, ALPHA and X must\n\
+conform and the result will be the same size.\n\
+\n\
+ALPHA must be real.  X may be complex.\n\
 \n\
-If ALPHA is a scalar, the result is the same size as X.  If ALPHA is a\n\
-range, X must be a vector or scalar, and the result is a matrix with\n\
-length(X) rows and length(ALPHA) columns.\n\
+If requested, IERR contains the following status information and is\n\
+the same size as the result.\n\
+\n
+  0  normal return\n\
+  1  input error, return NaN\n\
+  2  overflow, return Inf\n\
+  3  loss of significance by argument reduction results in less than\n\
+     half of machine accuracy\n\
+  4  complete loss of significance by argument reduction, return NaN\n\
+  5  error -- no computation, algorithm termination condition not met,\n\
+     return NaN")
+{
+  octave_value_list retval;
+
+  int nargin = args.length ();
+
+  int kind = 1;
+
+  if (nargin == 2)
+    {
+      retval = do_bessel (BESSEL_H1, "besselh", args, nargout);
+    }
+  else if (nargin == 3 || nargin == 4)
+    {
+      double d_kind = args(1).double_value ();
+
+      if (! error_state && D_NINT (d_kind) == d_kind)
+	{
+	  octave_value_list tmp_args;
+
+	  if (nargin == 4)
+	    tmp_args(2) = args(3);
+
+	  tmp_args(1) = args(2);
+	  tmp_args(0) = args(0);
+
+	  if (kind == 1)
+	    retval = do_bessel (BESSEL_H1, "besselh", tmp_args, nargout);
+	  else if (kind == 2)
+	    retval = do_bessel (BESSEL_H2, "besselh", tmp_args, nargout);
+	  else
+	    error ("besselh: expecting K = 1 or 2");
+	}
+      else
+	error ("besselh: invalid value of K");
+    }
+  else
+    print_usage ("besselh");
+
+  return retval;
+}
+
+DEFUN_DLD (airy, args, nargout,
+  "[A, IERR] = airy (K, Z, [, 1])\n\
+\n\
+Compute Airy functions of the first and second kind, and their\n\
+derivatives.\n\
+\n\
+  K   Function   Scale factor (if a third argument is supplied)\n\
+ ---  --------   ----------------------------------------------\n\
+  0   Ai (Z)     exp ((2/3) * Z * sqrt (Z))\n\
+  1   dAi(Z)/dZ  exp ((2/3) * Z * sqrt (Z))\n\
+  2   Bi (Z)     exp (-abs (real ((2/3) * Z *sqrt (Z))))\n\
+  3   dBi(Z)/dZ  exp (-abs (real ((2/3) * Z *sqrt (Z))))\n\
+\n\
+The function call airy (Z) is equivalent to airy (0, Z).\n\
 \n\
-ALPHA must be greater than or equal to zero.  If ALPHA is a range, it\n\
-must have an increment equal to one.")
+The result is the same size as Z.
+\n\
+If requested, IERR contains the following status information and is\n\
+the same size as the result.\n\
+\n
+  0  normal return\n\
+  1  input error, return NaN\n\
+  2  overflow, return Inf\n\
+  3  loss of significance by argument reduction results in less than\n\
+     half of machine accuracy\n\
+  4  complete loss of significance by argument reduction, return NaN\n\
+  5  error -- no computation, algorithm termination condition not met,\n\
+     return NaN")
 {
-  return do_bessel ('k', "besselk", args);
+  octave_value_list retval;
+
+  int nargin = args.length ();
+
+  if (nargin > 0 && nargin < 4)
+    {
+      bool scale = (nargin == 3);
+
+      int kind = 0;
+
+      ComplexMatrix z;
+
+      if (nargin > 1)
+	{
+	  double d_kind = args(0).double_value ();
+
+	  if (! error_state)
+	    {
+	      kind = (int) d_kind;
+
+	      if (kind < 0 || kind > 3)
+		error ("airy: expecting K = 0, 1, 2, or 3");
+	    }	      
+	  else
+	    error ("airy: expecting integer value for K");
+	}
+
+      if (! error_state)
+	{
+	  z = args(nargin == 1 ? 0 : 1).complex_matrix_value ();
+
+	  if (! error_state)
+	    {
+	      Array2<int> ierr;
+	      octave_value result;
+
+	      if (kind > 1)
+		result = biry (z, kind == 3, scale, ierr);
+	      else
+		result = airy (z, kind == 1, scale, ierr);
+
+	      if (nargout > 1)
+		retval(1) = int_array2_to_matrix (ierr);
+
+	      retval(0) = result;
+	    }
+	  else
+	    error ("airy: expecting complex matrix for Z");
+	}
+    }
+  else
+    print_usage ("airy");
+
+  return retval;
 }
 
 /*