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