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