home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mitsch75.zip / scheme-7_5_17-src.zip / scheme-7.5.17 / src / microcode / array.c < prev    next >
C/C++ Source or Header  |  1999-01-02  |  63KB  |  2,250 lines

  1. /* -*-C-*-
  2.  
  3. $Id: array.c,v 9.46 1999/01/02 06:11:34 cph Exp $
  4.  
  5. Copyright (c) 1987-1999 Massachusetts Institute of Technology
  6.  
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful, but
  13. WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15. General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21.  
  22. #include "scheme.h"
  23. #include "prims.h"
  24. #include "array.h"
  25. #include <math.h>
  26. #include <values.h>
  27. /* <values.h> contains some math constants */
  28.  
  29. /* ARRAY (as a scheme object)
  30.    is a usual array (in C) containing REAL numbers (float/double)
  31.    and tagged as a non-marked vector.
  32.  
  33.    Basic contents:
  34.    constructors, selectors, arithmetic operations,
  35.    conversion routines between C_Array, and Scheme_Vector
  36.  
  37.    see array.h for macros, NM_VECTOR, and extern */
  38.  
  39. /* mathematical constants */
  40. #ifdef PI
  41. #undef PI
  42. #endif
  43. #define PI           3.141592653589793238462643
  44. #define PI_OVER_2    1.570796326794896619231322
  45. #define TWOPI        6.283185307179586476925287
  46. #define SQRT_2          1.4142135623730950488
  47. #define ONE_OVER_SQRT_2  .7071067811865475244
  48. /* Abramowitz and Stegun p.3 */
  49.  
  50. REAL
  51. flonum_to_real (argument, arg_number)
  52.      fast SCHEME_OBJECT argument;
  53.      int arg_number;
  54. {
  55.   switch (OBJECT_TYPE (argument))
  56.     {
  57.     case TC_FIXNUM:
  58.       return ((REAL) (FIXNUM_TO_DOUBLE (argument)));
  59.  
  60.     case TC_BIG_FIXNUM:
  61.       if (! (BIGNUM_TO_DOUBLE_P (argument)))
  62.       error_bad_range_arg (arg_number);
  63.       return ((REAL) (bignum_to_double (argument)));
  64.  
  65.     case TC_BIG_FLONUM:
  66.       return ((REAL) (FLONUM_TO_DOUBLE (argument)));
  67.  
  68.     default:
  69.       error_wrong_type_arg (arg_number);
  70.       /* NOTREACHED */
  71.     }
  72. }
  73.  
  74. SCHEME_OBJECT
  75. allocate_array (length)
  76.      long length;
  77. {
  78. #if (REAL_IS_DEFINED_DOUBLE == 0)
  79.  
  80.   fast SCHEME_OBJECT result =
  81.     (allocate_non_marked_vector
  82.      (TC_NON_MARKED_VECTOR, ((length * REAL_SIZE) + 1), true));
  83.   FAST_MEMORY_SET (result, 1, length);
  84.   return (result);
  85.  
  86. #else /* (REAL_IS_DEFINED_DOUBLE != 0) */
  87.   
  88.   long n_words = (length * DOUBLE_SIZE);
  89.   ALIGN_FLOAT (Free);
  90.   Primitive_GC_If_Needed (n_words + 1);
  91.   {
  92.     SCHEME_OBJECT result = (MAKE_POINTER_OBJECT (TC_BIG_FLONUM, (Free)));
  93.     (*Free++) = (MAKE_OBJECT (TC_MANIFEST_NM_VECTOR, n_words));
  94.     Free += n_words;
  95.     return (result);
  96.   }
  97.  
  98. #endif /* (REAL_IS_DEFINED_DOUBLE != 0) */
  99. }
  100.  
  101. DEFINE_PRIMITIVE ("VECTOR->ARRAY", Prim_vector_to_array, 1, 1, 0)
  102. {
  103.   PRIMITIVE_HEADER (1);
  104.   CHECK_ARG (1, VECTOR_P);
  105.   {
  106.     SCHEME_OBJECT vector = (ARG_REF (1));
  107.     long length = (VECTOR_LENGTH (vector));
  108.     SCHEME_OBJECT result = (allocate_array (length));
  109.     fast SCHEME_OBJECT * scan_source = (& (VECTOR_REF (vector, 0)));
  110.     fast SCHEME_OBJECT * end_source = (scan_source + length);
  111.     fast REAL * scan_target = (ARRAY_CONTENTS (result));
  112.     while (scan_source < end_source)
  113.       (*scan_target++) = (flonum_to_real ((*scan_source++), 1));
  114.     PRIMITIVE_RETURN (result);
  115.   }
  116. }
  117.  
  118. DEFINE_PRIMITIVE ("ARRAY->VECTOR", Prim_array_to_vector, 1, 1, 0)
  119. {
  120.   PRIMITIVE_HEADER (1);
  121.   CHECK_ARG (1, ARRAY_P);
  122.   {
  123.     SCHEME_OBJECT array = (ARG_REF (1));
  124.     long length = (ARRAY_LENGTH (array));
  125.     fast REAL * scan_source = (ARRAY_CONTENTS (array));
  126.     fast REAL * end_source = (scan_source + length);
  127.     SCHEME_OBJECT result = (allocate_marked_vector (TC_VECTOR, length, true));
  128.     fast SCHEME_OBJECT * scan_result = (MEMORY_LOC (result, 1));
  129.     while (scan_source < end_source)
  130.       (*scan_result++) = (double_to_flonum ((double) (*scan_source++)));
  131.     PRIMITIVE_RETURN (result);
  132.   }
  133. }
  134.  
  135. DEFINE_PRIMITIVE ("ARRAY-ALLOCATE", Prim_array_allocate, 1,1, 0)
  136. {
  137.   fast REAL * scan;
  138.   long length;
  139.   SCHEME_OBJECT result;
  140.   PRIMITIVE_HEADER (1);
  141.  
  142.   length = (arg_nonnegative_integer (1));
  143.   result = (allocate_array (length));
  144.   for (scan = (ARRAY_CONTENTS (result)); --length >= 0; )
  145.     *scan++ = ((REAL) 0.0);
  146.   PRIMITIVE_RETURN (result);
  147. }
  148.  
  149. DEFINE_PRIMITIVE ("ARRAY-CONS-REALS", Prim_array_cons_reals, 3, 3, 0)
  150. {
  151.   PRIMITIVE_HEADER (3);
  152.   {
  153.     fast double from = (arg_real_number (1));
  154.     fast double dt = (arg_real_number (2));
  155.     long length = (arg_nonnegative_integer (3));
  156.     SCHEME_OBJECT result = (allocate_array (length));
  157.     fast REAL * scan_result = (ARRAY_CONTENTS (result));
  158.     fast int i;
  159.     for (i = 0; (i < length); i += 1)
  160.       {
  161.     (*scan_result++) = ((REAL) from);
  162.     from += dt;
  163.       }
  164.     PRIMITIVE_RETURN (result);
  165.   }
  166. }
  167.  
  168. DEFINE_PRIMITIVE ("ARRAY-LENGTH", Prim_array_length, 1, 1, 0)
  169. {
  170.   PRIMITIVE_HEADER (1);
  171.   CHECK_ARG (1, ARRAY_P);
  172.   PRIMITIVE_RETURN (LONG_TO_UNSIGNED_FIXNUM (ARRAY_LENGTH (ARG_REF (1))));
  173. }
  174.  
  175. DEFINE_PRIMITIVE ("ARRAY-REF", Prim_array_ref, 2, 2, 0)
  176. {
  177.   SCHEME_OBJECT array;
  178.   PRIMITIVE_HEADER (2);
  179.   CHECK_ARG (1, ARRAY_P);
  180.   array = (ARG_REF (1));
  181.   PRIMITIVE_RETURN
  182.     (double_to_flonum
  183.      ((double)
  184.       ((ARRAY_CONTENTS (array))
  185.        [arg_index_integer (2, (ARRAY_LENGTH (array)))])));
  186. }
  187.  
  188. DEFINE_PRIMITIVE ("ARRAY-SET!", Prim_array_set, 3, 3, 0)
  189. {
  190.   SCHEME_OBJECT array;
  191.   REAL * array_ptr;
  192.   double old_value, new_value;
  193.   PRIMITIVE_HEADER (3);
  194.   CHECK_ARG (1, ARRAY_P);
  195.   array = (ARG_REF (1));
  196.   array_ptr =
  197.     (& ((ARRAY_CONTENTS (array))
  198.     [arg_index_integer (2, (ARRAY_LENGTH (array)))]));
  199.   old_value = (*array_ptr);
  200.   new_value = (arg_real_number (3));
  201. #if (REAL_IS_DEFINED_DOUBLE == 0)
  202.   if ((new_value >= 0.0)
  203.       ? (new_value < ((double) FLT_MIN))
  204.       : (new_value > (0.0 - ((double) FLT_MIN))))
  205.     new_value = ((REAL) 0.0);
  206. #endif
  207.   (*array_ptr) = ((REAL) new_value);
  208.   PRIMITIVE_RETURN (double_to_flonum (old_value));
  209. }
  210.  
  211. /*____________________ file readers ___________
  212.   ascii and 2bint formats 
  213.   ______________________________________________*/
  214.  
  215. /* Reading data from files 
  216.    To read REAL numbers, use "lf" for double, "%f" for float 
  217.    */
  218. #if (REAL_IS_DEFINED_DOUBLE == 1)
  219. #define REALREAD  "%lf"
  220. #define REALREAD2 "%lf %lf"
  221. #else
  222. #define REALREAD  "%f"
  223. #define REALREAD2 "%f %f"
  224. #endif
  225.  
  226. static void
  227. C_Array_Read_Ascii_File (a, N, fp)          /* 16 ascii decimal digits */
  228.      REAL * a;
  229.      long N;
  230.      FILE * fp;
  231.   fast long i;
  232.   for (i = 0; (i < N); i += 1)
  233.     {
  234.       if ((fscanf (fp, REALREAD, (&(a[i])))) != 1)
  235.     { printf("Not enough values read ---\n last value a[%d] = % .16e \n", (i-1), a[i-1]);
  236.       error_external_return (); }
  237.     }
  238.   return;
  239. }
  240.  
  241. /* 2BINT FORMAT = integer stored in 2 consecutive bytes.
  242.    On many machines, "putw" and "getw" use 4 byte integers (C int)
  243.    so use "putc" "getc" as shown below.
  244.    */
  245.  
  246. static void
  247. C_Array_Read_2bint_File (a, N, fp)
  248.      REAL * a;
  249.      long N;
  250.      FILE * fp;
  251. {
  252.   fast long i;
  253.   fast int msd;
  254.   for (i = 0; (i < N); i += 1)
  255.     {
  256.       if (feof (fp))
  257.     error_external_return ();
  258.       msd = (getc (fp));
  259.       (a [i]) = ((REAL) ((msd << 8) | (getc (fp))));
  260.     }
  261.   return;
  262. }
  263.  
  264. DEFINE_PRIMITIVE ("ARRAY-READ-FROM-FILE", Prim_array_read_from_file, 3,3, 0)
  265. {
  266.   PRIMITIVE_HEADER (3);
  267.   CHECK_ARG (1, STRING_P);    /* 1 = filename */
  268.   /*                               2 = length of data */
  269.   CHECK_ARG (3, FIXNUM_P);    /* 3 = format of data   0=ascii 1=2bint  */
  270.   {
  271.     fast long length = (arg_nonnegative_integer (2));
  272.     fast SCHEME_OBJECT result = (allocate_array (length));
  273.     int format;
  274.     fast FILE * fp;
  275.     if ( (fp = fopen((STRING_ARG (1)), "r")) == NULL)
  276.       error_bad_range_arg (1);
  277.     
  278.     format = arg_nonnegative_integer(3);
  279.     if (format==0)
  280.       C_Array_Read_Ascii_File ((ARRAY_CONTENTS (result)), length, fp);
  281.     else if (format==1)
  282.       C_Array_Read_2bint_File ((ARRAY_CONTENTS (result)), length, fp);
  283.     else
  284.       error_bad_range_arg(3);    /* illegal format code */
  285.     
  286.     if ((fclose (fp)) != 0)
  287.       error_external_return ();
  288.     PRIMITIVE_RETURN (result);
  289.   }
  290. }
  291.  
  292. static void
  293. C_Array_Write_Ascii_File (a, N, fp)           /* 16 ascii decimal digits */
  294.      REAL * a;
  295.      long N;
  296.      FILE * fp;
  297. {
  298.   fast long i;
  299.   for (i = 0; (i < N); i += 1)
  300.     {
  301.       if (feof (fp))
  302.     error_external_return ();
  303.       fprintf (fp, "% .16e \n", a[i]);
  304.     }
  305.   return;
  306. }
  307.  
  308. DEFINE_PRIMITIVE ("ARRAY-WRITE-ASCII-FILE", Prim_array_write_ascii_file, 2, 2, 0)
  309. {
  310.   PRIMITIVE_HEADER (2);
  311.   CHECK_ARG (1, ARRAY_P);
  312.   CHECK_ARG (2, STRING_P);
  313.   {
  314.     fast SCHEME_OBJECT array = (ARG_REF (1));
  315.     fast FILE * fp = (fopen((STRING_ARG (2)), "w"));
  316.     if (fp == ((FILE *) 0))
  317.       error_bad_range_arg (2);
  318.     C_Array_Write_Ascii_File
  319.       ((ARRAY_CONTENTS (array)),
  320.        (ARRAY_LENGTH (array)),
  321.        fp);
  322.     if ((fclose (fp)) != 0)
  323.       error_external_return ();
  324.   }
  325.   PRIMITIVE_RETURN (UNSPECIFIC);
  326. }
  327.  
  328.  
  329.  
  330.  
  331. DEFINE_PRIMITIVE ("SUBARRAY-COPY!", Prim_subarray_copy, 5, 5, 0)
  332. {
  333.   PRIMITIVE_HEADER (5);
  334.   CHECK_ARG (1, ARRAY_P);    /* source array */
  335.   CHECK_ARG (2, ARRAY_P);    /* destination array */
  336.   {
  337.     REAL * source = (ARRAY_CONTENTS (ARG_REF (1)));
  338.     REAL * target = (ARRAY_CONTENTS (ARG_REF (2)));
  339.     long start_source = (arg_nonnegative_integer (3));
  340.     long start_target = (arg_nonnegative_integer (4));
  341.     long n_elements = (arg_nonnegative_integer (5));
  342.     if ((start_source + n_elements) > (ARRAY_LENGTH (ARG_REF (1))))
  343.       error_bad_range_arg (3);
  344.     if ((start_target + n_elements) > (ARRAY_LENGTH (ARG_REF (2))))
  345.       error_bad_range_arg (4);
  346.     {
  347.       fast REAL * scan_source = (source + start_source);
  348.       fast REAL * end_source = (scan_source + n_elements);
  349.       fast REAL * scan_target = (target + start_target);
  350.       while (scan_source < end_source)
  351.     (*scan_target++) = (*scan_source++);
  352.     }
  353.   }
  354.   PRIMITIVE_RETURN (UNSPECIFIC);
  355. }
  356.  
  357. DEFINE_PRIMITIVE ("ARRAY-REVERSE!", Prim_array_reverse, 1, 1, 0)
  358. {
  359.   PRIMITIVE_HEADER (1);
  360.   CHECK_ARG (1, ARRAY_P);
  361.   {
  362.     SCHEME_OBJECT array = (ARG_REF (1));
  363.     long length = (ARRAY_LENGTH (array));
  364.     long half_length = (length / 2);
  365.     fast REAL * array_ptr = (ARRAY_CONTENTS (array));
  366.     fast long i;
  367.     fast long j;
  368.     for (i = 0, j = (length - 1); (i < half_length); i += 1, j -= 1)
  369.       {
  370.     fast REAL Temp = (array_ptr [j]);
  371.     (array_ptr [j]) = (array_ptr [i]);
  372.     (array_ptr [i]) = Temp;
  373.       }
  374.   }
  375.   PRIMITIVE_RETURN (UNSPECIFIC);
  376. }
  377.  
  378. DEFINE_PRIMITIVE ("ARRAY-TIME-REVERSE!", Prim_array_time_reverse, 1, 1, 0)
  379. {
  380.   void C_Array_Time_Reverse ();
  381.   PRIMITIVE_HEADER (1);
  382.   CHECK_ARG (1, ARRAY_P);
  383.   C_Array_Time_Reverse
  384.     ((ARRAY_CONTENTS (ARG_REF (1))), (ARRAY_LENGTH (ARG_REF (1))));
  385.   PRIMITIVE_RETURN (UNSPECIFIC);
  386. }
  387.  
  388. /* time-reverse
  389.    x[0] remains fixed. (time=0)
  390.    x[i] swapped with x[n-i]. (mirror image around x[0]) */
  391.  
  392. void
  393. C_Array_Time_Reverse (x,n)
  394.      REAL *x;
  395.      long n;
  396. { long i, ni, n2;
  397.   REAL xt;
  398.   if ((n % 2) == 0)        /* even length */
  399.   { n2 = (n/2);
  400.     for (i=1; i<n2; i++)    /* i=1,2,..,n/2-1 */
  401.     {  ni = n-i;
  402.        xt    = x[i];
  403.        x[i]  = x[ni];
  404.        x[ni] = xt; }}
  405.   else                /* odd length */
  406.   { n2 = (n+1)/2;        /* (n+1)/2 = (n-1)/2 + 1 */
  407.     for (i=1; i<n2; i++)    /* i=1,2,..,(n-1)/2 */
  408.     {  ni = n-i;
  409.        xt   = x[i];
  410.        x[i] = x[ni];
  411.        x[ni] = xt; }}
  412. }
  413.  
  414. /* The following is smart
  415.    and avoids computation when offset or scale are degenerate 0,1 */
  416.  
  417. DEFINE_PRIMITIVE ("SUBARRAY-OFFSET-SCALE!", Prim_subarray_offset_scale, 5, 5, 0)
  418. {
  419.   long i, at, m,mplus;
  420.   REAL *a, offset,scale;
  421.   PRIMITIVE_HEADER (5);
  422.   CHECK_ARG (1, ARRAY_P);
  423.   CHECK_ARG (2, FIXNUM_P);
  424.   CHECK_ARG (3, FIXNUM_P);
  425.   a = ARRAY_CONTENTS(ARG_REF(1));
  426.   at = arg_nonnegative_integer(2); /*       at = starting index             */
  427.   m  = arg_nonnegative_integer(3); /*       m  = number of points to change */
  428.   mplus = at + m;
  429.   if (mplus > (ARRAY_LENGTH(ARG_REF(1)))) error_bad_range_arg(3);
  430.   offset = (arg_real (4));
  431.   scale = (arg_real (5));
  432.   if ((offset == 0.0) && (scale == 1.0))
  433.     ;                /* be smart */
  434.   else if (scale == 0.0)
  435.     for (i=at; i<mplus; i++)  a[i] = offset;
  436.   else if (offset == 0.0)
  437.     for (i=at; i<mplus; i++)  a[i] = scale * a[i];
  438.   else if (scale == 1.0)
  439.     for (i=at; i<mplus; i++)  a[i] = offset + a[i];
  440.   else
  441.     for (i=at; i<mplus; i++)  a[i] = offset + scale * a[i];
  442.   PRIMITIVE_RETURN (UNSPECIFIC);
  443. }
  444.  
  445. DEFINE_PRIMITIVE ("COMPLEX-SUBARRAY-COMPLEX-SCALE!", Prim_complex_subarray_complex_scale, 6,6, 0)
  446. { long i, at,m,mplus;
  447.   REAL *a,*b;            /* (a,b) = (real,imag) arrays */
  448.   double temp, minus_y,  x, y;    /* (x,y) = (real,imag) scale */
  449.   PRIMITIVE_HEADER (6);
  450.   CHECK_ARG (1, ARRAY_P);
  451.   CHECK_ARG (2, ARRAY_P);
  452.   at = (arg_nonnegative_integer (3)); /* starting index */
  453.   m  = (arg_nonnegative_integer (4)); /* number of points to change */
  454.   mplus = at + m;
  455.   if (mplus > (ARRAY_LENGTH(ARG_REF(1)))) error_bad_range_arg(4);
  456.   x = (arg_real_number (5));
  457.   y = (arg_real_number (6));
  458.   a = ARRAY_CONTENTS(ARG_REF(1));
  459.   b = ARRAY_CONTENTS(ARG_REF(2));
  460.   if ((ARRAY_LENGTH(ARG_REF(1))) != (ARRAY_LENGTH(ARG_REF(2))))
  461.     error_bad_range_arg(2);
  462.   if (x==0.0)            /* imaginary only */
  463.     if       (y==0.0)
  464.       for (i=at; i<mplus; i++)
  465.       { a[i] = 0.0;
  466.     b[i] = 0.0; }
  467.     else if  (y==1.0)
  468.       for (i=at; i<mplus; i++)
  469.       { temp = b[i];
  470.     b[i] = a[i];
  471.     a[i] = (-temp); }
  472.     else if  (y==-1.0)
  473.       for (i=at; i<mplus; i++)
  474.       { temp = b[i];
  475.     b[i] = (-a[i]);
  476.     a[i] = temp; }
  477.     else
  478.     { minus_y = (-y);
  479.       for (i=at; i<mplus; i++)
  480.       { temp =               y * ((double) a[i]);
  481.     a[i] = (REAL) (minus_y * ((double) b[i]));
  482.     b[i] = (REAL) temp; }}
  483.   else if (y==0.0)        /* real only */
  484.     if (x==1.0) ;
  485.     else for (i=at; i<mplus; i++)
  486.     { a[i] = (REAL) (x * ((double) a[i]));
  487.       b[i] = (REAL) (x * ((double) b[i])); }
  488.   else                /* full complex scale */
  489.     for (i=at; i<mplus; i++)
  490.     { temp =         ((double) a[i])*x - ((double) b[i])*y;
  491.       b[i] = (REAL) (((double) b[i])*x + ((double) a[i])*y);
  492.       a[i] = (REAL) temp; }
  493.   PRIMITIVE_RETURN (UNSPECIFIC);
  494. }
  495.  
  496. /* Accumulate
  497.    using combinators              *
  498.    corresponding type codes       1 */
  499.  
  500. DEFINE_PRIMITIVE ("COMPLEX-SUBARRAY-ACCUMULATE!", Prim_complex_subarray_accumulate, 6,6, 0)
  501. { long  at,m,mplus, tc, i;
  502.   REAL *a,*b;            /* (a,b) = (real,imag) input arrays */
  503.   REAL *c;    /* result = output array of length 2, holds a complex number */
  504.   double x, y, temp;
  505.   PRIMITIVE_HEADER (6);
  506.   CHECK_ARG (1, ARRAY_P);    /* a = input array (real) */
  507.   CHECK_ARG (2, ARRAY_P);    /* b = input array (imag) */
  508.   a = ARRAY_CONTENTS(ARG_REF(1));
  509.   b = ARRAY_CONTENTS(ARG_REF(2));
  510.   if ((ARRAY_LENGTH(ARG_REF(1))) != (ARRAY_LENGTH(ARG_REF(2))))
  511.     error_bad_range_arg(2);
  512.   tc = arg_nonnegative_integer(3); /*       tc = type code 0 or 1            */
  513.   at = arg_nonnegative_integer(4); /*       at = starting index              */
  514.   m  = arg_nonnegative_integer(5); /*       m  = number of points to process */
  515.   CHECK_ARG (6, ARRAY_P);    /* c = output array of length 2 */
  516.   c = ARRAY_CONTENTS(ARG_REF(6));
  517.   if ((ARRAY_LENGTH(ARG_REF(6))) != 2) error_bad_range_arg(6);
  518.   mplus = at + m;
  519.   if (mplus > (ARRAY_LENGTH(ARG_REF(1)))) error_bad_range_arg(5);
  520.   if (tc==1)
  521.   { x = 1.0;            /* real part of accumulator */
  522.     y = 0.0;            /* imag part of accumulator */
  523.     for (i=at;i<mplus;i++)
  524.     { temp = ((double) a[i])*x - ((double) b[i])*y;
  525.       y    = ((double) b[i])*x + ((double) a[i])*y;
  526.       x    = temp; }
  527.   }
  528.   else
  529.     error_bad_range_arg(3);
  530.   c[0] = ((REAL) x);        /* mechanism for returning complex number */
  531.   c[1] = ((REAL) y);        /* do not use lists, avoid heap pointer   */
  532.   PRIMITIVE_RETURN (UNSPECIFIC);
  533. }
  534.  
  535. DEFINE_PRIMITIVE ("CS-ARRAY-TO-COMPLEX-ARRAY!", Prim_cs_array_to_complex_array, 3, 3, 0)
  536. { long n,n2,n2_1, i;
  537.   REAL *a, *b,*c;
  538.   PRIMITIVE_HEADER (3);
  539.   CHECK_ARG (1, ARRAY_P);
  540.   CHECK_ARG (2, ARRAY_P);
  541.   CHECK_ARG (3, ARRAY_P);
  542.   a = ARRAY_CONTENTS(ARG_REF(1));
  543.   n = ARRAY_LENGTH(ARG_REF(1));
  544.   b = ARRAY_CONTENTS(ARG_REF(2));
  545.   c = ARRAY_CONTENTS(ARG_REF(3));
  546.   if (n!=(ARRAY_LENGTH(ARG_REF(2)))) error_bad_range_arg(2);
  547.   if (n!=(ARRAY_LENGTH(ARG_REF(3)))) error_bad_range_arg(3);
  548.   b[0] = a[0];
  549.   c[0] = 0.0;
  550.   n2 = n/2;            /* integer division truncates down */
  551.   n2_1 = n2+1;
  552.   if (2*n2 == n)        /* even length, n2 is only real */
  553.   { b[n2]  = a[n2];  c[n2]  = 0.0; }
  554.   else /* odd length, make the loop include the n2 index */
  555.   { n2   = n2+1;
  556.     n2_1 = n2; }
  557.   for (i=1; i<n2; i++)   { b[i] = a[i];
  558.                c[i] = a[n-i]; }
  559.   for (i=n2_1; i<n; i++) { b[i] =  a[n-i];
  560.                c[i] = (-a[i]); }
  561.   PRIMITIVE_RETURN (UNSPECIFIC);
  562. }
  563.  
  564. DEFINE_PRIMITIVE ("CS-ARRAY-MULTIPLY-INTO-SECOND-ONE!", Prim_cs_array_multiply_into_second_one, 2, 2, 0)
  565. { long n,n2;
  566.   REAL *a, *b;
  567.   void cs_array_multiply_into_second_one();
  568.   PRIMITIVE_HEADER (2);
  569.   CHECK_ARG (1, ARRAY_P);
  570.   CHECK_ARG (2, ARRAY_P);
  571.   a = ARRAY_CONTENTS(ARG_REF(1));
  572.   n = ARRAY_LENGTH(ARG_REF(1));
  573.   b = ARRAY_CONTENTS(ARG_REF(2));
  574.   if (n!=(ARRAY_LENGTH(ARG_REF(2)))) error_bad_range_arg(2);
  575.   n2 = n/2;            /* integer division truncates down */
  576.   cs_array_multiply_into_second_one(a,b, n,n2);
  577.   PRIMITIVE_RETURN (UNSPECIFIC);
  578. }
  579.  
  580. void
  581. cs_array_multiply_into_second_one (a,b, n,n2)
  582.      REAL *a, *b;
  583.      long n,n2;
  584. {
  585.   REAL temp;
  586.   long i,ni;
  587.   b[0]   = a[0]  * b[0];
  588.   if (2*n2 == n)        /* even length, n2 is only real */
  589.     b[n2]  = a[n2] * b[n2];
  590.   else
  591.     n2 = n2+1; /* odd length, make the loop include the n2 index */
  592.   for (i=1; i<n2; i++)
  593.     {
  594.       ni = n-i;
  595.       temp   = a[i]*b[i]   -  a[ni]*b[ni]; /* real part */
  596.       b[ni]  = a[i]*b[ni]  +  a[ni]*b[i]; /*  imag part */
  597.       b[i]   = temp;
  598.     }
  599. }
  600.  
  601. DEFINE_PRIMITIVE ("CS-ARRAY-DIVIDE-INTO-XXX!", Prim_cs_array_divide_into_xxx, 4, 4, 0)
  602. {
  603.   long n,n2, one_or_two;
  604.   REAL *a, *b, inf;
  605.   void cs_array_divide_into_z();
  606.   PRIMITIVE_HEADER (4);
  607.   CHECK_ARG (1, ARRAY_P);
  608.   CHECK_ARG (2, ARRAY_P);
  609.   inf = (arg_real (3));
  610.   /* where to store result of division */
  611.   one_or_two = (arg_nonnegative_integer (4));
  612.   a = ARRAY_CONTENTS(ARG_REF(1));
  613.   b = ARRAY_CONTENTS(ARG_REF(2));
  614.   n = ARRAY_LENGTH(ARG_REF(1));
  615.   if (n!=(ARRAY_LENGTH(ARG_REF(2)))) error_bad_range_arg(2);
  616.   n2 = n/2;            /* integer division truncates down */
  617.   if (one_or_two == 1)
  618.     cs_array_divide_into_z(a,b, a,  n,n2, inf);
  619.   else if (one_or_two == 2)
  620.     cs_array_divide_into_z(a,b, b,  n,n2, inf);
  621.   else
  622.     error_bad_range_arg(4);
  623.   PRIMITIVE_RETURN (UNSPECIFIC);
  624. }
  625.  
  626. void
  627. cs_array_divide_into_second_one (a,b, n,n2,inf)    /* used in image.c */
  628.      REAL *a,*b, inf;
  629.      long n,n2;
  630. {
  631.   void cs_array_divide_into_z ();
  632.   cs_array_divide_into_z (a,b, b, n,n2,inf);
  633. }
  634.  
  635. void
  636. cs_array_divide_into_z (a,b, z, n,n2, inf) /* z can be either a or b */
  637.      REAL *a,*b,*z, inf;
  638.      long n,n2;
  639. { long i,ni;
  640.   REAL temp, radius;
  641.  
  642.   if (b[0] == 0.0)
  643.     if (a[0] == 0.0) z[0] = 1.0;
  644.     else             z[0] = a[0] * inf;
  645.   else               z[0] = a[0] / b[0];
  646.  
  647.   if (2*n2 == n)        /* even length, n2 is only real */
  648.     if (b[n2] == 0.0)
  649.       if (a[n2] == 0.0) z[n2] = 1.0;
  650.       else              z[n2] = a[n2] * inf;
  651.     else                z[n2] = a[n2] / b[n2];
  652.   else
  653.     n2 = n2+1; /* odd length, make the loop include the n2 index */
  654.  
  655.   for (i=1; i<n2; i++)
  656.   { ni = n-i;
  657.     radius = b[i]*b[i] + b[ni]*b[ni]; /* b^2 denominator = real^2 + imag^2 */
  658.  
  659.     if (radius == 0.0) {
  660.       if (a[i]  == 0.0) z[i]  = 1.0;
  661.       else              z[i]  = a[i] * inf;
  662.       if (a[ni] == 0.0) z[ni] = 1.0;
  663.       else              z[ni] = a[ni] * inf; }
  664.     else {
  665.       temp  = a[i]*b[i]    +  a[ni]*b[ni];
  666.       z[ni] = (a[ni]*b[i]  -  a[i]*b[ni]) / radius; /* imag part */
  667.       z[i]  = temp                        / radius; /* real part */
  668.     }}
  669. }
  670.  
  671. /* ARRAY-UNARY-FUNCTION!
  672.    apply unary-function elementwise on array
  673.    Available functions : */
  674.  
  675. void
  676. REALabs (a,b)
  677.      REAL *a,*b;
  678. {
  679.   (*b) = ( (REAL) fabs( (double) (*a)) );
  680. }
  681.  
  682. void
  683. REALexp (a,b)
  684.      REAL *a,*b;
  685. {
  686.   fast double y;
  687.   if ((y = exp((double) (*a))) == HUGE)
  688.     error_bad_range_arg (1);    /* OVERFLOW */
  689.   (*b) = ((REAL) y);
  690. }
  691.  
  692. void
  693. REALlog (a,b)
  694.      REAL *a,*b;
  695. {
  696.   if ((*a) < 0.0)
  697.     error_bad_range_arg(1);    /* log(negative) */
  698.   (*b) = ( (REAL) log( (double) (*a)) );
  699. }
  700.  
  701. void
  702. REALtruncate (a,b)
  703.      REAL *a,*b;        /* towards zero */
  704. {
  705.   double integral_part, modf();
  706.   modf( ((double) (*a)), &integral_part);
  707.   (*b) = ( (REAL) integral_part);
  708. }
  709.  
  710. void
  711. REALround (a,b)
  712.      REAL *a,*b;        /* towards nearest integer */
  713. {
  714.   double integral_part, modf();
  715.   if ((*a) >= 0.0)        /* It may be faster to look at the sign
  716.                    of mantissa, and dispatch */
  717.     modf( ((double) ((*a)+0.5)), &integral_part);
  718.   else
  719.     modf( ((double) ((*a)-0.5)), &integral_part);
  720.   (*b) = ( (REAL) integral_part);
  721. }
  722.  
  723. void
  724. REALsquare (a,b)
  725.      REAL *a,*b;
  726. {
  727.   (*b) = ( (REAL) ((*a) * (*a)) );
  728. }
  729.  
  730. void
  731. REALsqrt (a,b)
  732.      REAL *a,*b;
  733. {
  734.   if ((*a) < 0.0)
  735.     error_bad_range_arg(1);    /* sqrt(negative) */
  736.   (*b) = ( (REAL) sqrt( (double) (*a)) );
  737. }
  738.  
  739. void
  740. REALsin (a,b)
  741.      REAL *a,*b;
  742. {
  743.   (*b) = ( (REAL) sin( (double) (*a)) );
  744. }
  745.  
  746. void
  747. REALcos (a,b)
  748.      REAL *a,*b;
  749. {
  750.   (*b) = ( (REAL) cos( (double) (*a)) );
  751. }
  752.  
  753. void
  754. REALtan (a,b)
  755.      REAL *a,*b;
  756. {
  757.   (*b) = ( (REAL) tan( (double) (*a)) );
  758. }
  759.  
  760. void
  761. REALasin (a,b)
  762.      REAL *a,*b;
  763. {
  764.   (*b) = ( (REAL) asin( (double) (*a)) );
  765. }
  766.  
  767. void
  768. REALacos (a,b)
  769.      REAL *a,*b;
  770. {
  771.   (*b) = ( (REAL) acos( (double) (*a)) );
  772. }
  773.  
  774. void
  775. REALatan (a,b)
  776.      REAL *a,*b;
  777. {
  778.   (*b) = ( (REAL) atan( (double) (*a)) );
  779. }
  780.  
  781. void
  782. REALgamma (a,b)
  783.      REAL *a,*b;
  784. {
  785.   fast double y;
  786.   if ((y = gamma(((double) (*a)))) > LN_MAXDOUBLE)
  787.     error_bad_range_arg(1);    /* gamma( non-positive integer ) */
  788.   (*b) = ((REAL) (signgam * exp(y))); /* see HPUX Section 3 */
  789. }
  790.  
  791. void
  792. REALerf (a,b)
  793.      REAL *a,*b;
  794. {
  795.   (*b) = ( (REAL) erf((double) (*a)) );
  796. }
  797.  
  798. void
  799. REALerfc (a,b)
  800.      REAL *a,*b;
  801. {
  802.   (*b) = ( (REAL) erfc((double) (*a)) );
  803. }
  804.  
  805. void
  806. REALbessel1 (order,a,b)        /* Bessel of first kind */
  807.      long order;
  808.      REAL *a,*b;
  809. {
  810.   if (order == 0)
  811.     (*b) = ( (REAL) j0((double) (*a)) );
  812.   if (order == 1)
  813.     (*b) = ( (REAL) j1((double) (*a)) );
  814.   else
  815.     (*b) = ( (REAL) jn(((int) order), ((double) (*a))) );
  816. }
  817.  
  818. void
  819. REALbessel2 (order,a,b)        /* Bessel of second kind */
  820.      long order;
  821.      REAL *a,*b;
  822. {
  823.   if ((*a) <= 0.0)
  824.     error_bad_range_arg(1);    /* Blows Up */
  825.   if (order == 0)
  826.     (*b) = ( (REAL) y0((double) (*a)) );
  827.   if (order == 1)
  828.     (*b) = ( (REAL) y1((double) (*a)) );
  829.   else
  830.     (*b) = ( (REAL) yn(((int) order), ((double) (*a))) );
  831. }
  832.  
  833. /* Table to store the available unary-functions.
  834.    Also some binary functions at the end -- not available right now.
  835.    The (1 and 2)s denote the numofargs (1 for unary 2 for binary) */
  836.  
  837. struct array_func_table
  838. {
  839.   long numofargs;
  840.   void (*func)();
  841. }
  842. Array_Function_Table [] =
  843. {
  844.   1, REALabs,            /*0*/
  845.   1, REALexp,            /*1*/
  846.   1, REALlog,            /*2*/
  847.   1, REALtruncate,        /*3*/
  848.   1, REALround,            /*4*/
  849.   1, REALsquare,        /*5*/
  850.   1, REALsqrt,            /*6*/
  851.   1, REALsin,            /*7*/
  852.   1, REALcos,            /*8*/
  853.   1, REALtan,            /*9*/
  854.   1, REALasin,            /*10*/
  855.   1, REALacos,            /*11*/
  856.   1, REALatan,            /*12*/
  857.   1, REALgamma,            /*13*/
  858.   1, REALerf,            /*14*/
  859.   1, REALerfc,            /*15*/
  860.   2, REALbessel1,        /*16*/
  861.   2, REALbessel2        /*17*/
  862.   };
  863.  
  864. #define MAX_ARRAY_FUNCTC 17
  865.  
  866. /* array-unary-function!    could be called        array-operation-1!
  867.    following the naming convention for other similar procedures
  868.    but it is specialized to mappings only, so we have special name. */
  869.  
  870. DEFINE_PRIMITIVE ("ARRAY-UNARY-FUNCTION!", Prim_array_unary_function, 2,2, 0)
  871. {
  872.   long n, i;
  873.   REAL *a,*b;
  874.   long tc;
  875.   void (*f)();
  876.   PRIMITIVE_HEADER (2);
  877.   CHECK_ARG (1, ARRAY_P);    /*      a  = input (and output) array    */
  878.   CHECK_ARG (2, FIXNUM_P);    /*      tc = type code                   */
  879.   tc = arg_nonnegative_integer(2);
  880.   if (tc > MAX_ARRAY_FUNCTC) error_bad_range_arg(2);
  881.   f = ((Array_Function_Table[tc]).func);
  882.   if (1 != (Array_Function_Table[tc]).numofargs) error_wrong_type_arg(2);
  883.   /* check it is a unary function */
  884.   a = ARRAY_CONTENTS(ARG_REF(1));
  885.   b = a;
  886.   n = ARRAY_LENGTH(ARG_REF(1));
  887.   for (i=0; i<n; i++)
  888.     (*f) ( &(a[i]), &(b[i]) );    /* a into b */
  889.   PRIMITIVE_RETURN (UNSPECIFIC);
  890. }
  891.  
  892. /* Accumulate
  893.    using combinators              +  or  *
  894.    corresponding type codes       0      1 */
  895.  
  896. DEFINE_PRIMITIVE ("SUBARRAY-ACCUMULATE", Prim_subarray_accumulate, 4,4, 0)
  897. {
  898.   long at,m,mplus, tc, i;
  899.   REAL *a;
  900.   double result;
  901.   PRIMITIVE_HEADER (4);
  902.   CHECK_ARG (1, ARRAY_P);    /*           a = input array                 */
  903.   a  = ARRAY_CONTENTS(ARG_REF(1));
  904.   tc = arg_nonnegative_integer(2); /*       tc = type code 0 or 1            */
  905.   at = arg_nonnegative_integer(3); /*       at = starting index              */
  906.   m  = arg_nonnegative_integer(4); /*       m  = number of points to process */
  907.   mplus = at + m;
  908.   if (mplus > (ARRAY_LENGTH(ARG_REF(1)))) error_bad_range_arg(4);
  909.   if (tc == 0)
  910.     {
  911.       result = 0.0;
  912.       for (i=at;i<mplus;i++)
  913.     result = result + ((double) a[i]);
  914.     }
  915.   else if (tc == 1)
  916.     {
  917.       result = 1.0;
  918.       for (i=at;i<mplus;i++)
  919.     result = result * ((double) a[i]);
  920.     }
  921.   else
  922.     error_bad_range_arg (2);
  923.   PRIMITIVE_RETURN (double_to_flonum (result));
  924. }
  925.  
  926. /* The following searches for value within tolerance
  927.    starting from index=from in array.
  928.    Returns first index where match occurs (useful for finding zeros). */
  929.  
  930. DEFINE_PRIMITIVE ("ARRAY-SEARCH-VALUE-TOLERANCE-FROM", Prim_array_search_value_tolerance_from, 4, 4, 0)
  931. {
  932.   SCHEME_OBJECT array;
  933.   fast long length;
  934.   fast REAL * a;
  935.   fast REAL value;        /* value to search for */
  936.   fast double tolerance;    /* tolerance allowed */
  937.   PRIMITIVE_HEADER (4);
  938.   CHECK_ARG (1, ARRAY_P);
  939.   array = (ARG_REF (1));
  940.   length = (ARRAY_LENGTH (array));
  941.   a = (ARRAY_CONTENTS (array));
  942.   value = (arg_real (2));
  943.   tolerance = (arg_real (3));
  944.   {
  945.     fast long i;
  946.     for (i = (arg_index_integer (4, length)); i<length; i+=1)
  947.       if (tolerance >= (fabs ((double) ((a [i]) - value))))
  948.     PRIMITIVE_RETURN (LONG_TO_UNSIGNED_FIXNUM (i));
  949.   }
  950.   PRIMITIVE_RETURN (SHARP_F);
  951. }
  952.  
  953. DEFINE_PRIMITIVE ("SUBARRAY-MIN-MAX-INDEX", Prim_subarray_min_max_index, 3, 3, 0)
  954. {
  955.   PRIMITIVE_HEADER (3);
  956.   CHECK_ARG (1, ARRAY_P);
  957.   {
  958.     REAL * a = (ARRAY_CONTENTS (ARG_REF (1)));
  959.     long at = (arg_nonnegative_integer (2)); /* starting index */
  960.     long m  = (arg_nonnegative_integer (3)); /* number of points to process */
  961.     long mplus = (at + m);
  962.     long nmin;
  963.     long nmax;
  964.     if (mplus > (ARRAY_LENGTH (ARG_REF (1))))
  965.       error_bad_range_arg (3);
  966.     
  967.     C_Array_Find_Min_Max ((& (a [at])), m, (&nmin), (&nmax));
  968.     nmin = nmin + at;        /* offset appropriately */
  969.     nmax = nmax + at;
  970.     
  971.     PRIMITIVE_RETURN
  972.       (cons ((LONG_TO_FIXNUM (nmin)),
  973.          (cons ((LONG_TO_FIXNUM (nmax)),
  974.             EMPTY_LIST))));
  975.   }
  976. }
  977.  
  978. void
  979. C_Array_Find_Min_Max (x, n, nmin, nmax)
  980.      fast REAL * x;
  981.      fast long n;
  982.      long * nmin;
  983.      long * nmax;
  984. { REAL *xold = x;
  985.   register REAL xmin, xmax;
  986.   register long nnmin, nnmax;
  987.   register long count;
  988.  
  989.   nnmin = nnmax = 0;
  990.   xmin = xmax = *x++;
  991.   n--;
  992.   count = 1;
  993.   if(n>0)
  994.   {
  995.     do {
  996.       if(*x < xmin) {
  997.     nnmin = count++ ;
  998.     xmin = *x++ ;
  999.       } else if(*x > xmax) {
  1000.     nnmax = count++ ;
  1001.     xmax = *x++ ;
  1002.       } else {
  1003.     count++ ;
  1004.     x++ ;
  1005.       }
  1006.     } while( --n > 0 ) ;
  1007.   }
  1008.   *nmin = nnmin ;
  1009.   *nmax = nnmax ;
  1010. }
  1011.  
  1012.  
  1013. /* array-average
  1014.    can be done with (array-reduce +) and division by array-length.
  1015.    But there is also this C primitive.
  1016.    Keep it around, may be useful someday. */
  1017.  
  1018. /* Computes the average in pieces, so as to reduce
  1019.    roundoff smearing in cumulative sum.
  1020.    example= first huge positive numbers, then small nums,
  1021.    then huge negative numbers. */
  1022.  
  1023. static void
  1024. C_Array_Find_Average (Array, Length, pAverage)
  1025.      long Length;
  1026.      REAL * Array;
  1027.      REAL * pAverage;
  1028. {
  1029.   long i;
  1030.   long array_index;
  1031.   REAL average_n, sum;
  1032.  
  1033.   average_n = 0.0;
  1034.   array_index = 0;
  1035.   while (array_index < Length)
  1036.     {
  1037.       sum = 0.0;
  1038.       for (i=0;((array_index<Length) && (i<2000));i++) {
  1039.     sum += Array[array_index];
  1040.     array_index++;
  1041.       }
  1042.       average_n += (sum / ((REAL) Length));
  1043.     }
  1044.   (*pAverage) = average_n;
  1045.   return;
  1046. }
  1047.  
  1048. DEFINE_PRIMITIVE ("ARRAY-AVERAGE", Prim_array_find_average, 1, 1, 0)
  1049. {
  1050.   SCHEME_OBJECT array;
  1051.   REAL average;
  1052.   PRIMITIVE_HEADER (1);
  1053.   CHECK_ARG (1, ARRAY_P);
  1054.   array = (ARG_REF (1));
  1055.   C_Array_Find_Average
  1056.     ((ARRAY_CONTENTS (array)),
  1057.      (ARRAY_LENGTH (array)),
  1058.      (&average));
  1059.   PRIMITIVE_RETURN (double_to_flonum ((double) average));
  1060. }
  1061.  
  1062. void
  1063. C_Array_Make_Histogram (Array, Length, Histogram, npoints)
  1064.      REAL Array[], Histogram[];
  1065.      long Length, npoints;
  1066. {
  1067.   REAL Max, Min, Offset, Scale;
  1068.   long i, nmin, nmax, index;
  1069.   C_Array_Find_Min_Max (Array, Length, (&nmin), (&nmax));
  1070.   Min = (Array [nmin]);
  1071.   Max = (Array [nmax]);
  1072.   Find_Offset_Scale_For_Linear_Map
  1073.     (Min, Max, 0.0, ((REAL) npoints), (&Offset), (&Scale));
  1074.   for (i = 0; (i < npoints); i += 1)
  1075.     (Histogram [i]) = 0.0;
  1076.   for (i = 0; (i < Length); i += 1)
  1077.     {
  1078.       /* Everything from 0 to 1 maps to bin 0, and so on */
  1079.       index = ((long) (floor ((double) ((Scale * (Array [i])) + Offset))));
  1080.       /* max that won't floor to legal array index */
  1081.       if (index == npoints)
  1082.     index = (index - 1);
  1083.       (Histogram [index]) += 1.0;
  1084.     }
  1085.   return;
  1086. }
  1087.  
  1088. DEFINE_PRIMITIVE ("ARRAY-MAKE-HISTOGRAM", Prim_array_make_histogram, 2, 2, 0)
  1089. {
  1090.   PRIMITIVE_HEADER (2);
  1091.   CHECK_ARG (1, ARRAY_P);
  1092.   {
  1093.     fast SCHEME_OBJECT array = (ARG_REF (1));
  1094.     long length = (ARRAY_LENGTH (array));
  1095.     long npoints = (arg_integer_in_range (2, 1, ((2 * length) + 1)));
  1096.     SCHEME_OBJECT result = (allocate_array (npoints));
  1097.     C_Array_Make_Histogram
  1098.       ((ARRAY_CONTENTS (array)),
  1099.        length,
  1100.        (ARRAY_CONTENTS (result)),
  1101.        npoints);
  1102.     PRIMITIVE_RETURN (result);
  1103.   }
  1104. }
  1105.  
  1106. /* The following geometrical map is slightly tricky. */
  1107. void
  1108. Find_Offset_Scale_For_Linear_Map (Min, Max, New_Min, New_Max, Offset, Scale)
  1109.      REAL Min, Max, New_Min, New_Max, *Offset, *Scale;
  1110. {
  1111.   if (Min != Max)
  1112.     {
  1113.       (*Scale)  = ((New_Max - New_Min) / (Max - Min));
  1114.       (*Offset) = (New_Min - ((*Scale) * Min));
  1115.     }
  1116.   else
  1117.     {
  1118.       (*Scale) =
  1119.     ((Max == 0.0)
  1120.      ? 0.0
  1121.      : (0.25 * (mabs ((New_Max - New_Min) / Max))));
  1122.       (*Offset) = ((New_Max + New_Min) / 2.0);
  1123.     }
  1124.   return;
  1125. }
  1126.  
  1127.  
  1128. DEFINE_PRIMITIVE ("ARRAY-CLIP-MIN-MAX!", Prim_array_clip_min_max, 3, 3, 0)
  1129. {
  1130.   PRIMITIVE_HEADER (3);
  1131.   CHECK_ARG (1, ARRAY_P);
  1132.   {
  1133.     SCHEME_OBJECT array = (ARG_REF (1));
  1134.     REAL xmin = (arg_real (2));
  1135.     REAL xmax = (arg_real (3));
  1136.     long Length = (ARRAY_LENGTH (array));
  1137.     REAL * From_Here = (ARRAY_CONTENTS (array));
  1138.     REAL * To_Here = From_Here;
  1139.     long i;
  1140.     if (xmin > xmax)
  1141.       error_bad_range_arg (3);
  1142.     for (i = 0; (i < Length); i += 1)
  1143.       {
  1144.     if ((*From_Here) < xmin)
  1145.       (*To_Here++) = xmin;
  1146.     else if ((*From_Here) > xmax)
  1147.       (*To_Here++) = xmax;
  1148.     else
  1149.       (*To_Here++) = (*From_Here);
  1150.     From_Here += 1;
  1151.       }
  1152.   }
  1153.   PRIMITIVE_RETURN (UNSPECIFIC);
  1154. }
  1155.  
  1156. /* complex-array-operation-1!
  1157.    groups together procedures that use 1 complex-array
  1158.    and store the result in place */
  1159.  
  1160. DEFINE_PRIMITIVE ("COMPLEX-ARRAY-OPERATION-1!", Prim_complex_array_operation_1, 3,3, 0)
  1161. { long n, i, opcode;
  1162.   REAL *a, *b;
  1163.   void complex_array_to_polar(), complex_array_exp(), complex_array_sqrt();
  1164.   void complex_array_sin(), complex_array_cos();
  1165.   void complex_array_asin(), complex_array_acos(), complex_array_atan();
  1166.   PRIMITIVE_HEADER (3);
  1167.   CHECK_ARG (1, FIXNUM_P);    /* operation opcode */
  1168.   CHECK_ARG (2, ARRAY_P);    /* input array -- n      real part         */
  1169.   CHECK_ARG (3, ARRAY_P);    /* input array -- n      imag part         */
  1170.   n = ARRAY_LENGTH(ARG_REF(2));
  1171.   if (n != ARRAY_LENGTH(ARG_REF(3))) error_bad_range_arg(3);
  1172.   a  = ARRAY_CONTENTS(ARG_REF(2)); /*  real part */
  1173.   b  = ARRAY_CONTENTS(ARG_REF(3)); /*  imag part */
  1174.   opcode = arg_nonnegative_integer(1);
  1175.   if (opcode==1)
  1176.     complex_array_to_polar(a,b,n);
  1177.   else if (opcode==2)
  1178.     complex_array_exp(a,b,n);
  1179.   else if (opcode==3)
  1180.     complex_array_sqrt(a,b,n);
  1181.  
  1182.   else if (opcode==4)
  1183.     complex_array_sin(a,b,n);
  1184.   else if (opcode==5)
  1185.     complex_array_cos(a,b,n);
  1186.   /* for tan(z) use sin(z)/cos(z) */
  1187.   
  1188.   else if (opcode==6)
  1189.     complex_array_asin(a,b,n);
  1190.   else if (opcode==7)
  1191.     complex_array_acos(a,b,n);
  1192.   else if (opcode==8)
  1193.     complex_array_atan(a,b,n);
  1194.   
  1195.   else
  1196.     error_bad_range_arg(1);    /* illegal opcode */
  1197.   PRIMITIVE_RETURN (UNSPECIFIC);
  1198. }
  1199.  
  1200. void
  1201. complex_array_to_polar (a,b,n)
  1202.      REAL *a,*b;
  1203.      long n;
  1204. {
  1205.   long i;
  1206.   double x,y, temp;
  1207.   for (i=0; i<n; i++)
  1208.     {
  1209.       x = (double) a[i];
  1210.       y = (double) b[i];
  1211.       temp = sqrt(x*x + y*y);
  1212.       if (temp == 0.0)
  1213.     b[i] = 0.0;        /* choose angle = 0    for x,y=0,0 */
  1214.       else
  1215.     b[i] = (REAL) atan2(y,x);
  1216.       a[i]   = (REAL) temp;
  1217.     }
  1218. }
  1219.  
  1220. void
  1221. complex_array_exp (a,b,n)
  1222.      REAL *a,*b;
  1223.      long n;
  1224. {
  1225.   long i;
  1226.   double x,y, temp;
  1227.  
  1228.   for (i=0; i<n; i++)
  1229.     {
  1230.       x = (double) a[i];
  1231.       y = (double) b[i];
  1232.       if ((temp = exp(x)) == HUGE) error_bad_range_arg(2); /* overflow */
  1233.       a[i] = (REAL) (temp*cos(y));
  1234.       b[i] = (REAL) (temp*sin(y));
  1235.     }
  1236. }
  1237.  
  1238. void
  1239. complex_array_sqrt (a,b,n)
  1240.      REAL *a,*b;
  1241.      long n;
  1242. {
  1243.   long i;
  1244.   double x,y, r;
  1245.  
  1246.   for (i=0; i<n; i++)
  1247.     {
  1248.       x = (double) a[i];
  1249.       y = (double) b[i];
  1250.       r = sqrt( x*x + y*y);
  1251.       a[i] = sqrt((r+x)/2.0);
  1252.       if (y>=0.0)
  1253.     b[i] =  sqrt((r-x)/2.0); /* choose principal root */
  1254.       else            /* see Abramowitz (p.17 3.7.27) */
  1255.     b[i] = -sqrt((r-x)/2.0);
  1256.     }
  1257. }
  1258.  
  1259. void
  1260. complex_array_sin (a,b,n)
  1261.      REAL *a,*b;
  1262.      long n;
  1263. {
  1264.   long i;
  1265.   double x, ey,fy;
  1266.   REAL temp;
  1267.  
  1268.   for (i=0; i<n; i++)
  1269.     {
  1270.       x = (double) a[i];
  1271.       ey = exp((double) b[i]);    /* radius should be small to avoid overflow */
  1272.       fy = 1.0/ey;        /* exp(-y) */
  1273.       /* expanded (e(iz)-e(-iz))*(-.5i) formula */
  1274.       temp = (REAL) (sin(x) * (ey + fy) * 0.5);
  1275.       /* see my notes in Abram.p.71 */
  1276.       b[i] = (REAL) (cos(x) * (ey - fy) * 0.5);
  1277.       a[i] = temp;
  1278.     }
  1279. }
  1280.  
  1281. void
  1282. complex_array_cos (a,b,n)
  1283.      REAL *a,*b;
  1284.      long n;
  1285. {
  1286.   long i;
  1287.   double x, ey,fy;
  1288.   REAL temp;
  1289.  
  1290.   for (i=0; i<n; i++)
  1291.     {
  1292.       x = (double) a[i];
  1293.       ey = exp((double) b[i]);    /* radius should be small to avoid overflow */
  1294.       fy = 1.0/ey;        /* exp(-y) */
  1295.       /* expanded (e(iz)+e(-iz))*.5 formula */
  1296.       temp = (REAL) (cos(x) * (ey + fy) * 0.5);
  1297.       b[i] = (REAL) (sin(x) * (fy - ey) * 0.5); /* see my notes in Abram.p.71*/
  1298.       a[i] = temp;
  1299.     }
  1300. }
  1301.  
  1302.  
  1303. void
  1304. complex_array_asin (a,b,n)
  1305.      REAL *a,*b;
  1306.      long n;
  1307. { /* logarithmic formula as in R3.99, about 21ops plus log,atan - see my notes */
  1308.   long i; 
  1309.   double oldx,oldy, x,y, real,imag, r;
  1310.   
  1311.   for (i=0; i<n; i++)
  1312.   {
  1313.     oldx = (double) a[i];
  1314.     oldy = (double) b[i];
  1315.     
  1316.     x = 1.0 - oldx*oldx + oldy*oldy; /* 1 - z*z */
  1317.     y = -2.0 * oldx * oldy;
  1318.     
  1319.     r = sqrt(x*x + y*y);    /* sqrt(1-z*z)  */
  1320.     real = sqrt((r+x)/2.0);
  1321.     if (y>=0.0)
  1322.       imag =  sqrt((r-x)/2.0);    /* choose principal root */
  1323.     else            /* see Abramowitz (p.17 3.7.27) */
  1324.       imag = -sqrt((r-x)/2.0);
  1325.     
  1326.     real = real - oldy;        /* i*z + sqrt(...) */
  1327.     imag = imag + oldx;
  1328.     
  1329.     b[i] = (REAL) (- log (sqrt (real*real + imag*imag))); /* -i*log(...) */
  1330.     a[i] = (REAL) atan2( imag, real); /* chosen angle is okay 
  1331.                      Also 0/0 doesnot occur */
  1332.   }
  1333. }
  1334.  
  1335. void
  1336. complex_array_acos (a,b,n)
  1337.      REAL *a,*b;
  1338.      long n;
  1339. {
  1340.   long i;
  1341.  
  1342.   complex_array_asin (a,b,n);
  1343.   
  1344.   for (i=0; i<n; i++)
  1345.     {
  1346.       a[i] = PI_OVER_2 - a[i];
  1347.       b[i] =           - b[i];
  1348.     }
  1349. }
  1350.   
  1351.  
  1352. void
  1353. complex_array_atan (a,b,n)
  1354.      REAL *a,*b;
  1355.      long n;
  1356. { /* logarithmic formula, expanded, simplified - see my notes */
  1357.   long i; 
  1358.   double x,y, xx, real,imag, d;
  1359.   
  1360.   for (i=0; i<n; i++)
  1361.   {
  1362.     x = (double) a[i];
  1363.     y = (double) b[i];
  1364.     
  1365.     xx = x*x;
  1366.     imag = 1.0 + y;        /* temp var */
  1367.     d  = xx + imag*imag;
  1368.     
  1369.     real = (1 - y*y - xx) / d;
  1370.     imag = (2.0 * x)  / d;
  1371.     
  1372.     b[i] = (REAL) ((log (sqrt (real*real + imag*imag))) / -2.0);
  1373.     a[i] = (atan2 (imag,real)) / 2.0;
  1374.   }
  1375. }
  1376.  
  1377.  
  1378. /* complex-array-operation-1b!
  1379.    groups together procedures that use 1 complex-array & 1 number
  1380.    and store the result in place (e.g. invert 1/x) */
  1381.  
  1382. DEFINE_PRIMITIVE ("COMPLEX-ARRAY-OPERATION-1B!", Prim_complex_array_operation_1b, 4,4, 0)
  1383. {
  1384.   long n, i, opcode;
  1385.   REAL *a, *b, inf;
  1386.   void complex_array_invert ();
  1387.   PRIMITIVE_HEADER (4);
  1388.   CHECK_ARG (1, FIXNUM_P);    /* operation opcode */
  1389.   CHECK_ARG (2, ARRAY_P);    /* input array -- n      real part         */
  1390.   CHECK_ARG (3, ARRAY_P);    /* input array -- n      imag part         */
  1391.   inf = (arg_real (4));        /* User-Provided Infinity */
  1392.   n = ARRAY_LENGTH(ARG_REF(2));
  1393.   if (n != ARRAY_LENGTH(ARG_REF(3))) error_bad_range_arg(3);
  1394.   a  = ARRAY_CONTENTS(ARG_REF(2)); /*  real part */
  1395.   b  = ARRAY_CONTENTS(ARG_REF(3)); /*  imag part */
  1396.   opcode = arg_nonnegative_integer(1);
  1397.   if (opcode==1)
  1398.     complex_array_invert(a,b, n, inf);  /* performs 1/x */
  1399.   else if (opcode==2)
  1400.     error_bad_range_arg(1);    /* illegal opcode */
  1401.   else
  1402.     error_bad_range_arg(1);    /* illegal opcode */
  1403.   PRIMITIVE_RETURN (UNSPECIFIC);
  1404. }
  1405.  
  1406. void
  1407. complex_array_invert (a,b, n, inf)
  1408.      REAL *a,*b, inf;
  1409.      long n;
  1410. {
  1411.   long i;
  1412.   double x,y, r;
  1413.   for (i=0; i<n; i++)
  1414.     {
  1415.       x = (double) a[i];
  1416.       y = (double) b[i];
  1417.       r = (x*x + y*y);
  1418.       if (r==0.0)
  1419.     {
  1420.       a[i] = inf;
  1421.       b[i] = inf;
  1422.     }
  1423.       else
  1424.     {
  1425.       a[i] = (REAL)  x/r;
  1426.       b[i] = (REAL) -y/r;
  1427.     }
  1428.     }
  1429. }
  1430.  
  1431. /* complex-array-operation-1a
  1432.    groups together procedures that use 1 complex-array
  1433.    and store result in a 3rd real array. */
  1434.  
  1435. DEFINE_PRIMITIVE ("COMPLEX-ARRAY-OPERATION-1A", Prim_complex_array_operation_1a, 4,4, 0)
  1436. {
  1437.   long n, i, opcode;
  1438.   REAL *a, *b, *c;
  1439.   void complex_array_magnitude(), complex_array_angle();
  1440.   PRIMITIVE_HEADER (4);
  1441.   CHECK_ARG (1, FIXNUM_P);    /* operation opcode */
  1442.   CHECK_ARG (2, ARRAY_P);    /* input array -- n      real part         */
  1443.   CHECK_ARG (3, ARRAY_P);    /* input array -- n      imag part         */
  1444.   CHECK_ARG (4, ARRAY_P);    /* output array -- n                       */
  1445.   n = ARRAY_LENGTH(ARG_REF(2));
  1446.   if (n != ARRAY_LENGTH(ARG_REF(3))) error_bad_range_arg(3);
  1447.   if (n != ARRAY_LENGTH(ARG_REF(4))) error_bad_range_arg(4);
  1448.   a  = ARRAY_CONTENTS(ARG_REF(2)); /*  real part */
  1449.   b  = ARRAY_CONTENTS(ARG_REF(3)); /*  imag part */
  1450.   c  = ARRAY_CONTENTS(ARG_REF(4)); /*  output    */
  1451.   opcode = arg_nonnegative_integer(1);
  1452.   if (opcode==1)
  1453.     complex_array_magnitude(a,b,c,n);
  1454.   else if (opcode==2)
  1455.     complex_array_angle(a,b,c,n);
  1456.   else
  1457.     error_bad_range_arg(1);    /* illegal opcode */
  1458.   PRIMITIVE_RETURN (UNSPECIFIC);
  1459. }
  1460.  
  1461. void
  1462. complex_array_magnitude (a,b,c,n)
  1463.      REAL *a,*b,*c;
  1464.      long n;
  1465. {
  1466.   long i;
  1467.   for (i=0; i<n; i++)
  1468.     c[i] = (REAL) sqrt( (double) a[i]*a[i] + b[i]*b[i] );
  1469. }
  1470.  
  1471. void
  1472. complex_array_angle (a,b,c,n)
  1473.      REAL *a,*b,*c;
  1474.      long n;
  1475. {
  1476.   long i;
  1477.   for (i=0; i<n; i++)
  1478.   {
  1479.     if ((a[i] == 0.0) && (b[i]==0.0))
  1480.       c[i] = 0.0;        /* choose angle=0 for point (0,0) */
  1481.     else
  1482.       c[i] = (REAL) atan2( (double) b[i], (double) a[i]);
  1483.     /* angle ==   -pi (exclusive) to +pi (inclusive) */
  1484.   }
  1485. }
  1486.  
  1487. DEFINE_PRIMITIVE ("CS-ARRAY-MAGNITUDE!", Prim_cs_array_magnitude, 1, 1, 0)
  1488. {
  1489.   long n, i;
  1490.   REAL *a;
  1491.   void cs_array_magnitude();
  1492.   PRIMITIVE_HEADER (1);
  1493.   CHECK_ARG (1, ARRAY_P);
  1494.   a = ARRAY_CONTENTS(ARG_REF(1)); /* input cs-array */
  1495.   n = ARRAY_LENGTH(ARG_REF(1));    /* becomes a standard array on return  */
  1496.   cs_array_magnitude(a,n);
  1497.   PRIMITIVE_RETURN (UNSPECIFIC);
  1498. }
  1499.  
  1500. /* result is a standard array (even signal, real data) */
  1501. void
  1502. cs_array_magnitude (a,n)
  1503.      REAL *a;
  1504.      long n;
  1505. {
  1506.   long i, n2, ni;
  1507.   n2 = n/2;            /* integer division truncates down */
  1508.   a[0]  = (REAL) fabs((double) a[0]); /*   imag=0 */
  1509.   if (2*n2 == n)        /* even length, n2 is only real */
  1510.     a[n2] = (REAL) fabs((double) a[n2]); /*  imag=0 */
  1511.   else
  1512.     /* odd length, make the loop include the n2 index */
  1513.     n2 = n2+1;
  1514.   for (i=1; i<n2; i++)
  1515.     {
  1516.       ni = n-i;
  1517.       a[i]   = (REAL)  sqrt( (double) a[i]*a[i] + (double) a[ni]*a[ni] );
  1518.       a[ni]  = a[i];        /* even signal */
  1519.     }
  1520. }
  1521.  
  1522. /* Rectangular and Polar
  1523.    A cs-array has even magnitude and odd angle (almost)
  1524.    hence a polar cs-array stores magnitude in the first half (real part)
  1525.    and angle in the second half (imag part)
  1526.    except for a[0] real-only and a[n2] (n even)
  1527.    The angle of a[0] is either 0 (pos. sign) or pi (neg. sign),
  1528.    but there is no place in an n-point cs-array to store this, so
  1529.    a[0] and a[n2] when n even are left unchanged  when going polar.
  1530.    as opposed to taking their absolute values, for magnitude. */
  1531.  
  1532. DEFINE_PRIMITIVE ("CS-ARRAY-TO-POLAR!", Prim_cs_array_to_polar, 1,1, 0)
  1533. {
  1534.   long n, i;
  1535.   REAL *a;
  1536.   void cs_array_to_polar();
  1537.   PRIMITIVE_HEADER (1);
  1538.   CHECK_ARG (1, ARRAY_P);
  1539.   a  = ARRAY_CONTENTS(ARG_REF(1));
  1540.   n = ARRAY_LENGTH(ARG_REF(1));
  1541.   cs_array_to_polar(a,n);
  1542.   PRIMITIVE_RETURN (UNSPECIFIC);
  1543. }
  1544.  
  1545. void
  1546. cs_array_to_polar (a,n)
  1547.      REAL *a;
  1548.      long n;
  1549. {
  1550.   long i, n2;
  1551.   double real, imag;        /* temporary variables */
  1552.   n2 = n/2;            /* integer division truncates down */
  1553.   /* a[0] stores both magnitude and angle
  1554.      (pos. sign angle=0 , neg. sign angle=pi) */
  1555.   if (2*n2 == n)        /* even length, n2 is only real */
  1556.     ;                /* a[n2] stores sign information like a[0] */
  1557.   else
  1558.     /* odd length, make the loop include the n2 index */
  1559.     n2 = n2+1;
  1560.   for (i=1; i<n2; i++)
  1561.     {
  1562.       real = (double) a[i];
  1563.       imag = (double) a[n-i];
  1564.       a[i]   = (REAL)  sqrt( real*real + imag*imag );
  1565.       if (a[i] == 0.0)
  1566.     a[n-i] = 0.0;
  1567.       else
  1568.     a[n-i] = (REAL) atan2( imag, real );
  1569.     }
  1570. }
  1571.  
  1572. DEFINE_PRIMITIVE ("CS-ARRAY-TO-RECTANGULAR!", Prim_cs_array_to_rectangular, 1,1, 0)
  1573. {
  1574.   long n,n2, i;
  1575.   double magn,angl;        /* temporary variables */
  1576.   REAL *a;
  1577.   PRIMITIVE_HEADER (1);
  1578.   CHECK_ARG (1, ARRAY_P);
  1579.   a  = ARRAY_CONTENTS(ARG_REF(1));
  1580.   n = ARRAY_LENGTH(ARG_REF(1));
  1581.   n2 = n/2;            /* integer division truncates down */
  1582.   ;                /* a[0] is okay */
  1583.   if (2*n2 == n)        /* even length, n2 is real only */
  1584.     ;                /* a[n2] is okay */
  1585.   else
  1586.     n2 = n2+1; /* odd length, make the loop include the n2 index */
  1587.   for (i=1; i<n2; i++)
  1588.   { magn = (double) a[i];
  1589.     angl = (double) a[n-i];
  1590.     a[i]   = (REAL)  magn * cos(angl);
  1591.     a[n-i] = (REAL)  magn * sin(angl); }
  1592.   PRIMITIVE_RETURN (UNSPECIFIC);
  1593. }
  1594.  
  1595. /* Convolution in the Time-Domain */
  1596. /* In the following macro
  1597.    To1 and To2 should be (Length1-1) and (Length2-1) respectively. */
  1598.  
  1599. #define C_Convolution_Point_Macro(X, Y, To1, To2, N, Result)        \
  1600. {                                    \
  1601.   long Min_of_N_To1 = (min ((N), (To1)));                \
  1602.   long mi, N_minus_mi;                            \
  1603.   REAL Sum = 0.0;                            \
  1604.   for (mi = (max (0, ((N) - (To2)))), N_minus_mi = ((N) - mi);        \
  1605.        (mi <= Min_of_N_To1);                        \
  1606.        mi += 1, N_minus_mi -= 1)                    \
  1607.     Sum += ((X [mi]) * (Y [N_minus_mi]));                \
  1608.   (Result) = Sum;                            \
  1609. }
  1610.  
  1611. DEFINE_PRIMITIVE ("CONVOLUTION-POINT", Prim_convolution_point, 3, 3, 0)
  1612. {
  1613.   long Length1, Length2, N;
  1614.   REAL *Array1, *Array2;
  1615.   REAL C_Result;
  1616.   PRIMITIVE_HEADER (3);
  1617.   CHECK_ARG (1, ARRAY_P);
  1618.   CHECK_ARG (2, ARRAY_P);
  1619.   Length1 = ARRAY_LENGTH (ARG_REF (1));
  1620.   Length2 = ARRAY_LENGTH (ARG_REF (2));
  1621.   N = (arg_nonnegative_integer (3));
  1622.   Array1 = ARRAY_CONTENTS (ARG_REF (1));
  1623.   Array2 = ARRAY_CONTENTS (ARG_REF (2));
  1624.   C_Convolution_Point_Macro(Array1, Array2, Length1-1, Length2-1, N, C_Result);
  1625.   PRIMITIVE_RETURN (double_to_flonum ((double) C_Result));
  1626. }
  1627.  
  1628. DEFINE_PRIMITIVE ("ARRAY-CONVOLUTION-IN-TIME!", Prim_array_convolution_in_time, 3, 3, 0)
  1629. {
  1630.   long n,m,l, n_1,m_1, i;
  1631.   REAL *a,*b,*c;
  1632.   PRIMITIVE_HEADER (3);
  1633.   CHECK_ARG (1, ARRAY_P);
  1634.   CHECK_ARG (2, ARRAY_P);
  1635.   CHECK_ARG (3, ARRAY_P);
  1636.   a = ARRAY_CONTENTS(ARG_REF(1));
  1637.   b = ARRAY_CONTENTS(ARG_REF(2));
  1638.   c = ARRAY_CONTENTS(ARG_REF(3));
  1639.   n = ARRAY_LENGTH(ARG_REF(1));
  1640.   m = ARRAY_LENGTH(ARG_REF(2));
  1641.   l = n+m-1;            /* resulting length */
  1642.   if (l != ARRAY_LENGTH(ARG_REF(3))) error_bad_range_arg(3);
  1643.   n_1 = n-1; m_1 = m-1;
  1644.   for (i=0; i<l; i++)
  1645.   { C_Convolution_Point_Macro(a, b, n_1, m_1, i, c[i]); }
  1646.   PRIMITIVE_RETURN (UNSPECIFIC);
  1647. }
  1648.  
  1649. DEFINE_PRIMITIVE ("ARRAY-MULTIPLY-INTO-SECOND-ONE!", Prim_array_multiply_into_second_one, 2, 2, 0)
  1650. {
  1651.   long Length, i;
  1652.   REAL *To_Here;
  1653.   REAL *From_Here_1, *From_Here_2;
  1654.   PRIMITIVE_HEADER (2);
  1655.   CHECK_ARG (1, ARRAY_P);
  1656.   CHECK_ARG (2, ARRAY_P);
  1657.   Length = ARRAY_LENGTH (ARG_REF (1));
  1658.   if (Length != ARRAY_LENGTH (ARG_REF (2))) error_bad_range_arg (2);
  1659.   From_Here_1 = ARRAY_CONTENTS (ARG_REF (1));
  1660.   From_Here_2 = ARRAY_CONTENTS (ARG_REF (2));
  1661.   To_Here = From_Here_2;
  1662.   for (i=0; i < Length; i++)
  1663.     {
  1664.       *To_Here++ = (*From_Here_1) * (*From_Here_2);
  1665.       From_Here_1++ ;
  1666.       From_Here_2++ ;
  1667.     }
  1668.   PRIMITIVE_RETURN (UNSPECIFIC);
  1669. }
  1670.  
  1671. /* complex-array-operation-2!
  1672.    groups together procedures that use 2 complex-arrays
  1673.    and store result in either 1st or 2nd */
  1674.  
  1675. DEFINE_PRIMITIVE ("COMPLEX-ARRAY-OPERATION-2!", Prim_complex_array_operation_2, 5,5, 0)
  1676. {
  1677.   long n, opcode;
  1678.   REAL *ax,*ay, *bx,*by;
  1679.   void complex_array_multiply_into_second_one();
  1680.   PRIMITIVE_HEADER (5);
  1681.   CHECK_ARG (1, FIXNUM_P);    /* operation opcode */
  1682.   CHECK_ARG (2, ARRAY_P);    /* ax array -- n      real         */
  1683.   CHECK_ARG (3, ARRAY_P);    /* ay array -- n      imag         */
  1684.   CHECK_ARG (4, ARRAY_P);    /* bx array -- n      real         */
  1685.   CHECK_ARG (5, ARRAY_P);    /* by array -- n      imag         */
  1686.   n = ARRAY_LENGTH(ARG_REF(2));
  1687.   if (n != ARRAY_LENGTH(ARG_REF(3))) error_bad_range_arg(3);
  1688.   if (n != ARRAY_LENGTH(ARG_REF(4))) error_bad_range_arg(4);
  1689.   if (n != ARRAY_LENGTH(ARG_REF(4))) error_bad_range_arg(5);
  1690.   ax  = ARRAY_CONTENTS(ARG_REF(2)); /*  real */
  1691.   ay  = ARRAY_CONTENTS(ARG_REF(3)); /*  imag */
  1692.   bx  = ARRAY_CONTENTS(ARG_REF(4)); /*  real */
  1693.   by  = ARRAY_CONTENTS(ARG_REF(5)); /*  imag */
  1694.   opcode = arg_nonnegative_integer(1);
  1695.   if (opcode==1)
  1696.     complex_array_multiply_into_second_one(ax,ay,bx,by, n);
  1697.   else if (opcode==2)
  1698.     error_bad_range_arg(1);    /* illegal opcode */
  1699.   else
  1700.     error_bad_range_arg(1);    /* illegal opcode */
  1701.   PRIMITIVE_RETURN (UNSPECIFIC);
  1702. }
  1703.  
  1704. void
  1705. complex_array_multiply_into_second_one (ax,ay,bx,by, n)
  1706.      REAL *ax,*ay,*bx,*by;
  1707.      long n;
  1708. {
  1709.   long i;
  1710.   REAL temp;
  1711.   for (i=0;i<n;i++)
  1712.     {
  1713.       temp   = ax[i]*bx[i]  -  ay[i]*by[i]; /*  real part */
  1714.       by[i]  = ax[i]*by[i]  +  ay[i]*bx[i]; /*  imag part */
  1715.       bx[i]  = temp;
  1716.     }
  1717. }
  1718.  
  1719. void
  1720. C_Array_Complex_Multiply_Into_First_One (a,b,c,d, length) /* used in fft.c */
  1721.      REAL *a,*b,*c,*d;
  1722.      long length;
  1723. {
  1724.   long i;
  1725.   REAL temp;
  1726.   for (i=0;i<length;i++)
  1727.     {
  1728.       temp = a[i]*c[i] - b[i]*d[i];
  1729.       b[i] = a[i]*d[i] + b[i]*c[i];
  1730.       a[i] = temp;
  1731.     }
  1732. }
  1733.  
  1734. DEFINE_PRIMITIVE ("ARRAY-DIVIDE-INTO-XXX!", Prim_array_divide_into_xxx, 4,4, 0)
  1735. {
  1736.   long n, i, one_or_two;
  1737.   REAL *x,*y,*z, inf;
  1738.   void array_divide_into_z();
  1739.   PRIMITIVE_HEADER (4);
  1740.   CHECK_ARG (1, ARRAY_P);
  1741.   CHECK_ARG (2, ARRAY_P);
  1742.   inf = (arg_real (3));
  1743.   /* where to store result of division */
  1744.   one_or_two = (arg_nonnegative_integer (4));
  1745.   x = ARRAY_CONTENTS(ARG_REF(1));
  1746.   y = ARRAY_CONTENTS(ARG_REF(2));
  1747.   n = ARRAY_LENGTH(ARG_REF(1));
  1748.   if (n!=(ARRAY_LENGTH(ARG_REF(2)))) error_bad_range_arg(2);
  1749.   if (one_or_two == 1)
  1750.     array_divide_into_z( x,y, x,  n, inf);
  1751.   else if (one_or_two == 2)
  1752.     array_divide_into_z( x,y, y,  n, inf);
  1753.   else
  1754.     error_bad_range_arg(4);
  1755.   PRIMITIVE_RETURN (UNSPECIFIC);
  1756. }
  1757.  
  1758. void
  1759. array_divide_into_z (x,y, z, n, inf) /* z can either x or y */
  1760.      REAL *x,*y,*z, inf;
  1761.      long n;
  1762. {
  1763.   long i;
  1764.   for (i=0; i<n; i++)
  1765.     {
  1766.       if (y[i] == 0.0)
  1767.     {
  1768.       if (x[i] == 0.0)
  1769.         z[i] = 1.0;
  1770.       else
  1771.         z[i] = inf * x[i];
  1772.     }
  1773.       else
  1774.     z[i] = x[i] / y[i];
  1775.     }
  1776. }
  1777.  
  1778. /* complex-array-operation-2b!
  1779.    groups together procedures that use 2 complex-arrays
  1780.    & 1 additional real number
  1781.    and store result in either 1st or 2nd (e.g. division) */
  1782.  
  1783. DEFINE_PRIMITIVE ("COMPLEX-ARRAY-OPERATION-2B!", Prim_complex_array_operation_2b, 6,6, 0)
  1784. { long n, opcode;
  1785.   REAL *ax,*ay, *bx,*by,  inf;
  1786.   void complex_array_divide_into_z();
  1787.   PRIMITIVE_HEADER (6);
  1788.   CHECK_ARG (1, FIXNUM_P);    /* operation opcode */
  1789.   CHECK_ARG (2, ARRAY_P);    /* ax array -- n      real         */
  1790.   CHECK_ARG (3, ARRAY_P);    /* ay array -- n      imag         */
  1791.   CHECK_ARG (4, ARRAY_P);    /* bx array -- n      real         */
  1792.   CHECK_ARG (5, ARRAY_P);    /* by array -- n      imag         */
  1793.   inf = (arg_real (6));        /* User-Provided Infinity */
  1794.   n = ARRAY_LENGTH(ARG_REF(2));
  1795.   if (n != ARRAY_LENGTH(ARG_REF(3))) error_bad_range_arg(3);
  1796.   if (n != ARRAY_LENGTH(ARG_REF(4))) error_bad_range_arg(4);
  1797.   if (n != ARRAY_LENGTH(ARG_REF(4))) error_bad_range_arg(5);
  1798.   ax  = ARRAY_CONTENTS(ARG_REF(2)); /*  real */
  1799.   ay  = ARRAY_CONTENTS(ARG_REF(3)); /*  imag */
  1800.   bx  = ARRAY_CONTENTS(ARG_REF(4)); /*  real */
  1801.   by  = ARRAY_CONTENTS(ARG_REF(5)); /*  imag */
  1802.   opcode = arg_nonnegative_integer(1);
  1803.   if (opcode==1)
  1804.     complex_array_divide_into_z (ax,ay,bx,by, ax,ay,  n, inf);
  1805.   else if (opcode==2)
  1806.     complex_array_divide_into_z (ax,ay,bx,by, bx,by,  n, inf);
  1807.   else
  1808.     error_bad_range_arg(1);    /* illegal opcode */
  1809.   PRIMITIVE_RETURN (UNSPECIFIC);
  1810. }
  1811.  
  1812. void
  1813. complex_array_divide_into_z (xr,xi, yr,yi, zr,zi, n, inf)
  1814.      REAL *xr,*xi, *yr,*yi, *zr,*zi, inf;
  1815.      long n;
  1816. {
  1817.   long i;
  1818.   fast double temp, radius;
  1819.   for (i=0; i<n; i++)
  1820.     {
  1821.       radius = (double) (yr[i] * yr[i]) + (yi[i] * yi[i]); /* denominator */
  1822.       if (radius == 0.0)
  1823.     {
  1824.       if (xr[i] == 0.0)
  1825.         zr[i] = 1.0;
  1826.       else
  1827.         zr[i] = inf * xr[i];
  1828.       if (xi[i] == 0.0)
  1829.         zi[i] = 1.0;
  1830.       else
  1831.         zi[i] = inf * xi[i];
  1832.     }
  1833.       else
  1834.     {
  1835.       temp =  (double) (xr[i] * yr[i]  +  xi[i] * yi[i]);
  1836.       zi[i] = (REAL) (xi[i] * yr[i]  -  xr[i] * yi[i]) / radius;
  1837.       zr[i] = (REAL) temp                              / radius;
  1838.     }
  1839.     }
  1840. }
  1841.  
  1842. DEFINE_PRIMITIVE ("ARRAY-LINEAR-SUPERPOSITION-INTO-SECOND-ONE!", Prim_array_linear_superposition_into_second_one, 4, 4, 0)
  1843. {
  1844.   long n, i;
  1845.   REAL *To_Here, Coeff1, Coeff2;
  1846.   REAL *From_Here_1, *From_Here_2;
  1847.   PRIMITIVE_HEADER (4);
  1848.   Coeff1 = (arg_real (1));
  1849.   CHECK_ARG (2, ARRAY_P);
  1850.   Coeff2 = (arg_real (3));
  1851.   CHECK_ARG (4, ARRAY_P);
  1852.   n = (ARRAY_LENGTH (ARG_REF (2)));
  1853.   if (n != (ARRAY_LENGTH (ARG_REF (4))))
  1854.     error_bad_range_arg (4);
  1855.   From_Here_1 = (ARRAY_CONTENTS (ARG_REF (2)));
  1856.   From_Here_2 = (ARRAY_CONTENTS (ARG_REF (4)));
  1857.   To_Here = From_Here_2;
  1858.   for (i=0; i < n; i++)
  1859.     {
  1860.       *To_Here++ = (Coeff1 * (*From_Here_1)) + (Coeff2 * (*From_Here_2));
  1861.       From_Here_1++ ;
  1862.       From_Here_2++ ;
  1863.     }
  1864.   PRIMITIVE_RETURN (UNSPECIFIC);
  1865. }
  1866.  
  1867. /*  m_pi = 3.14159265358979323846264338327950288419716939937510; */
  1868.  
  1869. DEFINE_PRIMITIVE ("SAMPLE-PERIODIC-FUNCTION", Prim_sample_periodic_function, 4, 4, 0)
  1870. {
  1871.   long N, i, Function_Number;
  1872.   double Signal_Frequency, Sampling_Frequency, DT, DTi;
  1873.   double twopi = 6.28318530717958;
  1874.   SCHEME_OBJECT Result, Pfunction_number, Psignal_frequency;
  1875.   SCHEME_OBJECT Pfunction_Number;
  1876.   REAL *To_Here;
  1877.   double unit_square_wave(), unit_triangle_wave();
  1878.   PRIMITIVE_HEADER (4);
  1879.   Function_Number = (arg_index_integer (1, 11));
  1880.   Signal_Frequency = (arg_real_number (2));
  1881.   if (Signal_Frequency == 0)
  1882.     error_bad_range_arg (2);
  1883.   Sampling_Frequency = (arg_real_number (3));
  1884.   if (Sampling_Frequency == 0)
  1885.     error_bad_range_arg (3);
  1886.   N = (arg_nonnegative_integer (4));
  1887.   Result = (allocate_array (N));
  1888.   To_Here = ARRAY_CONTENTS(Result);
  1889.   DT = (double) (twopi * Signal_Frequency * (1 / Sampling_Frequency));
  1890.   if (Function_Number == 0)
  1891.     for (i=0, DTi=0.0; i < N; i++, DTi += DT)
  1892.       *To_Here++ = (REAL) cos(DTi);
  1893.   else if (Function_Number == 1)
  1894.     for (i=0, DTi=0.0; i < N; i++, DTi += DT)
  1895.       *To_Here++ = (REAL) sin(DTi);
  1896.   else if (Function_Number == 2)
  1897.     for (i=0, DTi=0.0; i < N; i++, DTi += DT)
  1898.       *To_Here++ = (REAL) unit_square_wave(DTi);
  1899.   else if (Function_Number == 3)
  1900.     for (i=0, DTi=0.0; i < N; i++, DTi += DT)
  1901.       *To_Here++ = (REAL) unit_triangle_wave(DTi);
  1902.   else
  1903.     error_bad_range_arg (1);
  1904.   PRIMITIVE_RETURN (Result);
  1905. }
  1906.  
  1907. double
  1908. hamming (t, length)
  1909.      double t, length;
  1910. {
  1911.   double twopi = 6.28318530717958;
  1912.   double pi = twopi/2.;
  1913.   double t_bar = cos(twopi * (t / length));
  1914.   if ((t<length) && (t>0.0)) return(.08 + .46 * (1 - t_bar));
  1915.   else return (0);
  1916. }
  1917.  
  1918. double
  1919. unit_square_wave (t)
  1920.      double t;
  1921. {
  1922.   double twopi = 6.28318530717958;
  1923.   double fmod(), fabs();
  1924.   double pi = twopi/2.;
  1925.   double t_bar = ((REAL) fabs(fmod( ((double) t), twopi)));
  1926.   if (t_bar < pi) return(1);
  1927.   else return(-1);
  1928. }
  1929.  
  1930. double
  1931. unit_triangle_wave (t)
  1932.      double t;
  1933. {
  1934.   double twopi = 6.28318530717958;
  1935.   double pi = twopi/2.;
  1936.   double pi_half = pi/2.;
  1937.   double three_pi_half = pi+pi_half;
  1938.   double t_bar = ((double) fabs(fmod( ((double) t), twopi)));
  1939.   if (t_bar<pi_half)
  1940.     return (-(t_bar/pi));
  1941.   else if (t_bar<pi)
  1942.     return (t_bar/pi);
  1943.   else if (t_bar<three_pi_half)
  1944.     return ((twopi-t_bar)/pi);
  1945.   else
  1946.     return (-((twopi-t_bar)/pi));
  1947. }
  1948.  
  1949. DEFINE_PRIMITIVE ("ARRAY-HANNING!", Prim_array_hanning, 2,2, 0)
  1950. {
  1951.   long n, hanning_power;
  1952.   REAL *a;
  1953.   void C_Array_Make_Hanning();
  1954.   PRIMITIVE_HEADER (2);
  1955.   CHECK_ARG (1, ARRAY_P);    /* input array -- n */
  1956.   CHECK_ARG (2, FIXNUM_P);    /* hanning power */
  1957.   a  = ARRAY_CONTENTS(ARG_REF(1));
  1958.   n = ARRAY_LENGTH(ARG_REF(1));
  1959.   hanning_power = arg_nonnegative_integer(2);
  1960.   C_Array_Make_Hanning (a, n, hanning_power);
  1961.   PRIMITIVE_RETURN (UNSPECIFIC);
  1962. }
  1963.  
  1964. void
  1965. C_Array_Make_Hanning (f1, length, power)
  1966.      REAL f1[];
  1967.      long length, power;
  1968. {
  1969.   double window_length;
  1970.   long i;
  1971.   double integer_power(), hanning();
  1972.   window_length = ((double) length);
  1973.   for (i=0;i<length;i++)
  1974.     {
  1975.       f1[i] = ((REAL) hanning(((double) i), window_length));
  1976.       f1[i] = (REAL) integer_power(((double) f1[i]), power);
  1977.     }
  1978. }
  1979.  
  1980. double
  1981. hanning (t, length)
  1982.      double t, length;
  1983. {
  1984.   double twopi = 6.283185307179586476925287;
  1985.   double t_bar;
  1986.   t_bar = cos(twopi * (t / length));
  1987.   if ((t<length) && (t>0.0))
  1988.     return(.5 * (1 - t_bar));
  1989.   else
  1990.     return (0.0);
  1991. }
  1992.  
  1993. double
  1994. integer_power (a, n)
  1995.      double a;
  1996.      long n;
  1997. {
  1998.   double b;
  1999.   double integer_power();
  2000.  
  2001.   if (n<0) exit(-1);
  2002.   else if (n==0) return(1.0);
  2003.   else if (n==1) return(a);
  2004.   else if ((n%2) == 0)
  2005.     {
  2006.       b = integer_power(a, n/2);
  2007.       return(b*b);
  2008.     }
  2009.   else
  2010.     return(a * integer_power(a, (n-1)));
  2011. }
  2012.  
  2013. /* array-operation-1!
  2014.    groups together procedures that use 1 array
  2015.    and store the result in place (e.g. random) */
  2016.  
  2017. DEFINE_PRIMITIVE ("ARRAY-OPERATION-1!", Prim_array_operation_1, 2,2, 0)
  2018. {
  2019.   long n, opcode;
  2020.   REAL *a;
  2021.   void array_random();
  2022.   PRIMITIVE_HEADER (2);
  2023.   CHECK_ARG (1, FIXNUM_P);    /* operation opcode */
  2024.   CHECK_ARG (2, ARRAY_P);    /* input array -- n */
  2025.   n = ARRAY_LENGTH(ARG_REF(2));
  2026.   a  = ARRAY_CONTENTS(ARG_REF(2));
  2027.   opcode = arg_nonnegative_integer(1);
  2028.   if (opcode==1)
  2029.     array_random(a,n);
  2030.   else if (opcode==2)
  2031.     error_bad_range_arg(1);    /* illegal opcode */
  2032.   else
  2033.     error_bad_range_arg(1);    /* illegal opcode */
  2034.   PRIMITIVE_RETURN (UNSPECIFIC);
  2035. }
  2036.  
  2037. void
  2038. array_random (a,n)
  2039.      REAL *a;
  2040.      long n;
  2041. {
  2042.   long i;
  2043.   /* HPUX 3: Rand uses a multiplicative congruential random-number generator
  2044.      with period 2^32 that returns successive pseudo-random numbers in the
  2045.      range from 0 to 2^15-1 */
  2046.   for (i=0;i<n;i++)
  2047.     a[i] = ((REAL) rand()) * (3.0517578125e-5);
  2048.   /* 3.051xxx = 2^(-15) makes the range from 0 to 1 */
  2049. }
  2050.  
  2051. /* The following should go away.
  2052.    superceded by ARRAY-CONS-INTEGERS, ARRAY-UNARY-FUNCTION and array-random */
  2053. DEFINE_PRIMITIVE ("SAMPLE-APERIODIC-FUNCTION", Prim_sample_aperiodic_function, 3, 3, 0)
  2054. {
  2055.   long N, i, Function_Number;
  2056.   double Sampling_Frequency, DT, DTi;
  2057.   double twopi = 6.28318530717958;
  2058.   SCHEME_OBJECT Result;
  2059.   REAL *To_Here, twopi_dt;
  2060.   PRIMITIVE_HEADER (3);
  2061.   Function_Number = (arg_index_integer (1, 7));
  2062.   Sampling_Frequency = (arg_real_number (2));
  2063.   if (Sampling_Frequency == 0)
  2064.     error_bad_range_arg (2);
  2065.   N = (arg_nonnegative_integer (3));
  2066.   Result = (allocate_array (N));
  2067.   To_Here = ARRAY_CONTENTS(Result);
  2068.   DT = (twopi * (1 / Sampling_Frequency));
  2069.   if      (Function_Number == 0)
  2070.     /* HPUX 3: Rand uses a multiplicative congruential random-number generator
  2071.        with period 2^32 that returns successive pseudo-random numbers in the
  2072.        range from 0 to 2^15-1 */
  2073.     for (i=0; i<N; i++)
  2074.       /* 2^(-15) makes range from 0 to 1 */
  2075.       *To_Here++ = 3.0517578125e-5 * ((REAL) rand());
  2076.   else if (Function_Number == 1)
  2077.   { double length=DT*N;
  2078.     for (i=0, DTi=0.0; i < N; i++, DTi += DT)
  2079.       *To_Here++ = (REAL) hanning(DTi, length);
  2080.   }
  2081.   else if (Function_Number == 2)
  2082.   { double length=DT*N;
  2083.     for (i=0, DTi=0.0; i < N; i++, DTi += DT)
  2084.       *To_Here++ = (REAL) hamming(DTi, length);
  2085.   }
  2086.   else if (Function_Number == 3)
  2087.     for (i=0, DTi=0.0; i < N; i++, DTi += DT)
  2088.       *To_Here++ = (REAL) sqrt(DTi);
  2089.   else if (Function_Number == 4)
  2090.     for (i=0, DTi=0.0; i < N; i++, DTi += DT)
  2091.       *To_Here++ = (REAL) log(DTi);
  2092.   else if (Function_Number == 5)
  2093.     for (i=0, DTi=0.0; i < N; i++, DTi += DT)
  2094.       *To_Here++ = (REAL) exp(DTi);
  2095.   else
  2096.     error_bad_range_arg (1);
  2097.   PRIMITIVE_RETURN (Result);
  2098. }
  2099.  
  2100. DEFINE_PRIMITIVE ("ARRAY-PERIODIC-DOWNSAMPLE", Prim_array_periodic_downsample, 2, 2, 0)
  2101. {
  2102.   long Length, Pseudo_Length, Sampling_Ratio;
  2103.   REAL *Array, *To_Here;
  2104.   SCHEME_OBJECT Result;
  2105.   long i, array_index;
  2106.   PRIMITIVE_HEADER (2);
  2107.   CHECK_ARG (1, ARRAY_P);
  2108.   Length = ARRAY_LENGTH(ARG_REF (1));
  2109.   Sampling_Ratio = ((arg_integer (2)) % Length);
  2110.   if (Sampling_Ratio < 1)
  2111.     error_bad_range_arg (2);
  2112.   Array = ARRAY_CONTENTS(ARG_REF (1));
  2113.   Result = (allocate_array (Length));
  2114.   To_Here = ARRAY_CONTENTS(Result);
  2115.   Pseudo_Length = Length * Sampling_Ratio;
  2116.   /* new Array has the same Length by assuming periodicity */
  2117.   for (i=0; i<Pseudo_Length; i += Sampling_Ratio)
  2118.   { array_index = i % Length;
  2119.     *To_Here++ = Array[array_index]; }
  2120.   PRIMITIVE_RETURN (Result);
  2121. }
  2122.  
  2123. /* Shift is not done in place (no side-effects). */
  2124. DEFINE_PRIMITIVE ("ARRAY-PERIODIC-SHIFT", Prim_array_periodic_shift, 2, 2, 0)
  2125. {
  2126.   long Length, Shift;
  2127.   REAL *Array, *To_Here;
  2128.   SCHEME_OBJECT Result;
  2129.   long i, array_index;
  2130.   PRIMITIVE_HEADER (2);
  2131.   CHECK_ARG (1, ARRAY_P);
  2132.   Length = ARRAY_LENGTH(ARG_REF (1));
  2133.   /* periodic waveform, same sign as dividend */
  2134.   Shift = ((arg_integer (2)) % Length);
  2135.   Array = ARRAY_CONTENTS(ARG_REF (1));
  2136.   Result = (allocate_array (Length));
  2137.   To_Here = ARRAY_CONTENTS(Result);
  2138.   /* new Array has the same Length by assuming periodicity */
  2139.   for (i=0; i<Length; i++) {
  2140.     array_index = (i+Shift) % Length;
  2141.     if (array_index<0) array_index = Length + array_index; /* wrap around */
  2142.     *To_Here++ = Array[array_index]; }
  2143.   PRIMITIVE_RETURN (Result);
  2144. }
  2145.  
  2146. /* This is done here because array-map is very slow */
  2147. DEFINE_PRIMITIVE ("ARRAY-APERIODIC-DOWNSAMPLE", Prim_array_aperiodic_downsample, 2, 2, 0)
  2148. {
  2149.   long Length, New_Length, Sampling_Ratio;
  2150.   REAL *Array, *To_Here;
  2151.   SCHEME_OBJECT Result;
  2152.   long i, array_index;
  2153.   PRIMITIVE_HEADER (2);
  2154.   CHECK_ARG (1, ARRAY_P);
  2155.   Array = ARRAY_CONTENTS(ARG_REF (1));
  2156.   Length = ARRAY_LENGTH(ARG_REF (1));
  2157.   Sampling_Ratio = (arg_integer_in_range (2, 1, (Length + 1)));
  2158.   if (Length < 1) error_bad_range_arg (1);
  2159.   /* 1 for first one and then the rest --- integer division chops */
  2160.   New_Length = 1 + ((Length-1)/Sampling_Ratio);
  2161.   Result = (allocate_array (New_Length));
  2162.   To_Here = ARRAY_CONTENTS(Result);
  2163.   for (i=0; i<Length; i += Sampling_Ratio)
  2164.     *To_Here++ = Array[i];
  2165.   PRIMITIVE_RETURN (Result);
  2166. }
  2167.  
  2168. /* one more hack for speed */
  2169.  
  2170. /* (SOLVE-SYSTEM A B N)
  2171.     Solves the system of equations Ax = b.  A and B are
  2172.     arrays and b is the order of the system.  Returns x.
  2173.     From the Fortran procedure in Strang. */
  2174.  
  2175. DEFINE_PRIMITIVE ("SOLVE-SYSTEM", Prim_gaussian_elimination, 2, 2, 0)
  2176. {
  2177.   REAL *A, *B, *X;
  2178.   long Length;
  2179.   SCHEME_OBJECT Result;
  2180.   PRIMITIVE_HEADER (2);
  2181.   CHECK_ARG (1, ARRAY_P);
  2182.   CHECK_ARG (2, ARRAY_P);
  2183.   Length  = ARRAY_LENGTH(ARG_REF (2));
  2184.   if ((Length*Length) != ARRAY_LENGTH(ARG_REF (1))) error_bad_range_arg (2);
  2185.   A = ARRAY_CONTENTS(ARG_REF (1));
  2186.   B = ARRAY_CONTENTS(ARG_REF (2));
  2187.   Result = (allocate_array (Length));
  2188.   X = ARRAY_CONTENTS(Result);
  2189.   C_Array_Copy(B, X, Length);
  2190.   C_Gaussian_Elimination(A, X, Length);
  2191.   PRIMITIVE_RETURN (Result);
  2192. }
  2193.  
  2194. /* C routine side-effects b. */
  2195. C_Gaussian_Elimination (a, b, n)
  2196.      REAL *a, *b;
  2197.      long n;
  2198. {
  2199.   long *pvt;
  2200.   REAL p, t;
  2201.   long i, j, k, m;
  2202.   Primitive_GC_If_Needed (n);
  2203.   pvt = ((long *) Free);
  2204.   *(pvt+n-1) = 1;
  2205.   if (n != 1) {
  2206.     for (k=1; k<n; k++) {
  2207.       m = k;
  2208.       for (i=k+1; i<=n; i++)
  2209.     if (fabs(*(a+i+(k-1)*n-1)) > fabs(*(a+m+(k-1)*n-1)))
  2210.       m = i;
  2211.       *(pvt+k-1) = m;
  2212.       if (m != k)
  2213.     *(pvt+n-1) = - *(pvt+n-1);
  2214.       p = *(a+m+(k-1)*n-1);
  2215.       *(a+m+(k-1)*n-1) = *(a+k+(k-1)*n-1);
  2216.       *(a+k+(k-1)*n-1) = p;
  2217.       if (p != 0.0) {
  2218.     for (i=k+1; i<=n; i++)
  2219.       *(a+i+(k-1)*n-1) = - *(a+i+(k-1)*n-1) / p;
  2220.     for (j=k+1; j<=n; j++) {
  2221.       t = *(a+m+(j-1)*n-1);
  2222.       *(a+m+(j-1)*n-1) = *(a+k+(j-1)*n-1);
  2223.       *(a+k+(j-1)*n-1) = t;
  2224.       if (t != 0.0)
  2225.         for (i=k+1; i<=n; i++)
  2226.           *(a+i+(j-1)*n-1) = *(a+i+(j-1)*n-1) + *(a+i+(k-1)*n-1) * t;
  2227.     }
  2228.       }
  2229.     }
  2230.     for (k=1; k<n; k++) {
  2231.       m = *(pvt+k-1);
  2232.       t = *(b+m-1);
  2233.       *(b+m-1) = *(b+k-1);
  2234.       *(b+k-1) = t;
  2235.       for (i=k+1; i<=n; i++)
  2236.     *(b+i-1) = *(b+i-1) + *(a+i+(k-1)*n-1) * t;
  2237.     }
  2238.     for (j=1; j<n; j++) {
  2239.       k = n - j + 1;
  2240.       *(b+k-1) = *(b+k-1) / *(a+k+(k-1)*n-1);
  2241.       t = - *(b+k-1);
  2242.       for (i=1; i <= n-j; i++)
  2243.     *(b+i-1) = *(b+i-1) + *(a+i+(k-1)*n-1) * t;
  2244.     }
  2245.   }
  2246.   *b = *b / *a;
  2247.   return;
  2248. }
  2249.