1 /*
2  *  MATRIX ALLOCATION MODULE
3  *
4  *  Author:                     Advising professor:
5  *      Kenneth S. Kundert          Alberto Sangiovanni-Vincentelli
6  *      UC Berkeley
7  *
8  *  This file contains the allocation and deallocation routines for the
9  *  sparse matrix routines.
10  *
11  *  >>> User accessible functions contained in this file:
12  *  spCreate
13  *  spDestroy
14  *  spError
15  *  spWhereSingular
16  *  spGetSize
17  *  spSetReal
18  *  spSetComplex
19  *  spFillinCount
20  *  spElementCount
21  *
22  *  >>> Other functions contained in this file:
23  *  spcGetElement
24  *  InitializeElementBlocks
25  *  spcGetFillin
26  *  RecordAllocation
27  *  AllocateBlockOfAllocationList
28  *  EnlargeMatrix
29  *  ExpandTranslationArrays
30  */
31 
32 
33 /*
34  *  Revision and copyright information.
35  *
36  *  Copyright (c) 1985,86,87,88,89,90
37  *  by Kenneth S. Kundert and the University of California.
38  *
39  *  Permission to use, copy, modify, and distribute this software and
40  *  its documentation for any purpose and without fee is hereby granted,
41  *  provided that the copyright notices appear in all copies and
42  *  supporting documentation and that the authors and the University of
43  *  California are properly credited.  The authors and the University of
44  *  California make no representations as to the suitability of this
45  *  software for any purpose.  It is provided `as is', without express
46  *  or implied warranty.
47  */
48 
49 #ifdef notdef
50 static char copyright[] =
51     "Sparse1.3: Copyright (c) 1985,86,87,88,89,90 by Kenneth S. Kundert";
52 static char RCSid[] =
53     "@(#)$Header: spAllocate.c,v 1.3 88/06/24 05:00:11 kundert Exp $";
54 #endif
55 
56 
57 
58 /*
59  *  IMPORTS
60  *
61  *  >>> Import descriptions:
62  *  spConfig.h
63  *      Macros that customize the sparse matrix routines.
64  *  spMatrix.h
65  *      Macros and declarations to be imported by the user.
66  *  spDefs.h
67  *      Matrix type and macro definitions for the sparse matrix routines.
68  */
69 
70 #define spINSIDE_SPARSE
71 #include "spconfig.h"
72 #include "spmatrix.h"
73 #include "spdefs.h"
74 
75 
76 
77 
78 
79 /*
80  *  Function declarations
81  */
82 
83 #ifdef __STDC__
84 static void InitializeElementBlocks( MatrixPtr, int, int );
85 static void RecordAllocation( MatrixPtr, char* );
86 static void AllocateBlockOfAllocationList( MatrixPtr );
87 #else /* __STDC__ */
88 static void InitializeElementBlocks();
89 static void RecordAllocation();
90 static void AllocateBlockOfAllocationList();
91 #endif /* __STDC__ */
92 
93 
94 
95 
96 /*
97  *  MATRIX ALLOCATION
98  *
99  *  Allocates and initializes the data structures associated with a matrix.
100  *
101  *  >>> Returned:
102  *  A pointer to the matrix is returned cast into the form of a pointer to
103  *  a character.  This pointer is then passed and used by the other matrix
104  *  routines to refer to a particular matrix.  If an error occurs, the NULL
105  *  pointer is returned.
106  *
107  *  >>> Arguments:
108  *  Size  <input>  (int)
109  *      Size of matrix or estimate of size of matrix if matrix is EXPANDABLE.
110  *  Complex  <input>  (int)
111  *      Type of matrix.  If Complex is 0 then the matrix is real, otherwise
112  *      the matrix will be complex.  Note that if the routines are not set up
113  *      to handle the type of matrix requested, then a spPANIC error will occur.
114  *      Further note that if a matrix will be both real and complex, it must
115  *      be specified here as being complex.
116  *  pError  <output>  (int *)
117  *      Returns error flag, needed because function spError() will not work
118  *      correctly if spCreate() returns NULL.
119  *
120  *  >>> Local variables:
121  *  AllocatedSize  (int)
122  *      The size of the matrix being allocated.
123  *  Matrix  (MatrixPtr)
124  *      A pointer to the matrix frame being created.
125  *
126  *  >>> Possible errors:
127  *  spNO_MEMORY
128  *  spPANIC
129  *  Error is cleared in this routine.
130  */
131 
132 char *
spCreate(Size,Complex,pError)133 spCreate( Size, Complex, pError )
134 
135 int  Size, *pError;
136 BOOLEAN  Complex;
137 {
138 register  unsigned  SizePlusOne;
139 register  MatrixPtr  Matrix;
140 register  int  I;
141 int  AllocatedSize;
142 
143 /* Begin `spCreate'. */
144 /* Clear error flag. */
145     *pError = spOKAY;
146 
147 /* Test for valid size. */
148     if ((Size < 0) OR (Size == 0 AND NOT EXPANDABLE))
149     {   *pError = spPANIC;
150         return NULL;
151     }
152 
153 /* Test for valid type. */
154 #if NOT spCOMPLEX
155     if (Complex)
156     {   *pError = spPANIC;
157         return NULL;
158     }
159 #endif
160 #if NOT REAL
161     if (NOT Complex)
162     {   *pError = spPANIC;
163         return NULL;
164     }
165 #endif
166 
167 /* Create Matrix. */
168     AllocatedSize = MAX( Size, MINIMUM_ALLOCATED_SIZE );
169     SizePlusOne = (unsigned)(AllocatedSize + 1);
170 
171     if ((Matrix = ALLOC(struct MatrixFrame, 1)) == NULL)
172     {   *pError = spNO_MEMORY;
173         return NULL;
174     }
175 
176 /* Initialize matrix */
177     Matrix->ID = SPARSE_ID;
178     Matrix->Complex = Complex;
179     Matrix->PreviousMatrixWasComplex = Complex;
180     Matrix->Factored = NO;
181     Matrix->Elements = 0;
182     Matrix->Error = *pError;
183     Matrix->Fillins = 0;
184     Matrix->Reordered = NO;
185     Matrix->NeedsOrdering = YES;
186     Matrix->NumberOfInterchangesIsOdd = NO;
187     Matrix->Partitioned = NO;
188     Matrix->RowsLinked = NO;
189     Matrix->InternalVectorsAllocated = NO;
190     Matrix->SingularCol = 0;
191     Matrix->SingularRow = 0;
192     Matrix->Size = Size;
193     Matrix->AllocatedSize = AllocatedSize;
194     Matrix->ExtSize = Size;
195     Matrix->AllocatedExtSize = AllocatedSize;
196     Matrix->CurrentSize = 0;
197     Matrix->ExtToIntColMap = NULL;
198     Matrix->ExtToIntRowMap = NULL;
199     Matrix->IntToExtColMap = NULL;
200     Matrix->IntToExtRowMap = NULL;
201     Matrix->MarkowitzRow = NULL;
202     Matrix->MarkowitzCol = NULL;
203     Matrix->MarkowitzProd = NULL;
204     Matrix->DoCmplxDirect = NULL;
205     Matrix->DoRealDirect = NULL;
206     Matrix->Intermediate = NULL;
207     Matrix->RelThreshold = DEFAULT_THRESHOLD;
208     Matrix->AbsThreshold = 0.0;
209 
210     Matrix->TopOfAllocationList = NULL;
211     Matrix->RecordsRemaining = 0;
212     Matrix->ElementsRemaining = 0;
213     Matrix->FillinsRemaining = 0;
214 
215     RecordAllocation( Matrix, (char *)Matrix );
216     if (Matrix->Error == spNO_MEMORY) goto MemoryError;
217 
218 /* Take out the trash. */
219     Matrix->TrashCan.Real = 0.0;
220 #if spCOMPLEX
221     Matrix->TrashCan.Imag = 0.0;
222 #endif
223     Matrix->TrashCan.Row = 0;
224     Matrix->TrashCan.Col = 0;
225     Matrix->TrashCan.NextInRow = NULL;
226     Matrix->TrashCan.NextInCol = NULL;
227 #if INITIALIZE
228     Matrix->TrashCan.pInitInfo = NULL;
229 #endif
230 
231 /* Allocate space in memory for Diag pointer vector. */
232     CALLOC( Matrix->Diag, ElementPtr, SizePlusOne);
233     if (Matrix->Diag == NULL)
234         goto MemoryError;
235 
236 /* Allocate space in memory for FirstInCol pointer vector. */
237     CALLOC( Matrix->FirstInCol, ElementPtr, SizePlusOne);
238     if (Matrix->FirstInCol == NULL)
239         goto MemoryError;
240 
241 /* Allocate space in memory for FirstInRow pointer vector. */
242     CALLOC( Matrix->FirstInRow, ElementPtr, SizePlusOne);
243     if (Matrix->FirstInRow == NULL)
244         goto MemoryError;
245 
246 /* Allocate space in memory for IntToExtColMap vector. */
247     if (( Matrix->IntToExtColMap = ALLOC(int, SizePlusOne)) == NULL)
248         goto MemoryError;
249 
250 /* Allocate space in memory for IntToExtRowMap vector. */
251     if (( Matrix->IntToExtRowMap = ALLOC(int, SizePlusOne)) == NULL)
252         goto MemoryError;
253 
254 /* Initialize MapIntToExt vectors. */
255     for (I = 1; I <= AllocatedSize; I++)
256     {   Matrix->IntToExtRowMap[I] = I;
257         Matrix->IntToExtColMap[I] = I;
258     }
259 
260 #if TRANSLATE
261 /* Allocate space in memory for ExtToIntColMap vector. */
262     if (( Matrix->ExtToIntColMap = ALLOC(int, SizePlusOne)) == NULL)
263         goto MemoryError;
264 
265 /* Allocate space in memory for ExtToIntRowMap vector. */
266     if (( Matrix->ExtToIntRowMap = ALLOC(int, SizePlusOne)) == NULL)
267         goto MemoryError;
268 
269 /* Initialize MapExtToInt vectors. */
270     for (I = 1; I <= AllocatedSize; I++)
271     {   Matrix->ExtToIntColMap[I] = -1;
272         Matrix->ExtToIntRowMap[I] = -1;
273     }
274     Matrix->ExtToIntColMap[0] = 0;
275     Matrix->ExtToIntRowMap[0] = 0;
276 #endif
277 
278 /* Allocate space for fill-ins and initial set of elements. */
279     InitializeElementBlocks( Matrix, SPACE_FOR_ELEMENTS*AllocatedSize,
280                                      SPACE_FOR_FILL_INS*AllocatedSize );
281     if (Matrix->Error == spNO_MEMORY)
282         goto MemoryError;
283 
284     return (char *)Matrix;
285 
286 MemoryError:
287 
288 /* Deallocate matrix and return no pointer to matrix if there is not enough
289    memory. */
290     *pError = spNO_MEMORY;
291     spDestroy( (char *)Matrix);
292     return NULL;
293 }
294 
295 
296 
297 
298 
299 
300 
301 
302 
303 /*
304  *  ELEMENT ALLOCATION
305  *
306  *  This routine allocates space for matrix elements. It requests large blocks
307  *  of storage from the system and doles out individual elements as required.
308  *  This technique, as opposed to allocating elements individually, tends to
309  *  speed the allocation process.
310  *
311  *  >>> Returned:
312  *  A pointer to an element.
313  *
314  *  >>> Arguments:
315  *  Matrix  <input>  (MatrixPtr)
316  *      Pointer to matrix.
317  *
318  *  >>> Local variables:
319  *  pElement  (ElementPtr)
320  *      A pointer to the first element in the group of elements being allocated.
321  *
322  *  >>> Possible errors:
323  *  spNO_MEMORY
324  */
325 
326 ElementPtr
spcGetElement(Matrix)327 spcGetElement( Matrix )
328 
329 MatrixPtr Matrix;
330 {
331 ElementPtr  pElement;
332 
333 /* Begin `spcGetElement'. */
334 
335 /* Allocate block of MatrixElements if necessary. */
336     if (Matrix->ElementsRemaining == 0)
337     {   pElement = ALLOC(struct MatrixElement, ELEMENTS_PER_ALLOCATION);
338         RecordAllocation( Matrix, (char *)pElement );
339         if (Matrix->Error == spNO_MEMORY) return NULL;
340         Matrix->ElementsRemaining = ELEMENTS_PER_ALLOCATION;
341         Matrix->NextAvailElement = pElement;
342     }
343 
344 /* Update Element counter and return pointer to Element. */
345     Matrix->ElementsRemaining--;
346     return Matrix->NextAvailElement++;
347 
348 }
349 
350 
351 
352 
353 
354 
355 
356 
357 /*
358  *  ELEMENT ALLOCATION INITIALIZATION
359  *
360  *  This routine allocates space for matrix fill-ins and an initial set of
361  *  elements.  Besides being faster than allocating space for elements one
362  *  at a time, it tends to keep the fill-ins physically close to the other
363  *  matrix elements in the computer memory.  This keeps virtual memory paging
364  *  to a minimum.
365  *
366  *  >>> Arguments:
367  *  Matrix  <input>    (MatrixPtr)
368  *      Pointer to the matrix.
369  *  InitialNumberOfElements  <input> (int)
370  *      This number is used as the size of the block of memory, in
371  *      MatrixElements, reserved for elements. If more than this number of
372  *      elements are generated, then more space is allocated later.
373  *  NumberOfFillinsExpected  <input> (int)
374  *      This number is used as the size of the block of memory, in
375  *      MatrixElements, reserved for fill-ins. If more than this number of
376  *      fill-ins are generated, then more space is allocated, but they may
377  *      not be physically close in computer's memory.
378  *
379  *  >>> Local variables:
380  *  pElement  (ElementPtr)
381  *      A pointer to the first element in the group of elements being allocated.
382  *
383  *  >>> Possible errors:
384  *  spNO_MEMORY
385  */
386 
387 static void
InitializeElementBlocks(Matrix,InitialNumberOfElements,NumberOfFillinsExpected)388 InitializeElementBlocks( Matrix, InitialNumberOfElements,
389                          NumberOfFillinsExpected )
390 
391 MatrixPtr Matrix;
392 int  InitialNumberOfElements, NumberOfFillinsExpected;
393 {
394 ElementPtr  pElement;
395 
396 /* Begin `InitializeElementBlocks'. */
397 
398 /* Allocate block of MatrixElements for elements. */
399     pElement = ALLOC(struct MatrixElement, InitialNumberOfElements);
400     RecordAllocation( Matrix, (char *)pElement );
401     if (Matrix->Error == spNO_MEMORY) return;
402     Matrix->ElementsRemaining = InitialNumberOfElements;
403     Matrix->NextAvailElement = pElement;
404 
405 /* Allocate block of MatrixElements for fill-ins. */
406     pElement = ALLOC(struct MatrixElement, NumberOfFillinsExpected);
407     RecordAllocation( Matrix, (char *)pElement );
408     if (Matrix->Error == spNO_MEMORY) return;
409     Matrix->FillinsRemaining = NumberOfFillinsExpected;
410     Matrix->NextAvailFillin = pElement;
411 
412 /* Allocate a fill-in list structure. */
413     Matrix->FirstFillinListNode = ALLOC(struct FillinListNodeStruct,1);
414     RecordAllocation( Matrix, (char *)Matrix->FirstFillinListNode );
415     if (Matrix->Error == spNO_MEMORY) return;
416     Matrix->LastFillinListNode = Matrix->FirstFillinListNode;
417 
418     Matrix->FirstFillinListNode->pFillinList = pElement;
419     Matrix->FirstFillinListNode->NumberOfFillinsInList =NumberOfFillinsExpected;
420     Matrix->FirstFillinListNode->Next = NULL;
421 
422     return;
423 }
424 
425 
426 
427 
428 
429 
430 
431 
432 
433 
434 /*
435  *  FILL-IN ALLOCATION
436  *
437  *  This routine allocates space for matrix fill-ins. It requests large blocks
438  *  of storage from the system and doles out individual elements as required.
439  *  This technique, as opposed to allocating elements individually, tends to
440  *  speed the allocation process.
441  *
442  *  >>> Returned:
443  *  A pointer to the fill-in.
444  *
445  *  >>> Arguments:
446  *  Matrix  <input>  (MatrixPtr)
447  *      Pointer to matrix.
448  *
449  *  >>> Possible errors:
450  *  spNO_MEMORY
451  */
452 
453 ElementPtr
spcGetFillin(Matrix)454 spcGetFillin( Matrix )
455 
456 MatrixPtr Matrix;
457 {
458 struct FillinListNodeStruct *pListNode;
459 ElementPtr  pFillins;
460 
461 /* Begin `spcGetFillin'. */
462 
463 #if NOT STRIP OR LINT
464     if (Matrix->FillinsRemaining == 0)
465         return spcGetElement( Matrix );
466 #endif
467 #if STRIP OR LINT
468 
469     if (Matrix->FillinsRemaining == 0)
470     {   pListNode = Matrix->LastFillinListNode;
471 
472 /* First see if there are any stripped fill-ins left. */
473         if (pListNode->Next != NULL)
474         {   Matrix->LastFillinListNode = pListNode = pListNode->Next;
475             Matrix->FillinsRemaining = pListNode->NumberOfFillinsInList;
476             Matrix->NextAvailFillin = pListNode->pFillinList;
477         }
478         else
479         {
480 /* Allocate block of fill-ins. */
481             pFillins = ALLOC(struct MatrixElement, ELEMENTS_PER_ALLOCATION);
482             RecordAllocation( Matrix, (char *)pFillins );
483             if (Matrix->Error == spNO_MEMORY) return NULL;
484             Matrix->FillinsRemaining = ELEMENTS_PER_ALLOCATION;
485             Matrix->NextAvailFillin = pFillins;
486 
487 /* Allocate a fill-in list structure. */
488             pListNode->Next = ALLOC(struct FillinListNodeStruct,1);
489             RecordAllocation( Matrix, (char *)pListNode->Next );
490             if (Matrix->Error == spNO_MEMORY) return NULL;
491             Matrix->LastFillinListNode = pListNode = pListNode->Next;
492 
493             pListNode->pFillinList = pFillins;
494             pListNode->NumberOfFillinsInList = ELEMENTS_PER_ALLOCATION;
495             pListNode->Next = NULL;
496         }
497     }
498 #endif
499 
500 /* Update Fill-in counter and return pointer to Fill-in. */
501     Matrix->FillinsRemaining--;
502     return Matrix->NextAvailFillin++;
503 }
504 
505 
506 
507 
508 
509 
510 
511 
512 
513 /*
514  *  RECORD A MEMORY ALLOCATION
515  *
516  *  This routine is used to record all memory allocations so that the memory
517  *  can be freed later.
518  *
519  *  >>> Arguments:
520  *  Matrix  <input>    (MatrixPtr)
521  *      Pointer to the matrix.
522  *  AllocatedPtr  <input>  (char *)
523  *      The pointer returned by malloc or calloc.  These pointers are saved in
524  *      a list so that they can be easily freed.
525  *
526  *  >>> Possible errors:
527  *  spNO_MEMORY
528  */
529 
530 static void
RecordAllocation(Matrix,AllocatedPtr)531 RecordAllocation( Matrix, AllocatedPtr )
532 
533 MatrixPtr Matrix;
534 char  *AllocatedPtr;
535 {
536 /* Begin `RecordAllocation'. */
537 /*
538  * If Allocated pointer is NULL, assume that malloc returned a NULL pointer,
539  * which indicates a spNO_MEMORY error.
540  */
541     if (AllocatedPtr == NULL)
542     {   Matrix->Error = spNO_MEMORY;
543         return;
544     }
545 
546 /* Allocate block of MatrixElements if necessary. */
547     if (Matrix->RecordsRemaining == 0)
548     {   AllocateBlockOfAllocationList( Matrix );
549         if (Matrix->Error == spNO_MEMORY)
550         {   FREE(AllocatedPtr);
551             return;
552         }
553     }
554 
555 /* Add Allocated pointer to Allocation List. */
556     (++Matrix->TopOfAllocationList)->AllocatedPtr = AllocatedPtr;
557     Matrix->RecordsRemaining--;
558     return;
559 
560 }
561 
562 
563 
564 
565 
566 
567 
568 
569 /*
570  *  ADD A BLOCK OF SLOTS TO ALLOCATION LIST
571  *
572  *  This routine increases the size of the allocation list.
573  *
574  *  >>> Arguments:
575  *  Matrix  <input>    (MatrixPtr)
576  *      Pointer to the matrix.
577  *
578  *  >>> Local variables:
579  *  ListPtr  (AllocationListPtr)
580  *      Pointer to the list that contains the pointers to segments of memory
581  *      that were allocated by the operating system for the current matrix.
582  *
583  *  >>> Possible errors:
584  *  spNO_MEMORY
585  */
586 
587 static void
AllocateBlockOfAllocationList(Matrix)588 AllocateBlockOfAllocationList( Matrix )
589 
590 MatrixPtr Matrix;
591 {
592 register  int  I;
593 register  AllocationListPtr  ListPtr;
594 
595 /* Begin `AllocateBlockOfAllocationList'. */
596 /* Allocate block of records for allocation list. */
597     ListPtr = ALLOC(struct AllocationRecord, (ELEMENTS_PER_ALLOCATION+1));
598     if (ListPtr == NULL)
599     {   Matrix->Error = spNO_MEMORY;
600         return;
601     }
602 
603 /* String entries of allocation list into singly linked list.  List is linked
604    such that any record points to the one before it. */
605 
606     ListPtr->NextRecord = Matrix->TopOfAllocationList;
607     Matrix->TopOfAllocationList = ListPtr;
608     ListPtr += ELEMENTS_PER_ALLOCATION;
609     for (I = ELEMENTS_PER_ALLOCATION; I > 0; I--)
610     {    ListPtr->NextRecord = ListPtr - 1;
611          ListPtr--;
612     }
613 
614 /* Record allocation of space for allocation list on allocation list. */
615     Matrix->TopOfAllocationList->AllocatedPtr = (char *)ListPtr;
616     Matrix->RecordsRemaining = ELEMENTS_PER_ALLOCATION;
617 
618     return;
619 }
620 
621 
622 
623 
624 
625 
626 
627 
628 /*
629  *  MATRIX DEALLOCATION
630  *
631  *  Deallocates pointers and elements of Matrix.
632  *
633  *  >>> Arguments:
634  *  Matrix  <input>  (char *)
635  *      Pointer to the matrix frame which is to be removed from memory.
636  *
637  *  >>> Local variables:
638  *  ListPtr  (AllocationListPtr)
639  *      Pointer into the linked list of pointers to allocated data structures.
640  *      Points to pointer to structure to be freed.
641  *  NextListPtr  (AllocationListPtr)
642  *      Pointer into the linked list of pointers to allocated data structures.
643  *      Points to the next pointer to structure to be freed.  This is needed
644  *      because the data structure to be freed could include the current node
645  *      in the allocation list.
646  */
647 
648 void
spDestroy(eMatrix)649 spDestroy( eMatrix )
650 
651 register char *eMatrix;
652 {
653 MatrixPtr Matrix = (MatrixPtr)eMatrix;
654 register  AllocationListPtr  ListPtr, NextListPtr;
655 
656 
657 /* Begin `spDestroy'. */
658     ASSERT( IS_SPARSE( Matrix ) );
659 
660 /* Deallocate the vectors that are located in the matrix frame. */
661     FREE( Matrix->IntToExtColMap );
662     FREE( Matrix->IntToExtRowMap );
663     FREE( Matrix->ExtToIntColMap );
664     FREE( Matrix->ExtToIntRowMap );
665     FREE( Matrix->Diag );
666     FREE( Matrix->FirstInRow );
667     FREE( Matrix->FirstInCol );
668     FREE( Matrix->MarkowitzRow );
669     FREE( Matrix->MarkowitzCol );
670     FREE( Matrix->MarkowitzProd );
671     FREE( Matrix->DoCmplxDirect );
672     FREE( Matrix->DoRealDirect );
673     FREE( Matrix->Intermediate );
674 
675 /* Sequentially step through the list of allocated pointers freeing pointers
676  * along the way. */
677     ListPtr = Matrix->TopOfAllocationList;
678     while (ListPtr != NULL)
679     {   NextListPtr = ListPtr->NextRecord;
680         if ((char *) ListPtr == ListPtr->AllocatedPtr)
681         {
682             FREE( ListPtr );
683         }
684         else
685         {
686             FREE( ListPtr->AllocatedPtr );
687         }
688         ListPtr = NextListPtr;
689     }
690     return;
691 }
692 
693 
694 
695 
696 
697 
698 
699 /*
700  *  RETURN MATRIX ERROR STATUS
701  *
702  *  This function is used to determine the error status of the given matrix.
703  *
704  *  >>> Returned:
705  *      The error status of the given matrix.
706  *
707  *  >>> Arguments:
708  *  eMatrix  <input>  (char *)
709  *      The matrix for which the error status is desired.
710  */
711 
712 int
spError(eMatrix)713 spError( eMatrix )
714 
715 char  *eMatrix;
716 {
717 /* Begin `spError'. */
718 
719     if (eMatrix != NULL)
720     {   ASSERT(((MatrixPtr)eMatrix)->ID == SPARSE_ID);
721         return ((MatrixPtr)eMatrix)->Error;
722     }
723     else return spNO_MEMORY;   /* This error may actually be spPANIC,
724                                 * no way to tell. */
725 }
726 
727 
728 
729 
730 
731 
732 
733 
734 
735 /*
736  *  WHERE IS MATRIX SINGULAR
737  *
738  *  This function returns the row and column number where the matrix was
739  *  detected as singular or where a zero was detected on the diagonal.
740  *
741  *  >>> Arguments:
742  *  eMatrix  <input>  (char *)
743  *      The matrix for which the error status is desired.
744  *  pRow  <output>  (int *)
745  *      The row number.
746  *  pCol  <output>  (int *)
747  *      The column number.
748  */
749 
750 void
spWhereSingular(eMatrix,pRow,pCol)751 spWhereSingular( eMatrix, pRow, pCol )
752 
753 char *eMatrix;
754 int *pRow, *pCol;
755 {
756 MatrixPtr Matrix = (MatrixPtr)eMatrix;
757 
758 /* Begin `spWhereSingular'. */
759     ASSERT( IS_SPARSE( Matrix ) );
760 
761     if (Matrix->Error == spSINGULAR OR Matrix->Error == spZERO_DIAG)
762     {   *pRow = Matrix->SingularRow;
763         *pCol = Matrix->SingularCol;
764     }
765     else *pRow = *pCol = 0;
766     return;
767 }
768 
769 
770 
771 
772 
773 
774 /*
775  *  MATRIX SIZE
776  *
777  *  Returns the size of the matrix.  Either the internal or external size of
778  *  the matrix is returned.
779  *
780  *  >>> Arguments:
781  *  eMatrix  <input>  (char *)
782  *      Pointer to matrix.
783  *  External  <input>  (BOOLEAN)
784  *      If External is set true, the external size , i.e., the value of the
785  *      largest external row or column number encountered is returned.
786  *      Otherwise the true size of the matrix is returned.  These two sizes
787  *      may differ if the TRANSLATE option is set true.
788  */
789 
790 int
spGetSize(eMatrix,External)791 spGetSize( eMatrix, External )
792 
793 char  *eMatrix;
794 BOOLEAN  External;
795 {
796 MatrixPtr Matrix = (MatrixPtr)eMatrix;
797 
798 /* Begin `spGetSize'. */
799     ASSERT( IS_SPARSE( Matrix ) );
800 
801 #if TRANSLATE
802     if (External)
803         return Matrix->ExtSize;
804     else
805         return Matrix->Size;
806 #else
807     return Matrix->Size;
808 #endif
809 }
810 
811 
812 
813 
814 
815 
816 
817 
818 /*
819  *  SET MATRIX COMPLEX OR REAL
820  *
821  *  Forces matrix to be either real or complex.
822  *
823  *  >>> Arguments:
824  *  eMatrix  <input>  (char *)
825  *      Pointer to matrix.
826  */
827 
828 void
spSetReal(eMatrix)829 spSetReal( eMatrix )
830 
831 char *eMatrix;
832 {
833 /* Begin `spSetReal'. */
834 
835     ASSERT( IS_SPARSE( (MatrixPtr)eMatrix ) AND REAL);
836     ((MatrixPtr)eMatrix)->Complex = NO;
837     return;
838 }
839 
840 
841 void
spSetComplex(eMatrix)842 spSetComplex( eMatrix )
843 
844 char  *eMatrix;
845 {
846 /* Begin `spSetComplex'. */
847 
848     ASSERT( IS_SPARSE( (MatrixPtr)eMatrix ) AND spCOMPLEX);
849     ((MatrixPtr)eMatrix)->Complex = YES;
850     return;
851 }
852 
853 
854 
855 
856 
857 
858 
859 
860 
861 /*
862  *  ELEMENT OR FILL-IN COUNT
863  *
864  *  Two functions used to return simple statistics.  Either the number
865  *  of total elements, or the number of fill-ins can be returned.
866  *
867  *  >>> Arguments:
868  *  eMatrix  <input>  (char *)
869  *      Pointer to matrix.
870  */
871 
872 int
spFillinCount(eMatrix)873 spFillinCount( eMatrix )
874 
875 char *eMatrix;
876 {
877 /* Begin `spFillinCount'. */
878 
879     ASSERT( IS_SPARSE( (MatrixPtr)eMatrix ) );
880     return ((MatrixPtr)eMatrix)->Fillins;
881 }
882 
883 
884 int
spElementCount(eMatrix)885 spElementCount( eMatrix )
886 
887 char  *eMatrix;
888 {
889 /* Begin `spElementCount'. */
890 
891     ASSERT( IS_SPARSE( (MatrixPtr)eMatrix ) );
892     return ((MatrixPtr)eMatrix)->Elements;
893 }
894