vecop.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. /**************************************************************************
  2. **
  3. ** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved.
  4. **
  5. ** Meschach Library
  6. **
  7. ** This Meschach Library is provided "as is" without any express
  8. ** or implied warranty of any kind with respect to this software.
  9. ** In particular the authors shall not be liable for any direct,
  10. ** indirect, special, incidental or consequential damages arising
  11. ** in any way from use of the software.
  12. **
  13. ** Everyone is granted permission to copy, modify and redistribute this
  14. ** Meschach Library, provided:
  15. ** 1. All copies contain this copyright notice.
  16. ** 2. All modified copies shall carry a notice stating who
  17. ** made the last modification and the date of such modification.
  18. ** 3. No charge is made for this software or works derived from it.
  19. ** This clause shall not be construed as constraining other software
  20. ** distributed on the same medium as this software, nor is a
  21. ** distribution fee considered a charge.
  22. **
  23. ***************************************************************************/
  24. /* vecop.c 1.3 8/18/87 */
  25. #include <stdio.h>
  26. #include "matrix.h"
  27. static char rcsid[] = "$Id: vecop.c,v 1.5 1996/08/20 18:18:10 stewart Exp $";
  28. /* _in_prod -- inner product of two vectors from i0 downwards
  29. -- that is, returns a(i0:dim)^T.b(i0:dim) */
  30. #ifndef ANSI_C
  31. double _in_prod(a,b,i0)
  32. VEC *a,*b;
  33. unsigned int i0;
  34. #else
  35. double _in_prod(const VEC *a, const VEC *b, unsigned int i0)
  36. #endif
  37. {
  38. unsigned int limit;
  39. /* Real *a_v, *b_v; */
  40. /* register Real sum; */
  41. if ( a==(VEC *)NULL || b==(VEC *)NULL )
  42. error(E_NULL,"_in_prod");
  43. limit = min(a->dim,b->dim);
  44. if ( i0 > limit )
  45. error(E_BOUNDS,"_in_prod");
  46. return __ip__(&(a->ve[i0]),&(b->ve[i0]),(int)(limit-i0));
  47. /*****************************************
  48. a_v = &(a->ve[i0]); b_v = &(b->ve[i0]);
  49. for ( i=i0; i<limit; i++ )
  50. sum += a_v[i]*b_v[i];
  51. sum += (*a_v++)*(*b_v++);
  52. return (double)sum;
  53. ******************************************/
  54. }
  55. /* sv_mlt -- scalar-vector multiply -- out <- scalar*vector
  56. -- may be in-situ */
  57. #ifndef ANSI_C
  58. VEC *sv_mlt(scalar,vector,out)
  59. double scalar;
  60. VEC *vector,*out;
  61. #else
  62. VEC *sv_mlt(double scalar, const VEC *vector, VEC *out)
  63. #endif
  64. {
  65. /* unsigned int dim, i; */
  66. /* Real *out_ve, *vec_ve; */
  67. if ( vector==(VEC *)NULL )
  68. error(E_NULL,"sv_mlt");
  69. if ( out==(VEC *)NULL || out->dim != vector->dim )
  70. out = v_resize(out,vector->dim);
  71. if ( scalar == 0.0 )
  72. return v_zero(out);
  73. if ( scalar == 1.0 )
  74. return v_copy(vector,out);
  75. __smlt__(vector->ve,(double)scalar,out->ve,(int)(vector->dim));
  76. /**************************************************
  77. dim = vector->dim;
  78. out_ve = out->ve; vec_ve = vector->ve;
  79. for ( i=0; i<dim; i++ )
  80. out->ve[i] = scalar*vector->ve[i];
  81. (*out_ve++) = scalar*(*vec_ve++);
  82. **************************************************/
  83. return (out);
  84. }
  85. /* v_add -- vector addition -- out <- v1+v2 -- may be in-situ */
  86. #ifndef ANSI_C
  87. VEC *v_add(vec1,vec2,out)
  88. VEC *vec1,*vec2,*out;
  89. #else
  90. VEC *v_add(const VEC *vec1, const VEC *vec2, VEC *out)
  91. #endif
  92. {
  93. unsigned int dim;
  94. /* Real *out_ve, *vec1_ve, *vec2_ve; */
  95. if ( vec1==(VEC *)NULL || vec2==(VEC *)NULL )
  96. error(E_NULL,"v_add");
  97. if ( vec1->dim != vec2->dim )
  98. error(E_SIZES,"v_add");
  99. if ( out==(VEC *)NULL || out->dim != vec1->dim )
  100. out = v_resize(out,vec1->dim);
  101. dim = vec1->dim;
  102. __add__(vec1->ve,vec2->ve,out->ve,(int)dim);
  103. /************************************************************
  104. out_ve = out->ve; vec1_ve = vec1->ve; vec2_ve = vec2->ve;
  105. for ( i=0; i<dim; i++ )
  106. out->ve[i] = vec1->ve[i]+vec2->ve[i];
  107. (*out_ve++) = (*vec1_ve++) + (*vec2_ve++);
  108. ************************************************************/
  109. return (out);
  110. }
  111. /* v_mltadd -- scalar/vector multiplication and addition
  112. -- out = v1 + scale.v2 */
  113. #ifndef ANSI_C
  114. VEC *v_mltadd(v1,v2,scale,out)
  115. VEC *v1,*v2,*out;
  116. double scale;
  117. #else
  118. VEC *v_mltadd(const VEC *v1, const VEC *v2, double scale, VEC *out)
  119. #endif
  120. {
  121. /* register unsigned int dim, i; */
  122. /* Real *out_ve, *v1_ve, *v2_ve; */
  123. if ( v1==(VEC *)NULL || v2==(VEC *)NULL )
  124. error(E_NULL,"v_mltadd");
  125. if ( v1->dim != v2->dim )
  126. error(E_SIZES,"v_mltadd");
  127. if ( scale == 0.0 )
  128. return v_copy(v1,out);
  129. if ( scale == 1.0 )
  130. return v_add(v1,v2,out);
  131. if ( v2 != out )
  132. {
  133. tracecatch(out = v_copy(v1,out),"v_mltadd");
  134. /* dim = v1->dim; */
  135. __mltadd__(out->ve,v2->ve,scale,(int)(v1->dim));
  136. }
  137. else
  138. {
  139. tracecatch(out = sv_mlt(scale,v2,out),"v_mltadd");
  140. out = v_add(v1,out,out);
  141. }
  142. /************************************************************
  143. out_ve = out->ve; v1_ve = v1->ve; v2_ve = v2->ve;
  144. for ( i=0; i < dim ; i++ )
  145. out->ve[i] = v1->ve[i] + scale*v2->ve[i];
  146. (*out_ve++) = (*v1_ve++) + scale*(*v2_ve++);
  147. ************************************************************/
  148. return (out);
  149. }
  150. /* v_sub -- vector subtraction -- may be in-situ */
  151. #ifndef ANSI_C
  152. VEC *v_sub(vec1,vec2,out)
  153. VEC *vec1,*vec2,*out;
  154. #else
  155. VEC *v_sub(const VEC *vec1, const VEC *vec2, VEC *out)
  156. #endif
  157. {
  158. /* unsigned int i, dim; */
  159. /* Real *out_ve, *vec1_ve, *vec2_ve; */
  160. if ( vec1==(VEC *)NULL || vec2==(VEC *)NULL )
  161. error(E_NULL,"v_sub");
  162. if ( vec1->dim != vec2->dim )
  163. error(E_SIZES,"v_sub");
  164. if ( out==(VEC *)NULL || out->dim != vec1->dim )
  165. out = v_resize(out,vec1->dim);
  166. __sub__(vec1->ve,vec2->ve,out->ve,(int)(vec1->dim));
  167. /************************************************************
  168. dim = vec1->dim;
  169. out_ve = out->ve; vec1_ve = vec1->ve; vec2_ve = vec2->ve;
  170. for ( i=0; i<dim; i++ )
  171. out->ve[i] = vec1->ve[i]-vec2->ve[i];
  172. (*out_ve++) = (*vec1_ve++) - (*vec2_ve++);
  173. ************************************************************/
  174. return (out);
  175. }
  176. /* v_map -- maps function f over components of x: out[i] = f(x[i])
  177. -- v_map sets out[i] = f(params,x[i]) */
  178. #ifndef ANSI_C
  179. VEC *v_map(f,x,out)
  180. double (*f)();
  181. VEC *x, *out;
  182. #else
  183. #ifdef PROTOTYPES_IN_STRUCT
  184. VEC *v_map(double (*f)(double), const VEC *x, VEC *out)
  185. #else
  186. VEC *v_map(double (*f)(), const VEC *x, VEC *out)
  187. #endif
  188. #endif
  189. {
  190. Real *x_ve, *out_ve;
  191. int i, dim;
  192. if ( ! x || ! f )
  193. error(E_NULL,"v_map");
  194. if ( ! out || out->dim != x->dim )
  195. out = v_resize(out,x->dim);
  196. dim = x->dim; x_ve = x->ve; out_ve = out->ve;
  197. for ( i = 0; i < dim; i++ )
  198. *out_ve++ = (*f)(*x_ve++);
  199. return out;
  200. }
  201. /* _v_map -- sets out[i] <- f(params, x[i]), i = 0, 1, .., dim-1 */
  202. #ifndef ANSI_C
  203. VEC *_v_map(f,params,x,out)
  204. double (*f)();
  205. void *params;
  206. VEC *x, *out;
  207. #else
  208. #ifdef PROTOTYPES_IN_STRUCT
  209. VEC *_v_map(double (*f)(void *,double), void *params, const VEC *x, VEC *out)
  210. #else
  211. VEC *_v_map(double (*f)(), void *params, const VEC *x, VEC *out)
  212. #endif
  213. #endif
  214. {
  215. Real *x_ve, *out_ve;
  216. int i, dim;
  217. if ( ! x || ! f )
  218. error(E_NULL,"_v_map");
  219. if ( ! out || out->dim != x->dim )
  220. out = v_resize(out,x->dim);
  221. dim = x->dim; x_ve = x->ve; out_ve = out->ve;
  222. for ( i = 0; i < dim; i++ )
  223. *out_ve++ = (*f)(params,*x_ve++);
  224. return out;
  225. }
  226. /* v_lincomb -- returns sum_i a[i].v[i], a[i] real, v[i] vectors */
  227. #ifndef ANSI_C
  228. VEC *v_lincomb(n,v,a,out)
  229. int n; /* number of a's and v's */
  230. Real a[];
  231. VEC *v[], *out;
  232. #else
  233. VEC *v_lincomb(int n, const VEC *v[], const Real a[], VEC *out)
  234. #endif
  235. {
  236. int i;
  237. if ( ! a || ! v )
  238. error(E_NULL,"v_lincomb");
  239. if ( n <= 0 )
  240. return VNULL;
  241. for ( i = 1; i < n; i++ )
  242. if ( out == v[i] )
  243. error(E_INSITU,"v_lincomb");
  244. out = sv_mlt(a[0],v[0],out);
  245. for ( i = 1; i < n; i++ )
  246. {
  247. if ( ! v[i] )
  248. error(E_NULL,"v_lincomb");
  249. if ( v[i]->dim != out->dim )
  250. error(E_SIZES,"v_lincomb");
  251. out = v_mltadd(out,v[i],a[i],out);
  252. }
  253. return out;
  254. }
  255. #ifdef ANSI_C
  256. /* v_linlist -- linear combinations taken from a list of arguments;
  257. calling:
  258. v_linlist(out,v1,a1,v2,a2,...,vn,an,NULL);
  259. where vi are vectors (VEC *) and ai are numbers (double)
  260. */
  261. VEC *v_linlist(VEC *out,VEC *v1,double a1,...)
  262. {
  263. va_list ap;
  264. VEC *par;
  265. double a_par;
  266. if ( ! v1 )
  267. return VNULL;
  268. va_start(ap, a1);
  269. out = sv_mlt(a1,v1,out);
  270. while (par = va_arg(ap,VEC *)) { /* NULL ends the list*/
  271. a_par = va_arg(ap,double);
  272. if (a_par == 0.0) continue;
  273. if ( out == par )
  274. error(E_INSITU,"v_linlist");
  275. if ( out->dim != par->dim )
  276. error(E_SIZES,"v_linlist");
  277. if (a_par == 1.0)
  278. out = v_add(out,par,out);
  279. else if (a_par == -1.0)
  280. out = v_sub(out,par,out);
  281. else
  282. out = v_mltadd(out,par,a_par,out);
  283. }
  284. va_end(ap);
  285. return out;
  286. }
  287. #elif VARARGS
  288. /* v_linlist -- linear combinations taken from a list of arguments;
  289. calling:
  290. v_linlist(out,v1,a1,v2,a2,...,vn,an,NULL);
  291. where vi are vectors (VEC *) and ai are numbers (double)
  292. */
  293. VEC *v_linlist(va_alist) va_dcl
  294. {
  295. va_list ap;
  296. VEC *par, *out;
  297. double a_par;
  298. va_start(ap);
  299. out = va_arg(ap,VEC *);
  300. par = va_arg(ap,VEC *);
  301. if ( ! par ) {
  302. va_end(ap);
  303. return VNULL;
  304. }
  305. a_par = va_arg(ap,double);
  306. out = sv_mlt(a_par,par,out);
  307. while (par = va_arg(ap,VEC *)) { /* NULL ends the list*/
  308. a_par = va_arg(ap,double);
  309. if (a_par == 0.0) continue;
  310. if ( out == par )
  311. error(E_INSITU,"v_linlist");
  312. if ( out->dim != par->dim )
  313. error(E_SIZES,"v_linlist");
  314. if (a_par == 1.0)
  315. out = v_add(out,par,out);
  316. else if (a_par == -1.0)
  317. out = v_sub(out,par,out);
  318. else
  319. out = v_mltadd(out,par,a_par,out);
  320. }
  321. va_end(ap);
  322. return out;
  323. }
  324. #endif
  325. /* v_star -- computes componentwise (Hadamard) product of x1 and x2
  326. -- result out is returned */
  327. #ifndef ANSI_C
  328. VEC *v_star(x1, x2, out)
  329. VEC *x1, *x2, *out;
  330. #else
  331. VEC *v_star(const VEC *x1, const VEC *x2, VEC *out)
  332. #endif
  333. {
  334. int i;
  335. if ( ! x1 || ! x2 )
  336. error(E_NULL,"v_star");
  337. if ( x1->dim != x2->dim )
  338. error(E_SIZES,"v_star");
  339. out = v_resize(out,x1->dim);
  340. for ( i = 0; i < x1->dim; i++ )
  341. out->ve[i] = x1->ve[i] * x2->ve[i];
  342. return out;
  343. }
  344. /* v_slash -- computes componentwise ratio of x2 and x1
  345. -- out[i] = x2[i] / x1[i]
  346. -- if x1[i] == 0 for some i, then raise E_SING error
  347. -- result out is returned */
  348. #ifndef ANSI_C
  349. VEC *v_slash(x1, x2, out)
  350. VEC *x1, *x2, *out;
  351. #else
  352. VEC *v_slash(const VEC *x1, const VEC *x2, VEC *out)
  353. #endif
  354. {
  355. int i;
  356. Real tmp;
  357. if ( ! x1 || ! x2 )
  358. error(E_NULL,"v_slash");
  359. if ( x1->dim != x2->dim )
  360. error(E_SIZES,"v_slash");
  361. out = v_resize(out,x1->dim);
  362. for ( i = 0; i < x1->dim; i++ )
  363. {
  364. tmp = x1->ve[i];
  365. if ( tmp == 0.0 )
  366. error(E_SING,"v_slash");
  367. out->ve[i] = x2->ve[i] / tmp;
  368. }
  369. return out;
  370. }
  371. /* v_min -- computes minimum component of x, which is returned
  372. -- also sets min_idx to the index of this minimum */
  373. #ifndef ANSI_C
  374. double v_min(x, min_idx)
  375. VEC *x;
  376. int *min_idx;
  377. #else
  378. double v_min(const VEC *x, int *min_idx)
  379. #endif
  380. {
  381. int i, i_min;
  382. Real min_val, tmp;
  383. if ( ! x )
  384. error(E_NULL,"v_min");
  385. if ( x->dim <= 0 )
  386. error(E_SIZES,"v_min");
  387. i_min = 0;
  388. min_val = x->ve[0];
  389. for ( i = 1; i < x->dim; i++ )
  390. {
  391. tmp = x->ve[i];
  392. if ( tmp < min_val )
  393. {
  394. min_val = tmp;
  395. i_min = i;
  396. }
  397. }
  398. if ( min_idx != NULL )
  399. *min_idx = i_min;
  400. return min_val;
  401. }
  402. /* v_max -- computes maximum component of x, which is returned
  403. -- also sets max_idx to the index of this maximum */
  404. #ifndef ANSI_C
  405. double v_max(x, max_idx)
  406. VEC *x;
  407. int *max_idx;
  408. #else
  409. double v_max(const VEC *x, int *max_idx)
  410. #endif
  411. {
  412. int i, i_max;
  413. Real max_val, tmp;
  414. if ( ! x )
  415. error(E_NULL,"v_max");
  416. if ( x->dim <= 0 )
  417. error(E_SIZES,"v_max");
  418. i_max = 0;
  419. max_val = x->ve[0];
  420. for ( i = 1; i < x->dim; i++ )
  421. {
  422. tmp = x->ve[i];
  423. if ( tmp > max_val )
  424. {
  425. max_val = tmp;
  426. i_max = i;
  427. }
  428. }
  429. if ( max_idx != NULL )
  430. *max_idx = i_max;
  431. return max_val;
  432. }
  433. #define MAX_STACK 60
  434. /* v_sort -- sorts vector x, and generates permutation that gives the order
  435. of the components; x = [1.3, 3.7, 0.5] -> [0.5, 1.3, 3.7] and
  436. the permutation is order = [2, 0, 1].
  437. -- if order is NULL on entry then it is ignored
  438. -- the sorted vector x is returned */
  439. #ifndef ANSI_C
  440. VEC *v_sort(x, order)
  441. VEC *x;
  442. PERM *order;
  443. #else
  444. VEC *v_sort(VEC *x, PERM *order)
  445. #endif
  446. {
  447. Real *x_ve, tmp, v;
  448. /* int *order_pe; */
  449. int dim, i, j, l, r, tmp_i;
  450. int stack[MAX_STACK], sp;
  451. if ( ! x )
  452. error(E_NULL,"v_sort");
  453. if ( order != PNULL && order->size != x->dim )
  454. order = px_resize(order, x->dim);
  455. x_ve = x->ve;
  456. dim = x->dim;
  457. if ( order != PNULL )
  458. px_ident(order);
  459. if ( dim <= 1 )
  460. return x;
  461. /* using quicksort algorithm in Sedgewick,
  462. "Algorithms in C", Ch. 9, pp. 118--122 (1990) */
  463. sp = 0;
  464. l = 0; r = dim-1; v = x_ve[0];
  465. for ( ; ; )
  466. {
  467. while ( r > l )
  468. {
  469. /* "i = partition(x_ve,l,r);" */
  470. v = x_ve[r];
  471. i = l-1;
  472. j = r;
  473. for ( ; ; )
  474. {
  475. while ( x_ve[++i] < v )
  476. ;
  477. --j;
  478. while ( x_ve[j] > v && j != 0 )
  479. --j;
  480. if ( i >= j ) break;
  481. tmp = x_ve[i];
  482. x_ve[i] = x_ve[j];
  483. x_ve[j] = tmp;
  484. if ( order != PNULL )
  485. {
  486. tmp_i = order->pe[i];
  487. order->pe[i] = order->pe[j];
  488. order->pe[j] = tmp_i;
  489. }
  490. }
  491. tmp = x_ve[i];
  492. x_ve[i] = x_ve[r];
  493. x_ve[r] = tmp;
  494. if ( order != PNULL )
  495. {
  496. tmp_i = order->pe[i];
  497. order->pe[i] = order->pe[r];
  498. order->pe[r] = tmp_i;
  499. }
  500. if ( i-l > r-i )
  501. { stack[sp++] = l; stack[sp++] = i-1; l = i+1; }
  502. else
  503. { stack[sp++] = i+1; stack[sp++] = r; r = i-1; }
  504. }
  505. /* recursion elimination */
  506. if ( sp == 0 )
  507. break;
  508. r = stack[--sp];
  509. l = stack[--sp];
  510. }
  511. return x;
  512. }
  513. /* v_sum -- returns sum of entries of a vector */
  514. #ifndef ANSI_C
  515. double v_sum(x)
  516. VEC *x;
  517. #else
  518. double v_sum(const VEC *x)
  519. #endif
  520. {
  521. int i;
  522. Real sum;
  523. if ( ! x )
  524. error(E_NULL,"v_sum");
  525. sum = 0.0;
  526. for ( i = 0; i < x->dim; i++ )
  527. sum += x->ve[i];
  528. return sum;
  529. }
  530. /* v_conv -- computes convolution product of two vectors */
  531. #ifndef ANSI_C
  532. VEC *v_conv(x1, x2, out)
  533. VEC *x1, *x2, *out;
  534. #else
  535. VEC *v_conv(const VEC *x1, const VEC *x2, VEC *out)
  536. #endif
  537. {
  538. int i;
  539. if ( ! x1 || ! x2 )
  540. error(E_NULL,"v_conv");
  541. if ( x1 == out || x2 == out )
  542. error(E_INSITU,"v_conv");
  543. if ( x1->dim == 0 || x2->dim == 0 )
  544. return out = v_resize(out,0);
  545. out = v_resize(out,x1->dim + x2->dim - 1);
  546. v_zero(out);
  547. for ( i = 0; i < x1->dim; i++ )
  548. __mltadd__(&(out->ve[i]),x2->ve,x1->ve[i],x2->dim);
  549. return out;
  550. }
  551. /* v_pconv -- computes a periodic convolution product
  552. -- the period is the dimension of x2 */
  553. #ifndef ANSI_C
  554. VEC *v_pconv(x1, x2, out)
  555. VEC *x1, *x2, *out;
  556. #else
  557. VEC *v_pconv(const VEC *x1, const VEC *x2, VEC *out)
  558. #endif
  559. {
  560. int i;
  561. if ( ! x1 || ! x2 )
  562. error(E_NULL,"v_pconv");
  563. if ( x1 == out || x2 == out )
  564. error(E_INSITU,"v_pconv");
  565. out = v_resize(out,x2->dim);
  566. if ( x2->dim == 0 )
  567. return out;
  568. v_zero(out);
  569. for ( i = 0; i < x1->dim; i++ )
  570. {
  571. __mltadd__(&(out->ve[i]),x2->ve,x1->ve[i],x2->dim - i);
  572. if ( i > 0 )
  573. __mltadd__(out->ve,&(x2->ve[x2->dim - i]),x1->ve[i],i);
  574. }
  575. return out;
  576. }