1 /*
2
3 Copyright (C) 2008-2015 Michele Martone
4
5 This file is part of librsb.
6
7 librsb is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 librsb is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with librsb; see the file COPYING.
19 If not, see <http://www.gnu.org/licenses/>.
20
21 */
22 /* @cond INNERDOC */
23 /**
24 * @file
25 * @brief CSR to COO conversion code
26 * @author Michele Martone
27 * */
28 #include "rsb_common.h"
29
rsb__do_prefix_sum_coo_idx_t(rsb_nnz_idx_t * IA,rsb_nnz_idx_t nnz)30 void rsb__do_prefix_sum_coo_idx_t(rsb_nnz_idx_t *IA, rsb_nnz_idx_t nnz)
31 {
32 /* FIXME: shall optimize */
33 rsb_nnz_idx_t i;
34 for(i=1;RSB_LIKELY(i<nnz);++i)
35 IA[i] += IA[i-1];
36 }
37
rsb__do_switch_fullword_array_to_compressed(rsb_nnz_idx_t * IA,rsb_nnz_idx_t nnz,rsb_nnz_idx_t m)38 rsb_err_t rsb__do_switch_fullword_array_to_compressed(rsb_nnz_idx_t *IA, rsb_nnz_idx_t nnz, rsb_nnz_idx_t m)
39 {
40 /**
41 FIXME: no test case
42 see rsb__do_switch_compressed_array_to_fullword_coo
43 FIXME: need a no-calloc version
44 TODO: rsb__do_switch_fullword_array_to_compressed -> rsb__idx_fia2fpa
45 */
46 rsb_err_t errval = RSB_ERR_NO_ERROR;
47 rsb_nnz_idx_t i;
48 rsb_coo_idx_t * IP = NULL;
49 IP = rsb__calloc(sizeof(rsb_coo_idx_t)*(m+1));
50 if(!IP)
51 {
52 errval = RSB_ERR_ENOMEM;
53 RSB_PERR_GOTO(err,RSB_ERRM_ES);
54 }
55 #if 0
56 for(i=0;RSB_LIKELY(i<nnz);++i)
57 if(IA[i]>=m || IA[i]<0)
58 {
59 errval = RSB_ERR_BADARGS;
60 RSB_PERR_GOTO(err,"0 <= IA[%d]=%d < m=%d ?\n",i,IA[i],m);
61 }
62 #endif
63 for(i=0;RSB_LIKELY(i<nnz);++i)
64 IP[IA[i]+1]++;
65 for(i=0;RSB_LIKELY(i<m);++i)
66 IP[i+1] += IP[i];
67 RSB_COA_MEMCPY(IA,IP,0,0,m+1);
68 err:
69 RSB_CONDITIONAL_FREE(IP);
70 RSB_DO_ERR_RETURN(errval)
71 }
72
rsb__do_switch_compressed_array_to_fullword_coo(rsb_nnz_idx_t * RSB_RESTRICT IP,rsb_nnz_idx_t m,rsb_coo_idx_t off,rsb_coo_idx_t * RSB_RESTRICT TA)73 rsb_err_t rsb__do_switch_compressed_array_to_fullword_coo(rsb_nnz_idx_t *RSB_RESTRICT IP, rsb_nnz_idx_t m, rsb_coo_idx_t off, rsb_coo_idx_t *RSB_RESTRICT TA)
74 {
75 /**
76 FIXME: no test case
77 Requires m+1 temporary space.
78 see rsb__do_switch_fullword_array_to_compressed
79 TODO: rsb__do_switch_compressed_array_to_fullword_coo -> rsb__idx_fpa2fia
80 */
81 rsb_err_t errval = RSB_ERR_NO_ERROR;
82 rsb_nnz_idx_t /*k,*/li,ri;
83 //rsb_nnz_idx_t nnz = IP[m+1];
84 rsb_coo_idx_t i;
85 rsb_coo_idx_t * RSB_RESTRICT IA = TA;
86
87 if(!IA)
88 IA = rsb__malloc(sizeof(rsb_coo_idx_t)*(m+1));
89 if(!IA)
90 {
91 errval = RSB_ERR_ENOMEM;
92 RSB_PERR_GOTO(err,RSB_ERRM_ES);
93 }
94 RSB_COA_MEMCPY(IA,IP,0,0,m+1);
95 for(i=0;RSB_LIKELY(i<m);++i)
96 {
97 ri = IA[i+1];
98 li = IA[i];
99 rsb__util_coo_array_set(IP+li,ri-li,i+off);
100 }
101 err:
102 if(IA!=TA)
103 RSB_CONDITIONAL_FREE(IA);
104 RSB_DO_ERR_RETURN(errval)
105 }
106
rsb_do_switch_in_place_csr_to_in_place_coo(struct rsb_mtx_t * mtxAp,rsb_bool_t do_shift)107 rsb_err_t rsb_do_switch_in_place_csr_to_in_place_coo(struct rsb_mtx_t * mtxAp, rsb_bool_t do_shift)
108 {
109 /**
110 \ingroup gr_internals
111 */
112 rsb_err_t errval = RSB_ERR_NO_ERROR;
113 rsb_nnz_idx_t li,ri;
114 rsb_coo_idx_t i;
115 // IA needs expansion
116 rsb_coo_idx_t * IA = NULL;
117
118 if( mtxAp->flags & RSB_FLAG_USE_HALFWORD_INDICES)
119 {
120 rsb__do_switch_array_to_fullword_coo((rsb_half_idx_t*)(mtxAp->bindx),mtxAp->nnz,0);
121 }
122 else
123 {
124 }
125
126 if(rsb__is_coo_matrix(mtxAp))
127 {
128 // FIXME: TODO (nothing todo)
129 goto err;
130 }
131 IA = rsb__malloc(sizeof(rsb_coo_idx_t)*(mtxAp->Mdim+1));
132 if(!IA)
133 {
134 RSB_PERR_GOTO(err,RSB_ERRM_ES);
135 errval = RSB_ERR_ENOMEM;
136 }
137 RSB_COA_MEMCPY(IA,mtxAp->bpntr,0,0,mtxAp->Mdim+1);
138 for(i=0;RSB_LIKELY(i<mtxAp->Mdim);++i)
139 {
140 ri = IA[i+1];
141 li = IA[i];
142 rsb__util_coo_array_set(mtxAp->bpntr+li,ri-li,i);
143 }
144 if(do_shift)
145 {
146 // JA needs displacement of mtxAp->coff
147 rsb__util_coo_array_add(mtxAp->bindx,mtxAp->nnz,mtxAp->coff);
148 // IA needs displacement of mtxAp->coff
149 rsb__util_coo_array_add(mtxAp->bpntr,mtxAp->nnz,mtxAp->roff);
150 }
151 // VA is opaque to us: no processing is needed
152 RSB_CONDITIONAL_FREE(IA);
153 err:
154 RSB_DO_ERR_RETURN(errval)
155 }
156
rsb_do_count_lowtri_in_csr(const struct rsb_coo_matrix_t * csrp)157 rsb_nnz_idx_t rsb_do_count_lowtri_in_csr(const struct rsb_coo_matrix_t *csrp)
158 {
159 register rsb_coo_idx_t i;
160 register rsb_nnz_idx_t lnz = 0;
161 const rsb_coo_idx_t *IA = csrp->IA;
162 const rsb_coo_idx_t *JA = csrp->JA;
163 for(i=0;i<csrp->nr;++i)
164 {
165 register rsb_nnz_idx_t nnz0 = IA[i+0];
166 register rsb_nnz_idx_t nnz1 = IA[i+1];
167 lnz += rsb__nnz_split_coo_bsearch(JA+nnz0,i+1,nnz1-nnz0);
168 }
169 return lnz;
170 }
171
rsb__do_count_upptri_in_csr(const struct rsb_coo_matrix_t * csrp)172 rsb_nnz_idx_t rsb__do_count_upptri_in_csr(const struct rsb_coo_matrix_t *csrp)
173 {
174 register rsb_coo_idx_t i;
175 register rsb_nnz_idx_t unz = 0;
176 const rsb_coo_idx_t *IA = csrp->IA;
177 const rsb_coo_idx_t *JA = csrp->JA;
178 for(i=0;i<csrp->nr;++i)
179 {
180 register rsb_nnz_idx_t nnz0 = IA[i+0];
181 register rsb_nnz_idx_t nnz1 = IA[i+1];
182 unz += nnz1-nnz0-rsb__nnz_split_coo_bsearch(JA+nnz0,i,nnz1-nnz0);
183 }
184 return unz;
185 }
186
rsb__do_copy_lowtri_from_csr_to_coo(const struct rsb_coo_matrix_t * csrp,struct rsb_coo_matrix_t * coop)187 rsb_nnz_idx_t rsb__do_copy_lowtri_from_csr_to_coo(const struct rsb_coo_matrix_t *csrp, struct rsb_coo_matrix_t *coop)
188 {
189 register rsb_coo_idx_t i;
190 register rsb_nnz_idx_t lnz = 0;
191 const rsb_coo_idx_t *IA = csrp->IA;
192 const rsb_coo_idx_t *JA = csrp->JA;
193 const rsb_coo_idx_t *VA = csrp->VA;
194 size_t el_size = RSB_SIZEOF(csrp->typecode);
195 for(i=0;i<csrp->nr;++i)
196 {
197 register rsb_nnz_idx_t nnz0 = IA[i+0];
198 register rsb_nnz_idx_t nnz1 = IA[i+1];
199 nnz1 = nnz0+rsb__nnz_split_coo_bsearch(JA+nnz0,i+1,nnz1-nnz0);
200 RSB_CSR2COO_MEMCPY(coop->VA,coop->IA,coop->JA,VA,i,JA,lnz,nnz0,nnz1-nnz0,el_size);
201 lnz += nnz1-nnz0;
202 }
203 return lnz;
204 }
205
rsb__do_copy_upptri_from_csr_to_coo(const struct rsb_coo_matrix_t * csrp,struct rsb_coo_matrix_t * coop)206 rsb_nnz_idx_t rsb__do_copy_upptri_from_csr_to_coo(const struct rsb_coo_matrix_t *csrp, struct rsb_coo_matrix_t *coop)
207 {
208 register rsb_coo_idx_t i;
209 register rsb_nnz_idx_t unz = 0;
210 const rsb_coo_idx_t *IA = csrp->IA;
211 const rsb_coo_idx_t *JA = csrp->JA;
212 const rsb_coo_idx_t *VA = csrp->VA;
213 size_t el_size = RSB_SIZEOF(csrp->typecode);
214 for(i=0;i<csrp->nr;++i)
215 {
216 register rsb_nnz_idx_t nnz0 = IA[i+0];
217 register rsb_nnz_idx_t nnz1 = IA[i+1];
218 nnz0 = nnz0+rsb__nnz_split_coo_bsearch(JA+nnz0,i,nnz1-nnz0);
219 RSB_CSR2COO_MEMCPY(coop->VA,coop->IA,coop->JA,VA,i,JA,unz,nnz0,nnz1-nnz0,el_size);
220 unz += nnz1-nnz0;
221 }
222 return unz;
223 }
224
rsb__do_count_tri_in_csr(const struct rsb_coo_matrix_t * csrp,rsb_nnz_idx_t * lnzp,rsb_nnz_idx_t * unzp)225 rsb_nnz_idx_t rsb__do_count_tri_in_csr(const struct rsb_coo_matrix_t *csrp, rsb_nnz_idx_t *lnzp, rsb_nnz_idx_t *unzp)
226 {
227 /* FIXME: should optimize */
228 if(lnzp)
229 *lnzp = rsb_do_count_lowtri_in_csr(csrp);
230 if(unzp)
231 *unzp = rsb__do_count_upptri_in_csr(csrp);
232 return (lnzp?*lnzp:0)+(unzp?*unzp:0);
233 }
rsb__do_copy_tri_from_csr_to_coo(const struct rsb_coo_matrix_t * csrp,struct rsb_coo_matrix_t * lcoop,struct rsb_coo_matrix_t * ucoop)234 rsb_nnz_idx_t rsb__do_copy_tri_from_csr_to_coo(const struct rsb_coo_matrix_t *csrp, struct rsb_coo_matrix_t *lcoop, struct rsb_coo_matrix_t *ucoop)
235 {
236 /* FIXME: should optimize */
237 return rsb__do_copy_lowtri_from_csr_to_coo(csrp,lcoop)+rsb__do_copy_upptri_from_csr_to_coo(csrp,ucoop);
238 }
239
240 /* @endcond */
241