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