LCOV - code coverage report
Current view: top level - experimental/test - LG_check_argminmax.c (source / functions) Hit Total Coverage
Test: LAGraph code coverage report. Commit id: 7b9d2ee. Current time (UTC): 2025-06-03T21:57:17Z Lines: 87 87 100.0 %
Date: 2025-06-03 22:02:40 Functions: 1 1 100.0 %

          Line data    Source code
       1             : //----------------------------------------------------------------------------
       2             : // LAGraph/experimental/test/LG_check_argminmax.c: simple arg min/max method
       3             : // ----------------------------------------------------------------------------
       4             : 
       5             : // LAGraph, (c) 2019-2025 by The LAGraph Contributors, All Rights Reserved.
       6             : // SPDX-License-Identifier: BSD-2-Clause
       7             : //
       8             : // For additional details (including references to third party source code and
       9             : // other files) see the LICENSE file or contact permission@sei.cmu.edu. See
      10             : // Contributors.txt for a full list of contributors. Created, in part, with
      11             : // funding and support from the U.S. Government (see Acknowledgments.txt file).
      12             : // DM22-0790
      13             : 
      14             : // Contributed by Tim Davis, Texas A&M University
      15             : 
      16             : // ----------------------------------------------------------------------------
      17             : 
      18             : #include "LG_Xtest.h"
      19             : #include "LG_internal.h"
      20             : 
      21             : #undef  LG_FREE_WORK
      22             : #define LG_FREE_WORK                    \
      23             : {                                       \
      24             :     LAGraph_Free ((void **) &I, msg) ;  \
      25             :     LAGraph_Free ((void **) &J, msg) ;  \
      26             :     LAGraph_Free ((void **) &X, msg) ;  \
      27             :     LAGraph_Free ((void **) &v, msg) ;  \
      28             :     LAGraph_Free ((void **) &p, msg) ;  \
      29             : }
      30             : 
      31             : #undef  LG_FREE_ALL
      32             : #define LG_FREE_ALL                     \
      33             : {                                       \
      34             :     LG_FREE_WORK ;                      \
      35             :     GrB_free (x_result) ;               \
      36             :     GrB_free (p_result) ;               \
      37             : }
      38             : 
      39             : //------------------------------------------------------------------------------
      40             : // LG_check_argminmax: compute argmin/max of each row/column of A
      41             : //------------------------------------------------------------------------------
      42             : 
      43             : // This method is single threaded and thus slow (like many LG_check_* methods).
      44             : // For simplicity, this method does all its computations in FP64, and then
      45             : // typecasts its results when done.  This can cause loss of precision if the
      46             : // input matrix is of type int64 or uint64 and has entries larger than about
      47             : // 2^52.  It can compute a different result for the position p if dim==0;
      48             : // otherwise, its results should match LAGraph_argminmax.
      49             : 
      50         265 : int LG_check_argminmax
      51             : (
      52             :     // output
      53             :     GrB_Vector *x_result,       // min/max value in each row/col of A
      54             :     GrB_Vector *p_result,       // index of min/max value in each row/col of A
      55             :     // input
      56             :     GrB_Matrix A,
      57             :     int dim,                    // dim=1: cols of A, dim=2: rows of A
      58             :                                 // dim=0: return a scalar A(i,j) in x(0) and
      59             :                                 // its row and col in p.
      60             :     bool is_min,
      61             :     char *msg
      62             : )
      63             : {
      64             : 
      65             :     //--------------------------------------------------------------------------
      66             :     // check inputs
      67             :     //--------------------------------------------------------------------------
      68             : 
      69         265 :     LG_CLEAR_MSG ;
      70             : 
      71         265 :     uint64_t *I = NULL, *J = NULL, *p = NULL ;
      72         265 :     double *X = NULL, *v = NULL ;
      73             : 
      74         265 :     LG_ASSERT (A != NULL, GrB_NULL_POINTER) ;
      75         265 :     LG_ASSERT (x_result != NULL, GrB_NULL_POINTER) ;
      76         265 :     LG_ASSERT (p_result != NULL, GrB_NULL_POINTER) ;
      77             : 
      78         265 :     (*x_result) = NULL ;
      79         265 :     (*p_result) = NULL ;
      80             : 
      81             :     //--------------------------------------------------------------------------
      82             :     // extract the entries from the matrix
      83             :     //--------------------------------------------------------------------------
      84             : 
      85             :     GrB_Index nrows, ncols, nvals, n, np ;
      86         265 :     GRB_TRY (GrB_Matrix_nrows (&nrows, A)) ;
      87         265 :     GRB_TRY (GrB_Matrix_ncols (&ncols, A)) ;
      88         265 :     GRB_TRY (GrB_Matrix_nvals (&nvals, A)) ;
      89             : 
      90         265 :     switch (dim)
      91             :     {
      92          88 :         case 0: n = 1     ; np = 2 ; break ;
      93          88 :         case 1: n = ncols ; np = n ; break ;
      94          88 :         case 2: n = nrows ; np = n ; break ;
      95           1 :         default: LG_ASSERT (false, GrB_INVALID_VALUE) ;
      96             :     }
      97             : 
      98             :     //--------------------------------------------------------------------------
      99             :     // extract the entries from the matrix
     100             :     //--------------------------------------------------------------------------
     101             : 
     102         264 :     LG_TRY (LAGraph_Malloc ((void **) &I, nvals, sizeof (uint64_t), msg)) ;
     103         264 :     LG_TRY (LAGraph_Malloc ((void **) &J, nvals, sizeof (uint64_t), msg)) ;
     104         264 :     LG_TRY (LAGraph_Malloc ((void **) &X, nvals, sizeof (double), msg)) ;
     105             : 
     106         264 :     GRB_TRY (GrB_Matrix_extractTuples_FP64 (I, J, X, &nvals, A)) ;
     107             : 
     108         264 :     GrB_Type type = NULL ;
     109             :     #if LAGRAPH_SUITSPARSE
     110             :     GRB_TRY (GxB_Matrix_type (&type, A)) ;
     111             :     #else
     112             :     char typename [LAGRAPH_MAX_NAME_LEN+1] ;
     113         264 :     LG_TRY (LAGraph_Matrix_TypeName (typename, A, msg)) ;
     114         264 :     LG_TRY (LAGraph_TypeFromName (&type, typename, msg)) ;
     115             :     #endif
     116             : 
     117             :     //--------------------------------------------------------------------------
     118             :     // allocate temporary arrays for the results
     119             :     //--------------------------------------------------------------------------
     120             : 
     121         264 :     LG_TRY (LAGraph_Calloc ((void **) &v, n, sizeof (double), msg)) ;
     122         264 :     LG_TRY (LAGraph_Malloc ((void **) &p, np, sizeof (uint64_t), msg)) ;
     123       93324 :     for (int64_t k = 0 ; k < np ; k++)
     124             :     {
     125             :         // kth entry is not yet present
     126       93060 :         p [k] = -1 ;
     127             :     }
     128             : 
     129             :     //--------------------------------------------------------------------------
     130             :     // compute the argmin/argmax
     131             :     //--------------------------------------------------------------------------
     132             : 
     133         264 :     if (dim == 0)
     134             :     {
     135             : 
     136             :         //----------------------------------------------------------------------
     137             :         // global argmin/argmax
     138             :         //----------------------------------------------------------------------
     139             : 
     140          88 :         if (nvals > 0)
     141             :         {
     142             :             // (v,p) = first entry in the matrix
     143          88 :             v [0] = X [0] ;
     144          88 :             p [0] = I [0] ;
     145          88 :             p [1] = J [0] ;
     146             : 
     147     1855590 :             for (int64_t k = 1 ; k < nvals ; k++)
     148             :             {
     149     1855502 :                 if (is_min)
     150             :                 {
     151             :                     // argmin
     152      927751 :                     if (X [k] < v [0])
     153             :                     {
     154          98 :                         v [0] = X [k] ;
     155          98 :                         p [0] = I [k] ;
     156          98 :                         p [1] = J [k] ;
     157             :                     }
     158             :                 }
     159             :                 else
     160             :                 {
     161             :                     // argmax
     162      927751 :                     if (X [k] > v [0])
     163             :                     {
     164         101 :                         v [0] = X [k] ;
     165         101 :                         p [0] = I [k] ;
     166         101 :                         p [1] = J [k] ;
     167             :                     }
     168             :                 }
     169             :             }
     170             : 
     171             :         }
     172             : 
     173             :     }
     174         176 :     else if (dim == 1)
     175             :     {
     176             : 
     177             :         //----------------------------------------------------------------------
     178             :         // argmin/argmax of each column of A
     179             :         //----------------------------------------------------------------------
     180             : 
     181     1855678 :         for (int64_t k = 0 ; k < nvals ; k++)
     182             :         {
     183     1855590 :             int64_t i = I [k] ;
     184     1855590 :             int64_t j = J [k] ;
     185     1855590 :             double x = X [k] ;
     186     1855590 :             if (p [j] == -1)
     187             :             {
     188             :                 // first entry seen in column j
     189       46442 :                 v [j] = x ;
     190       46442 :                 p [j] = i ;
     191             :             }
     192     1809148 :             else if (is_min)
     193             :             {
     194      904574 :                 if (x < v [j])
     195             :                 {
     196       30132 :                     v [j] = x ;
     197       30132 :                     p [j] = i ;
     198             :                 }
     199             :             }
     200             :             else
     201             :             {
     202      904574 :                 if (x > v [j])
     203             :                 {
     204       44540 :                     v [j] = x ;
     205       44540 :                     p [j] = i ;
     206             :                 }
     207             :             }
     208             :         }
     209             : 
     210             :     }
     211             :     else // (dim == 2)
     212             :     {
     213             : 
     214             :         //----------------------------------------------------------------------
     215             :         // argmin/argmax of each row of A
     216             :         //----------------------------------------------------------------------
     217             : 
     218     1855678 :         for (int64_t k = 0 ; k < nvals ; k++)
     219             :         {
     220     1855590 :             int64_t i = I [k] ;
     221     1855590 :             int64_t j = J [k] ;
     222     1855590 :             double x = X [k] ;
     223     1855590 :             if (p [i] == -1)
     224             :             {
     225             :                 // first entry seen in row i
     226       46442 :                 v [i] = x ;
     227       46442 :                 p [i] = j ;
     228             :             }
     229     1809148 :             else if (is_min)
     230             :             {
     231      904574 :                 if (x < v [i])
     232             :                 {
     233       30064 :                     v [i] = x ;
     234       30064 :                     p [i] = j ;
     235             :                 }
     236             :             }
     237             :             else
     238             :             {
     239      904574 :                 if (x > v [i])
     240             :                 {
     241       44176 :                     v [i] = x ;
     242       44176 :                     p [i] = j ;
     243             :                 }
     244             :             }
     245             :         }
     246             :     }
     247             : 
     248             :     //--------------------------------------------------------------------------
     249             :     // create the output vectors and fill with the results
     250             :     //--------------------------------------------------------------------------
     251             : 
     252         264 :     LG_TRY (GrB_Vector_new (x_result, type, n)) ;
     253         264 :     LG_TRY (GrB_Vector_new (p_result, GrB_INT64, np)) ;
     254             : 
     255         264 :     if (dim == 0)
     256             :     {
     257          88 :         if (nvals > 0)
     258             :         {
     259          88 :             GRB_TRY (GrB_Vector_setElement_FP64  (*x_result, v [0], 0)) ;
     260          88 :             GRB_TRY (GrB_Vector_setElement_INT64 (*p_result, p [0], 0)) ;
     261          88 :             GRB_TRY (GrB_Vector_setElement_INT64 (*p_result, p [1], 1)) ;
     262             :         }
     263             :     }
     264             :     else
     265             :     {
     266       93060 :         for (int64_t k = 0 ; k < n ; k++)
     267             :         {
     268       92884 :             if (p [k] != -1)
     269             :             {
     270       92884 :                 GRB_TRY (GrB_Vector_setElement_FP64  (*x_result, v [k], k)) ;
     271       92884 :                 GRB_TRY (GrB_Vector_setElement_INT64 (*p_result, p [k], k)) ;
     272             :             }
     273             :         }
     274             :     }
     275             : 
     276         264 :     GRB_TRY (GrB_wait (*x_result, GrB_MATERIALIZE)) ;
     277         264 :     GRB_TRY (GrB_wait (*p_result, GrB_MATERIALIZE)) ;
     278             : 
     279             :     //--------------------------------------------------------------------------
     280             :     // free workspace and return result
     281             :     //--------------------------------------------------------------------------
     282             : 
     283         264 :     LG_FREE_WORK ;
     284         264 :     return (GrB_SUCCESS) ;
     285             : }
     286             : 

Generated by: LCOV version 1.14