iter0.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. /**************************************************************************
  2. **
  3. ** Copyright (C) 1993 David E. Stewart & 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. /* iter0.c 14/09/93 */
  25. /* ITERATIVE METHODS - service functions */
  26. /* functions for creating and releasing ITER structures;
  27. for memory information;
  28. for getting some values from an ITER variable;
  29. for changing values in an ITER variable;
  30. see also iter.c
  31. */
  32. #include <stdio.h>
  33. #include <math.h>
  34. #include "iter.h"
  35. static char rcsid[] = "$Id: iter0.c,v 1.3 1995/01/30 14:50:56 des Exp $";
  36. /* standard functions */
  37. /* standard information */
  38. #ifndef ANSI_C
  39. void iter_std_info(ip,nres,res,Bres)
  40. ITER *ip;
  41. double nres;
  42. VEC *res, *Bres;
  43. #else
  44. void iter_std_info(const ITER *ip, double nres, VEC *res, VEC *Bres)
  45. #endif
  46. {
  47. if (nres >= 0.0)
  48. #ifndef MEX
  49. printf(" %d. residual = %g\n",ip->steps,nres);
  50. #else
  51. mexPrintf(" %d. residual = %g\n",ip->steps,nres);
  52. #endif
  53. else
  54. #ifndef MEX
  55. printf(" %d. residual = %g (WARNING !!! should be >= 0) \n",
  56. ip->steps,nres);
  57. #else
  58. mexPrintf(" %d. residual = %g (WARNING !!! should be >= 0) \n",
  59. ip->steps,nres);
  60. #endif
  61. }
  62. /* standard stopping criterion */
  63. #ifndef ANSI_C
  64. int iter_std_stop_crit(ip, nres, res, Bres)
  65. ITER *ip;
  66. double nres;
  67. VEC *res, *Bres;
  68. #else
  69. int iter_std_stop_crit(const ITER *ip, double nres, VEC *res, VEC *Bres)
  70. #endif
  71. {
  72. /* standard stopping criterium */
  73. if (nres <= ip->init_res*ip->eps) return TRUE;
  74. return FALSE;
  75. }
  76. /* iter_get - create a new structure pointing to ITER */
  77. #ifndef ANSI_C
  78. ITER *iter_get(lenb, lenx)
  79. int lenb, lenx;
  80. #else
  81. ITER *iter_get(int lenb, int lenx)
  82. #endif
  83. {
  84. ITER *ip;
  85. if ((ip = NEW(ITER)) == (ITER *) NULL)
  86. error(E_MEM,"iter_get");
  87. else if (mem_info_is_on()) {
  88. mem_bytes(TYPE_ITER,0,sizeof(ITER));
  89. mem_numvar(TYPE_ITER,1);
  90. }
  91. /* default values */
  92. ip->shared_x = FALSE;
  93. ip->shared_b = FALSE;
  94. ip->k = 0;
  95. ip->limit = ITER_LIMIT_DEF;
  96. ip->eps = ITER_EPS_DEF;
  97. ip->steps = 0;
  98. if (lenb > 0) ip->b = v_get(lenb);
  99. else ip->b = (VEC *)NULL;
  100. if (lenx > 0) ip->x = v_get(lenx);
  101. else ip->x = (VEC *)NULL;
  102. ip->Ax = (Fun_Ax) NULL;
  103. ip->A_par = NULL;
  104. ip->ATx = (Fun_Ax) NULL;
  105. ip->AT_par = NULL;
  106. ip->Bx = (Fun_Ax) NULL;
  107. ip->B_par = NULL;
  108. ip->info = iter_std_info;
  109. ip->stop_crit = iter_std_stop_crit;
  110. ip->init_res = 0.0;
  111. return ip;
  112. }
  113. /* iter_free - release memory */
  114. #ifndef ANSI_C
  115. int iter_free(ip)
  116. ITER *ip;
  117. #else
  118. int iter_free(ITER *ip)
  119. #endif
  120. {
  121. if (ip == (ITER *)NULL) return -1;
  122. if (mem_info_is_on()) {
  123. mem_bytes(TYPE_ITER,sizeof(ITER),0);
  124. mem_numvar(TYPE_ITER,-1);
  125. }
  126. if ( !ip->shared_x && ip->x != NULL ) v_free(ip->x);
  127. if ( !ip->shared_b && ip->b != NULL ) v_free(ip->b);
  128. free((char *)ip);
  129. return 0;
  130. }
  131. #ifndef ANSI_C
  132. ITER *iter_resize(ip,new_lenb,new_lenx)
  133. ITER *ip;
  134. int new_lenb, new_lenx;
  135. #else
  136. ITER *iter_resize(ITER *ip, int new_lenb, int new_lenx)
  137. #endif
  138. {
  139. VEC *old;
  140. if ( ip == (ITER *) NULL)
  141. error(E_NULL,"iter_resize");
  142. old = ip->x;
  143. ip->x = v_resize(ip->x,new_lenx);
  144. if ( ip->shared_x && old != ip->x )
  145. warning(WARN_SHARED_VEC,"iter_resize");
  146. old = ip->b;
  147. ip->b = v_resize(ip->b,new_lenb);
  148. if ( ip->shared_b && old != ip->b )
  149. warning(WARN_SHARED_VEC,"iter_resize");
  150. return ip;
  151. }
  152. #ifndef MEX
  153. /* print out ip structure - for diagnostic purposes mainly */
  154. #ifndef ANSI_C
  155. void iter_dump(fp,ip)
  156. ITER *ip;
  157. FILE *fp;
  158. #else
  159. void iter_dump(FILE *fp, ITER *ip)
  160. #endif
  161. {
  162. if (ip == NULL) {
  163. fprintf(fp," ITER structure: NULL\n");
  164. return;
  165. }
  166. fprintf(fp,"\n ITER structure:\n");
  167. fprintf(fp," ip->shared_x = %s, ip->shared_b = %s\n",
  168. (ip->shared_x ? "TRUE" : "FALSE"),
  169. (ip->shared_b ? "TRUE" : "FALSE") );
  170. fprintf(fp," ip->k = %d, ip->limit = %d, ip->steps = %d, ip->eps = %g\n",
  171. ip->k,ip->limit,ip->steps,ip->eps);
  172. fprintf(fp," ip->x = 0x%p, ip->b = 0x%p\n",ip->x,ip->b);
  173. fprintf(fp," ip->Ax = 0x%p, ip->A_par = 0x%p\n",ip->Ax,ip->A_par);
  174. fprintf(fp," ip->ATx = 0x%p, ip->AT_par = 0x%p\n",ip->ATx,ip->AT_par);
  175. fprintf(fp," ip->Bx = 0x%p, ip->B_par = 0x%p\n",ip->Bx,ip->B_par);
  176. fprintf(fp," ip->info = 0x%p, ip->stop_crit = 0x%p, ip->init_res = %g\n",
  177. ip->info,ip->stop_crit,ip->init_res);
  178. fprintf(fp,"\n");
  179. }
  180. #endif
  181. /* copy the structure ip1 to ip2 preserving vectors x and b of ip2
  182. (vectors x and b in ip2 are the same before and after iter_copy2)
  183. if ip2 == NULL then a new structure is created with x and b being NULL
  184. and other members are taken from ip1
  185. */
  186. #ifndef ANSI_C
  187. ITER *iter_copy2(ip1,ip2)
  188. ITER *ip1, *ip2;
  189. #else
  190. ITER *iter_copy2(ITER *ip1, ITER *ip2)
  191. #endif
  192. {
  193. VEC *x, *b;
  194. int shx, shb;
  195. if (ip1 == (ITER *)NULL)
  196. error(E_NULL,"iter_copy2");
  197. if (ip2 == (ITER *)NULL) {
  198. if ((ip2 = NEW(ITER)) == (ITER *) NULL)
  199. error(E_MEM,"iter_copy2");
  200. else if (mem_info_is_on()) {
  201. mem_bytes(TYPE_ITER,0,sizeof(ITER));
  202. mem_numvar(TYPE_ITER,1);
  203. }
  204. ip2->x = ip2->b = NULL;
  205. ip2->shared_x = ip2->shared_x = FALSE;
  206. }
  207. x = ip2->x;
  208. b = ip2->b;
  209. shb = ip2->shared_b;
  210. shx = ip2->shared_x;
  211. MEM_COPY(ip1,ip2,sizeof(ITER));
  212. ip2->x = x;
  213. ip2->b = b;
  214. ip2->shared_x = shx;
  215. ip2->shared_b = shb;
  216. return ip2;
  217. }
  218. /* copy the structure ip1 to ip2 copying also the vectors x and b */
  219. #ifndef ANSI_C
  220. ITER *iter_copy(ip1,ip2)
  221. ITER *ip1, *ip2;
  222. #else
  223. ITER *iter_copy(const ITER *ip1, ITER *ip2)
  224. #endif
  225. {
  226. VEC *x, *b;
  227. if (ip1 == (ITER *)NULL)
  228. error(E_NULL,"iter_copy");
  229. if (ip2 == (ITER *)NULL) {
  230. if ((ip2 = NEW(ITER)) == (ITER *) NULL)
  231. error(E_MEM,"iter_copy2");
  232. else if (mem_info_is_on()) {
  233. mem_bytes(TYPE_ITER,0,sizeof(ITER));
  234. mem_numvar(TYPE_ITER,1);
  235. }
  236. }
  237. x = ip2->x;
  238. b = ip2->b;
  239. MEM_COPY(ip1,ip2,sizeof(ITER));
  240. if (ip1->x)
  241. ip2->x = v_copy(ip1->x,x);
  242. if (ip1->b)
  243. ip2->b = v_copy(ip1->b,b);
  244. ip2->shared_x = ip2->shared_b = FALSE;
  245. return ip2;
  246. }
  247. /*** functions to generate sparse matrices with random entries ***/
  248. /* iter_gen_sym -- generate symmetric positive definite
  249. n x n matrix,
  250. nrow - number of nonzero entries in a row
  251. */
  252. #ifndef ANSI_C
  253. SPMAT *iter_gen_sym(n,nrow)
  254. int n, nrow;
  255. #else
  256. SPMAT *iter_gen_sym(int n, int nrow)
  257. #endif
  258. {
  259. SPMAT *A;
  260. VEC *u;
  261. Real s1;
  262. int i, j, k, k_max;
  263. if (nrow <= 1) nrow = 2;
  264. /* nrow should be even */
  265. if ((nrow & 1)) nrow -= 1;
  266. A = sp_get(n,n,nrow);
  267. u = v_get(A->m);
  268. v_zero(u);
  269. for ( i = 0; i < A->m; i++ )
  270. {
  271. k_max = ((rand() >> 8) % (nrow/2));
  272. for ( k = 0; k <= k_max; k++ )
  273. {
  274. j = (rand() >> 8) % A->n;
  275. s1 = mrand();
  276. sp_set_val(A,i,j,s1);
  277. sp_set_val(A,j,i,s1);
  278. u->ve[i] += fabs(s1);
  279. u->ve[j] += fabs(s1);
  280. }
  281. }
  282. /* ensure that A is positive definite */
  283. for ( i = 0; i < A->m; i++ )
  284. sp_set_val(A,i,i,u->ve[i] + 1.0);
  285. V_FREE(u);
  286. return A;
  287. }
  288. /* iter_gen_nonsym -- generate non-symmetric m x n sparse matrix, m >= n
  289. nrow - number of entries in a row;
  290. diag - number which is put in diagonal entries and then permuted
  291. (if diag is zero then 1.0 is there)
  292. */
  293. #ifndef ANSI_C
  294. SPMAT *iter_gen_nonsym(m,n,nrow,diag)
  295. int m, n, nrow;
  296. double diag;
  297. #else
  298. SPMAT *iter_gen_nonsym(int m, int n, int nrow, double diag)
  299. #endif
  300. {
  301. SPMAT *A;
  302. PERM *px;
  303. int i, j, k, k_max;
  304. Real s1;
  305. if (nrow <= 1) nrow = 2;
  306. if (diag == 0.0) diag = 1.0;
  307. A = sp_get(m,n,nrow);
  308. px = px_get(n);
  309. for ( i = 0; i < A->m; i++ )
  310. {
  311. k_max = (rand() >> 8) % (nrow-1);
  312. for ( k = 0; k <= k_max; k++ )
  313. {
  314. j = (rand() >> 8) % A->n;
  315. s1 = mrand();
  316. sp_set_val(A,i,j,-s1);
  317. }
  318. }
  319. /* to make it likely that A is nonsingular, use pivot... */
  320. for ( i = 0; i < 2*A->n; i++ )
  321. {
  322. j = (rand() >> 8) % A->n;
  323. k = (rand() >> 8) % A->n;
  324. px_transp(px,j,k);
  325. }
  326. for ( i = 0; i < A->n; i++ )
  327. sp_set_val(A,i,px->pe[i],diag);
  328. PX_FREE(px);
  329. return A;
  330. }
  331. #if ( 0 )
  332. /* iter_gen_nonsym -- generate non-symmetric positive definite
  333. n x n sparse matrix;
  334. nrow - number of entries in a row
  335. */
  336. #ifndef ANSI_C
  337. SPMAT *iter_gen_nonsym_posdef(n,nrow)
  338. int n, nrow;
  339. #else
  340. SPMAT *iter_gen_nonsym(int m, int n, int nrow, double diag)
  341. #endif
  342. {
  343. SPMAT *A;
  344. PERM *px;
  345. VEC *u;
  346. int i, j, k, k_max;
  347. Real s1;
  348. if (nrow <= 1) nrow = 2;
  349. A = sp_get(n,n,nrow);
  350. px = px_get(n);
  351. u = v_get(A->m);
  352. v_zero(u);
  353. for ( i = 0; i < A->m; i++ )
  354. {
  355. k_max = (rand() >> 8) % (nrow-1);
  356. for ( k = 0; k <= k_max; k++ )
  357. {
  358. j = (rand() >> 8) % A->n;
  359. s1 = mrand();
  360. sp_set_val(A,i,j,-s1);
  361. u->ve[i] += fabs(s1);
  362. }
  363. }
  364. /* ensure that A is positive definite */
  365. for ( i = 0; i < A->m; i++ )
  366. sp_set_val(A,i,i,u->ve[i] + 1.0);
  367. PX_FREE(px);
  368. V_FREE(u);
  369. return A;
  370. }
  371. #endif