1 /* vct support
2  *
3  * a vct is an object containing a mus_float_t array and its size
4  *
5  * C side:
6  *   void mus_vct_init(void)                    called to declare the various functions and the vct type
7  *   bool mus_is_vct(Xen obj)                   is obj a vct
8  *   Xen xen_make_vct(int len, mus_float_t *data)     make a new vct
9  *   Xen xen_make_vct_wrapper(int len, mus_float_t *data) make a new vct that doesn't free data when garbage collector strikes
10  *   vct *xen_to_vct(Xen arg)                   given Xen arg, return vct
11  *   void mus_vct_set_print_length(int val)     set vct print length (default 10) (also mus_vct_print_length)
12  *
13  *   (make-vct len (filler 0.0))      make new vct
14  *   (vct? obj)                       is obj a vct
15  *   (vct-ref v index)                return v[index]
16  *   (vct-set! v index val)           v[index] = val
17  *   (vct-copy v)                     return a copy of v
18  *   (vct-length v)                   return length of v
19  *   (vct-add! v1 v2 (offset 0))      v1[i+offset] = v1[i+offset] + v2[i] -> v1
20  *   (vct-subtract! v1 v2)            v1[i] = v1[i] - v2[i] -> v1
21  *   (vct-offset! v1 scl)             v1[i] += scl -> v1
22  *   (vct-multiply! v1 v2)            v1[i] *= v2[i] -> v1
23  *   (vct-scale! v1 scl)              v1[i] *= scl -> v1
24  *   (vct-abs! v)                     v[i] = abs(v[i])
25  *   (vct-fill! v1 val)               v1[i] = val -> v1
26  *   (vct-map! v1 proc)               set each element of v1 to value of function proc()
27  *   (vct-peak v1)                    max val (abs) in v
28  *   (vct-equal? v1 v2 diff)          is element-wise relative-difference of v1 and v2 ever greater than diff?
29  *   (list->vct lst)                  return vct with elements of list lst
30  *   (vct->list v1)                   return list with elements of vct v1
31  *   (vector->vct vect)               return vct with elements of vector vect
32  *   (vct->vector v)                  return vector of vct contents
33  *   (vct-move! v new old)            v[new++] = v[old++] -> v
34  *   (vct-subseq v start end vnew)    vnew = v[start..end]
35  *   (vct-reverse! v (len #f))        reverse contents (using len as end point if given)
36  *   (vct->string v)                  scheme-readable description of vct
37  *
38  *   (vct* obj1 obj2) combines vct-multiply and vct-scale
39  *   (vct+ obj1 obj2) combines vct-add and vct-offset
40  *
41  * The intended use is a sort of latter-day array-processing system that handles huge
42  * one-dimensional vectors -- fft's, etc.  Some of these functions can be found in
43  * the Snd package; others can be found in the CLM package (clm2xen.c).
44  */
45 
46 #include "mus-config.h"
47 
48 #if USE_SND
49   #include "snd.h"
50 #endif
51 
52 #include <stddef.h>
53 #include <math.h>
54 #include <stdlib.h>
55 #include <stdio.h>
56 #include <string.h>
57 
58 #if _MSC_VER
59   #pragma warning(disable: 4244)
60 #endif
61 
62 #include "_sndlib.h"
63 #include "xen.h"
64 #include "clm.h"
65 #include "sndlib2xen.h"
66 #include "clm2xen.h"
67 #include "vct.h"
68 
69 #if (!HAVE_SCHEME)
70 struct vct {
71   mus_long_t length;
72   mus_float_t *data;
73   bool dont_free;
74 };
75 
mus_vct_length(vct * v)76 mus_long_t mus_vct_length(vct *v) {return(v->length);}
mus_vct_data(vct * v)77 mus_float_t *mus_vct_data(vct *v) {return(v->data);}
78 #endif
79 
80 #if HAVE_SCHEME
81 
82 #define S_make_vct       "make-float-vector"
83 #define S_vct_add        "float-vector-add!"
84 #define S_vct_subtract   "float-vector-subtract!"
85 #define S_vct_copy       "float-vector-copy"
86 #define S_vct_length     "float-vector-length"
87 #define S_vct_multiply   "float-vector-multiply!"
88 #define S_vct_offset     "float-vector-offset!"
89 #define S_vct_ref        "float-vector-ref"
90 #define S_vct_scale      "float-vector-scale!"
91 #define S_vct_abs        "float-vector-abs!"
92 #define S_vct_fill       "float-vector-fill!"
93 #define S_vct_set        "float-vector-set!"
94 #define S_vct_peak       "float-vector-peak"
95 #define S_vct_equal      "float-vector-equal?"
96 #define S_is_vct         "float-vector?"
97 #define S_list_to_vct    "list->float-vector"
98 #define S_vct_to_list    "float-vector->list"
99 #define S_vector_to_vct  "vector->float-vector"
100 #define S_vct_to_vector  "float-vector->vector"
101 #define S_vct_move       "float-vector-move!"
102 #define S_vct_subseq     "float-vector-subseq"
103 #define S_vct_reverse    "float-vector-reverse!"
104 #define S_vct_to_string  "float-vector->string"
105 #define S_vct_times      "float-vector*"
106 #define S_vct_plus       "float-vector+"
107 #define A_VCT            "a float-vector"
108 #else
109 #define S_make_vct       "make-vct"
110 #define S_vct_add        "vct-add!"
111 #define S_vct_subtract   "vct-subtract!"
112 #define S_vct_copy       "vct-copy"
113 #define S_vct_length     "vct-length"
114 #define S_vct_multiply   "vct-multiply!"
115 #define S_vct_offset     "vct-offset!"
116 #define S_vct_ref        "vct-ref"
117 #define S_vct_scale      "vct-scale!"
118 #define S_vct_abs        "vct-abs!"
119 #define S_vct_fill       "vct-fill!"
120 #define S_vct_set        "vct-set!"
121 #define S_vct_peak       "vct-peak"
122 #define S_vct_equal      "vct-equal?"
123 #define S_is_vct         "vct?"
124 #define S_list_to_vct    "list->vct"
125 #define S_vct_to_list    "vct->list"
126 #define S_vector_to_vct  "vector->vct"
127 #define S_vct_to_vector  "vct->vector"
128 #define S_vct_move       "vct-move!"
129 #define S_vct_subseq     "vct-subseq"
130 #define S_vct_reverse    "vct-reverse!"
131 #define S_vct_to_string  "vct->string"
132 #if HAVE_RUBY
133   #define S_vct_times    "vct_multiply"
134   #define S_vct_plus     "vct_add"
135 #else
136   #define S_vct_times    "vct*"
137   #define S_vct_plus     "vct+"
138 #endif
139 #define A_VCT            "a vct"
140 #endif
141 
142 #ifndef PROC_FALSE
143   #if HAVE_RUBY
144     #define PROC_FALSE "false"
145     #define PROC_TRUE "true"
146   #else
147     #define PROC_FALSE "#f"
148     #define PROC_TRUE  "#t"
149   #endif
150 #endif
151 
152 #if USE_SND
153   #define VCT_PRINT_LENGTH DEFAULT_PRINT_LENGTH
154 #else
155   #define VCT_PRINT_LENGTH 10
156 #endif
157 
158 
159 #if WITH_VECTORIZE
mus_clear_floats(mus_float_t * dst,mus_long_t len)160 void mus_clear_floats(mus_float_t *dst, mus_long_t len)
161 {
162   mus_long_t k;
163   for (k = 0; k < len; k++) dst[k] = 0.0;
164 }
165 
mus_copy_floats(mus_float_t * dst,mus_float_t * src,mus_long_t len)166 void mus_copy_floats(mus_float_t *dst, mus_float_t *src, mus_long_t len)
167 {
168   mus_long_t k;
169   for (k = 0; k < len; k++) dst[k] = src[k];
170 }
171 
mus_add_floats(mus_float_t * dst,mus_float_t * src,mus_long_t len)172 void mus_add_floats(mus_float_t *dst, mus_float_t *src, mus_long_t len)
173 {
174   mus_long_t k;
175   for (k = 0; k < len; k++) dst[k] += src[k];
176 }
177 
mus_abs_floats(mus_float_t * dst,mus_long_t len)178 void mus_abs_floats(mus_float_t *dst, mus_long_t len)
179 {
180   mus_long_t k;
181   for (k = 0; k < len; k++) dst[k] = fabs(dst[k]);
182 }
183 #endif
184 
185 
186 static int vct_print_length = VCT_PRINT_LENGTH;
187 
mus_vct_set_print_length(int len)188 void mus_vct_set_print_length(int len)
189 {
190   vct_print_length = len;
191 }
192 
mus_vct_print_length(void)193 int mus_vct_print_length(void)
194 {
195   return(vct_print_length);
196 }
197 
198 
xen_to_vct(Xen arg)199 vct *xen_to_vct(Xen arg)
200 {
201   if (mus_is_vct(arg))
202     return((vct *)Xen_to_vct(arg));
203   return(NULL);
204 }
205 
206 
207 #define VCT_PRINT_BUFFER_SIZE 64
208 
209 
210 #if (!HAVE_SCHEME)
211 
212 static Xen_object_type_t vct_tag;
213 
mus_is_vct(Xen obj)214 bool mus_is_vct(Xen obj)
215 {
216   return(Xen_c_object_is_type(obj, vct_tag));
217 }
218 
219 
vct_free(vct * v)220 static void vct_free(vct *v)
221 {
222   if (v)
223     {
224       if ((!(v->dont_free)) &&
225 	  (v->data))
226 	free(v->data);
227       v->data = NULL;
228       free(v);
229     }
230 }
231 
Xen_wrap_free(vct,free_vct,vct_free)232 Xen_wrap_free(vct, free_vct, vct_free)
233 
234 static char *mus_vct_to_string(vct *v)
235 {
236   mus_long_t len, size;
237   char *buf;
238   char flt[VCT_PRINT_BUFFER_SIZE];
239   mus_float_t *d;
240 
241   if (!v) return(NULL);
242   len = vct_print_length;
243   if (len > mus_vct_length(v)) len = mus_vct_length(v);
244   d = mus_vct_data(v);
245   size = (len + 1) * VCT_PRINT_BUFFER_SIZE;
246   buf = (char *)calloc(size, sizeof(char));
247   snprintf(buf, size, "#<vct[len=%" print_mus_long "]", mus_vct_length(v));
248 
249   if ((len > 0) && (d))
250     {
251       int i;
252       strcat(buf, ":");
253       for (i = 0; i < len; i++)
254 	{
255 	  snprintf(flt, VCT_PRINT_BUFFER_SIZE, " %.3f", d[i]);
256 	  strcat(buf, flt);
257 	}
258       if (mus_vct_length(v) > vct_print_length)
259 	strcat(buf, " ...");
260     }
261   strcat(buf, ">");
262   return(buf);
263 }
264 #endif
265 
266 
mus_vct_to_readable_string(vct * v)267 char *mus_vct_to_readable_string(vct *v)
268 {
269   int i, len, size;
270   char *buf;
271   char flt[VCT_PRINT_BUFFER_SIZE];
272   mus_float_t *d;
273 
274   if (!v) return(NULL);
275   len = (int)(mus_vct_length(v));
276   size = (len + 1) * VCT_PRINT_BUFFER_SIZE;
277   buf = (char *)calloc(size, sizeof(char));
278   d = mus_vct_data(v);
279 
280 #if HAVE_SCHEME
281   snprintf(buf, size, "(float-vector");
282 #endif
283 #if HAVE_RUBY || HAVE_FORTH
284   snprintf(buf, size, "vct(");
285 #endif
286 
287   for (i = 0; i < len; i++)
288     {
289 #if HAVE_SCHEME || HAVE_FORTH
290       snprintf(flt, VCT_PRINT_BUFFER_SIZE, " %.3f", d[i]);
291 #endif
292 #if HAVE_RUBY
293       snprintf(flt, VCT_PRINT_BUFFER_SIZE, "%.3f%s", d[i], i + 1 < len ? ", " : "");
294 #endif
295       strcat(buf, flt);
296     }
297 
298 #if HAVE_FORTH
299   strcat(buf, " ");
300 #endif
301   strcat(buf, ")");
302 
303   return(buf);
304 }
305 
306 
g_vct_to_readable_string(Xen obj)307 static Xen g_vct_to_readable_string(Xen obj)
308 {
309   char *vstr;
310   Xen result;
311   #define H_vct_to_string "(" S_vct_to_string " v): readable description of v"
312 
313   Xen_check_type(mus_is_vct(obj), obj, 1, S_vct_to_string, A_VCT);
314 
315   vstr = mus_vct_to_readable_string(Xen_to_vct(obj));
316   result = C_string_to_Xen_string(vstr);
317   free(vstr);
318   return(result);
319 }
320 
mus_vct_is_equal(vct * v1,vct * v2)321 bool mus_vct_is_equal(vct *v1, vct *v2)
322 {
323   if (v1 == v2) return(true);
324   return((mus_vct_length(v1) == mus_vct_length(v2)) &&
325 	 (mus_arrays_are_equal(mus_vct_data(v1), mus_vct_data(v2),
326 			       mus_float_equal_fudge_factor(),
327 			       mus_vct_length(v1))));
328 }
329 
330 
331 #if (!HAVE_SCHEME)
332 
g_is_vct(Xen obj)333 static Xen g_is_vct(Xen obj)
334 {
335   #define H_is_vct "(" S_is_vct " obj): is obj a " S_vct
336   return(C_bool_to_Xen_boolean(mus_is_vct(obj)));
337 }
338 
Xen_wrap_print(vct,print_vct,mus_vct_to_string)339 Xen_wrap_print(vct, print_vct, mus_vct_to_string)
340 
341 static Xen equalp_vct(Xen obj1, Xen obj2)
342 {
343   if ((!(mus_is_vct(obj1))) || (!(mus_is_vct(obj2)))) return(Xen_false);
344   return(C_bool_to_Xen_boolean(mus_vct_is_equal(Xen_to_vct(obj1), Xen_to_vct(obj2))));
345 }
346 
mus_vct_make(mus_long_t len)347 vct *mus_vct_make(mus_long_t len)
348 {
349   vct *new_vct;
350   new_vct = (vct *)malloc(sizeof(vct));
351   new_vct->length = len;
352   if (len > 0)
353     new_vct->data = (mus_float_t *)calloc(len, sizeof(mus_float_t));
354   else new_vct->data = NULL;
355   new_vct->dont_free = false;
356   return(new_vct);
357 }
358 
359 
mus_vct_wrap(mus_long_t len,mus_float_t * data)360 vct *mus_vct_wrap(mus_long_t len, mus_float_t *data)
361 {
362   vct *new_vct;
363   new_vct = (vct *)malloc(sizeof(vct));
364   new_vct->length = len;
365   new_vct->data = data;
366   new_vct->dont_free = true;
367   return(new_vct);
368 }
369 
370 
mus_vct_free(vct * v)371 vct *mus_vct_free(vct *v)
372 {
373   vct_free(v);
374   return(NULL);
375 }
376 
377 
xen_make_vct(mus_long_t len,mus_float_t * data)378 Xen xen_make_vct(mus_long_t len, mus_float_t *data)
379 {
380   vct *new_vct;
381 
382   if (len < 0) return(Xen_false);
383   if ((len > 0) &&
384       (!data))
385     Xen_error(Xen_make_error_type("out-of-memory"),
386 	      Xen_list_2(C_string_to_Xen_string(S_make_vct ": can't allocate size ~A"),
387 			 C_int_to_Xen_integer(len)));
388 
389   new_vct = (vct *)malloc(sizeof(vct));
390   new_vct->length = len;
391   new_vct->data = data;
392   new_vct->dont_free = false;
393   return(Xen_make_object(vct_tag, new_vct, 0, free_vct));
394 }
395 
396 
xen_make_vct_wrapper(mus_long_t len,mus_float_t * data)397 Xen xen_make_vct_wrapper(mus_long_t len, mus_float_t *data)
398 {
399   vct *new_vct;
400   new_vct = (vct *)malloc(sizeof(vct));
401   new_vct->length = len;
402   new_vct->data = data;
403   new_vct->dont_free = true;
404   return(Xen_make_object(vct_tag, new_vct, 0, free_vct));
405 }
406 
407 
vct_to_xen(vct * v)408 Xen vct_to_xen(vct *v)
409 {
410   return(Xen_make_object(vct_tag, v, 0, free_vct));
411 }
412 
413 
414 static Xen g_vct_fill(Xen obj, Xen val);
415 
g_make_vct(Xen len,Xen filler)416 static Xen g_make_vct(Xen len, Xen filler)
417 {
418   #if HAVE_RUBY
419     #define vct_make_example "v = make_vct(32, 1.0)"
420   #endif
421   #if HAVE_FORTH
422     #define vct_make_example "32 1.0 make-vct value v"
423   #endif
424   #if HAVE_SCHEME
425     #define vct_make_example "(make-float-vector 32 1.0)"
426   #endif
427 
428   #define H_make_vct "(" S_make_vct " len :optional (initial-element 0)): returns a new " S_vct " of length len filled with \
429 initial-element: \n  " vct_make_example
430 
431   mus_long_t size;
432   Xen_check_type(Xen_is_llong(len), len, 1, S_make_vct, "an integer");
433   Xen_check_type(Xen_is_number(filler) || !Xen_is_bound(filler), filler, 2, S_make_vct, "a number");
434 
435   size = Xen_llong_to_C_llong(len);
436   if (size < 0)
437     Xen_out_of_range_error(S_make_vct, 1, len, "new vct size < 0?");
438 
439   if ((size > mus_max_malloc()) ||
440       (((mus_long_t)(size * sizeof(mus_float_t))) > mus_max_malloc()))
441     Xen_out_of_range_error(S_make_vct, 1, len, "new vct size is too large (see mus-max-malloc)");
442 
443   if (Xen_is_number(filler))
444     return(g_vct_fill(xen_make_vct(size, (mus_float_t *)calloc(size, sizeof(mus_float_t))), filler));
445 
446   return(xen_make_vct(size, (mus_float_t *)calloc(size, sizeof(mus_float_t))));
447 }
448 
449 
g_vct_length(Xen obj)450 static Xen g_vct_length(Xen obj)
451 {
452   #define H_vct_length "(" S_vct_length " v): length of " S_vct " v"
453   vct *v;
454   Xen_check_type(mus_is_vct(obj), obj, 1, S_vct_length, A_VCT);
455   v = Xen_to_vct(obj);
456   return(C_llong_to_Xen_llong(mus_vct_length(v)));
457 }
458 
459 
g_vct_copy(Xen obj)460 static Xen g_vct_copy(Xen obj)
461 {
462   #define H_vct_copy "(" S_vct_copy " v): returns a copy of " S_vct " v"
463   vct *v;
464   mus_float_t *copied_data = NULL;
465   mus_long_t len;
466 
467   Xen_check_type(mus_is_vct(obj), obj, 1, S_vct_copy, A_VCT);
468 
469   v = Xen_to_vct(obj);
470   len = mus_vct_length(v);
471   if (len > 0)
472     {
473       copied_data = (mus_float_t *)malloc(len * sizeof(mus_float_t));
474       mus_copy_floats(copied_data, mus_vct_data(v), len);
475     }
476   return(xen_make_vct(len, copied_data));
477 }
478 
479 #else /* HAVE_SCHEME */
mus_vct_make(mus_long_t len)480 vct *mus_vct_make(mus_long_t len)
481 {
482   s7_int di[1];
483   di[0] = len;
484   return(s7_make_float_vector(s7, len, 1, di));
485 }
486 
xen_make_vct(mus_long_t len,mus_float_t * data)487 Xen xen_make_vct(mus_long_t len, mus_float_t *data)
488 {
489   return(s7_make_float_vector_wrapper(s7, len, (s7_double *)data, 1, NULL, true));     /* freed by s7 */
490 }
491 
xen_make_vct_wrapper(mus_long_t len,mus_float_t * data)492 Xen xen_make_vct_wrapper(mus_long_t len, mus_float_t *data)
493 {
494   s7_int di[1];
495   di[0] = len;
496   return(s7_make_float_vector_wrapper(s7, len, (s7_double *)data, 1, di, false));     /* not freed by s7 */
497 }
498 
mus_vct_wrap(mus_long_t len,mus_float_t * data)499 vct *mus_vct_wrap(mus_long_t len, mus_float_t *data)
500 {
501   return(xen_make_vct_wrapper(len, data));
502 }
503 
g_vct_copy(Xen obj)504 static Xen g_vct_copy(Xen obj)
505 {
506   #define H_vct_copy "(" S_vct_copy " v): returns a copy of " S_vct " v"
507   Xen_check_type(mus_is_vct(obj), obj, 1, S_vct_copy, A_VCT);
508   return(s7_vector_copy(s7, obj));
509 }
510 #endif
511 
512 
g_vct_move(Xen obj,Xen newi,Xen oldi,Xen backwards)513 static Xen g_vct_move(Xen obj, Xen newi, Xen oldi, Xen backwards)
514 {
515   #define H_vct_moveB "(" S_vct_move " obj new old :optional backwards): moves " S_vct " obj data from old to new: v[new++] = v[old++], or \
516 v[new--] = v[old--] if backwards is " PROC_FALSE "."
517   vct *v;
518   mus_long_t i, j, ni, nj;
519   mus_float_t *d;
520 
521   Xen_check_type(mus_is_vct(obj), obj, 1, S_vct_move, A_VCT);
522   Xen_check_type(Xen_is_llong(newi), newi, 2, S_vct_move, "an integer");
523   Xen_check_type(Xen_is_llong(oldi), oldi, 3, S_vct_move, "an integer");
524   Xen_check_type(Xen_is_boolean_or_unbound(backwards), backwards, 4, S_vct_move, "a boolean");
525 
526   v = Xen_to_vct(obj);
527   d = mus_vct_data(v);
528   ni = Xen_llong_to_C_llong(newi);
529   nj = Xen_llong_to_C_llong(oldi);
530 
531   if ((Xen_is_boolean(backwards)) &&
532       (!Xen_is_false(backwards)))
533     {
534       if (ni >= mus_vct_length(v))
535 	Xen_out_of_range_error(S_vct_move, 2, newi, "new-index too high");
536       if (nj >= mus_vct_length(v))
537 	Xen_out_of_range_error(S_vct_move, 3, oldi, "old-index too high");
538       for (i = ni, j = nj; (j >= 0) && (i >= 0); i--, j--)
539 	d[i] = d[j];
540     }
541   else
542     {
543       mus_long_t len;
544       if (ni < 0)
545 	Xen_out_of_range_error(S_vct_move, 2, newi, "new-index < 0?");
546       if (nj < 0)
547 	Xen_out_of_range_error(S_vct_move, 3, oldi, "old-index < 0?");
548       len = mus_vct_length(v);
549       for (i = ni, j = nj; (j < len) && (i < len); i++, j++)
550 	d[i] = d[j];
551     }
552   return(obj);
553 }
554 
555 #if (!HAVE_SCHEME)
g_vct_ref(Xen obj,Xen pos)556 static Xen g_vct_ref(Xen obj, Xen pos)
557 {
558   #define H_vct_ref "(" S_vct_ref " v n): element n of " S_vct " v, v[n]"
559   vct *v;
560   mus_long_t loc;
561 
562   Xen_check_type(mus_is_vct(obj), obj, 1, S_vct_ref, A_VCT);
563   Xen_check_type(Xen_is_llong(pos), pos, 2, S_vct_ref, "an integer");
564 
565   v = Xen_to_vct(obj);
566   loc = Xen_llong_to_C_llong(pos);
567 
568   if (loc < 0)
569     Xen_out_of_range_error(S_vct_ref, 2, pos, "index < 0?");
570   if (loc >= mus_vct_length(v))
571     Xen_out_of_range_error(S_vct_ref, 2, pos, "index too high?");
572 
573   return(C_double_to_Xen_real(mus_vct_data(v)[loc]));
574 }
575 
576 
g_vct_set(Xen obj,Xen pos,Xen val)577 static Xen g_vct_set(Xen obj, Xen pos, Xen val)
578 {
579   #define H_vct_setB "(" S_vct_set " v n val): sets element of " S_vct " v to val, v[n] = val"
580   vct *v;
581   mus_long_t loc;
582   double x;
583   mus_float_t *d;
584 
585   Xen_check_type(mus_is_vct(obj), obj, 1, S_vct_set, A_VCT);
586   Xen_check_type(Xen_is_llong(pos), pos, 2, S_vct_set, "an integer");
587   Xen_check_type(Xen_is_number(val), val, 3, S_vct_set, "a real number");
588 
589   x = Xen_real_to_C_double(val);
590   v = Xen_to_vct(obj);
591   loc = Xen_llong_to_C_llong(pos);
592 
593   if (loc < 0)
594     Xen_out_of_range_error(S_vct_set, 2, pos, "index < 0?");
595   if (loc >= mus_vct_length(v))
596     Xen_out_of_range_error(S_vct_set, 2, pos, "index >= vct-length?");
597 
598   d = mus_vct_data(v);
599   d[loc] = x;
600   return(val);
601 }
602 #endif
603 
604 
g_vct_multiply(Xen obj1,Xen obj2)605 static Xen g_vct_multiply(Xen obj1, Xen obj2)
606 {
607   #define H_vct_multiplyB "(" S_vct_multiply " v1 v2): element-wise multiply of " S_vct "s v1 and v2: v1[i] *= v2[i], returns v1"
608   mus_long_t i, lim, lim1;
609   vct *v1, *v2;
610   mus_float_t *d1, *d2;
611 
612   Xen_check_type(mus_is_vct(obj1), obj1, 1, S_vct_multiply, A_VCT);
613   Xen_check_type(mus_is_vct(obj2), obj2, 2, S_vct_multiply, A_VCT);
614 
615   v1 = Xen_to_vct(obj1);
616   v2 = Xen_to_vct(obj2);
617   d1 = mus_vct_data(v1);
618   d2 = mus_vct_data(v2);
619   lim = mus_vct_length(v1);
620   lim1 = mus_vct_length(v2);
621   if (lim > lim1) lim = lim1;
622   for (i = 0; i < lim; i++) d1[i] *= d2[i];
623   return(obj1);
624 }
625 
626 #if WITH_VECTORIZE
627 static void vct_add(mus_float_t *d1, mus_float_t *d2, mus_long_t lim) __attribute__((optimize("tree-vectorize")));
vct_add(mus_float_t * d1,mus_float_t * d2,mus_long_t lim)628 static void vct_add(mus_float_t *d1, mus_float_t *d2, mus_long_t lim)
629 {
630   mus_add_floats(d1, d2, lim);
631 }
632 #else
vct_add(mus_float_t * d1,mus_float_t * d2,mus_long_t lim)633 static void vct_add(mus_float_t *d1, mus_float_t *d2, mus_long_t lim)
634 {
635   mus_long_t i, lim8;
636   lim8 = lim - 16;
637   i = 0;
638   while (i <= lim8)
639     {
640       d1[i] += d2[i]; i++;
641       d1[i] += d2[i]; i++;
642       d1[i] += d2[i]; i++;
643       d1[i] += d2[i]; i++;
644       d1[i] += d2[i]; i++;
645       d1[i] += d2[i]; i++;
646       d1[i] += d2[i]; i++;
647       d1[i] += d2[i]; i++;
648       d1[i] += d2[i]; i++;
649       d1[i] += d2[i]; i++;
650       d1[i] += d2[i]; i++;
651       d1[i] += d2[i]; i++;
652       d1[i] += d2[i]; i++;
653       d1[i] += d2[i]; i++;
654       d1[i] += d2[i]; i++;
655       d1[i] += d2[i]; i++;
656     }
657   for (; i < lim; i++)
658     d1[i] += d2[i];
659 }
660 #endif
661 
g_vct_add(Xen obj1,Xen obj2,Xen offs)662 static Xen g_vct_add(Xen obj1, Xen obj2, Xen offs)
663 {
664   #define H_vct_addB "(" S_vct_add " v1 v2 :optional (offset 0)): element-wise add of " S_vct "s v1 and v2: v1[i + offset] += v2[i], returns v1"
665   mus_long_t lim, len1;
666   vct *v1, *v2;
667   mus_float_t *d1, *d2;
668 
669   Xen_check_type(mus_is_vct(obj1), obj1, 1, S_vct_add, A_VCT);
670   Xen_check_type(mus_is_vct(obj2), obj2, 2, S_vct_add, A_VCT);
671   Xen_check_type(Xen_is_llong_or_unbound(offs), offs, 3, S_vct_add, "an integer");
672 
673   v1 = Xen_to_vct(obj1);
674   v2 = Xen_to_vct(obj2);
675   d1 = mus_vct_data(v1);
676   d2 = mus_vct_data(v2);
677   len1 = mus_vct_length(v1);
678   lim = mus_vct_length(v2);
679   if (lim > len1) lim = len1;
680   if (lim == 0) return(obj1);
681 
682   if (Xen_is_llong(offs))
683     {
684       mus_long_t j;
685       j = Xen_llong_to_C_llong(offs);
686       if (j < 0)
687 	Xen_out_of_range_error(S_vct_add, 3, offs, "offset < 0?");
688       if (j > len1)
689 	Xen_out_of_range_error(S_vct_add, 3, offs, "offset > length of vct?");
690 
691       if ((j + lim) > len1)
692 	lim = (len1 - j);
693 
694       vct_add((mus_float_t *)(d1 + j), d2, lim);
695     }
696   else vct_add(d1, d2, lim);
697   return(obj1);
698 }
699 
700 
g_vct_subtract(Xen obj1,Xen obj2)701 static Xen g_vct_subtract(Xen obj1, Xen obj2)
702 {
703   #define H_vct_subtractB "(" S_vct_subtract " v1 v2): element-wise subtract of " S_vct "s v1 and v2: v1[i] -= v2[i], returns v1"
704   mus_long_t i, lim, lim1, lim4;
705   vct *v1, *v2;
706   mus_float_t *d1, *d2;
707 
708   Xen_check_type(mus_is_vct(obj1), obj1, 1, S_vct_subtract, A_VCT);
709   Xen_check_type(mus_is_vct(obj2), obj2, 2, S_vct_subtract, A_VCT);
710 
711   v1 = Xen_to_vct(obj1);
712   v2 = Xen_to_vct(obj2);
713   d1 = mus_vct_data(v1);
714   d2 = mus_vct_data(v2);
715   lim = mus_vct_length(v1);
716   lim1 = mus_vct_length(v2);
717   if (lim > lim1) lim = lim1;
718   lim4 = lim - 4;
719 
720   i = 0;
721   while (i <= lim4)
722     {
723       d1[i] -= d2[i]; i++;
724       d1[i] -= d2[i]; i++;
725       d1[i] -= d2[i]; i++;
726       d1[i] -= d2[i]; i++;
727     }
728   for (; i < lim; i++)
729     d1[i] -= d2[i];
730 
731   return(obj1);
732 }
733 
734 
g_vct_abs(Xen obj)735 static Xen g_vct_abs(Xen obj)
736 {
737   #define H_vct_absB "(" S_vct_abs " v): v[i] = abs(v[i]), return v."
738   mus_long_t lim;
739   vct *v;
740   mus_float_t *d;
741 
742   Xen_check_type(mus_is_vct(obj), obj, 0, S_vct_abs, A_VCT);
743 
744   v = Xen_to_vct(obj);
745   d = mus_vct_data(v);
746   lim = mus_vct_length(v);
747   mus_abs_floats(d, lim);
748   return(obj);
749 }
750 
751 
g_vct_equal(Xen uv1,Xen uv2,Xen udiff)752 static Xen g_vct_equal(Xen uv1, Xen uv2, Xen udiff)
753 {
754   #define H_vct_equal "(" S_vct_equal " v1 v2 diff): is element-wise relative-difference of v1 and v2 ever greater than diff?"
755   mus_long_t i, lim;
756   vct *v1, *v2;
757   mus_float_t *d1, *d2;
758   mus_float_t diff, max_diff = 0.0;
759 
760   Xen_check_type(mus_is_vct(uv1), uv1, 1, S_vct_equal, A_VCT);
761   Xen_check_type(mus_is_vct(uv2), uv2, 2, S_vct_equal, A_VCT);
762   Xen_check_type(Xen_is_number(udiff), udiff, 3, S_vct_equal, "a number");
763 
764   v1 = Xen_to_vct(uv1);
765   d1 = mus_vct_data(v1);
766   v2 = Xen_to_vct(uv2);
767   d2 = mus_vct_data(v2);
768   diff = Xen_real_to_C_double(udiff);
769 
770   lim = mus_vct_length(v1);
771   if (mus_vct_length(v2) < lim) lim = mus_vct_length(v2);
772 
773   for (i = 0; i < lim; i++)
774     {
775       mus_float_t x1, x2, z;
776       x1 = fabs(d1[i]);
777       x2 = fabs(d2[i]);
778       z = fabs(d1[i] - d2[i]);
779       if (x1 > x2)
780 	z /= x1;
781       else
782 	{
783 	  if (x2 > 0.0)
784 	    z /= x2;
785 	}
786       if (z > diff)
787 	return(Xen_false);
788       if (z > max_diff)
789 	max_diff = z;
790     }
791 
792   return(C_double_to_Xen_real(max_diff));
793 }
794 
795 #if WITH_VECTORIZE
796 static void vct_scale(mus_float_t *d, mus_float_t scl, mus_long_t len) __attribute__((optimize("tree-vectorize")));
797 #endif
798 
vct_scale(mus_float_t * d,mus_float_t scl,mus_long_t len)799 static void vct_scale(mus_float_t *d, mus_float_t scl, mus_long_t len)
800 {
801   if (scl == 0.0)
802     mus_clear_floats(d, len);
803   else
804     {
805       if (scl != 1.0)
806 	{
807 	  mus_long_t i, lim4;
808 	  lim4 = len - 4;
809 	  i = 0;
810 	  while (i <= lim4)
811 	    {
812 	      d[i++] *= scl;
813 	      d[i++] *= scl;
814 	      d[i++] *= scl;
815 	      d[i++] *= scl;
816 	    }
817 	  for (; i < len; i++)
818 	    d[i] *= scl;
819 	}
820     }
821 }
822 
g_vct_scale(Xen obj1,Xen obj2)823 static Xen g_vct_scale(Xen obj1, Xen obj2)
824 {
825   #define H_vct_scaleB "(" S_vct_scale " v val): scale each element of v by val: v[i] *= val, returns v"
826 
827   /* Xen_check_type(s7_is_float_vector(obj1), obj1, 1, "float-vector-scale!", "a float-vector");
828    * return(s7_float_vector_scale(s7, obj1, obj2));
829    */
830   vct *v1;
831 
832   Xen_check_type(mus_is_vct(obj1), obj1, 1, S_vct_scale, A_VCT);
833   Xen_check_type(Xen_is_number(obj2), obj2, 2, S_vct_scale, "a number");
834 
835   v1 = Xen_to_vct(obj1);
836   if (mus_vct_length(v1) == 0) return(obj1);
837   vct_scale(mus_vct_data(v1), Xen_real_to_C_double(obj2), mus_vct_length(v1));
838   return(obj1);
839 }
840 
841 
g_vct_offset(Xen obj1,Xen obj2)842 static Xen g_vct_offset(Xen obj1, Xen obj2)
843 {
844   #define H_vct_offsetB "(" S_vct_offset " v val): add val to each element of v: v[i] += val, returns v"
845   vct *v1;
846   mus_float_t scl;
847   mus_float_t *d;
848   mus_long_t len;
849 
850   Xen_check_type(mus_is_vct(obj1), obj1, 1, S_vct_offset, A_VCT);
851   Xen_check_type(Xen_is_number(obj2), obj2, 2, S_vct_offset, "a number");
852 
853   v1 = Xen_to_vct(obj1);
854   if (mus_vct_length(v1) == 0) return(obj1);
855   d = mus_vct_data(v1);
856   len = mus_vct_length(v1);
857 
858   scl = Xen_real_to_C_double(obj2);
859   if (scl != 0.0)
860     {
861       mus_long_t i;
862       for (i = 0; i < len; i++)
863 	d[i] += scl;
864     }
865   return(obj1);
866 }
867 
868 #if HAVE_SCHEME
869 #define S_vct_spatter "float-vector-spatter"
g_vct_spatter(Xen fv,XEN iv,XEN end,XEN val)870 static Xen g_vct_spatter(Xen fv, XEN iv, XEN end, XEN val)
871 {
872   #define H_vct_spatter "(" S_vct_spatter " fv iv end val) places val in fv at locations determined by iv"
873   s7_double *fv_vals;
874   s7_int *iv_vals;
875   s7_double x;
876   int i, len;
877 
878   if (!s7_is_float_vector(fv)) s7_wrong_type_arg_error(s7, S_vct_spatter, 1, fv, "a float-vector");
879   if (!s7_is_int_vector(iv)) s7_wrong_type_arg_error(s7, S_vct_spatter, 2, iv, "an int-vector");
880   if (!s7_is_integer(end)) s7_wrong_type_arg_error(s7, S_vct_spatter, 3, end, "an integer");
881   if (!s7_is_real(val)) s7_wrong_type_arg_error(s7, S_vct_spatter, 4, val, "a real");
882 
883   fv_vals = s7_float_vector_elements(fv);
884   iv_vals = s7_int_vector_elements(iv);
885   len = s7_integer(end);
886   x = s7_real(val);
887   for (i = 0; i < len; i++)
888     fv_vals[iv_vals[i]] = x;
889 
890   return(val);
891 }
892 
893 #define S_vct_interpolate "float-vector-interpolate"
g_vct_interpolate(Xen fv,Xen start_index,Xen end_index,Xen start_x,XEN incr,XEN val1,XEN val2)894 static Xen g_vct_interpolate(Xen fv, Xen start_index, Xen end_index, Xen start_x, XEN incr, XEN val1, XEN val2)
895 {
896   #define H_vct_interpolate "(" S_vct_interpolate " fv index0 index1 x0 dx x1 x2) sets the values of fv between\
897 index0 and index1 interpolating between x2 and x1 by incrementing x0 by dx"
898   s7_double x0, dx, x1, x2;
899   int i, beg, lim;
900   s7_double *fv_vals;
901   fv_vals = s7_float_vector_elements(fv);
902 
903   if (!s7_is_float_vector(fv)) s7_wrong_type_arg_error(s7, S_vct_interpolate, 1, fv, "a float-vector");
904   if (!s7_is_integer(start_index)) s7_wrong_type_arg_error(s7, S_vct_spatter, 2, start_index, "an integer");
905   if (!s7_is_integer(end_index)) s7_wrong_type_arg_error(s7, S_vct_spatter, 3, end_index, "an integer");
906   if (!s7_is_real(start_x)) s7_wrong_type_arg_error(s7, S_vct_spatter, 4, start_x, "a real");
907   if (!s7_is_real(incr)) s7_wrong_type_arg_error(s7, S_vct_spatter, 5, incr, "a real");
908   if (!s7_is_real(val1)) s7_wrong_type_arg_error(s7, S_vct_spatter, 6, val1, "a real");
909   if (!s7_is_real(val2)) s7_wrong_type_arg_error(s7, S_vct_spatter, 7, val2, "a real");
910 
911   beg = s7_integer(start_index);
912   lim = s7_integer(end_index);
913   x0 = s7_real(start_x);
914   dx = s7_real(incr);
915   x1 = s7_real(val1);
916   x2 = s7_real(val2);
917   for (i = beg; i < lim; i++, x0 += dx)
918     fv_vals[i] = (x0 * x1) + ((1.0 - x0) * x2);
919   return(val1);
920 }
921 #endif
922 
923 
924 #if (!HAVE_SCHEME)
g_vct_fill(Xen obj1,Xen obj2)925 static Xen g_vct_fill(Xen obj1, Xen obj2)
926 {
927   #define H_vct_fillB "(" S_vct_fill " v val): set each element of v to val: v[i] = val, returns v"
928   mus_long_t i, len; /* unsigned int is much slower */
929   vct *v1;
930   mus_float_t scl;
931   mus_float_t *d;
932 
933   Xen_check_type(mus_is_vct(obj1), obj1, 1, S_vct_fill, A_VCT);
934   Xen_check_type(Xen_is_number(obj2), obj2, 2, S_vct_fill, "a number");
935 
936   v1 = Xen_to_vct(obj1);
937   len = mus_vct_length(v1);
938   if (len == 0) return(obj1);
939   d = mus_vct_data(v1);
940 
941   scl = Xen_real_to_C_double(obj2);
942   if (scl == 0.0)
943     mus_clear_floats(d, len);
944   else
945     {
946       mus_long_t lim8;
947       lim8 = len - 8;
948       i = 0;
949       while (i <= lim8)
950 	{
951 	  d[i++] = scl;
952 	  d[i++] = scl;
953 	  d[i++] = scl;
954 	  d[i++] = scl;
955 	  d[i++] = scl;
956 	  d[i++] = scl;
957 	  d[i++] = scl;
958 	  d[i++] = scl;
959 	}
960       for (; i < len; i++)
961 	d[i] = scl;
962     }
963   return(obj1);
964 }
965 #endif
966 
mus_vct_peak(vct * v)967 double mus_vct_peak(vct *v)
968 {
969   mus_float_t val = 0.0;
970   mus_float_t *d;
971   mus_long_t i, len;
972 
973   len = mus_vct_length(v);
974   if (len == 0) return(0.0);
975   d = mus_vct_data(v);
976 
977   for (i = 0; i < len; i++)
978     val = (fabs(d[i]) > val) ? fabs(d[i]) : val;
979   return(val);
980 }
981 
982 
g_vct_peak(Xen obj)983 Xen g_vct_peak(Xen obj)
984 {
985   #define H_vct_peak "(" S_vct_peak " v): max of abs of elements of v"
986   Xen_check_type(mus_is_vct(obj), obj, 1, S_vct_peak, A_VCT);
987   return(C_double_to_Xen_real(mus_vct_peak(Xen_to_vct(obj))));
988 }
989 
990 
991 #if HAVE_SCHEME
992 #define S_vct_peak_and_location "float-vector-peak-and-location"
993 #else
994 #define S_vct_peak_and_location "vct-peak-and-location"
995 #endif
996 
997 
g_vct_peak_and_location(Xen obj)998 static Xen g_vct_peak_and_location(Xen obj)
999 {
1000   #define H_vct_peak_and_location "(" S_vct_peak_and_location " v): max of abs of elements of v and its position in v"
1001   mus_float_t val = 0.0;
1002   mus_long_t i, loc = 0, len;
1003   vct *v;
1004   mus_float_t *d;
1005 
1006   Xen_check_type(mus_is_vct(obj), obj, 1, S_vct_peak_and_location, "a " S_vct);
1007   v = Xen_to_vct(obj);
1008   d = mus_vct_data(v);
1009   len = mus_vct_length(v);
1010 
1011   for (i = 0; i < len; i++)
1012     {
1013       mus_float_t absv;
1014       absv = fabs(d[i]);
1015       if (absv > val)
1016 	{
1017 	  val = absv;
1018 	  loc = i;
1019 	}
1020     }
1021   return(Xen_list_2(C_double_to_Xen_real(val), C_int_to_Xen_integer(loc)));
1022 }
1023 
1024 
g_vct_subseq(Xen vobj,Xen start,Xen end,Xen newv)1025 static Xen g_vct_subseq(Xen vobj, Xen start, Xen end, Xen newv)
1026 {
1027   #define H_vct_subseq "(" S_vct_subseq " v start :optional end vnew): v[start..end], placed in vnew if given or new " S_vct
1028   vct *vold, *vnew;
1029   mus_float_t *dnew, *dold;
1030   Xen res;
1031   mus_long_t i, old_len, new_len, j, istart;
1032 
1033   Xen_check_type(mus_is_vct(vobj), vobj, 1, S_vct_subseq, A_VCT);
1034   Xen_check_type(Xen_is_llong(start), start, 2, S_vct_subseq, "an integer");
1035   Xen_check_type(Xen_is_llong_or_unbound(end), end, 3, S_vct_subseq, "an integer");
1036 
1037   istart = Xen_llong_to_C_llong(start);
1038   if (istart < 0)
1039     Xen_out_of_range_error(S_vct_subseq, 2, start, "start < 0?");
1040 
1041   vold = Xen_to_vct(vobj);
1042   old_len = mus_vct_length(vold);
1043 
1044   if (Xen_is_llong(end))
1045     {
1046       mus_long_t iend;
1047       iend = Xen_llong_to_C_llong(end);
1048       if (iend < istart)
1049 	Xen_out_of_range_error(S_vct_subseq, 3, end, "end < start?");
1050       if (iend > old_len)
1051 	Xen_out_of_range_error(S_vct_subseq, 3, end, "end > vct length?");
1052       new_len = iend - istart + 1;
1053     }
1054   else new_len = old_len - istart;
1055 
1056   if (new_len <= 0)
1057     return(Xen_false);
1058 
1059   if (mus_is_vct(newv))
1060     res = newv;
1061   else res = xen_make_vct(new_len, (mus_float_t *)calloc(new_len, sizeof(mus_float_t)));
1062   vnew = Xen_to_vct(res);
1063 
1064   if (new_len > mus_vct_length(vnew))
1065     new_len = mus_vct_length(vnew);
1066   dnew = mus_vct_data(vnew);
1067   dold = mus_vct_data(vold);
1068 
1069   for (i = istart, j = 0; (j < new_len) && (i < old_len); i++, j++)
1070     dnew[j] = dold[i];
1071 
1072   return(res);
1073 }
1074 
1075 
xen_list_to_vct(Xen lst)1076 Xen xen_list_to_vct(Xen lst)
1077 {
1078   #define H_list_to_vct "(" S_list_to_vct " lst): returns a new " S_vct " filled with elements of list lst"
1079   mus_long_t len = 0, i;
1080   vct *v;
1081   mus_float_t *d;
1082   Xen scv, lst1;
1083 
1084   Xen_check_type(Xen_is_list(lst), lst, 1, S_list_to_vct, "a list");
1085   len = Xen_list_length(lst);
1086   if (len > 0)
1087     scv = xen_make_vct(len, (mus_float_t *)calloc(len, sizeof(mus_float_t)));
1088   else scv = xen_make_vct(0, NULL);
1089 
1090   v = Xen_to_vct(scv);
1091   d = mus_vct_data(v);
1092   for (i = 0, lst1 = Xen_copy_arg(lst); i < len; i++, lst1 = Xen_cdr(lst1))
1093     {
1094       if (Xen_is_number(Xen_car(lst1)))
1095 	d[i] = (mus_float_t)Xen_real_to_C_double(Xen_car(lst1));
1096       else Xen_wrong_type_arg_error(S_list_to_vct, i, Xen_car(lst1), "a number");
1097     }
1098 
1099   return(scv);
1100 }
1101 
1102 
mus_array_to_list(mus_float_t * arr,mus_long_t i,mus_long_t len)1103 Xen mus_array_to_list(mus_float_t *arr, mus_long_t i, mus_long_t len)
1104 {
1105   if (i < (len - 1))
1106     return(Xen_cons(C_double_to_Xen_real(arr[i]),
1107 		    mus_array_to_list(arr, i + 1, len)));
1108   else return(Xen_cons(C_double_to_Xen_real(arr[i]),
1109 		       Xen_empty_list));
1110 }
1111 
1112 
1113 #if (!HAVE_SCHEME)
g_vct(Xen args)1114 static Xen g_vct(Xen args)
1115 {
1116   #define H_vct "(" S_vct " args...): returns a new " S_vct " with args as contents; same as " S_list_to_vct ": (" S_vct " 1 2 3)"
1117   return(xen_list_to_vct(args));
1118 }
1119 
1120 
g_vct_to_list(Xen vobj)1121 static Xen g_vct_to_list(Xen vobj)
1122 {
1123   #define H_vct_to_list "(" S_vct_to_list " v): returns a new list with elements of " S_vct " v"
1124   vct *v;
1125   Xen_check_type(mus_is_vct(vobj), vobj, 1, S_vct_to_list, A_VCT);
1126 
1127   v = Xen_to_vct(vobj);
1128   if (mus_vct_length(v) == 0)
1129     return(Xen_empty_list);
1130 
1131   return(mus_array_to_list(mus_vct_data(v), 0, mus_vct_length(v)));
1132 }
1133 
1134 
g_vector_to_vct(Xen vect)1135 static Xen g_vector_to_vct(Xen vect)
1136 {
1137   #define H_vector_to_vct "(" S_vector_to_vct " vect): returns a new " S_vct " with the elements of vector vect"
1138   mus_long_t len, i;
1139   vct *v;
1140   mus_float_t *d;
1141   Xen scv;
1142 
1143   Xen_check_type(Xen_is_vector(vect), vect, 1, S_vector_to_vct, "a vector");
1144 
1145   len = (mus_long_t)Xen_vector_length(vect);
1146   if (len > 0)
1147     scv = xen_make_vct(len, (mus_float_t *)calloc(len, sizeof(mus_float_t)));
1148   else scv = xen_make_vct(0, NULL);
1149 
1150   v = Xen_to_vct(scv);
1151   d = mus_vct_data(v);
1152   for (i = 0; i < len; i++)
1153     d[i] = (mus_float_t)Xen_real_to_C_double(Xen_vector_ref(vect, i));
1154 
1155   return(scv);
1156 }
1157 
1158 
g_vct_to_vector(Xen vobj)1159 static Xen g_vct_to_vector(Xen vobj)
1160 {
1161   #define H_vct_to_vector "(" S_vct_to_vector " v): returns a new vector with the elements of " S_vct
1162   vct *v;
1163   mus_float_t *d;
1164   mus_long_t i, len;
1165   Xen new_vect;
1166 
1167   Xen_check_type(mus_is_vct(vobj), vobj, 1, S_vct_to_vector, A_VCT);
1168   v = Xen_to_vct(vobj);
1169   len = mus_vct_length(v);
1170   new_vect = Xen_make_vector(len, C_double_to_Xen_real(0.0));
1171 
1172 #if HAVE_RUBY && HAVE_RB_GC_DISABLE
1173   rb_gc_disable();
1174   /* uh oh -- gc is triggered by C_double_to_Xen_real causing segfault, even if we
1175    *   protect (via Xen_protect_from_gc) new_vect -- I guess the double currently
1176    *   being created is causing the trouble?
1177    */
1178 #endif
1179 
1180   d = mus_vct_data(v);
1181   for (i = 0; i < len; i++)
1182     Xen_vector_set(new_vect, i, C_double_to_Xen_real(d[i]));
1183 
1184 #if HAVE_RUBY && HAVE_RB_GC_DISABLE
1185   rb_gc_enable();
1186 #endif
1187 
1188   return(new_vect);
1189 }
1190 
1191 
g_vct_reverse(Xen vobj,Xen size)1192 static Xen g_vct_reverse(Xen vobj, Xen size)
1193 {
1194   #define H_vct_reverse "(" S_vct_reverse " v len): in-place reversal of " S_vct " contents"
1195   vct *v;
1196   mus_float_t *d;
1197   mus_long_t i, j, len = -1;
1198 
1199   Xen_check_type(mus_is_vct(vobj), vobj, 1, S_vct_reverse, A_VCT);
1200   Xen_check_type(Xen_is_llong_or_unbound(size), size, 2, S_vct_reverse, "an integer");
1201 
1202   v = Xen_to_vct(vobj);
1203   if (Xen_is_llong(size))
1204     len = Xen_llong_to_C_llong(size);
1205   if ((len <= 0) || (len > mus_vct_length(v)))
1206     len = mus_vct_length(v);
1207   if (len == 1) return(vobj);
1208   d = mus_vct_data(v);
1209 
1210   for (i = 0, j = len - 1; i < j; i++, j--)
1211     {
1212       mus_float_t temp;
1213       temp = d[i];
1214       d[i] = d[j];
1215       d[j] = temp;
1216     }
1217   return(vobj);
1218 }
1219 #endif
1220 
1221 
1222 #if HAVE_SCHEME
1223 #define S_vct_max "float-vector-max"
1224 #define S_vct_min "float-vector-min"
1225 #else
1226 #define S_vct_max "vct-max"
1227 #define S_vct_min "vct-min"
1228 #endif
1229 
vct_max(mus_float_t * d,mus_long_t len)1230 static mus_float_t vct_max(mus_float_t *d, mus_long_t len)
1231 {
1232   mus_long_t i;
1233   mus_float_t mx;
1234   mx = d[0];
1235   for (i = 1; i < len; i++)
1236     if (d[i] > mx)
1237       mx = d[i];
1238   return(mx);
1239 }
1240 
1241 #if HAVE_SCHEME
float_vector_max_d_p(s7_pointer v)1242 static s7_double float_vector_max_d_p(s7_pointer v)
1243 {
1244   return(vct_max(s7_float_vector_elements(v), s7_vector_length(v)));
1245 }
1246 #endif
1247 
g_vct_max(Xen vobj)1248 static Xen g_vct_max(Xen vobj)
1249 {
1250   #define H_vct_max "(" S_vct_max " v): returns the maximum element of " S_vct
1251   vct *v;
1252   mus_long_t len;
1253 
1254   Xen_check_type(mus_is_vct(vobj), vobj, 1, S_vct_max, A_VCT);
1255   v = Xen_to_vct(vobj);
1256 
1257   len = mus_vct_length(v);
1258   if (len > 0)
1259     return(C_double_to_Xen_real(vct_max(mus_vct_data(v), len)));
1260   return(C_double_to_Xen_real(0.0));
1261 }
1262 
1263 
vct_min(mus_float_t * d,mus_long_t len)1264 static mus_float_t vct_min(mus_float_t *d, mus_long_t len)
1265 {
1266   mus_long_t i;
1267   mus_float_t mx;
1268   mx = d[0];
1269   for (i = 1; i < len; i++)
1270     if (d[i] < mx)
1271       mx = d[i];
1272   return(mx);
1273 }
1274 
1275 #if HAVE_SCHEME
float_vector_min_d_p(s7_pointer v)1276 static s7_double float_vector_min_d_p(s7_pointer v)
1277 {
1278   return(vct_min(s7_float_vector_elements(v), s7_vector_length(v)));
1279 }
1280 #endif
1281 
g_vct_min(Xen vobj)1282 static Xen g_vct_min(Xen vobj)
1283 {
1284   #define H_vct_min "(" S_vct_min " v): returns the minimum element of " S_vct
1285   vct *v;
1286   mus_long_t len;
1287 
1288   Xen_check_type(mus_is_vct(vobj), vobj, 1, S_vct_min, A_VCT);
1289   v = Xen_to_vct(vobj);
1290 
1291   len = mus_vct_length(v);
1292   if (len > 0)
1293     return(C_double_to_Xen_real(vct_min(mus_vct_data(v), len)));
1294   return(C_double_to_Xen_real(0.0));
1295 }
1296 
1297 
g_vct_times(Xen obj1,Xen obj2)1298 static Xen g_vct_times(Xen obj1, Xen obj2)
1299 {
1300   #define H_vct_times "(" S_vct_times " obj1 obj2): either " S_vct_multiply " or " S_vct_scale ", depending on the types of its arguments"
1301   if (mus_is_vct(obj1))
1302     {
1303       if (mus_is_vct(obj2))
1304 	return(g_vct_multiply(obj1, obj2));
1305       return(g_vct_scale(obj1, obj2));
1306     }
1307   return(g_vct_scale(obj2, obj1));
1308 }
1309 
1310 
g_vct_plus(Xen obj1,Xen obj2)1311 static Xen g_vct_plus(Xen obj1, Xen obj2)
1312 {
1313   #define H_vct_plus "(" S_vct_plus " obj1 obj2): either " S_vct_add " or " S_vct_offset ", depending on the types of its arguments"
1314   if (mus_is_vct(obj1))
1315     {
1316       if (mus_is_vct(obj2))
1317 	return(g_vct_add(obj1, obj2, Xen_undefined));
1318       return(g_vct_offset(obj1, obj2));
1319     }
1320   return(g_vct_offset(obj2, obj1));
1321 }
1322 
1323 #if HAVE_RUBY
g_vct_each(Xen obj)1324 static Xen g_vct_each(Xen obj)
1325 {
1326   mus_long_t i;
1327   vct *v;
1328   mus_float_t *d;
1329 
1330   v = Xen_to_vct(obj);
1331   d = mus_vct_data(v);
1332 
1333   for (i = 0; i < mus_vct_length(v); i++)
1334     rb_yield(C_double_to_Xen_real(d[i]));
1335   return(obj);
1336 }
1337 
1338 
g_vct_compare(Xen vr1,Xen vr2)1339 static Xen g_vct_compare(Xen vr1, Xen vr2)
1340 {
1341   if ((mus_is_vct(vr1)) && (mus_is_vct(vr2)))
1342     {
1343       mus_long_t i, len;
1344       vct *v1, *v2;
1345       mus_float_t *d1, *d2;
1346 
1347       v1 = Xen_to_vct(vr1);
1348       v2 = Xen_to_vct(vr2);
1349       d1 = mus_vct_data(v1);
1350       d2 = mus_vct_data(v2);
1351 
1352       len = mus_vct_length(v1);
1353       if (len > mus_vct_length(v2)) len = mus_vct_length(v2);
1354       for (i = 0; i < len; i++)
1355 	if (d1[i] < d2[i])
1356 	  return(C_int_to_Xen_integer(-1));
1357 	else
1358 	  if (d1[i] > d2[i])
1359 	    return(C_int_to_Xen_integer(1));
1360       len = mus_vct_length(v1) - mus_vct_length(v2);
1361       if (len == 0) return(C_int_to_Xen_integer(0));
1362       if (len > 0) return(C_int_to_Xen_integer(1));
1363     }
1364   return(C_int_to_Xen_integer(-1));
1365 }
1366 
1367 
g_rb_make_vct(int argc,Xen * argv,Xen self)1368 static Xen g_rb_make_vct(int argc, Xen *argv, Xen self)
1369 {
1370   mus_long_t size;
1371   Xen len, filler;
1372   rb_scan_args(argc, argv, "11", &len, &filler);
1373   Xen_check_type(Xen_is_llong(len), len, 1, "Vct.new", "an integer");
1374   size = Xen_llong_to_C_llong(len);
1375   if (size <= 0)
1376     Xen_out_of_range_error("Vct.new", 1, len, "len <= 0?");
1377   if (Xen_is_number(filler))
1378     return(g_vct_fill(xen_make_vct(size, (mus_float_t *)calloc(size, sizeof(mus_float_t))), filler));
1379   if (rb_block_given_p()) {
1380     mus_long_t i;
1381     mus_float_t *buffer = (mus_float_t *)calloc(size, sizeof(mus_float_t));
1382     for (i = 0; i < size; i++) {
1383       buffer[i] = Xen_real_to_C_double(rb_yield(C_int_to_Xen_integer(i)));
1384     }
1385     return xen_make_vct(size, buffer);
1386   }
1387   return(xen_make_vct(size, (mus_float_t *)calloc(size, sizeof(mus_float_t))));
1388 }
1389 
1390 
g_vct_map(Xen obj)1391 static Xen g_vct_map(Xen obj)
1392 {
1393   if (rb_block_given_p())
1394     {
1395       mus_long_t i;
1396       vct *v;
1397       mus_float_t *d;
1398 
1399       v = Xen_to_vct(obj);
1400       d = mus_vct_data(v);
1401       mus_float_t *buffer = (mus_float_t *)calloc(mus_vct_length(v), sizeof(mus_float_t));
1402 
1403       for (i = 0; i < mus_vct_length(v); i++)
1404 	buffer[i] = Xen_real_to_C_double(rb_yield(C_double_to_Xen_real(d[i])));
1405       return xen_make_vct(mus_vct_length(v), buffer);
1406     }
1407   return obj;
1408 }
1409 
1410 
g_vct_map_store(Xen obj)1411 static Xen g_vct_map_store(Xen obj)
1412 {
1413   if (rb_block_given_p())
1414     {
1415       mus_long_t i;
1416       vct *v;
1417       mus_float_t *d;
1418 
1419       v = Xen_to_vct(obj);
1420       d = mus_vct_data(v);
1421 
1422       for (i = 0; i < mus_vct_length(v); i++)
1423 	d[i] = Xen_real_to_C_double(rb_yield(C_double_to_Xen_real(d[i])));
1424     }
1425   return obj;
1426 }
1427 
1428 
1429 /* v1.add!(v2[,offset=0]) destructive */
1430 
rb_vct_add(int argc,Xen * argv,Xen obj1)1431 static Xen rb_vct_add(int argc, Xen *argv, Xen obj1)
1432 {
1433   Xen obj2, offs;
1434   rb_scan_args(argc, argv, "11", &obj2, &offs);
1435   return g_vct_add(obj1, obj2, (argc == 2) ? offs : Xen_undefined);
1436 }
1437 
1438 
1439 /* v1.add(v2[,offset=0]) returns new vct */
1440 
rb_vct_add_cp(int argc,Xen * argv,Xen obj1)1441 static Xen rb_vct_add_cp(int argc, Xen *argv, Xen obj1)
1442 {
1443   Xen obj2, offs;
1444   rb_scan_args(argc, argv, "11", &obj2, &offs);
1445   return g_vct_add(g_vct_copy(obj1), obj2, (argc == 2) ? offs : Xen_undefined);
1446 }
1447 
1448 
1449 /* v1.subtract(v2) returns new vct */
1450 
rb_vct_subtract_cp(Xen obj1,Xen obj2)1451 static Xen rb_vct_subtract_cp(Xen obj1, Xen obj2)
1452 {
1453   return g_vct_subtract(g_vct_copy(obj1), obj2);
1454 }
1455 
1456 
rb_vct_offset_cp(Xen obj,Xen scl)1457 static Xen rb_vct_offset_cp(Xen obj, Xen scl)
1458 {
1459   return g_vct_offset(g_vct_copy(obj), scl);
1460 }
1461 
1462 
rb_vct_multiply_cp(Xen obj1,Xen obj2)1463 static Xen rb_vct_multiply_cp(Xen obj1, Xen obj2)
1464 {
1465   return g_vct_multiply(g_vct_copy(obj1), obj2);
1466 }
1467 
1468 
rb_vct_scale_cp(Xen obj,Xen scl)1469 static Xen rb_vct_scale_cp(Xen obj, Xen scl)
1470 {
1471   return g_vct_scale(g_vct_copy(obj), scl);
1472 }
1473 
1474 
1475 /* destructive */
1476 
rb_vct_move(int argc,Xen * argv,Xen obj)1477 static Xen rb_vct_move(int argc, Xen *argv, Xen obj)
1478 {
1479   Xen vnew, old, backward;
1480   rb_scan_args(argc, argv, "21", &vnew, &old, &backward);
1481   return g_vct_move(obj, vnew, old, (argc == 3) ? backward : Xen_undefined);
1482 }
1483 
1484 
1485 /* returns new vct */
1486 
rb_vct_move_cp(int argc,Xen * argv,Xen obj)1487 static Xen rb_vct_move_cp(int argc, Xen *argv, Xen obj)
1488 {
1489   Xen vnew, old, backward;
1490   rb_scan_args(argc, argv, "21", &vnew, &old, &backward);
1491   return g_vct_move(g_vct_copy(obj), vnew, old, (argc == 3) ? backward : Xen_undefined);
1492 }
1493 
1494 
rb_vct_subseq(int argc,Xen * argv,Xen obj)1495 static Xen rb_vct_subseq(int argc, Xen *argv, Xen obj)
1496 {
1497   Xen start, end, vnew;
1498   rb_scan_args(argc, argv, "12", &start, &end, &vnew);
1499     return g_vct_subseq(obj, start, (argc > 1) ? end :Xen_undefined, (argc > 2) ? vnew : Xen_undefined);
1500 }
1501 
1502 
1503 /* destructive */
1504 
rb_vct_reverse(int argc,Xen * argv,Xen obj)1505 static Xen rb_vct_reverse(int argc, Xen *argv, Xen obj)
1506 {
1507   Xen len;
1508   rb_scan_args(argc, argv, "01", &len);
1509   return g_vct_reverse(obj, (argc > 0) ? len : Xen_undefined);
1510 }
1511 
1512 
1513 /* returns new vct */
1514 
rb_vct_reverse_cp(int argc,Xen * argv,Xen obj)1515 static Xen rb_vct_reverse_cp(int argc, Xen *argv, Xen obj)
1516 {
1517   Xen len;
1518   rb_scan_args(argc, argv, "01", &len);
1519   return g_vct_reverse(g_vct_copy(obj), (argc > 0) ? len : Xen_undefined);
1520 }
1521 
1522 
rb_vct_first(Xen obj)1523 static Xen rb_vct_first(Xen obj)
1524 {
1525   return g_vct_ref(obj, C_int_to_Xen_integer(0));
1526 }
1527 
1528 
rb_set_vct_first(Xen obj,Xen val)1529 static Xen rb_set_vct_first(Xen obj, Xen val)
1530 {
1531   return g_vct_set(obj, C_int_to_Xen_integer(0), val);
1532 }
1533 
1534 
rb_vct_last(Xen obj)1535 static Xen rb_vct_last(Xen obj)
1536 {
1537   return g_vct_ref(obj, C_int_to_Xen_integer(mus_vct_length(Xen_to_vct(obj)) - 1));
1538 }
1539 
1540 
rb_set_vct_last(Xen obj,Xen val)1541 static Xen rb_set_vct_last(Xen obj, Xen val)
1542 {
1543   return g_vct_set(obj, C_int_to_Xen_integer(mus_vct_length(Xen_to_vct(obj)) - 1), val);
1544 }
1545 #endif
1546 
1547 
1548 #if HAVE_FORTH
ficl_values_to_vct(ficlVm * vm)1549 static void ficl_values_to_vct(ficlVm *vm)
1550 {
1551 #define h_values_to_vct "( len-floats len -- vct )  \
1552 Returns a new vct of length LEN with len items found on stack.\n\
1553 0.5 0.3 0.1  3  >vct  .g => #<vct[len=3]: 0.500 0.300 0.100>"
1554   long size;
1555   FICL_STACK_CHECK(vm->dataStack, 1, 0);
1556   size = ficlStackPopInteger(vm->dataStack);
1557   if (size > 0)
1558     {
1559       mus_float_t *data = (mus_float_t *)calloc(size, sizeof(mus_float_t));
1560       if (data)
1561 	{
1562 	  long i;
1563 	  FICL_STACK_CHECK(vm->dataStack, size, 1);
1564 	  for (i = size - 1; i >= 0; i--)
1565 	    data[i] = ficlStackPop2Float(vm->dataStack);
1566 	  ficlStackPushUnsigned(vm->dataStack, xen_make_vct(size, data));
1567 	}
1568       else fth_throw(FTH_SYSTEM_ERROR, "cannot create Vct");
1569     }
1570   else ficlStackPushUnsigned(vm->dataStack, fth_false());
1571 }
1572 
1573 
ficl_begin_vct(ficlVm * vm)1574 static void ficl_begin_vct(ficlVm *vm)
1575 {
1576 #define h_begin_vct "( -- )  \
1577 Creates a vct with contents between `vct(' and closing paren `)'.\n\
1578 vct( 0.5 0.3 0.1 ) .g => #<vct[len=3]: 0.500 0.300 0.100>"
1579   fth_begin_values_to_obj(vm, (char *)">vct", FTH_FALSE);
1580 }
1581 #endif
1582 
1583 
1584 #if (!HAVE_SCHEME)
Xen_wrap_2_optional_args(g_make_vct_w,g_make_vct)1585   Xen_wrap_2_optional_args(g_make_vct_w, g_make_vct)
1586   Xen_wrap_2_args(g_vct_fill_w, g_vct_fill)
1587   Xen_wrap_any_args(g_vct_w, g_vct)
1588   Xen_wrap_1_arg(g_vct_length_w, g_vct_length)
1589   Xen_wrap_2_optional_args(g_vct_reverse_w, g_vct_reverse)
1590   Xen_wrap_1_arg(g_vct_to_list_w, g_vct_to_list)
1591   Xen_wrap_1_arg(g_list_to_vct_w, xen_list_to_vct)
1592   Xen_wrap_1_arg(g_vector_to_vct_w, g_vector_to_vct)
1593   Xen_wrap_1_arg(g_vct_to_vector_w, g_vct_to_vector)
1594   Xen_wrap_1_arg(g_is_vct_w, g_is_vct)
1595   Xen_wrap_2_args(g_vct_ref_w, g_vct_ref)
1596   Xen_wrap_3_args(g_vct_set_w, g_vct_set)
1597 #endif
1598 Xen_wrap_1_arg(g_vct_copy_w, g_vct_copy)
1599 Xen_wrap_2_args(g_vct_multiply_w, g_vct_multiply)
1600 Xen_wrap_2_args(g_vct_scale_w, g_vct_scale)
1601 Xen_wrap_1_arg(g_vct_abs_w, g_vct_abs)
1602 Xen_wrap_3_optional_args(g_vct_add_w, g_vct_add)
1603 Xen_wrap_2_args(g_vct_subtract_w, g_vct_subtract)
1604 Xen_wrap_2_args(g_vct_offset_w, g_vct_offset)
1605 Xen_wrap_1_arg(g_vct_peak_w, g_vct_peak)
1606 Xen_wrap_3_args(g_vct_equal_w, g_vct_equal)
1607 Xen_wrap_1_arg(g_vct_peak_and_location_w, g_vct_peak_and_location)
1608 Xen_wrap_4_optional_args(g_vct_move_w, g_vct_move)
1609 Xen_wrap_4_optional_args(g_vct_subseq_w, g_vct_subseq)
1610 Xen_wrap_1_arg(g_vct_to_readable_string_w, g_vct_to_readable_string)
1611 Xen_wrap_2_args(g_vct_times_w, g_vct_times)
1612 Xen_wrap_2_args(g_vct_plus_w, g_vct_plus)
1613 Xen_wrap_1_arg(g_vct_max_w, g_vct_max)
1614 Xen_wrap_1_arg(g_vct_min_w, g_vct_min)
1615 #if HAVE_SCHEME
1616 Xen_wrap_4_args(g_vct_spatter_w, g_vct_spatter)
1617 Xen_wrap_7_args(g_vct_interpolate_w, g_vct_interpolate)
1618 #endif
1619 
1620 void mus_vct_init(void)
1621 {
1622 #if HAVE_SCHEME
1623   s7_pointer pl_ff, pl_rf, pl_fff, pl_fffi, pl_ffr, pl_pf, pl_bffr, pl_ftt, pl_ffiib, pl_ffiif, pl_sf, pl_rfvir, pl_rfiir;
1624 #else
1625   vct_tag = Xen_make_object_type("Vct", sizeof(vct));
1626 
1627   /* for ruby and forth, I think we can define Frame, SoundData, and Mixer to be Vct's with
1628    *   some handlers for the channel arg.  Then nothing in the *.rb|fs file has to change
1629    *   except all the deprecated names like "region-frames" -> framples.
1630    *
1631    *   Not sure how to do this -- is it "alias" in Ruby?
1632    */
1633 #endif
1634 
1635 #if HAVE_FORTH
1636   fth_set_object_inspect(vct_tag,   print_vct);
1637   fth_set_object_dump(vct_tag,      g_vct_to_readable_string);
1638   fth_set_object_to_array(vct_tag,  g_vct_to_vector);
1639   fth_set_object_copy(vct_tag,      g_vct_copy);
1640   fth_set_object_value_ref(vct_tag, g_vct_ref);
1641   fth_set_object_value_set(vct_tag, g_vct_set);
1642   fth_set_object_equal(vct_tag,     equalp_vct);
1643   fth_set_object_length(vct_tag,    g_vct_length);
1644   fth_set_object_free(vct_tag,      free_vct);
1645   fth_set_object_apply(vct_tag, Xen_procedure_cast g_vct_ref, 1, 0, 0);
1646   FTH_PRIM(FTH_FICL_DICT(), (char *)">vct",   ficl_values_to_vct, h_values_to_vct);
1647   FTH_PRIM(FTH_FICL_DICT(), (char *)"vct(",   ficl_begin_vct,     h_begin_vct);
1648   Xen_eval_C_string("start-prefixes : vct( vct( ; end-prefixes");
1649 #endif
1650 
1651 #if HAVE_RUBY
1652   rb_include_module(vct_tag, rb_mComparable);
1653   rb_include_module(vct_tag, rb_mEnumerable);
1654 
1655   rb_define_method(vct_tag, "to_s",     Xen_procedure_cast print_vct, 0);
1656   rb_define_method(vct_tag, "eql?",     Xen_procedure_cast equalp_vct, 1);
1657   rb_define_method(vct_tag, "[]",       Xen_procedure_cast g_vct_ref, 1);
1658   rb_define_method(vct_tag, "[]=",      Xen_procedure_cast g_vct_set, 2);
1659   rb_define_method(vct_tag, "length",   Xen_procedure_cast g_vct_length, 0);
1660   rb_define_method(vct_tag, "each",     Xen_procedure_cast g_vct_each, 0);
1661   rb_define_method(vct_tag, "<=>",      Xen_procedure_cast g_vct_compare, 1);
1662   rb_define_singleton_method(vct_tag, "new", Xen_procedure_cast g_rb_make_vct, -1);
1663   rb_define_method(vct_tag, "map",      Xen_procedure_cast g_vct_map, 0);
1664   rb_define_method(vct_tag, "map!",     Xen_procedure_cast g_vct_map_store, 0);
1665   rb_define_method(vct_tag, "to_a",     Xen_procedure_cast g_vct_to_vector, 0);
1666   rb_define_method(rb_cArray, "to_vct", Xen_procedure_cast g_vector_to_vct, 0);
1667 
1668   rb_define_method(vct_tag, "to_str",    Xen_procedure_cast g_vct_to_readable_string, 0);
1669   rb_define_method(vct_tag, "dup",       Xen_procedure_cast g_vct_copy, 0);
1670   rb_define_method(vct_tag, "peak",      Xen_procedure_cast g_vct_peak, 0);
1671   rb_define_method(vct_tag, "add",       Xen_procedure_cast rb_vct_add_cp, -1);
1672   rb_define_method(vct_tag, "add!",      Xen_procedure_cast rb_vct_add, -1);
1673   rb_define_method(vct_tag, "subtract",  Xen_procedure_cast rb_vct_subtract_cp, 1);
1674   rb_define_method(vct_tag, "subtract!", Xen_procedure_cast g_vct_subtract, 1);
1675   rb_define_method(vct_tag, "offset",    Xen_procedure_cast rb_vct_offset_cp, 1);
1676   rb_define_method(vct_tag, "offset!",   Xen_procedure_cast g_vct_offset, 1);
1677   rb_define_method(vct_tag, "multiply",  Xen_procedure_cast rb_vct_multiply_cp, 1);
1678   rb_define_method(vct_tag, "multiply!", Xen_procedure_cast g_vct_multiply, 1);
1679   rb_define_method(vct_tag, "scale",     Xen_procedure_cast rb_vct_scale_cp, 1);
1680   rb_define_method(vct_tag, "scale!",    Xen_procedure_cast g_vct_scale, 1);
1681   rb_define_method(vct_tag, "fill",      Xen_procedure_cast g_vct_fill, 1);
1682   rb_define_method(vct_tag, "move",      Xen_procedure_cast rb_vct_move_cp, -1);
1683   rb_define_method(vct_tag, "move!",     Xen_procedure_cast rb_vct_move, -1);
1684   rb_define_method(vct_tag, "subseq",    Xen_procedure_cast rb_vct_subseq, -1);
1685   rb_define_method(vct_tag, "reverse",   Xen_procedure_cast rb_vct_reverse_cp, -1);
1686   rb_define_method(vct_tag, "reverse!",  Xen_procedure_cast rb_vct_reverse, -1);
1687   rb_define_method(vct_tag, "first",     Xen_procedure_cast rb_vct_first, 0);
1688   rb_define_method(vct_tag, "first=",    Xen_procedure_cast rb_set_vct_first, 1);
1689   rb_define_method(vct_tag, "last",      Xen_procedure_cast rb_vct_last, 0);
1690   rb_define_method(vct_tag, "last=",     Xen_procedure_cast rb_set_vct_last, 1);
1691 #endif
1692 
1693 #if HAVE_SCHEME
1694   {
1695     s7_pointer s, i, p, b, r, f, t;
1696     s = s7_make_symbol(s7, "string?");
1697     i = s7_make_symbol(s7, "integer?");
1698     p = s7_make_symbol(s7, "pair?");
1699     r = s7_make_symbol(s7, "real?");
1700     b = s7_make_symbol(s7, "boolean?");
1701     f = s7_make_symbol(s7, "float-vector?");
1702     t = s7_t(s7);
1703     pl_rf = s7_make_signature(s7, 2, r, f);
1704     pl_ff = s7_make_signature(s7, 2, f, f);
1705     pl_sf = s7_make_signature(s7, 2, s, f);
1706     pl_pf = s7_make_signature(s7, 2, p, f);
1707     pl_ftt = s7_make_signature(s7, 3, f, t, t);
1708     pl_fff = s7_make_signature(s7, 3, f, f, f);
1709     pl_ffr = s7_make_signature(s7, 3, f, f, r);
1710     pl_bffr = s7_make_signature(s7, 4, b, f, f, r);
1711     pl_fffi = s7_make_signature(s7, 4, f, f, f, i);
1712     pl_ffiib = s7_make_signature(s7, 5, f, f, i, i, b);
1713     pl_ffiif = s7_make_signature(s7, 5, f, f, i, i, f);
1714     pl_rfvir = s7_make_signature(s7, 5, r, f, s7_make_symbol(s7, "int-vector?"), i, r);
1715     pl_rfiir = s7_make_circular_signature(s7, 4, 5, r, f, i, i, r);
1716   }
1717 #endif
1718 
1719   Xen_define_typed_procedure(S_vct_multiply,      g_vct_multiply_w,  2, 0, 0, H_vct_multiplyB,		pl_fff);
1720   Xen_define_typed_procedure(S_vct_add,           g_vct_add_w,       2, 1, 0, H_vct_addB,		pl_fffi);
1721   Xen_define_typed_procedure(S_vct_subtract,      g_vct_subtract_w,  2, 0, 0, H_vct_subtractB,		pl_fff);
1722   Xen_define_typed_procedure(S_vct_offset,        g_vct_offset_w,    2, 0, 0, H_vct_offsetB,		pl_ffr);
1723   Xen_define_typed_procedure(S_vct_peak,          g_vct_peak_w,      1, 0, 0, H_vct_peak,		pl_rf);
1724   Xen_define_typed_procedure(S_vct_peak_and_location, g_vct_peak_and_location_w, 1, 0, 0, H_vct_peak_and_location, pl_pf);
1725   Xen_define_typed_procedure(S_vct_move,          g_vct_move_w,      3, 1, 0, H_vct_moveB,		pl_ffiib);
1726   Xen_define_typed_procedure(S_vct_subseq,        g_vct_subseq_w,    2, 2, 0, H_vct_subseq,		pl_ffiif);
1727   Xen_define_typed_procedure(S_vct_copy,          g_vct_copy_w,      1, 0, 0, H_vct_copy,		pl_ff);
1728 
1729 #if HAVE_FORTH
1730   Xen_define_dilambda(S_vct_ref,                 g_vct_ref_w, H_vct_ref, "set-" S_vct_ref, g_vct_set_w,  2, 0, 3, 0);
1731 #else
1732 #if (!HAVE_SCHEME)
1733   Xen_define_procedure(S_vct_ref,                g_vct_ref_w,       2, 0, 0, H_vct_ref);
1734 #endif
1735 #endif
1736 
1737   Xen_define_typed_procedure(S_vct_to_string,     g_vct_to_readable_string_w, 1, 0, 0, H_vct_to_string, pl_sf);
1738   Xen_define_typed_procedure(S_vct_times,         g_vct_times_w,     2, 0, 0, H_vct_times,		pl_ftt);
1739   Xen_define_typed_procedure(S_vct_plus,          g_vct_plus_w,      2, 0, 0, H_vct_plus,		pl_ftt);
1740   Xen_define_typed_procedure(S_vct_max,           g_vct_max_w,       1, 0, 0, H_vct_max,		pl_rf);
1741   Xen_define_typed_procedure(S_vct_min,           g_vct_min_w,       1, 0, 0, H_vct_min,		pl_rf);
1742   Xen_define_typed_procedure(S_vct_scale,         g_vct_scale_w,     2, 0, 0, H_vct_scaleB,		pl_ftt);
1743   Xen_define_typed_procedure(S_vct_abs,           g_vct_abs_w,       1, 0, 0, H_vct_absB,		pl_ff);
1744   Xen_define_typed_procedure(S_vct_equal,         g_vct_equal_w,     3, 0, 0, H_vct_equal,		pl_bffr);
1745 
1746 #if (!HAVE_SCHEME)
1747   Xen_define_procedure(S_vct_set,           g_vct_set_w,       3, 0, 0, H_vct_setB);
1748   Xen_define_procedure(S_is_vct,            g_is_vct_w,        1, 0, 0, H_is_vct);
1749   Xen_define_procedure(S_vct_fill,          g_vct_fill_w,      2, 0, 0, H_vct_fillB);
1750   Xen_define_procedure(S_vct,               g_vct_w,           0, 0, 1, H_vct);
1751   Xen_define_procedure(S_vct_length,        g_vct_length_w,    1, 0, 0, H_vct_length);
1752   Xen_define_procedure(S_vct_reverse,       g_vct_reverse_w,   1, 1, 0, H_vct_reverse);
1753   Xen_define_procedure(S_vct_to_list,       g_vct_to_list_w,   1, 0, 0, H_vct_to_list);
1754   Xen_define_procedure(S_list_to_vct,       g_list_to_vct_w,   1, 0, 0, H_list_to_vct);
1755   Xen_define_procedure(S_vector_to_vct,     g_vector_to_vct_w, 1, 0, 0, H_vector_to_vct);
1756   Xen_define_procedure(S_vct_to_vector,     g_vct_to_vector_w, 1, 0, 0, H_vct_to_vector);
1757   Xen_define_procedure(S_make_vct,          g_make_vct_w,      1, 1, 0, H_make_vct);
1758 #else
1759   Xen_define_typed_procedure(S_vct_spatter,     g_vct_spatter_w,     4, 0, 0, H_vct_spatter,           pl_rfvir);
1760   Xen_define_typed_procedure(S_vct_interpolate, g_vct_interpolate_w, 7, 0, 0, H_vct_interpolate,       pl_rfiir);
1761 
1762   s7_set_d_p_function(s7, s7_name_to_value(s7, S_vct_min), float_vector_min_d_p);
1763   s7_set_d_p_function(s7, s7_name_to_value(s7, S_vct_max), float_vector_max_d_p);
1764 #endif
1765 }
1766