1 //------------------------------------------------------------------------------
2 // GB_Vector_extractElement: x = V(i)
3 //------------------------------------------------------------------------------
4 
5 // SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved.
6 // SPDX-License-Identifier: Apache-2.0
7 
8 //------------------------------------------------------------------------------
9 
10 // Extract the value of single scalar, x = V(i), typecasting from the
11 // type of V to the type of x, as needed.
12 
13 // Returns GrB_SUCCESS if V(i) is present, and sets x to its value.
14 // Returns GrB_NO_VALUE if V(i) is not present, and x is unmodified.
15 
16 // This template constructs GrB_Vector_extractElement_[TYPE], for each of the
17 // 13 built-in types, and the _UDT method for all user-defined types.
18 
19 // FUTURE: tolerate zombies
20 
GB_EXTRACT_ELEMENT(GB_XTYPE * x,const GrB_Vector V,GrB_Index i)21 GrB_Info GB_EXTRACT_ELEMENT     // extract a single entry, x = V(i)
22 (
23     GB_XTYPE *x,                // scalar to extract, not modified if not found
24     const GrB_Vector V,         // vector to extract a scalar from
25     GrB_Index i                 // index
26 )
27 {
28 
29     //--------------------------------------------------------------------------
30     // check inputs
31     //--------------------------------------------------------------------------
32 
33     GB_RETURN_IF_NULL_OR_FAULTY (V) ;
34     GB_RETURN_IF_NULL (x) ;
35 
36     // delete any lingering zombies, assemble any pending tuples, and unjumble
37     if (GB_ANY_PENDING_WORK (V))
38     {
39         GrB_Info info ;
40         GB_WHERE1 (GB_WHERE_STRING) ;
41         GB_BURBLE_START ("GrB_Vector_extractElement") ;
42         GB_OK (GB_Matrix_wait ((GrB_Matrix) V, "v", Context)) ;
43         GB_BURBLE_END ;
44     }
45 
46     ASSERT (!GB_ANY_PENDING_WORK (V)) ;
47 
48     // check index
49     if (i >= V->vlen)
50     {
51         return (GrB_INVALID_INDEX) ;
52     }
53 
54     // GB_XCODE and V must be compatible
55     GB_Type_code vcode = V->type->code ;
56     if (!GB_code_compatible (GB_XCODE, vcode))
57     {
58         return (GrB_DOMAIN_MISMATCH) ;
59     }
60 
61     if (V->nzmax == 0)
62     {
63         // quick return
64         return (GrB_NO_VALUE) ;
65     }
66 
67     //--------------------------------------------------------------------------
68     // find the entry V(i)
69     //--------------------------------------------------------------------------
70 
71     int64_t pleft ;
72     bool found ;
73     const int64_t *restrict Vp = V->p ;
74 
75     if (Vp != NULL)
76     {
77         // V is sparse
78         const int64_t *restrict Vi = V->i ;
79 
80         pleft = 0 ;
81         int64_t pright = Vp [1] - 1 ;
82 
83         // binary search for index i
84         // Time taken for this step is at most O(log(nnz(V))).
85         GB_BINARY_SEARCH (i, Vi, pleft, pright, found) ;
86     }
87     else
88     {
89         // V is bitmap or full
90         pleft = i ;
91         const int8_t *restrict Vb = V->b ;
92         if (Vb != NULL)
93         {
94             // V is bitmap
95             found = (Vb [pleft] == 1) ;
96         }
97         else
98         {
99             // V is full
100             found = true ;
101         }
102     }
103 
104     //--------------------------------------------------------------------------
105     // extract the element
106     //--------------------------------------------------------------------------
107 
108     if (found)
109     {
110         #if !defined ( GB_UDT_EXTRACT )
111         if (GB_XCODE == vcode)
112         {
113             // copy the value from V into x, no typecasting, for built-in
114             // types only.
115             GB_XTYPE *restrict Vx = ((GB_XTYPE *) (V->x)) ;
116             (*x) = Vx [pleft] ;
117         }
118         else
119         #endif
120         {
121             // typecast the value from V into x
122             size_t vsize = V->type->size ;
123             GB_cast_array ((GB_void *) x, GB_XCODE,
124                 ((GB_void *) V->x) +(pleft*vsize), vcode, NULL, vsize, 1, 1) ;
125         }
126         return (GrB_SUCCESS) ;
127     }
128     else
129     {
130         // Entry not found.
131         return (GrB_NO_VALUE) ;
132     }
133 }
134 
135 #undef GB_UDT_EXTRACT
136 #undef GB_EXTRACT_ELEMENT
137 #undef GB_XTYPE
138 #undef GB_XCODE
139 
140