sparseio.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  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. /*
  25. This file has the routines for sparse matrix input/output
  26. It works in conjunction with sparse.c, sparse.h etc
  27. */
  28. #include <stdio.h>
  29. #include "sparse.h"
  30. static char rcsid[] = "$Id: sparseio.c,v 1.4 1994/01/13 05:34:25 des Exp $";
  31. /* local variables */
  32. static char line[MAXLINE];
  33. /* sp_foutput -- output sparse matrix A to file/stream fp */
  34. #ifndef ANSI_C
  35. void sp_foutput(fp,A)
  36. FILE *fp;
  37. SPMAT *A;
  38. #else
  39. void sp_foutput(FILE *fp, const SPMAT *A)
  40. #endif
  41. {
  42. int i, j_idx, m /* , n */;
  43. SPROW *rows;
  44. row_elt *elts;
  45. fprintf(fp,"SparseMatrix: ");
  46. if ( A == SMNULL )
  47. {
  48. fprintf(fp,"*** NULL ***\n");
  49. error(E_NULL,"sp_foutput"); return;
  50. }
  51. fprintf(fp,"%d by %d\n",A->m,A->n);
  52. m = A->m; /* n = A->n; */
  53. if ( ! (rows=A->row) )
  54. {
  55. fprintf(fp,"*** NULL rows ***\n");
  56. error(E_NULL,"sp_foutput"); return;
  57. }
  58. for ( i = 0; i < m; i++ )
  59. {
  60. fprintf(fp,"row %d: ",i);
  61. if ( ! (elts=rows[i].elt) )
  62. {
  63. fprintf(fp,"*** NULL element list ***\n");
  64. continue;
  65. }
  66. for ( j_idx = 0; j_idx < rows[i].len; j_idx++ )
  67. {
  68. fprintf(fp,"%d:%-20.15g ",elts[j_idx].col,
  69. elts[j_idx].val);
  70. if ( j_idx % 3 == 2 && j_idx != rows[i].len-1 )
  71. fprintf(fp,"\n ");
  72. }
  73. fprintf(fp,"\n");
  74. }
  75. fprintf(fp,"#\n"); /* to stop looking beyond for next entry */
  76. }
  77. /* sp_foutput2 -- print out sparse matrix **as a dense matrix**
  78. -- see output format used in matrix.h etc */
  79. /******************************************************************
  80. void sp_foutput2(fp,A)
  81. FILE *fp;
  82. SPMAT *A;
  83. {
  84. int cnt, i, j, j_idx;
  85. SPROW *r;
  86. row_elt *elt;
  87. if ( A == SMNULL )
  88. {
  89. fprintf(fp,"Matrix: *** NULL ***\n");
  90. return;
  91. }
  92. fprintf(fp,"Matrix: %d by %d\n",A->m,A->n);
  93. for ( i = 0; i < A->m; i++ )
  94. {
  95. fprintf(fp,"row %d:",i);
  96. r = &(A->row[i]);
  97. elt = r->elt;
  98. cnt = j = j_idx = 0;
  99. while ( j_idx < r->len || j < A->n )
  100. {
  101. if ( j_idx >= r->len )
  102. fprintf(fp,"%14.9g ",0.0);
  103. else if ( j < elt[j_idx].col )
  104. fprintf(fp,"%14.9g ",0.0);
  105. else
  106. fprintf(fp,"%14.9g ",elt[j_idx++].val);
  107. if ( cnt++ % 4 == 3 )
  108. fprintf(fp,"\n");
  109. j++;
  110. }
  111. fprintf(fp,"\n");
  112. }
  113. }
  114. ******************************************************************/
  115. /* sp_dump -- prints ALL relevant information about the sparse matrix A */
  116. #ifndef ANSI_C
  117. void sp_dump(fp,A)
  118. FILE *fp;
  119. SPMAT *A;
  120. #else
  121. void sp_dump(FILE *fp, const SPMAT *A)
  122. #endif
  123. {
  124. int i, j, j_idx;
  125. SPROW *rows;
  126. row_elt *elts;
  127. fprintf(fp,"SparseMatrix dump:\n");
  128. if ( ! A )
  129. { fprintf(fp,"*** NULL ***\n"); return; }
  130. fprintf(fp,"Matrix at 0x%lx\n",(long)A);
  131. fprintf(fp,"Dimensions: %d by %d\n",A->m,A->n);
  132. fprintf(fp,"MaxDimensions: %d by %d\n",A->max_m,A->max_n);
  133. fprintf(fp,"flag_col = %d, flag_diag = %d\n",A->flag_col,A->flag_diag);
  134. fprintf(fp,"start_row @ 0x%lx:\n",(long)(A->start_row));
  135. for ( j = 0; j < A->n; j++ )
  136. {
  137. fprintf(fp,"%d ",A->start_row[j]);
  138. if ( j % 10 == 9 )
  139. fprintf(fp,"\n");
  140. }
  141. fprintf(fp,"\n");
  142. fprintf(fp,"start_idx @ 0x%lx:\n",(long)(A->start_idx));
  143. for ( j = 0; j < A->n; j++ )
  144. {
  145. fprintf(fp,"%d ",A->start_idx[j]);
  146. if ( j % 10 == 9 )
  147. fprintf(fp,"\n");
  148. }
  149. fprintf(fp,"\n");
  150. fprintf(fp,"Rows @ 0x%lx:\n",(long)(A->row));
  151. if ( ! A->row )
  152. { fprintf(fp,"*** NULL row ***\n"); return; }
  153. rows = A->row;
  154. for ( i = 0; i < A->m; i++ )
  155. {
  156. fprintf(fp,"row %d: len = %d, maxlen = %d, diag idx = %d\n",
  157. i,rows[i].len,rows[i].maxlen,rows[i].diag);
  158. fprintf(fp,"element list @ 0x%lx\n",(long)(rows[i].elt));
  159. if ( ! rows[i].elt )
  160. {
  161. fprintf(fp,"*** NULL element list ***\n");
  162. continue;
  163. }
  164. elts = rows[i].elt;
  165. for ( j_idx = 0; j_idx < rows[i].len; j_idx++, elts++ )
  166. fprintf(fp,"Col: %d, Val: %g, nxt_row = %d, nxt_idx = %d\n",
  167. elts->col,elts->val,elts->nxt_row,elts->nxt_idx);
  168. fprintf(fp,"\n");
  169. }
  170. }
  171. #define MINSCRATCH 100
  172. /* sp_finput -- input sparse matrix from stream/file fp
  173. -- uses friendly input routine if fp is a tty
  174. -- uses format identical to output format otherwise */
  175. #ifndef ANSI_C
  176. SPMAT *sp_finput(fp)
  177. FILE *fp;
  178. #else
  179. SPMAT *sp_finput(FILE *fp)
  180. #endif
  181. {
  182. int i, len, ret_val;
  183. int col, curr_col, m, n, tmp, tty;
  184. Real val;
  185. SPMAT *A;
  186. SPROW *rows;
  187. static row_elt *scratch;
  188. static int scratch_len = 0;
  189. if ( ! scratch )
  190. {
  191. scratch = NEW_A(MINSCRATCH,row_elt);
  192. if ( scratch == NULL )
  193. error(E_MEM,"sp_finput");
  194. scratch_len = MINSCRATCH;
  195. }
  196. for ( i = 0; i < scratch_len; i++ )
  197. scratch[i].nxt_row = scratch[i].nxt_idx = -1;
  198. tty = isatty(fileno(fp));
  199. if ( tty )
  200. {
  201. fprintf(stderr,"SparseMatrix: ");
  202. do {
  203. fprintf(stderr,"input rows cols: ");
  204. if ( ! fgets(line,MAXLINE,fp) )
  205. error(E_INPUT,"sp_finput");
  206. } while ( sscanf(line,"%u %u",&m,&n) != 2 );
  207. A = sp_get(m,n,5);
  208. rows = A->row;
  209. for ( i = 0; i < m; i++ )
  210. {
  211. /* get a row... */
  212. fprintf(stderr,"Row %d:\n",i);
  213. fprintf(stderr,"Enter <col> <val> or 'e' to end row\n");
  214. curr_col = -1;
  215. len = 0;
  216. for ( ; ; ) /* forever do... */
  217. {
  218. /* if we need more scratch space, let's get it!
  219. -- using amortized doubling */
  220. if ( len >= scratch_len )
  221. {
  222. scratch = RENEW(scratch,2*scratch_len,row_elt);
  223. if ( ! scratch )
  224. error(E_MEM,"sp_finput");
  225. scratch_len = 2*scratch_len;
  226. }
  227. do { /* get an entry... */
  228. fprintf(stderr,"Entry %d: ",len);
  229. if ( ! fgets(line,MAXLINE,fp) )
  230. error(E_INPUT,"sp_finput");
  231. if ( *line == 'e' || *line == 'E' )
  232. break;
  233. #if REAL == DOUBLE
  234. } while ( sscanf(line,"%u %lf",&col,&val) != 2 ||
  235. #elif REAL == FLOAT
  236. } while ( sscanf(line,"%u %f",&col,&val) != 2 ||
  237. #endif
  238. col >= n || col <= curr_col );
  239. if ( *line == 'e' || *line == 'E' )
  240. break;
  241. scratch[len].col = col;
  242. scratch[len].val = val;
  243. curr_col = col;
  244. len++;
  245. }
  246. /* Note: len = # elements in row */
  247. if ( len > 5 )
  248. {
  249. if (mem_info_is_on()) {
  250. mem_bytes(TYPE_SPMAT,
  251. A->row[i].maxlen*sizeof(row_elt),
  252. len*sizeof(row_elt));
  253. }
  254. rows[i].elt = (row_elt *)realloc((char *)rows[i].elt,
  255. len*sizeof(row_elt));
  256. rows[i].maxlen = len;
  257. }
  258. MEM_COPY(scratch,rows[i].elt,len*sizeof(row_elt));
  259. rows[i].len = len;
  260. rows[i].diag = sprow_idx(&(rows[i]),i);
  261. }
  262. }
  263. else /* not tty */
  264. {
  265. ret_val = 0;
  266. skipjunk(fp);
  267. fscanf(fp,"SparseMatrix:");
  268. skipjunk(fp);
  269. if ( (ret_val=fscanf(fp,"%u by %u",&m,&n)) != 2 )
  270. error((ret_val == EOF) ? E_EOF : E_FORMAT,"sp_finput");
  271. A = sp_get(m,n,5);
  272. /* initialise start_row */
  273. for ( i = 0; i < A->n; i++ )
  274. A->start_row[i] = -1;
  275. rows = A->row;
  276. for ( i = 0; i < m; i++ )
  277. {
  278. /* printf("Reading row # %d\n",i); */
  279. rows[i].diag = -1;
  280. skipjunk(fp);
  281. if ( (ret_val=fscanf(fp,"row %d :",&tmp)) != 1 ||
  282. tmp != i )
  283. error((ret_val == EOF) ? E_EOF : E_FORMAT,
  284. "sp_finput");
  285. curr_col = -1;
  286. len = 0;
  287. for ( ; ; ) /* forever do... */
  288. {
  289. /* if we need more scratch space, let's get it!
  290. -- using amortized doubling */
  291. if ( len >= scratch_len )
  292. {
  293. scratch = RENEW(scratch,2*scratch_len,row_elt);
  294. if ( ! scratch )
  295. error(E_MEM,"sp_finput");
  296. scratch_len = 2*scratch_len;
  297. }
  298. #if REAL == DOUBLE
  299. if ( (ret_val=fscanf(fp,"%u : %lf",&col,&val)) != 2 )
  300. #elif REAL == FLOAT
  301. if ( (ret_val=fscanf(fp,"%u : %f",&col,&val)) != 2 )
  302. #endif
  303. break;
  304. if ( col <= curr_col || col >= n )
  305. error(E_FORMAT,"sp_finput");
  306. scratch[len].col = col;
  307. scratch[len].val = val;
  308. len++;
  309. }
  310. if ( ret_val == EOF )
  311. error(E_EOF,"sp_finput");
  312. if ( len > rows[i].maxlen )
  313. {
  314. rows[i].elt = (row_elt *)realloc((char *)rows[i].elt,
  315. len*sizeof(row_elt));
  316. rows[i].maxlen = len;
  317. }
  318. MEM_COPY(scratch,rows[i].elt,len*sizeof(row_elt));
  319. rows[i].len = len;
  320. /* printf("Have read row # %d\n",i); */
  321. rows[i].diag = sprow_idx(&(rows[i]),i);
  322. /* printf("Have set diag index for row # %d\n",i); */
  323. }
  324. }
  325. return A;
  326. }