您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

1928 行
56KB

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