NEURON
sparse.c
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 
3 /**************************************************************************
4 **
5 ** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved.
6 **
7 ** Meschach Library
8 **
9 ** This Meschach Library is provided "as is" without any express
10 ** or implied warranty of any kind with respect to this software.
11 ** In particular the authors shall not be liable for any direct,
12 ** indirect, special, incidental or consequential damages arising
13 ** in any way from use of the software.
14 **
15 ** Everyone is granted permission to copy, modify and redistribute this
16 ** Meschach Library, provided:
17 ** 1. All copies contain this copyright notice.
18 ** 2. All modified copies shall carry a notice stating who
19 ** made the last modification and the date of such modification.
20 ** 3. No charge is made for this software or works derived from it.
21 ** This clause shall not be construed as constraining other software
22 ** distributed on the same medium as this software, nor is a
23 ** distribution fee considered a charge.
24 **
25 ***************************************************************************/
26 
27 /*
28  Sparse matrix package
29  See also: sparse.h, matrix.h
30  */
31 
32 #include <stdio.h>
33 #include <math.h>
34 #include <stdlib.h>
35 #include "sparse.h"
36 
37 
38 static char rcsid[] = "sparse.c,v 1.1 1997/12/04 17:55:48 hines Exp";
39 
40 #define MINROWLEN 10
41 
42 
43 
44 /* sp_get_val -- returns the (i,j) entry of the sparse matrix A */
45 double sp_get_val(A,i,j)
46 SPMAT *A;
47 int i, j;
48 {
49  SPROW *r;
50  int idx;
51 
52  if ( A == SMNULL )
53  error(E_NULL,"sp_get_val");
54  if ( i < 0 || i >= A->m || j < 0 || j >= A->n )
55  error(E_SIZES,"sp_get_val");
56 
57  r = A->row+i;
58  idx = sprow_idx(r,j);
59  if ( idx < 0 )
60  return 0.0;
61  /* else */
62  return r->elt[idx].val;
63 }
64 
65 /* sp_set_val -- sets the (i,j) entry of the sparse matrix A */
66 double sp_set_val(A,i,j,val)
67 SPMAT *A;
68 int i, j;
69 double val;
70 {
71  SPROW *r;
72  int idx, idx2, new_len;
73 
74  if ( A == SMNULL )
75  error(E_NULL,"sp_set_val");
76  if ( i < 0 || i >= A->m || j < 0 || j >= A->n )
77  error(E_SIZES,"sp_set_val");
78 
79  r = A->row+i;
80  idx = sprow_idx(r,j);
81  /* printf("sp_set_val: idx = %d\n",idx); */
82  if ( idx >= 0 )
83  { r->elt[idx].val = val; return val; }
84  /* else */ if ( idx < -1 )
85  {
86  /* Note: this destroys the column & diag access paths */
87  A->flag_col = A->flag_diag = FALSE;
88  /* shift & insert new value */
89  idx = -(idx+2); /* this is the intended insertion index */
90  if ( r->len >= r->maxlen )
91  {
92  r->len = r->maxlen;
93  new_len = max(2*r->maxlen+1,5);
94  if (mem_info_is_on()) {
95  mem_bytes(TYPE_SPMAT,A->row[i].maxlen*sizeof(row_elt),
96  new_len*sizeof(row_elt));
97  }
98 
99  r->elt = RENEW(r->elt,new_len,row_elt);
100  if ( ! r->elt ) /* can't allocate */
101  error(E_MEM,"sp_set_val");
102  r->maxlen = 2*r->maxlen+1;
103  }
104  for ( idx2 = r->len-1; idx2 >= idx; idx2-- )
105  MEM_COPY((char *)(&(r->elt[idx2])),
106  (char *)(&(r->elt[idx2+1])),sizeof(row_elt));
107  /************************************************************
108  if ( idx < r->len )
109  MEM_COPY((char *)(&(r->elt[idx])),(char *)(&(r->elt[idx+1])),
110  (r->len-idx)*sizeof(row_elt));
111  ************************************************************/
112  r->len++;
113  r->elt[idx].col = j;
114  return r->elt[idx].val = val;
115  }
116  /* else -- idx == -1, error in index/matrix! */
117  return 0.0;
118 }
119 
120 /* sp_mv_mlt -- sparse matrix/dense vector multiply
121  -- result is in out, which is returned unless out==NULL on entry
122  -- if out==NULL on entry then the result vector is created */
123 VEC *sp_mv_mlt(A,x,out)
124 SPMAT *A;
125 VEC *x, *out;
126 {
127  int i, j_idx, m, n, max_idx;
128  Real sum, *x_ve;
129  SPROW *r;
130  row_elt *elts;
131 
132  if ( ! A || ! x )
133  error(E_NULL,"sp_mv_mlt");
134  if ( x->dim != A->n )
135  error(E_SIZES,"sp_mv_mlt");
136  if ( ! out || out->dim < A->m )
137  out = v_resize(out,A->m);
138  if ( out == x )
139  error(E_INSITU,"sp_mv_mlt");
140  m = A->m; n = A->n;
141  x_ve = x->ve;
142 
143  for ( i = 0; i < m; i++ )
144  {
145  sum = 0.0;
146  r = &(A->row[i]);
147  max_idx = r->len;
148  elts = r->elt;
149  for ( j_idx = 0; j_idx < max_idx; j_idx++, elts++ )
150  sum += elts->val*x_ve[elts->col];
151  out->ve[i] = sum;
152  }
153  return out;
154 }
155 
156 /* sp_vm_mlt -- sparse matrix/dense vector multiply from left
157  -- result is in out, which is returned unless out==NULL on entry
158  -- if out==NULL on entry then result vector is created & returned */
159 VEC *sp_vm_mlt(A,x,out)
160 SPMAT *A;
161 VEC *x, *out;
162 {
163  int i, j_idx, m, n, max_idx;
164  Real tmp, *x_ve, *out_ve;
165  SPROW *r;
166  row_elt *elts;
167 
168  if ( ! A || ! x )
169  error(E_NULL,"sp_vm_mlt");
170  if ( x->dim != A->m )
171  error(E_SIZES,"sp_vm_mlt");
172  if ( ! out || out->dim < A->n )
173  out = v_resize(out,A->n);
174  if ( out == x )
175  error(E_INSITU,"sp_vm_mlt");
176 
177  m = A->m; n = A->n;
178  v_zero(out);
179  x_ve = x->ve; out_ve = out->ve;
180 
181  for ( i = 0; i < m; i++ )
182  {
183  r = A->row+i;
184  max_idx = r->len;
185  elts = r->elt;
186  tmp = x_ve[i];
187  for ( j_idx = 0; j_idx < max_idx; j_idx++, elts++ )
188  out_ve[elts->col] += elts->val*tmp;
189  }
190 
191  return out;
192 }
193 
194 
195 /* sp_get -- get sparse matrix
196  -- len is number of elements available for each row without
197  allocating further memory */
198 SPMAT *sp_get(m,n,maxlen)
199 int m, n, maxlen;
200 {
201  SPMAT *A;
202  SPROW *rows;
203  int i;
204 
205  if ( m < 0 || n < 0 )
206  error(E_NEG,"sp_get");
207 
208  maxlen = max(maxlen,1);
209 
210  A = NEW(SPMAT);
211  if ( ! A ) /* can't allocate */
212  error(E_MEM,"sp_get");
213  else if (mem_info_is_on()) {
214  mem_bytes(TYPE_SPMAT,0,sizeof(SPMAT));
215  mem_numvar(TYPE_SPMAT,1);
216  }
217  /* fprintf(stderr,"Have SPMAT structure\n"); */
218 
219  A->row = rows = NEW_A(m,SPROW);
220  if ( ! A->row ) /* can't allocate */
221  error(E_MEM,"sp_get");
222  else if (mem_info_is_on()) {
223  mem_bytes(TYPE_SPMAT,0,m*sizeof(SPROW));
224  }
225  /* fprintf(stderr,"Have row structure array\n"); */
226 
227  A->start_row = NEW_A(n,int);
228  A->start_idx = NEW_A(n,int);
229  if ( ! A->start_row || ! A->start_idx ) /* can't allocate */
230  error(E_MEM,"sp_get");
231  else if (mem_info_is_on()) {
232  mem_bytes(TYPE_SPMAT,0,2*n*sizeof(int));
233  }
234  for ( i = 0; i < n; i++ )
235  A->start_row[i] = A->start_idx[i] = -1;
236  /* fprintf(stderr,"Have start_row array\n"); */
237 
238  A->m = A->max_m = m;
239  A->n = A->max_n = n;
240 
241  for ( i = 0; i < m; i++, rows++ )
242  {
243  rows->elt = NEW_A(maxlen,row_elt);
244  if ( ! rows->elt )
245  error(E_MEM,"sp_get");
246  else if (mem_info_is_on()) {
247  mem_bytes(TYPE_SPMAT,0,maxlen*sizeof(row_elt));
248  }
249  /* fprintf(stderr,"Have row %d element array\n",i); */
250  rows->len = 0;
251  rows->maxlen = maxlen;
252  rows->diag = -1;
253  }
254 
255  return A;
256 }
257 
258 
259 /* sp_free -- frees up the memory for a sparse matrix */
260 int sp_free(A)
261 SPMAT *A;
262 {
263  SPROW *r;
264  int i;
265 
266  if ( ! A )
267  return -1;
268  if ( A->start_row != (int *)NULL ) {
269  if (mem_info_is_on()) {
270  mem_bytes(TYPE_SPMAT,A->max_n*sizeof(int),0);
271  }
272  free((char *)(A->start_row));
273  }
274  if ( A->start_idx != (int *)NULL ) {
275  if (mem_info_is_on()) {
276  mem_bytes(TYPE_SPMAT,A->max_n*sizeof(int),0);
277  }
278 
279  free((char *)(A->start_idx));
280  }
281  if ( ! A->row )
282  {
283  if (mem_info_is_on()) {
284  mem_bytes(TYPE_SPMAT,sizeof(SPMAT),0);
285  mem_numvar(TYPE_SPMAT,-1);
286  }
287 
288  free((char *)A);
289  return 0;
290  }
291  for ( i = 0; i < A->m; i++ )
292  {
293  r = &(A->row[i]);
294  if ( r->elt != (row_elt *)NULL ) {
295  if (mem_info_is_on()) {
296  mem_bytes(TYPE_SPMAT,A->row[i].maxlen*sizeof(row_elt),0);
297  }
298  free((char *)(r->elt));
299  }
300  }
301 
302  if (mem_info_is_on()) {
303  if (A->row)
304  mem_bytes(TYPE_SPMAT,A->max_m*sizeof(SPROW),0);
305  mem_bytes(TYPE_SPMAT,sizeof(SPMAT),0);
306  mem_numvar(TYPE_SPMAT,-1);
307  }
308 
309  free((char *)(A->row));
310  free((char *)A);
311 
312  return 0;
313 }
314 
315 
316 /* sp_copy -- constructs a copy of a given matrix
317  -- note that the max_len fields (etc) are no larger in the copy
318  than necessary
319  -- result is returned */
321 SPMAT *A;
322 {
323  SPMAT *out;
324  SPROW *row1, *row2;
325  int i;
326 
327  if ( A == SMNULL )
328  error(E_NULL,"sp_copy");
329  if ( ! (out=NEW(SPMAT)) )
330  error(E_MEM,"sp_copy");
331  else if (mem_info_is_on()) {
332  mem_bytes(TYPE_SPMAT,0,sizeof(SPMAT));
333  mem_numvar(TYPE_SPMAT,1);
334  }
335  out->m = out->max_m = A->m; out->n = out->max_n = A->n;
336 
337  /* set up rows */
338  if ( ! (out->row=NEW_A(A->m,SPROW)) )
339  error(E_MEM,"sp_copy");
340  else if (mem_info_is_on()) {
341  mem_bytes(TYPE_SPMAT,0,A->m*sizeof(SPROW));
342  }
343  for ( i = 0; i < A->m; i++ )
344  {
345  row1 = &(A->row[i]);
346  row2 = &(out->row[i]);
347  if ( ! (row2->elt=NEW_A(max(row1->len,3),row_elt)) )
348  error(E_MEM,"sp_copy");
349  else if (mem_info_is_on()) {
350  mem_bytes(TYPE_SPMAT,0,max(row1->len,3)*sizeof(row_elt));
351  }
352  row2->len = row1->len;
353  row2->maxlen = max(row1->len,3);
354  row2->diag = row1->diag;
355  MEM_COPY((char *)(row1->elt),(char *)(row2->elt),
356  row1->len*sizeof(row_elt));
357  }
358 
359  /* set up start arrays -- for column access */
360  if ( ! (out->start_idx=NEW_A(A->n,int)) ||
361  ! (out->start_row=NEW_A(A->n,int)) )
362  error(E_MEM,"sp_copy");
363  else if (mem_info_is_on()) {
364  mem_bytes(TYPE_SPMAT,0,2*A->n*sizeof(int));
365  }
366  MEM_COPY((char *)(A->start_idx),(char *)(out->start_idx),
367  A->n*sizeof(int));
368  MEM_COPY((char *)(A->start_row),(char *)(out->start_row),
369  A->n*sizeof(int));
370 
371  return out;
372 }
373 
374 /* sp_col_access -- set column access path; i.e. nxt_row, nxt_idx fields
375  -- returns A */
377 SPMAT *A;
378 {
379  int i, j, j_idx, len, m, n;
380  SPROW *row;
381  row_elt *r_elt;
382  int *start_row, *start_idx;
383 
384  if ( A == SMNULL )
385  error(E_NULL,"sp_col_access");
386 
387  m = A->m; n = A->n;
388 
389  /* initialise start_row and start_idx */
390  start_row = A->start_row; start_idx = A->start_idx;
391  for ( j = 0; j < n; j++ )
392  { *start_row++ = -1; *start_idx++ = -1; }
393 
394  start_row = A->start_row; start_idx = A->start_idx;
395 
396  /* now work UP the rows, setting nxt_row, nxt_idx fields */
397  for ( i = m-1; i >= 0; i-- )
398  {
399  row = &(A->row[i]);
400  r_elt = row->elt;
401  len = row->len;
402  for ( j_idx = 0; j_idx < len; j_idx++, r_elt++ )
403  {
404  j = r_elt->col;
405  r_elt->nxt_row = start_row[j];
406  r_elt->nxt_idx = start_idx[j];
407  start_row[j] = i;
408  start_idx[j] = j_idx;
409  }
410  }
411 
412  A->flag_col = TRUE;
413  return A;
414 }
415 
416 /* sp_diag_access -- set diagonal access path(s) */
418 SPMAT *A;
419 {
420  int i, m;
421  SPROW *row;
422 
423  if ( A == SMNULL )
424  error(E_NULL,"sp_diag_access");
425 
426  m = A->m;
427 
428  row = A->row;
429  for ( i = 0; i < m; i++, row++ )
430  row->diag = sprow_idx(row,i);
431 
432  A->flag_diag = TRUE;
433 
434  return A;
435 }
436 
437 /* sp_m2dense -- convert a sparse matrix to a dense one */
439 SPMAT *A;
440 MAT *out;
441 {
442  int i, j_idx;
443  SPROW *row;
444  row_elt *elt;
445 
446  if ( ! A )
447  error(E_NULL,"sp_m2dense");
448  if ( ! out || out->m < A->m || out->n < A->n )
449  out = m_get(A->m,A->n);
450 
451  m_zero(out);
452  for ( i = 0; i < A->m; i++ )
453  {
454  row = &(A->row[i]);
455  elt = row->elt;
456  for ( j_idx = 0; j_idx < row->len; j_idx++, elt++ )
457  out->me[i][elt->col] = elt->val;
458  }
459 
460  return out;
461 }
462 
463 
464 /* C = A+B, can be in situ */
466 SPMAT *A, *B, *C;
467 {
468  int i, in_situ;
469  SPROW *rc;
470  static SPROW *tmp;
471 
472  if ( ! A || ! B )
473  error(E_NULL,"sp_add");
474  if ( A->m != B->m || A->n != B->n )
475  error(E_SIZES,"sp_add");
476  if (C == A || C == B)
477  in_situ = TRUE;
478  else in_situ = FALSE;
479 
480  if ( ! C )
481  C = sp_get(A->m,A->n,5);
482  else {
483  if ( C->m != A->m || C->n != A->n )
484  error(E_SIZES,"sp_add");
485  if (!in_situ) sp_zero(C);
486  }
487 
488  if (tmp == (SPROW *)NULL && in_situ) {
489  tmp = sprow_get(MINROWLEN);
490  MEM_STAT_REG(tmp,TYPE_SPROW);
491  }
492 
493  if (in_situ)
494  for (i=0; i < A->m; i++) {
495  rc = &(C->row[i]);
496  sprow_add(&(A->row[i]),&(B->row[i]),0,tmp,TYPE_SPROW);
497  sprow_resize(rc,tmp->len,TYPE_SPMAT);
498  MEM_COPY(tmp->elt,rc->elt,tmp->len*sizeof(row_elt));
499  rc->len = tmp->len;
500  }
501  else
502  for (i=0; i < A->m; i++) {
503  sprow_add(&(A->row[i]),&(B->row[i]),0,&(C->row[i]),TYPE_SPMAT);
504  }
505 
506  C->flag_col = C->flag_diag = FALSE;
507 
508  return C;
509 }
510 
511 /* C = A-B, cannot be in situ */
513 SPMAT *A, *B, *C;
514 {
515  int i, in_situ;
516  SPROW *rc;
517  static SPROW *tmp;
518 
519  if ( ! A || ! B )
520  error(E_NULL,"sp_sub");
521  if ( A->m != B->m || A->n != B->n )
522  error(E_SIZES,"sp_sub");
523  if (C == A || C == B)
524  in_situ = TRUE;
525  else in_situ = FALSE;
526 
527  if ( ! C )
528  C = sp_get(A->m,A->n,5);
529  else {
530  if ( C->m != A->m || C->n != A->n )
531  error(E_SIZES,"sp_sub");
532  if (!in_situ) sp_zero(C);
533  }
534 
535  if (tmp == (SPROW *)NULL && in_situ) {
536  tmp = sprow_get(MINROWLEN);
537  MEM_STAT_REG(tmp,TYPE_SPROW);
538  }
539 
540  if (in_situ)
541  for (i=0; i < A->m; i++) {
542  rc = &(C->row[i]);
543  sprow_sub(&(A->row[i]),&(B->row[i]),0,tmp,TYPE_SPROW);
544  sprow_resize(rc,tmp->len,TYPE_SPMAT);
545  MEM_COPY(tmp->elt,rc->elt,tmp->len*sizeof(row_elt));
546  rc->len = tmp->len;
547  }
548  else
549  for (i=0; i < A->m; i++) {
550  sprow_sub(&(A->row[i]),&(B->row[i]),0,&(C->row[i]),TYPE_SPMAT);
551  }
552 
553  C->flag_col = C->flag_diag = FALSE;
554 
555  return C;
556 }
557 
558 /* C = A+alpha*B, cannot be in situ */
560 SPMAT *A, *B, *C;
561 double alpha;
562 {
563  int i, in_situ;
564  SPROW *rc;
565  static SPROW *tmp;
566 
567  if ( ! A || ! B )
568  error(E_NULL,"sp_mltadd");
569  if ( A->m != B->m || A->n != B->n )
570  error(E_SIZES,"sp_mltadd");
571  if (C == A || C == B)
572  in_situ = TRUE;
573  else in_situ = FALSE;
574 
575  if ( ! C )
576  C = sp_get(A->m,A->n,5);
577  else {
578  if ( C->m != A->m || C->n != A->n )
579  error(E_SIZES,"sp_mltadd");
580  if (!in_situ) sp_zero(C);
581  }
582 
583  if (tmp == (SPROW *)NULL && in_situ) {
584  tmp = sprow_get(MINROWLEN);
585  MEM_STAT_REG(tmp,TYPE_SPROW);
586  }
587 
588  if (in_situ)
589  for (i=0; i < A->m; i++) {
590  rc = &(C->row[i]);
591  sprow_mltadd(&(A->row[i]),&(B->row[i]),alpha,0,tmp,TYPE_SPROW);
592  sprow_resize(rc,tmp->len,TYPE_SPMAT);
593  MEM_COPY(tmp->elt,rc->elt,tmp->len*sizeof(row_elt));
594  rc->len = tmp->len;
595  }
596  else
597  for (i=0; i < A->m; i++) {
598  sprow_mltadd(&(A->row[i]),&(B->row[i]),alpha,0,
599  &(C->row[i]),TYPE_SPMAT);
600  }
601 
602  C->flag_col = C->flag_diag = FALSE;
603 
604  return C;
605 }
606 
607 
608 
609 /* B = alpha*A, can be in situ */
611 SPMAT *A, *B;
612 double alpha;
613 {
614  int i;
615 
616  if ( ! A )
617  error(E_NULL,"sp_smlt");
618  if ( ! B )
619  B = sp_get(A->m,A->n,5);
620  else
621  if ( A->m != B->m || A->n != B->n )
622  error(E_SIZES,"sp_smlt");
623 
624  for (i=0; i < A->m; i++) {
625  sprow_smlt(&(A->row[i]),alpha,0,&(B->row[i]),TYPE_SPMAT);
626  }
627  return B;
628 }
629 
630 
631 
632 /* sp_zero -- zero all the (represented) elements of a sparse matrix */
634 SPMAT *A;
635 {
636  int i, idx, len;
637  row_elt *elt;
638 
639  if ( ! A )
640  error(E_NULL,"sp_zero");
641 
642  for ( i = 0; i < A->m; i++ )
643  {
644  elt = A->row[i].elt;
645  len = A->row[i].len;
646  for ( idx = 0; idx < len; idx++ )
647  (*elt++).val = 0.0;
648  }
649 
650  return A;
651 }
652 
653 /* sp_copy2 -- copy sparse matrix (type 2)
654  -- keeps structure of the OUT matrix */
656 SPMAT *A, *OUT;
657 {
658  int i /* , idx, len1, len2 */;
659  SPROW *r1, *r2;
660  static SPROW *scratch = (SPROW *)NULL;
661  /* row_elt *e1, *e2; */
662 
663  if ( ! A )
664  error(E_NULL,"sp_copy2");
665  if ( ! OUT )
666  OUT = sp_get(A->m,A->n,10);
667  if ( ! scratch ) {
668  scratch = sprow_xpd(scratch,MINROWLEN,TYPE_SPROW);
669  MEM_STAT_REG(scratch,TYPE_SPROW);
670  }
671 
672  if ( OUT->m < A->m )
673  {
674  if (mem_info_is_on()) {
675  mem_bytes(TYPE_SPMAT,A->max_m*sizeof(SPROW),
676  A->m*sizeof(SPROW));
677  }
678 
679  OUT->row = RENEW(OUT->row,A->m,SPROW);
680  if ( ! OUT->row )
681  error(E_MEM,"sp_copy2");
682 
683  for ( i = OUT->m; i < A->m; i++ )
684  {
685  OUT->row[i].elt = NEW_A(MINROWLEN,row_elt);
686  if ( ! OUT->row[i].elt )
687  error(E_MEM,"sp_copy2");
688  else if (mem_info_is_on()) {
689  mem_bytes(TYPE_SPMAT,0,MINROWLEN*sizeof(row_elt));
690  }
691 
692  OUT->row[i].maxlen = MINROWLEN;
693  OUT->row[i].len = 0;
694  }
695  OUT->m = A->m;
696  }
697 
698  OUT->flag_col = OUT->flag_diag = FALSE;
699  /* sp_zero(OUT); */
700 
701  for ( i = 0; i < A->m; i++ )
702  {
703  r1 = &(A->row[i]); r2 = &(OUT->row[i]);
704  sprow_copy(r1,r2,scratch,TYPE_SPROW);
705  if ( r2->maxlen < scratch->len )
706  sprow_xpd(r2,scratch->len,TYPE_SPMAT);
707  MEM_COPY((char *)(scratch->elt),(char *)(r2->elt),
708  scratch->len*sizeof(row_elt));
709  r2->len = scratch->len;
710  /*******************************************************
711  e1 = r1->elt; e2 = r2->elt;
712  len1 = r1->len; len2 = r2->len;
713  for ( idx = 0; idx < len2; idx++, e2++ )
714  e2->val = 0.0;
715  for ( idx = 0; idx < len1; idx++, e1++ )
716  sprow_set_val(r2,e1->col,e1->val);
717  *******************************************************/
718  }
719 
721  return OUT;
722 }
723 
724 /* sp_resize -- resize a sparse matrix
725  -- don't destroying any contents if possible
726  -- returns resized matrix */
728 SPMAT *A;
729 int m, n;
730 {
731  int i, len;
732  SPROW *r;
733 
734  if (m < 0 || n < 0)
735  error(E_NEG,"sp_resize");
736 
737  if ( ! A )
738  return sp_get(m,n,10);
739 
740  if (m == A->m && n == A->n)
741  return A;
742 
743  if ( m <= A->max_m )
744  {
745  for ( i = A->m; i < m; i++ )
746  A->row[i].len = 0;
747  A->m = m;
748  }
749  else
750  {
751  if (mem_info_is_on()) {
752  mem_bytes(TYPE_SPMAT,A->max_m*sizeof(SPROW),
753  m*sizeof(SPROW));
754  }
755 
756  A->row = RENEW(A->row,(unsigned)m,SPROW);
757  if ( ! A->row )
758  error(E_MEM,"sp_resize");
759  for ( i = A->m; i < m; i++ )
760  {
761  if ( ! (A->row[i].elt = NEW_A(MINROWLEN,row_elt)) )
762  error(E_MEM,"sp_resize");
763  else if (mem_info_is_on()) {
764  mem_bytes(TYPE_SPMAT,0,MINROWLEN*sizeof(row_elt));
765  }
766  A->row[i].len = 0; A->row[i].maxlen = MINROWLEN;
767  }
768  A->m = A->max_m = m;
769  }
770 
771  /* update number of rows */
772  A->n = n;
773 
774  /* do we need to increase the size of start_idx[] and start_row[] ? */
775  if ( n > A->max_n )
776  { /* only have to update the start_idx & start_row arrays */
777  if (mem_info_is_on())
778  {
779  mem_bytes(TYPE_SPMAT,2*A->max_n*sizeof(int),
780  2*n*sizeof(int));
781  }
782 
783  A->start_row = RENEW(A->start_row,(unsigned)n,int);
784  A->start_idx = RENEW(A->start_idx,(unsigned)n,int);
785  if ( ! A->start_row || ! A->start_idx )
786  error(E_MEM,"sp_resize");
787  A->max_n = n; /* ...and update max_n */
788 
789  return A;
790  }
791 
792  if ( n <= A->n )
793  /* make sure that all rows are truncated just before column n */
794  for ( i = 0; i < A->m; i++ )
795  {
796  r = &(A->row[i]);
797  len = sprow_idx(r,n);
798  if ( len < 0 )
799  len = -(len+2);
800  if ( len < 0 )
801  error(E_MEM,"sp_resize");
802  r->len = len;
803  }
804 
805  return A;
806 }
807 
808 
809 /* sp_compact -- removes zeros and near-zeros from a sparse matrix */
811 SPMAT *A;
812 double tol;
813 {
814  int i, idx1, idx2;
815  SPROW *r;
816  row_elt *elt1, *elt2;
817 
818  if ( ! A )
819  error(E_NULL,"sp_compact");
820  if ( tol < 0.0 )
821  error(E_RANGE,"sp_compact");
822 
823  A->flag_col = A->flag_diag = FALSE;
824 
825  for ( i = 0; i < A->m; i++ )
826  {
827  r = &(A->row[i]);
828  elt1 = elt2 = r->elt;
829  idx1 = idx2 = 0;
830  while ( idx1 < r->len )
831  {
832  /* printf("# sp_compact: idx1 = %d, idx2 = %d\n",idx1,idx2); */
833  if ( fabs(elt1->val) <= tol )
834  { idx1++; elt1++; continue; }
835  if ( elt1 != elt2 )
836  MEM_COPY(elt1,elt2,sizeof(row_elt));
837  idx1++; elt1++;
838  idx2++; elt2++;
839  }
840  r->len = idx2;
841  }
842 
843  return A;
844 }
845 
846 /* varying number of arguments */
847 
848 #ifdef ANSI_C
849 
850 /* To allocate memory to many arguments.
851  The function should be called:
852  sp_get_vars(m,n,deg,&x,&y,&z,...,NULL);
853  where
854  int m,n,deg;
855  SPMAT *x, *y, *z,...;
856  The last argument should be NULL !
857  m x n is the dimension of matrices x,y,z,...
858  returned value is equal to the number of allocated variables
859 */
860 
861 int sp_get_vars(int m,int n,int deg,...)
862 {
863  va_list ap;
864  int i=0;
865  SPMAT **par;
866 
867  va_start(ap, deg);
868  while ((par = va_arg(ap,SPMAT **))) { /* NULL ends the list*/
869  *par = sp_get(m,n,deg);
870  i++;
871  }
872 
873  va_end(ap);
874  return i;
875 }
876 
877 
878 /* To resize memory for many arguments.
879  The function should be called:
880  sp_resize_vars(m,n,&x,&y,&z,...,NULL);
881  where
882  int m,n;
883  SPMAT *x, *y, *z,...;
884  The last argument should be NULL !
885  m X n is the resized dimension of matrices x,y,z,...
886  returned value is equal to the number of allocated variables.
887  If one of x,y,z,.. arguments is NULL then memory is allocated to this
888  argument.
889 */
890 
891 int sp_resize_vars(int m,int n,...)
892 {
893  va_list ap;
894  int i=0;
895  SPMAT **par;
896 
897  va_start(ap, n);
898  while ((par = va_arg(ap,SPMAT **))) { /* NULL ends the list*/
899  *par = sp_resize(*par,m,n);
900  i++;
901  }
902 
903  va_end(ap);
904  return i;
905 }
906 
907 /* To deallocate memory for many arguments.
908  The function should be called:
909  sp_free_vars(&x,&y,&z,...,NULL);
910  where
911  SPMAT *x, *y, *z,...;
912  The last argument should be NULL !
913  There must be at least one not NULL argument.
914  returned value is equal to the number of allocated variables.
915  Returned value of x,y,z,.. is VNULL.
916 */
917 
918 int sp_free_vars(SPMAT **va,...)
919 {
920  va_list ap;
921  int i=1;
922  SPMAT **par;
923 
924  sp_free(*va);
925  *va = (SPMAT *) NULL;
926  va_start(ap, va);
927  while ((par = va_arg(ap,SPMAT **))) { /* NULL ends the list*/
928  sp_free(*par);
929  *par = (SPMAT *)NULL;
930  i++;
931  }
932 
933  va_end(ap);
934  return i;
935 }
936 
937 
938 #elif VARARGS
939 
940 /* To allocate memory to many arguments.
941  The function should be called:
942  sp_get_vars(m,n,deg,&x,&y,&z,...,NULL);
943  where
944  int m,n,deg;
945  SPMAT *x, *y, *z,...;
946  The last argument should be NULL !
947  m x n is the dimension of matrices x,y,z,...
948  returned value is equal to the number of allocated variables
949 */
950 
951 int sp_get_vars(va_alist) va_dcl
952 {
953  va_list ap;
954  int i=0, m, n, deg;
955  SPMAT **par;
956 
957  va_start(ap);
958  m = va_arg(ap,int);
959  n = va_arg(ap,int);
960  deg = va_arg(ap,int);
961  while ((par = va_arg(ap,SPMAT **))) { /* NULL ends the list*/
962  *par = sp_get(m,n,deg);
963  i++;
964  }
965 
966  va_end(ap);
967  return i;
968 }
969 
970 
971 /* To resize memory for many arguments.
972  The function should be called:
973  sp_resize_vars(m,n,&x,&y,&z,...,NULL);
974  where
975  int m,n;
976  SPMAT *x, *y, *z,...;
977  The last argument should be NULL !
978  m X n is the resized dimension of matrices x,y,z,...
979  returned value is equal to the number of allocated variables.
980  If one of x,y,z,.. arguments is NULL then memory is allocated to this
981  argument.
982 */
983 
984 int sp_resize_vars(va_alist) va_dcl
985 {
986  va_list ap;
987  int i=0, m, n;
988  SPMAT **par;
989 
990  va_start(ap);
991  m = va_arg(ap,int);
992  n = va_arg(ap,int);
993  while ((par = va_arg(ap,SPMAT **))) { /* NULL ends the list*/
994  *par = sp_resize(*par,m,n);
995  i++;
996  }
997 
998  va_end(ap);
999  return i;
1000 }
1001 
1002 
1003 
1004 /* To deallocate memory for many arguments.
1005  The function should be called:
1006  sp_free_vars(&x,&y,&z,...,NULL);
1007  where
1008  SPMAT *x, *y, *z,...;
1009  The last argument should be NULL !
1010  There must be at least one not NULL argument.
1011  returned value is equal to the number of allocated variables.
1012  Returned value of x,y,z,.. is VNULL.
1013 */
1014 
1015 int sp_free_vars(va_alist) va_dcl
1016 {
1017  va_list ap;
1018  int i=0;
1019  SPMAT **par;
1020 
1021  va_start(ap);
1022  while ((par = va_arg(ap,SPMAT **))) { /* NULL ends the list*/
1023  sp_free(*par);
1024  *par = (SPMAT *)NULL;
1025  i++;
1026  }
1027 
1028  va_end(ap);
1029  return i;
1030 }
1031 
1032 
1033 
1034 #endif
1035 
MAT * m_get(int, int)
Definition: memory.c:36
SPROW * sprow_smlt(SPROW *r1, double alpha, int j0, SPROW *r_out, int type)
Definition: sprow.c:605
Real val
Definition: sparse.h:46
int sp_get_vars(int m, int n, int deg,...)
Definition: sparse.c:861
double max(double a, double b)
Definition: geometry3d.cpp:22
#define B(i)
Definition: multisplit.cpp:62
double sp_set_val(SPMAT *A, int i, int j, double val)
Definition: sparse.c:66
int sp_free(SPMAT *A)
Definition: sparse.c:260
int diag
Definition: sparse.h:50
SPMAT * sp_diag_access(SPMAT *A)
Definition: sparse.c:417
MAT * sp_m2dense(SPMAT *A, MAT *out)
Definition: sparse.c:438
#define E_NEG
Definition: err.h:114
#define Real
Definition: machine.h:189
static Object ** v_resize(void *v)
Definition: ivocvect.cpp:1297
SPMAT * sp_resize(SPMAT *A, int m, int n)
Definition: sparse.c:727
SPMAT * sp_sub(SPMAT *A, SPMAT *B, SPMAT *C)
Definition: sparse.c:512
#define NEW_A(num, type)
Definition: matrix.h:139
SPROW * sprow_copy(SPROW *, SPROW *, SPROW *, int type)
#define TRUE
Definition: err.c:57
row_elt * elt
Definition: sparse.h:51
int nxt_row
Definition: sparse.h:45
u_int n
Definition: matrix.h:74
Definition: sparse.h:44
int col
Definition: sparse.h:45
Real * ve
Definition: matrix.h:69
SPMAT * sp_zero(SPMAT *A)
Definition: sparse.c:633
int mem_info_is_on(void)
Definition: meminfo.c:221
SPMAT * sp_mltadd(SPMAT *A, SPMAT *B, double alpha, SPMAT *C)
Definition: sparse.c:559
Definition: matrix.h:67
SPMAT * sp_copy(SPMAT *A)
Definition: sparse.c:320
SPMAT * sp_compact(SPMAT *A, double tol)
Definition: sparse.c:810
SPROW * sprow_sub(SPROW *r1, SPROW *r2, int j0, SPROW *r_out, int type)
#define E_SIZES
Definition: err.h:95
Definition: sparse.h:54
int const size_t const size_t n
Definition: nrngsl.h:12
#define E_RANGE
Definition: err.h:104
int n
Definition: sparse.h:55
SPROW * sprow_resize(SPROW *r, int n, int type)
int val
Definition: dll.cpp:167
u_int dim
Definition: matrix.h:68
#define mem_bytes(type, old_size, new_size)
Definition: meminfo.h:136
int sp_resize_vars(int m, int n,...)
Definition: sparse.c:891
int m
Definition: sparse.h:55
SPROW * sprow_mltadd(SPROW *, SPROW *, double, int, SPROW *, int type)
Definition: sprow.c:399
int sprow_idx(SPROW *, int)
Definition: sprow.c:75
Definition: sparse.h:49
SPMAT * sp_get(int m, int n, int maxlen)
Definition: sparse.c:198
static char rcsid[]
Definition: sparse.c:38
void MEM_COPY(char *from, char *to, int len)
Definition: extras.c:37
#define E_NULL
Definition: err.h:102
size_t j
#define alpha
Definition: bkpfacto.c:43
SPROW * sprow_add(SPROW *r1, SPROW *r2, int j0, SPROW *r_out, int type)
VEC * sp_mv_mlt(SPMAT *A, VEC *x, VEC *out)
Definition: sparse.c:123
static char scratch[MAXLINE+1]
Definition: otherio.c:41
int len
Definition: sparse.h:50
#define SMNULL
Definition: sparse.h:74
int * start_idx
Definition: sparse.h:59
int max_n
Definition: sparse.h:55
static unsigned row
Definition: nonlin.cpp:89
#define MINROWLEN
Definition: sparse.c:40
VEC * v_zero(VEC *x)
Definition: init.c:40
SPROW * row
Definition: sparse.h:57
int maxlen
Definition: sparse.h:50
#define MEM_STAT_REG(var, type)
Definition: meminfo.h:133
#define FALSE
Definition: err.c:56
int nxt_idx
Definition: sparse.h:45
#define i
Definition: md1redef.h:12
#define A(i)
Definition: multisplit.cpp:61
static Object ** m_zero(void *v)
Definition: matrix.cpp:511
int sp_free_vars(SPMAT **va,...)
Definition: sparse.c:918
#define OUT
Definition: matrix.h:51
SPMAT * sp_add(SPMAT *A, SPMAT *B, SPMAT *C)
Definition: sparse.c:465
#define error(err_num, fn_name)
Definition: err.h:73
fabs
Definition: extdef.h:3
SPROW * sprow_get(int)
u_int m
Definition: matrix.h:74
SPMAT * sp_col_access(SPMAT *A)
Definition: sparse.c:376
#define mem_numvar(type, num)
Definition: meminfo.h:139
SPMAT * sp_smlt(SPMAT *A, double alpha, SPMAT *B)
Definition: sparse.c:610
int max_m
Definition: sparse.h:55
SPROW * sprow_xpd(SPROW *r, int n, int type)
for(i=0;i< n;i++)
int * start_row
Definition: sparse.h:58
#define RENEW(var, num, type)
Definition: matrix.h:142
double sp_get_val(SPMAT *A, int i, int j)
Definition: sparse.c:45
return NULL
Definition: cabcode.cpp:461
SPMAT * sp_copy2(SPMAT *A, SPMAT *OUT)
Definition: sparse.c:655
Real ** me
Definition: matrix.h:76
#define NEW(type)
Definition: matrix.h:136
Definition: matrix.h:73
#define E_MEM
Definition: err.h:97
#define E_INSITU
Definition: err.h:106
VEC * sp_vm_mlt(SPMAT *A, VEC *x, VEC *out)
Definition: sparse.c:159