amd_order.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /* ========================================================================= */
  2. /* === AMD_order =========================================================== */
  3. /* ========================================================================= */
  4. /* ------------------------------------------------------------------------- */
  5. /* AMD, Copyright (c) Timothy A. Davis, */
  6. /* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
  7. /* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */
  8. /* web: http://www.cise.ufl.edu/research/sparse/amd */
  9. /* ------------------------------------------------------------------------- */
  10. /* User-callable AMD minimum degree ordering routine. See amd.h for
  11. * documentation.
  12. */
  13. #include "amd_internal.h"
  14. /* ========================================================================= */
  15. /* === AMD_order =========================================================== */
  16. /* ========================================================================= */
  17. GLOBAL Int AMD_order
  18. (
  19. Int n,
  20. const Int Ap [ ],
  21. const Int Ai [ ],
  22. Int P [ ],
  23. double Control [ ],
  24. double Info [ ]
  25. )
  26. {
  27. Int *Len, *S, nz, i, *Pinv, info, status, *Rp, *Ri, *Cp, *Ci, ok ;
  28. size_t nzaat, slen ;
  29. double mem = 0 ;
  30. #ifndef NDEBUG
  31. AMD_debug_init ("amd") ;
  32. #endif
  33. /* clear the Info array, if it exists */
  34. info = Info != (double *) NULL ;
  35. if (info)
  36. {
  37. for (i = 0 ; i < AMD_INFO ; i++)
  38. {
  39. Info [i] = EMPTY ;
  40. }
  41. Info [AMD_N] = n ;
  42. Info [AMD_STATUS] = AMD_OK ;
  43. }
  44. /* make sure inputs exist and n is >= 0 */
  45. if (Ai == (Int *) NULL || Ap == (Int *) NULL || P == (Int *) NULL || n < 0)
  46. {
  47. if (info) Info [AMD_STATUS] = AMD_INVALID ;
  48. return (AMD_INVALID) ; /* arguments are invalid */
  49. }
  50. if (n == 0)
  51. {
  52. return (AMD_OK) ; /* n is 0 so there's nothing to do */
  53. }
  54. nz = Ap [n] ;
  55. if (info)
  56. {
  57. Info [AMD_NZ] = nz ;
  58. }
  59. if (nz < 0)
  60. {
  61. if (info) Info [AMD_STATUS] = AMD_INVALID ;
  62. return (AMD_INVALID) ;
  63. }
  64. /* check if n or nz will cause size_t overflow */
  65. if (((size_t) n) >= SIZE_T_MAX / sizeof (Int)
  66. || ((size_t) nz) >= SIZE_T_MAX / sizeof (Int))
  67. {
  68. if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ;
  69. return (AMD_OUT_OF_MEMORY) ; /* problem too large */
  70. }
  71. /* check the input matrix: AMD_OK, AMD_INVALID, or AMD_OK_BUT_JUMBLED */
  72. status = AMD_valid (n, n, Ap, Ai) ;
  73. if (status == AMD_INVALID)
  74. {
  75. if (info) Info [AMD_STATUS] = AMD_INVALID ;
  76. return (AMD_INVALID) ; /* matrix is invalid */
  77. }
  78. /* allocate two size-n integer workspaces */
  79. Len = amd_malloc (n * sizeof (Int)) ;
  80. Pinv = amd_malloc (n * sizeof (Int)) ;
  81. mem += n ;
  82. mem += n ;
  83. if (!Len || !Pinv)
  84. {
  85. /* :: out of memory :: */
  86. amd_free (Len) ;
  87. amd_free (Pinv) ;
  88. if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ;
  89. return (AMD_OUT_OF_MEMORY) ;
  90. }
  91. if (status == AMD_OK_BUT_JUMBLED)
  92. {
  93. /* sort the input matrix and remove duplicate entries */
  94. AMD_DEBUG1 (("Matrix is jumbled\n")) ;
  95. Rp = amd_malloc ((n+1) * sizeof (Int)) ;
  96. Ri = amd_malloc (MAX (nz,1) * sizeof (Int)) ;
  97. mem += (n+1) ;
  98. mem += MAX (nz,1) ;
  99. if (!Rp || !Ri)
  100. {
  101. /* :: out of memory :: */
  102. amd_free (Rp) ;
  103. amd_free (Ri) ;
  104. amd_free (Len) ;
  105. amd_free (Pinv) ;
  106. if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ;
  107. return (AMD_OUT_OF_MEMORY) ;
  108. }
  109. /* use Len and Pinv as workspace to create R = A' */
  110. AMD_preprocess (n, Ap, Ai, Rp, Ri, Len, Pinv) ;
  111. Cp = Rp ;
  112. Ci = Ri ;
  113. }
  114. else
  115. {
  116. /* order the input matrix as-is. No need to compute R = A' first */
  117. Rp = NULL ;
  118. Ri = NULL ;
  119. Cp = (Int *) Ap ;
  120. Ci = (Int *) Ai ;
  121. }
  122. /* --------------------------------------------------------------------- */
  123. /* determine the symmetry and count off-diagonal nonzeros in A+A' */
  124. /* --------------------------------------------------------------------- */
  125. nzaat = AMD_aat (n, Cp, Ci, Len, P, Info) ;
  126. AMD_DEBUG1 (("nzaat: %g\n", (double) nzaat)) ;
  127. ASSERT ((MAX (nz-n, 0) <= nzaat) && (nzaat <= 2 * (size_t) nz)) ;
  128. /* --------------------------------------------------------------------- */
  129. /* allocate workspace for matrix, elbow room, and 6 size-n vectors */
  130. /* --------------------------------------------------------------------- */
  131. S = NULL ;
  132. slen = nzaat ; /* space for matrix */
  133. ok = ((slen + nzaat/5) >= slen) ; /* check for size_t overflow */
  134. slen += nzaat/5 ; /* add elbow room */
  135. for (i = 0 ; ok && i < 7 ; i++)
  136. {
  137. ok = ((slen + n) > slen) ; /* check for size_t overflow */
  138. slen += n ; /* size-n elbow room, 6 size-n work */
  139. }
  140. mem += slen ;
  141. ok = ok && (slen < SIZE_T_MAX / sizeof (Int)) ; /* check for overflow */
  142. ok = ok && (slen < Int_MAX) ; /* S[i] for Int i must be OK */
  143. if (ok)
  144. {
  145. S = amd_malloc (slen * sizeof (Int)) ;
  146. }
  147. AMD_DEBUG1 (("slen %g\n", (double) slen)) ;
  148. if (!S)
  149. {
  150. /* :: out of memory :: (or problem too large) */
  151. amd_free (Rp) ;
  152. amd_free (Ri) ;
  153. amd_free (Len) ;
  154. amd_free (Pinv) ;
  155. if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ;
  156. return (AMD_OUT_OF_MEMORY) ;
  157. }
  158. if (info)
  159. {
  160. /* memory usage, in bytes. */
  161. Info [AMD_MEMORY] = mem * sizeof (Int) ;
  162. }
  163. /* --------------------------------------------------------------------- */
  164. /* order the matrix */
  165. /* --------------------------------------------------------------------- */
  166. AMD_1 (n, Cp, Ci, P, Pinv, Len, slen, S, Control, Info) ;
  167. /* --------------------------------------------------------------------- */
  168. /* free the workspace */
  169. /* --------------------------------------------------------------------- */
  170. amd_free (Rp) ;
  171. amd_free (Ri) ;
  172. amd_free (Len) ;
  173. amd_free (Pinv) ;
  174. amd_free (S) ;
  175. if (info) Info [AMD_STATUS] = status ;
  176. return (status) ; /* successful ordering */
  177. }