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