1 /*
2 
3 Copyright (C) 2008-2021 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  * @author Michele Martone
26  * @brief
27  * This source file contains postscript rendering functions.
28  * */
29 
30 #include "rsb_internals.h"
31 
32 RSB_INTERNALS_COMMON_HEAD_DECLS
33 
34 typedef float rsb_rf_t; /* real float */
35 #define RSB_RR_LEVELS 16
36 
37 #define RSB_PRINTF_MATRIX_TIME_ARGS(MTXAP)  \
38 					"ect: %5.2le""  "	\
39 					"est: %5.2le""  "	\
40 					"sat: %5.2le""  "	\
41 					"eit: %5.2le""  "	\
42 					"cpt: %5.2le"	\
43 					, \
44 					(MTXAP)->ect, (MTXAP)->est, (MTXAP)->sat, (MTXAP)->eit, (MTXAP)->cpt
45 
46 #define RSB_EPS_TRSL(DX,DY,SX,SY,XS,YS,MTXAP) DX = XS*(/*(MTXAP)->nc-*/(SX)); DY = YS*((MTXAP)->nr-(SY)); /* translate for EPS */
47 #define RSB_MTX_EFF_R(MTXAP) (MTXAP->bm-((MTXAP)->broff-(MTXAP)->roff)) /* effective rows count */
48 #define RSB_MTX_EFF_C(MTXAP) (MTXAP->bk-((MTXAP)->bcoff-(MTXAP)->coff)) /* effective columns count */
49 #define RSB_MTX_LAR(MTXAP) ((MTXAP)->roff+(MTXAP)->bm) /* last absolute row */
50 #define RSB_MTX_LAC(MTXAP) ((MTXAP)->coff+(MTXAP)->bk) /* last absolute column */
51 #define RSB_MTX_LER(MTXAP) ((MTXAP)->broff-(MTXAP)->roff) /* local empty rows */
52 #define RSB_MTX_LEC(MTXAP) ((MTXAP)->bcoff-(MTXAP)->coff) /* local empty columns */
53 #define RSB_EPS_NEWPATH "N" /* newpath */
54 #define RSB_EPS_MOVETO "M" /* moveto */
55 #define RSB_EPS_LINETO "L" /* lineto */
56 #define RSB_EPS_RLINETO "R" /* rlineto */
57 #define RSB_EPS_SCALEFONT "SCF" /* scalefont */
58 #define RSB_EPS_SETFONT "SF" /* setfont */
59 #define RSB_EPS_SETRGB "SRGB" /* setrgbcolor */
60 #define RSB_EPS_SETLINEWIDTH "SLW" /* setlinewidth */
61 #define RSB_EPS_CLOSEPATH "C" /* closepath */
62 
render_ps_box(FILE * fd,int r0,int c0,int dr,int dc,rsb_coo_idx_t orows,rsb_rf_t xs,rsb_rf_t ys,rsb_rf_t r,rsb_rf_t g,rsb_rf_t b)63 static rsb_err_t render_ps_box(FILE*fd, int r0, int c0, int dr, int dc, rsb_coo_idx_t orows, rsb_rf_t xs, rsb_rf_t ys, rsb_rf_t r, rsb_rf_t g, rsb_rf_t b)
64 {
65 	/**
66 	   \ingroup gr_internals
67 	   Prints out a box in the postscript language.
68 
69 	   \param r0 the box base row
70 	   \param c0 the box base column
71 	   \param dr the box height
72 	   \param dc the box width
73 	   \param orows the box offset row
74 	   \param xs the scale on x (rows)
75 	   \param ys the scale on y (column)
76 	   \param r red value
77 	   \param g green value
78 	   \param b blue value
79 	 */
80 #if RSB_ALLOW_STDOUT
81 		RSB_FPRINTF(fd,
82 			"newpath\n"
83 			"%g %g "RSB_EPS_MOVETO"\n"
84 			"%g %d "RSB_EPS_RLINETO"\n"
85 			"%d %g "RSB_EPS_RLINETO"\n"
86 			"%g %d "RSB_EPS_RLINETO"\n"
87 			"%d %d "RSB_EPS_RLINETO"\n"
88 			RSB_EPS_CLOSEPATH"\n"
89 			"%g %g %g "RSB_EPS_SETRGB"\n"
90 			"1 "RSB_EPS_SETLINEWIDTH"\n"
91 			"stroke\n\n"
92 			,
93 			c0*xs,(orows-r0)*ys,
94 			 (dc)*xs,  0,
95 			0,  -(dr)*ys,
96 			-(dc)*xs, 0,
97 /*			c0*xs,(orows-r0)*ys,
98 			 (submatrix->nc)*xs,  0,
99 			0,  -(submatrix->nr)*ys,
100 			-(submatrix->nc)*xs, 0,*/
101 			0, 0,
102 			r, g, b
103 			);
104 	return RSB_ERR_NO_ERROR;
105 #else /* RSB_ALLOW_STDOUT */
106 	return RSB_ERR_UNSUPPORTED_FEATURE;
107 #endif /* RSB_ALLOW_STDOUT */
108 }
109 
rsb_dump_postscript_z_curve(FILE * fd,const struct rsb_mtx_t * mtxAp,rsb_coo_idx_t roff,rsb_coo_idx_t coff,rsb_rf_t xs,rsb_rf_t ys,rsb_coo_idx_t orows,int level,int * p,int * pv)110 static rsb_err_t rsb_dump_postscript_z_curve(FILE*fd, const struct rsb_mtx_t * mtxAp, rsb_coo_idx_t roff, rsb_coo_idx_t coff, rsb_rf_t xs, rsb_rf_t ys, rsb_coo_idx_t orows, int level,int * p, int * pv)
111 {
112 	/**
113 	   \ingroup gr_internals
114 	 */
115 #if RSB_ALLOW_STDOUT
116 	rsb_submatrix_idx_t i,j;
117 	struct rsb_mtx_t * submatrix=NULL;
118 	const int levels = RSB_RR_LEVELS;
119 	const int want_eb=0;/* effective boundaries (FIXME: option currently unfinished) */
120 
121 	if(!mtxAp)
122 	{
123 		goto err;
124 	}
125 
126 	if(level>=levels-1)
127 		level=levels;
128 
129 #if 1
130 	if(pv)
131 	{
132 		rsb_submatrix_idx_t smi=0;
133 		RSB_SUBMATRIX_FOREACH_LEAF_PERMUTED(mtxAp,submatrix,smi,pv)
134 		//RSB_SUBMATRIX_FOREACH_LEAF(mtxAp,submatrix,smi)
135 		{
136 			rsb_dump_postscript_z_curve(fd,submatrix,submatrix->roff,submatrix->coff,xs,ys,orows,level+1,p,NULL);
137 
138 			if(smi<mtxAp->all_leaf_matrices_n-1)
139 			{
140 				rsb_rf_t fcoff=(rsb_rf_t)submatrix->coff;
141 				rsb_rf_t froff=(rsb_rf_t)submatrix->roff;
142 				rsb_rf_t fnc=(rsb_rf_t)submatrix->nc;
143 				rsb_rf_t fnr=(rsb_rf_t)submatrix->nr;
144 				rsb_rf_t shade= .8 - (.8*smi)/(mtxAp->all_leaf_matrices_n);
145 
146 				if(want_eb)
147 				{
148 					fcoff=(rsb_rf_t)submatrix->bcoff;
149 					froff=(rsb_rf_t)submatrix->broff;
150 					fnc=(rsb_rf_t)submatrix->bm;
151 					fnr=(rsb_rf_t)submatrix->bk;
152 				}
153 
154 				RSB_FPRINTF(fd,"%g %g %g "RSB_EPS_SETRGB" 1 "RSB_EPS_SETLINEWIDTH" stroke "RSB_EPS_NEWPATH" %g %g "RSB_EPS_MOVETO"\n",
155 				shade,shade,1.0, (fcoff*xs+fnc*(xs/2)), ((-froff+orows))*ys-(fnr)*(ys/2));
156 			}
157 
158 		}
159 		goto ret;
160 	}
161 #endif
162 
163 	if(rsb__is_terminal_recursive_matrix(mtxAp))
164 	{
165 		rsb_coo_idx_t scoff=coff;
166 		rsb_coo_idx_t sroff=roff;
167 		rsb_coo_idx_t snc=mtxAp->nc;
168 		rsb_coo_idx_t snr=mtxAp->nr;
169 		const int want_sc = 1;/* want submatrix comments */
170 
171 		if(want_eb)
172 		{
173 			sroff=roff+RSB_MTX_LER(mtxAp);
174 			scoff=coff+RSB_MTX_LEC(mtxAp);
175 			snr=mtxAp->bm;
176 			snc=mtxAp->bk;
177 		}
178 
179 		if(want_sc)
180 		RSB_FPRINTF(fd,"%% matrix at %d %d, level %d, xs %g, ys %g, orows %d\n",sroff,scoff,level,xs,ys,orows);
181 		if(*p>0)
182 			RSB_FPRINTF(fd, "%g %g "RSB_EPS_LINETO"\n" , scoff*xs+snc*(xs/2), ((rsb_rf_t)(orows-sroff))*ys-((rsb_rf_t)snr)*(ys/2));
183 		else
184 			RSB_FPRINTF(fd, "%g %g "RSB_EPS_MOVETO"\n" , scoff*xs+snc*(xs/2), ((rsb_rf_t)(orows-sroff))*ys-((rsb_rf_t)snr)*(ys/2));
185 		++*p;
186 	}
187 	else
188 	{
189 		RSB_SUBMATRIX_FOREACH(mtxAp,submatrix,i,j)
190 		if(submatrix)
191 		{
192 //			rsb_coo_idx_t scoff=submatrix->coff;
193 //			rsb_coo_idx_t sroff=submatrix->roff;
194 			rsb_coo_idx_t snc=submatrix->nc;
195 			rsb_coo_idx_t snr=submatrix->nr;
196 
197 			if(0)
198 			if(want_eb)
199 			{
200 		//		scoff=submatrix->bcoff;
201 		//		sroff=submatrix->broff;
202 		//		snr=submatrix->bm;
203 		//		snc=submatrix->bk;
204 			}
205 
206 			rsb_dump_postscript_z_curve(fd,submatrix, roff+(i?(mtxAp->nr-snr):0), coff+(j?mtxAp->nc-snc:0),xs,ys,orows, level+1,p,NULL);
207 		}
208 	}
209 ret:
210 	return RSB_ERR_NO_ERROR;
211 err:
212 	return RSB_ERR_GENERIC_ERROR;
213 #else /* RSB_ALLOW_STDOUT */
214 	return RSB_ERR_UNSUPPORTED_FEATURE;
215 #endif /* RSB_ALLOW_STDOUT */
216 }
217 
rsb__dump_postscript_ussv_order_curve(const struct rsb_mtx_t * mtxAp,rsb_rf_t xs,rsb_rf_t ys,int * p)218 static rsb_err_t rsb__dump_postscript_ussv_order_curve(const struct rsb_mtx_t * mtxAp, rsb_rf_t xs, rsb_rf_t ys, int * p)
219 {
220 	/**
221 	   \ingroup gr_internals
222 	   NEW, EXPERIMENTAL
223 	 */
224 #if RSB_ALLOW_STDOUT
225 	rsb_err_t errval = RSB_ERR_NO_ERROR;
226 	struct rsb_translated_matrix_t * all_leaf_matrices=NULL;
227 	rsb_submatrix_idx_t all_leaf_matrices_n=0,n;
228 	FILE*fd = RSB_DEFAULT_FD;
229 
230 	if(!mtxAp)
231 	{
232 		goto err;
233 	}
234 
235 	errval = rsb__do_get_submatrices_for_ussv(mtxAp,&all_leaf_matrices,&all_leaf_matrices_n,RSB_TRANSPOSITION_N);
236 	if(!all_leaf_matrices || RSB_SOME_ERROR(errval))
237 	{
238 		errval = RSB_ERR_ENOMEM;
239 	       	RSB_PERR_GOTO(err,RSB_ERRM_ES);
240 	}
241 
242 	if(RSB_SOME_ERROR(errval))
243 	{ RSB_PERR_GOTO(err,RSB_ERRM_ES) }
244 
245 	RSB_FPRINTF(fd,"%%%%there are %d leaves, %d for ussv\n",mtxAp->all_leaf_matrices_n,all_leaf_matrices_n);
246 #if 1
247 	for(n=0;n<all_leaf_matrices_n;++n)
248 	{
249 		rsb_coo_idx_t rows=all_leaf_matrices[n].nr;
250 		rsb_coo_idx_t cols=all_leaf_matrices[n].nc;
251 		rsb_coo_idx_t roff=all_leaf_matrices[n].roff;
252 		rsb_coo_idx_t coff=all_leaf_matrices[n].coff;
253 		rsb_coo_idx_t my=mtxAp->nr-((roff+rows/2));
254 		rsb_coo_idx_t mx=(coff+cols/2);
255 		rsb_rf_t mys=my;
256 		rsb_rf_t mxs=mx;
257 		mys*=ys/mtxAp->nc;
258 		mxs*=xs/mtxAp->nr;
259 //		my/=mtxAp->cols;
260 		RSB_FPRINTF(fd,"%% matrix %d at %d %d, %d x %d \n",n,roff,coff,rows,cols);
261 		if(*p>0)
262 			RSB_FPRINTF(fd, "%g %g "RSB_EPS_LINETO"\n" , mxs, mys);
263 		else
264 			RSB_FPRINTF(fd, "%g %g "RSB_EPS_MOVETO"\n" , mxs, mys);
265 		++*p;
266 	}
267 #endif
268 err:
269 	RSB_CONDITIONAL_FREE(all_leaf_matrices);
270 	RSB_DO_ERR_RETURN(errval)
271 #else /* RSB_ALLOW_STDOUT */
272 	RSB_DO_ERR_RETURN(RSB_ERR_UNSUPPORTED_FEATURE)
273 #endif /* RSB_ALLOW_STDOUT */
274 }
275 
rsb__dump_postscript(const int argc,char * const argv[])276 int rsb__dump_postscript(const int argc, char * const argv[])
277 {
278 	/**
279 	   \ingroup gr_internals
280 	*/
281 	rsb_err_t errval = RSB_ERR_NO_ERROR;
282 	rsb_option options[] = {
283 	    {"matrix-filename",	required_argument, NULL, 0x66},/* f */
284 	    {"dump-recursion",	no_argument, NULL, 'd'},/* NEW */
285 	    {"width",required_argument	, NULL, 0x5757},/* W */
286 	    {"height",required_argument	, NULL, 0x4848}, /* H */
287 	    {"auto-size",no_argument	, NULL, 'a'},
288 	    {"block-dump",no_argument	, NULL, 'B'},
289 	    {"nonzeros-dump",no_argument, NULL, 'N'},
290 	    {"block-rowsize",	required_argument, NULL, 0x72 },/* r */
291 	    {"block-columnsize",	required_argument, NULL, 0x63},/* c */
292 	    {"z-dump",	no_argument, NULL, 'z'},
293 	    {"ussv-dump",	no_argument, NULL, 'S'},
294 	    RSB_BENCH_PROG_OPTS
295 	    {0,0,0,0}
296 	};
297 
298 #ifdef RSB_NUMERICAL_TYPE_FLOAT
299 	rsb_type_t typecode = RSB_NUMERICAL_TYPE_DOUBLE ;
300 #else /* RSB_NUMERICAL_TYPE_FLOAT */
301 #ifdef RSB_NUMERICAL_TYPE_DOUBLE
302 	rsb_type_t typecode = RSB_NUMERICAL_TYPE_DOUBLE ;
303 #else /* RSB_NUMERICAL_TYPE_DOUBLE */
304 	rsb_type_t typecode = RSB_NUMERICAL_TYPE_DEFAULT;
305 #endif /* RSB_NUMERICAL_TYPE_DOUBLE */
306 #endif /* RSB_NUMERICAL_TYPE_FLOAT */
307 	rsb_blk_idx_t br=1;
308 	rsb_blk_idx_t bc=1;
309 
310 	const char * filename=NULL;
311 	int c,w = RSB_DEFAULT_MATRIX_RENDERING_COLS,h = RSB_DEFAULT_MATRIX_RENDERING_ROWS;
312 	int opt_index = 0;
313 	int dump_recursion=0;
314 	int g_auto_size=0;
315 	rsb_bool_t want_blocks=0,want_nonzeros=0,z_dump=0;
316 
317 	rsb_flags_t flags = RSB_FLAG_NOFLAGS;
318 
319 	if((errval = rsb_lib_init(RSB_NULL_INIT_OPTIONS))!=RSB_ERR_NO_ERROR)
320 	{
321 		RSB_PERR_GOTO(err,RSB_ERRM_ES);
322 	}
323 
324     	for (;;)
325 	{
326 		c = rsb_getopt_long(argc,argv,RSB_SAMPLE_PROGRAM_OPTIONS_GET_FLAGS"ar:c:df:BNzSn:"/*"W:H:"*/,options,&opt_index);
327 		if (c == -1)
328 			break;
329 		RSB_DO_FLAG_ADD(flags,rsb__sample_program_options_get_flags(c,optarg));	/* FIXME : NEW */
330 		switch (c)
331 		{
332 			case 'r':
333 			br = rsb__util_atoi(optarg);
334 			if(br<1) { errval = RSB_ERR_BADARGS; RSB_PERR_GOTO(err,RSB_ERRM_ES); }
335 			break;
336 			case 'c':
337 			bc = rsb__util_atoi(optarg);
338 			if(br<1) { errval = RSB_ERR_BADARGS; RSB_PERR_GOTO(err,RSB_ERRM_ES); }
339 			break;
340 			case 'f':
341 			filename = optarg;
342 			break;
343 			case 'N':
344 			want_nonzeros=1;
345 			break;
346 			case 'B':
347 			want_blocks=1;
348 			break;
349 			case 'a':
350 			g_auto_size=1;
351 			break;
352 			case 'd':
353 			dump_recursion=1;
354 			break;
355 			case 'S':
356 			z_dump=2;
357 			RSB_DO_FLAG_ADD(flags,RSB_FLAG_LOWER_TRIANGULAR);
358 			break;
359 			case 'z':
360 			z_dump=1;
361 			break;
362  			case 0x4848:
363 			h = rsb__util_atoi(optarg);
364 			if(h<1) { errval = RSB_ERR_BADARGS; RSB_PERR_GOTO(err,RSB_ERRM_ES); }
365 			break;
366 			case 0x5757:
367 			w = rsb__util_atoi(optarg);
368 			if(w<1) { errval = RSB_ERR_BADARGS; RSB_PERR_GOTO(err,RSB_ERRM_ES); }
369 			break;
370 			case 'T':
371 			typecode = toupper(*optarg);
372 			break;
373 			case 'n':
374 #if 1
375 			rsb__set_num_threads(rsb__util_atoi(optarg));
376 #else
377 			{
378 				rsb_thread_t ca_[1]={1};
379 				rsb_thread_t * ca=ca_;
380 				rsb_thread_t cn=1,ci=0;
381 				ca=NULL;cn=0;
382 				if(RSB_SOME_ERROR(errval = rsb__util_get_bx_array(optarg,&cn,&ca)))
383 				{
384 				       	RSB_PERR_GOTO(err,RSB_ERRM_ES);
385 				}
386 			}
387 #endif
388 			default:
389 			;
390 	    	}
391 	}
392 
393 	if(!filename)
394 	{
395 		const char*usagestring=" -aRzd -f pd.mtx";
396 		//errval = RSB_ERR_BADARGS;
397 		RSB_INFO("Did not specify a matrix file.\n");
398 		RSB_INFO("Usage example: %s %s\n",argv[0],usagestring);
399 		//RSB_ERROR(RSB_ERRM_ES);
400 		goto err;
401 	}
402 
403 	RSB_DO_FLAG_DEL(flags,RSB_FLAG_EXPERIMENTAL_IN_PLACE_CSR); /* FIXME : breaks  -r1 -c1 -Fbr -aRzD */
404 	if(g_auto_size)
405 	{
406 		/* rescale smartly to reflect the desired area and keep proportions (but lose both dimensions) */
407 		size_t cols,rows;
408 		rsb_rf_t area=1,p;
409 		rsb_flags_t flags = RSB_FLAG_NOFLAGS;
410 
411 		if(RSB_SOME_ERROR(rsb__do_util_get_matrix_dimensions(filename, &cols, &rows, NULL, &flags)))
412 			goto err;
413 
414 		area*=w;
415 		area*=h;
416 		p=((rsb_rf_t)cols)/((rsb_rf_t)rows);
417 		h=sqrt(area/p);
418 		w=h*p;
419 	}
420 
421 	if(!dump_recursion)
422 		want_nonzeros = 1;
423 
424 	errval = rsb__dump_postscript_recursion_from_matrix(filename,br,bc,w,h,flags,want_blocks,z_dump,want_nonzeros,dump_recursion,typecode);
425 err:
426 	RSB_MASK_OUT_SOME_ERRORS(errval)
427 	rsb__do_perror(NULL,errval);
428 	return RSB_ERR_TO_PROGRAM_ERROR(errval);
429 }
430 
rsb__dump_block_rectangles(FILE * fd,const struct rsb_mtx_t * mtxAp,rsb_coo_idx_t roff,rsb_coo_idx_t coff,rsb_rf_t xs,rsb_rf_t ys,rsb_coo_idx_t orows,int level)431 static rsb_err_t rsb__dump_block_rectangles(FILE*fd, const struct rsb_mtx_t * mtxAp, rsb_coo_idx_t roff, rsb_coo_idx_t coff, rsb_rf_t xs, rsb_rf_t ys, rsb_coo_idx_t orows, int level)
432 {
433 	/**
434 	 */
435 #if RSB_ALLOW_STDOUT
436 	rsb_submatrix_idx_t i,j;
437 	struct rsb_mtx_t * submatrix = NULL;
438 	const int levels = RSB_RR_LEVELS;
439 	const int want_eb = 0;/* want effective boundaries (working) */
440 	const int want_sc = 1;/* want submatrix comments */
441 	rsb_rf_t shade;
442 
443 	if(!mtxAp)
444 	{
445 		goto err;
446 	}
447 
448 	if(level>=levels-1)
449 		level=levels;
450 	shade = 1.0*(level)/levels;
451 
452 	if(want_sc)RSB_FPRINTF(fd,"%% matrix at %d %d, level %d\n",roff,coff,level);
453 	if(rsb__is_terminal_recursive_matrix(mtxAp))
454 	{
455 		rsb_coo_idx_t eroff=mtxAp->broff,ecoff=mtxAp->bcoff;
456 		rsb_coo_idx_t er=RSB_MTX_EFF_R(mtxAp),ec=RSB_MTX_EFF_C(mtxAp);
457 		if(want_eb==0)
458 			eroff=mtxAp->roff,ecoff=mtxAp->coff,er=mtxAp->nr,ec=mtxAp->nc;
459 		if(want_sc)RSB_FPRINTF(fd,"%% terminal matrix at %d %d\n",roff,coff);
460 		render_ps_box(fd,eroff, ecoff, er, ec, orows, xs, ys, shade, shade, shade);
461 	}
462 
463 	RSB_SUBMATRIX_FOREACH(mtxAp,submatrix,i,j)
464 	if(submatrix)
465 	{
466 		rsb__dump_block_rectangles(fd,submatrix, roff+(i?(mtxAp->nr-submatrix->nr):0), coff+(j?mtxAp->nc-submatrix->nc:0),xs,ys,orows, level+1);
467 	}
468 
469 	return RSB_ERR_NO_ERROR;
470 err:
471 	return RSB_ERR_GENERIC_ERROR;
472 #else /* RSB_ALLOW_STDOUT */
473 	return RSB_ERR_UNSUPPORTED_FEATURE;
474 #endif /* RSB_ALLOW_STDOUT */
475 }
476 
rsb__dump_postscript_recursion_from_mtx_t(FILE * fd,const char * filename,const struct rsb_mtx_t * mtxAp,rsb_blk_idx_t br,rsb_blk_idx_t bc,int width,int height,rsb_marf_t rflags,rsb_bool_t want_blocks,rsb_bool_t z_dump,rsb_bool_t want_nonzeros,int * pv)477 rsb_err_t rsb__dump_postscript_recursion_from_mtx_t(FILE*fd, const char * filename, const struct rsb_mtx_t*mtxAp, rsb_blk_idx_t br, rsb_blk_idx_t bc, int width, int height, rsb_marf_t rflags, rsb_bool_t want_blocks, rsb_bool_t z_dump, rsb_bool_t want_nonzeros, int *pv )
478 {
479 	/*
480 	 * ( rflags == RSB_FLAG_NOFLAGS ) is allowed and implies defaults.
481 	 * */
482 	rsb_err_t errval = RSB_ERR_NO_ERROR;
483 	rsb_coo_idx_t nrA = mtxAp->nr, ncA = mtxAp->nc;
484 	const int want_structure_comments_dump = 1;
485 	rsb_rf_t xs, ys;
486 
487 	if(fd && filename)
488 	{
489 		errval = RSB_ERR_BADARGS;
490 		RSB_PERR_GOTO(err,RSB_ERRM_ES);
491 	}
492 
493 	if(filename)
494 	{
495 		fd = rsb__util_fopen(filename,"w");
496 		if( fd == NULL )
497 		{
498 			errval=RSB_ERR_GENERIC_ERROR;
499 			goto err;
500 		}
501 	}
502 
503 	ys = ((rsb_rf_t)height)/nrA, xs = ((rsb_rf_t)width)/ncA;
504 	errval = rsb__do_print_postscript_header(fd, width, height, xs, ys );
505 
506 	if(want_structure_comments_dump)
507 	{
508 		RSB_POSTSCRIPT_DUMP_COMMENT(fd,RSB_PRINTF_MTX_SUMMARY_ARGS(mtxAp));
509 		RSB_POSTSCRIPT_DUMP_COMMENT(fd,RSB_PRINTF_MATRIX_TIME_ARGS(mtxAp));
510 		RSB_FPRINTF(fd,"%%%% ");
511 		rsb__fprint_matrix_implementation_code(mtxAp, "", mtxAp->flags, fd);
512 		RSB_FPRINTF(fd,"\n");
513 	}
514 
515 	if( rflags == RSB_MARF_EPS_L )
516 	{
517 			struct rsb_mtx_t * submatrix = NULL;
518 			rsb_submatrix_idx_t smi;
519 			double mnnz = 0, annz = 0;
520 			rsb_coo_idx_t hoo = -RSB_MIN(RSB_MIN(mtxAp->nr,mtxAp->nc)/1000,10); /* how much out; this shall turn some coloured lines inwards the box; on smaller matrices this shall be limited */
521 
522 			RSB_SUBMATRIX_FOREACH_LEAF(mtxAp,submatrix,smi)
523 				mnnz = RSB_MAX(mnnz,submatrix->nnz),
524 				annz += submatrix->nnz;
525 			annz /= mtxAp->all_leaf_matrices_n;
526 
527 			RSB_FPRINTF(fd,"%% colored boxes dump\n");
528 			RSB_SUBMATRIX_FOREACH_LEAF(mtxAp,submatrix,smi)
529 			{
530 				rsb_rf_t fx,fy;
531 				double rv,gv,bv, iv;
532 
533 				RSB_EPS_TRSL(fx,fy,submatrix->bcoff,submatrix->broff,xs,ys,mtxAp);
534 				RSB_FPRINTF(fd,RSB_EPS_NEWPATH" %g %g "RSB_EPS_MOVETO" ",fx,fy);
535 				RSB_FPRINTF(fd,"%g %g "RSB_EPS_RLINETO" ", xs*RSB_MTX_EFF_C(submatrix),0.0);
536 				RSB_FPRINTF(fd,"%g %g "RSB_EPS_RLINETO" ",0.0,-ys*RSB_MTX_EFF_R(submatrix));
537 				RSB_FPRINTF(fd,"%g %g "RSB_EPS_RLINETO" ",-xs*RSB_MTX_EFF_C(submatrix),0.0);
538 
539 				if(submatrix->nnz > annz)
540 					iv = 0.3 * ( ( - annz + submatrix->nnz ) / submatrix->nnz ),
541 					rv = gv = bv = 0.7,
542 					rv+=iv;
543 				else
544 					iv = 0.3 * ( ( + annz - submatrix->nnz ) / annz ),
545 					rv = gv = bv = 0.7,
546 				       	gv+=iv;
547 				RSB_FPRINTF(fd,RSB_EPS_CLOSEPATH" %g %g %g "RSB_EPS_SETRGB" 1 "RSB_EPS_SETLINEWIDTH" fill ",rv,gv,bv);
548 				RSB_FPRINTF(fd,"%% submatrix %d square\n",smi);
549 			}
550 
551 			RSB_FPRINTF(fd,"%% lhs dump\n");
552 			RSB_SUBMATRIX_FOREACH_LEAF(mtxAp,submatrix,smi)
553 			{
554 				rsb_rf_t fx,fy,tx,ty;
555 /*
556 				RSB_FPRINTF(fd,RSB_EPS_NEWPATH" ");
557 				RSB_EPS_TRSL(fx,fy,submatrix->coff ,submatrix->roff,xs,ys,mtxAp);
558 				RSB_EPS_TRSL(tx,ty,0               ,submatrix->roff,xs,ys,mtxAp);
559 				RSB_FPRINTF(fd,"%g %g "RSB_EPS_MOVETO" ",fx,fy);
560 				RSB_FPRINTF(fd,"%g %g lineto ",tx,ty);
561 				px=tx,py=ty;
562 				RSB_EPS_TRSL(fx,fy,submatrix->coff ,submatrix->roff+submatrix->nr,xs,ys,mtxAp);
563 				RSB_EPS_TRSL(tx,ty,0               ,submatrix->roff+submatrix->nr,xs,ys,mtxAp);
564 				RSB_FPRINTF(fd,"%g %g "RSB_EPS_MOVETO" ",fx,fy);
565 				RSB_FPRINTF(fd,"%g %g lineto ",tx,ty);
566 
567 				RSB_FPRINTF(fd,"closepath "); RSB_FPRINTF(fd,"1 0 1 "RSB_EPS_SETRGB" "); RSB_FPRINTF(fd,"1 setlinewidth "); RSB_FPRINTF(fd,"1 stroke ");
568 				RSB_FPRINTF(fd,"%% submatrix %d to-lhs\n",smi);
569 
570 				RSB_FPRINTF(fd,RSB_EPS_NEWPATH" ");
571 				RSB_FPRINTF(fd,"%g %g "RSB_EPS_MOVETO" ",px,py);
572 				RSB_FPRINTF(fd,"%g %g lineto ",tx,ty);
573 				RSB_FPRINTF(fd,"closepath "); RSB_FPRINTF(fd,"1 0 1 "RSB_EPS_SETRGB" "); RSB_FPRINTF(fd,"5 setlinewidth "); RSB_FPRINTF(fd,"1 stroke ");
574 				RSB_FPRINTF(fd,"%% submatrix %d lhs\n",smi);
575 				*/
576 
577 				RSB_EPS_TRSL(fx,fy,-hoo+submatrix->bcoff,-hoo+submatrix->broff      ,xs,ys,mtxAp);
578 				RSB_EPS_TRSL(tx,ty,-hoo+submatrix->bcoff,-hoo+RSB_MTX_LAR(submatrix),xs,ys,mtxAp);
579 				RSB_FPRINTF(fd,RSB_EPS_NEWPATH" %g %g "RSB_EPS_MOVETO" %g %g "RSB_EPS_LINETO" ",fx,fy,tx,ty);
580 				RSB_FPRINTF(fd,RSB_EPS_CLOSEPATH" 1 0 1 "RSB_EPS_SETRGB" 1 "RSB_EPS_SETLINEWIDTH" 1 stroke ");
581 				RSB_FPRINTF(fd,"%% submatrix %d lhs\n",smi);
582 			}
583 
584 			RSB_FPRINTF(fd,"%% rhs dump\n");
585 			RSB_SUBMATRIX_FOREACH_LEAF(mtxAp,submatrix,smi)
586 			{
587 				rsb_rf_t fx,fy,tx,ty;
588 				//rsb_rf_t ih = (RSB_DO_FLAG_HAS(submatrix->flags,RSB_FLAG_USE_HALFWORD_INDICES)) ? 1.0 : 0.0;
589 /*
590 				RSB_FPRINTF(fd,"%% submatrix %d\n",smi);
591 				RSB_FPRINTF(fd,RSB_EPS_NEWPATH" ");
592 
593 				RSB_EPS_TRSL(fx,fy,submatrix->coff ,submatrix->roff,xs,ys,mtxAp);
594 				RSB_EPS_TRSL(tx,ty,mtxAp->nr       ,submatrix->coff,xs,ys,mtxAp);
595 				RSB_FPRINTF(fd,"%g %g moveto ",fx,fy);
596 				RSB_FPRINTF(fd,"%g %g lineto ",tx,ty);
597 				px=tx,py=ty;
598 				RSB_EPS_TRSL(fx,fy,submatrix->coff+submatrix->nc,submatrix->roff,              xs,ys,mtxAp);
599 				RSB_EPS_TRSL(tx,ty,mtxAp->nr                    ,submatrix->coff+submatrix->nc,xs,ys,mtxAp);
600 				RSB_FPRINTF(fd,"%g %g moveto ",fx,fy);
601 				RSB_FPRINTF(fd,"%g %g lineto ",tx,ty);
602 				RSB_FPRINTF(fd,"closepath "); RSB_FPRINTF(fd,"0.5 1 0.5 setrgbcolor "); RSB_FPRINTF(fd,"1 setlinewidth "); RSB_FPRINTF(fd,"1 stroke ");
603 				RSB_FPRINTF(fd,"%% submatrix %d to-rhs\n",smi);
604 
605 				RSB_FPRINTF(fd,RSB_EPS_NEWPATH" ");
606 				RSB_FPRINTF(fd,"%g %g moveto ",px,py);
607 				RSB_FPRINTF(fd,"%g %g lineto ",tx,ty);
608 				RSB_FPRINTF(fd,"closepath "); RSB_FPRINTF(fd,"0.5 1 0.5 setrgbcolor "); RSB_FPRINTF(fd,"5 setlinewidth "); RSB_FPRINTF(fd,"1 stroke ");
609 				RSB_FPRINTF(fd,"%% submatrix %d rhs\n",smi);
610 			*/
611 				RSB_EPS_TRSL(fx,fy,-hoo+submatrix->bcoff,             -hoo+submatrix->broff,xs,ys,mtxAp);
612 				RSB_EPS_TRSL(tx,ty,-hoo+submatrix->coff+submatrix->bk,-hoo+submatrix->broff,xs,ys,mtxAp);
613 				RSB_FPRINTF(fd,RSB_EPS_NEWPATH" %g %g "RSB_EPS_MOVETO" %g %g "RSB_EPS_LINETO" ",fx,fy,tx,ty);
614 				RSB_FPRINTF(fd,RSB_EPS_CLOSEPATH" .5 1 .5 "RSB_EPS_SETRGB" 1 "RSB_EPS_SETLINEWIDTH" 1 stroke ");
615 				RSB_FPRINTF(fd,"%% submatrix %d rhs\n",smi);
616 			}
617 
618 			RSB_FPRINTF(fd,"%% node content labels\n");
619 			RSB_SUBMATRIX_FOREACH_LEAF(mtxAp,submatrix,smi)
620 			{
621 				rsb_rf_t ox,oy;
622 				char fstr[RSB_MAX_STRERRLEN];
623 				double fs;
624 
625 				RSB_EPS_TRSL(ox,oy,submatrix->coff,submatrix->roff+submatrix->nr/2,xs,ys,mtxAp);
626 				sprintf(fstr," %d/%d %s%s %0.1e",1+smi,mtxAp->all_leaf_matrices_n,(RSB_DO_FLAG_HAS(submatrix->flags,RSB_FLAG_USE_HALFWORD_INDICES))?"H":"",(submatrix->matrix_storage == RSB_MATRIX_STORAGE_BCOR)?"COO":"CSR",(double)(submatrix->nnz));
627 				fs = ( xs * submatrix->nc ) /  ( strlen(fstr) ) * 1.3 ;
628 				RSB_FPRINTF(fd,"/Courier-Bold findfont %g "RSB_EPS_SCALEFONT" "RSB_EPS_SETFONT" %g %g "RSB_EPS_MOVETO" (%s) 0 0 0 "RSB_EPS_SETRGB" show\n",fs,ox,oy,fstr);
629 			}
630 	}
631 
632 	RSB_POSTSCRIPT_DUMP_COMMENT(fd,"sparse blocks dump");
633 	errval = rsb__dump_block_rectangles(fd,mtxAp,0,0,xs,ys,mtxAp->nr,0);
634 
635 	if(z_dump)
636 	{
637 		int p = 0;
638 		RSB_POSTSCRIPT_DUMP_COMMENT(fd,"z dump\nnewpath");
639 
640 		if(z_dump==1)
641 			errval = rsb_dump_postscript_z_curve(fd,mtxAp, 0,0,xs,ys,mtxAp->nr,0,&p,pv);
642 		else
643 			errval = rsb__dump_postscript_ussv_order_curve(mtxAp,(rsb_rf_t)height,(rsb_rf_t)width,&p);
644 		RSB_FPRINTF(fd,
645 			"%d %d  %d setrgbcolor\n"
646 			"1 setlinewidth\n"
647 			"stroke\n\n"
648 			,
649 			0,0,1
650 			);
651 	}
652 	if(want_blocks)
653 		;/* dead code removed from here */
654 	if(filename)
655 	{
656 		fclose(fd);
657 	}
658 err:
659 	return errval;
660 }
661 
rsb_dump_postscript_from_coo(FILE * fd,rsb_coo_idx_t * IA,rsb_coo_idx_t * JA,void * VA,rsb_coo_idx_t m,rsb_coo_idx_t k,rsb_nnz_idx_t nnz,rsb_blk_idx_t br,rsb_blk_idx_t bc,int width,int height,rsb_bool_t all_nnz,rsb_type_t typecode)662 static rsb_err_t rsb_dump_postscript_from_coo(FILE*fd, rsb_coo_idx_t *IA, rsb_coo_idx_t *JA, void *VA, rsb_coo_idx_t m, rsb_coo_idx_t k, rsb_nnz_idx_t nnz, rsb_blk_idx_t br, rsb_blk_idx_t bc, int width, int height, rsb_bool_t all_nnz, rsb_type_t typecode)
663 {
664 	/**
665 	 \ingroup gr_internals
666 	 Need better error handling.
667 	 This function is experimentally used to render the sparse matrix.
668 	 */
669 #if RSB_ALLOW_STDOUT
670 	rsb_err_t errval = RSB_ERR_NO_ERROR;
671 	rsb_nnz_idx_t n=0;
672 	rsb_flags_t flags = RSB_FLAG_NOFLAGS;
673 	rsb_rf_t ys,xs;
674 	rsb_rf_t csh,csw,dx=0.0,dy=0.0,rd=1.0;
675 
676 	RSB_DO_FLAG_ADD(flags,RSB_FLAG_WANT_BCSS_STORAGE) ;
677 	RSB_DO_FLAG_ADD(flags,RSB_FLAG_SORTED_INPUT) ;
678 
679 if(1)
680 {
681 	       	rsb_coo_idx_t /* ri=0,ci=0,*/nr=m,nc=k;
682 	       	rsb_nnz_idx_t nzi=0;
683 	       	rsb_nnz_idx_t onnz=nnz;
684 		// RSB_STDERR("%s","FIXME: this is functioning code to render PostScript spy plots; it just needs to be called the right way ..\n");
685 		rsb_aligned_t max[RSB_CONST_ENOUGH_ALIGNED_FOR_ANY_TYPE];
686 		rsb_aligned_t min[RSB_CONST_ENOUGH_ALIGNED_FOR_ANY_TYPE];
687 		const int want_points_plot = 0; /* was 1 */
688 
689 		rsb__fill_with_ones(VA,typecode,nnz,1);
690 #if 1
691 		while( (nnz>100000 || nr>512 || nc>512 ) && (nr>2 && nc>2))
692 		{
693 			/*
694 				May be better to write a function *resize_to_nnz*.
695 				This code is quite poor but does the job.
696 			 */
697 		       	rsb_coo_idx_t nnr=nr/2, nnc=nc/2;
698 			rsb_flags_t flags = RSB_FLAG_NOFLAGS;
699 			// RSB_DO_FLAG_ADD(flags,RSB_FLAG_SORTED_INPUT) ;
700 			// RSB_STDERR("will rescale %d %d (%d nz) to %d %d...\n",nr,nc,nnz,nnr,nnc);
701 			errval = rsb__mtx_as_pixmap_resize(VA,IA,JA,nnz,&nnz,nr,nc,nnr,nnc,typecode,flags);
702 			RSB_DO_FLAG_ADD(flags,RSB_FLAG_SORTED_INPUT) ;
703 			// nnz = rsb_weed_out_duplicates(IA,JA,VA,nnz,typecode,RSB_FLAG_DUPLICATES_SUM/*|RSB_FLAG_SORTED_INPUT*/);
704 			if(RSB_SOME_ERROR(errval)) { RSB_PERR_GOTO(err,RSB_ERRM_ES) }
705 			nc=nnc; nr=nnr;
706 			nnc/=2; nnr/=2;
707 		}
708 #endif
709 #if 1
710 		// if( (nnz>100000 || nr>height || nc>width ) && (nr>2 && nc>2))
711 		if(1)
712 		{
713 		       	rsb_coo_idx_t nnr=height, nnc=width;
714 			rsb_flags_t flags = RSB_FLAG_NOFLAGS;
715 			RSB_DO_FLAG_ADD(flags,RSB_FLAG_SORTED_INPUT) ;
716 			// RSB_STDERR("will rescale further %d %d (%d nz) to %d %d...\n",nr,nc,nnz,nnr,nnc);
717 			if(nnr>nr)
718 				rd=((rsb_rf_t)nnr)/((rsb_rf_t)nr);
719 			errval = rsb__mtx_as_pixmap_resize(VA,IA,JA,nnz,&nnz,nr,nc,nnr,nnc,typecode,flags);
720 			if(RSB_SOME_ERROR(errval)) { RSB_PERR_GOTO(err,RSB_ERRM_ES) }
721 			nc=nnc; nr=nnr;
722 		}
723 #endif
724 		errval = rsb__util_sort_row_major_inner(VA,IA,JA,nnz,nr,nc, typecode,RSB_FLAG_NOFLAGS);
725 		if(RSB_SOME_ERROR(errval))
726 		{
727 		       	RSB_ERROR(RSB_ERRM_ES); /* RSB_PERR_GOTO(err,RSB_ERRM_ES)*/ /*not a critical error; however shall emit a warning : */
728 		}
729 		nnz = rsb_weed_out_duplicates(IA,JA,VA,nnz,typecode,RSB_FLAG_DUPLICATES_SUM|RSB_FLAG_SORTED_INPUT);
730 
731 		RSB_FPRINTF(fd,""
732 			"%%!PS-Adobe-3.0 EPSF-3.0\n"
733 			"%%%%Creator: "RSB_PACKAGE_STRING"\n"
734 			"%%%%Title: matrix spy plot (originally %d x %d / %d, here %d x %d/%d)\n"
735 			"%%%%CreationDate: \n"
736 			"%%%%DocumentData: Clean7Bit\n"
737 			"%%%%Origin: 0 0\n"
738 			"%%%%BoundingBox: 0 0 %d %d\n"
739 			"%%%%LanguageLevel: 2\n"
740 			"%%%%Pages: 1\n"
741 			"%%%%Page: 1 1\n"
742 			/* "0.5 0.5 0.5 setrgbcolor\n" */
743 			,m,k,onnz,nr,nc,nnz,nc,nr);
744 		RSB_FPRINTF(fd,"save /$LIBRSB_DICT 3 dict def $LIBRSB_DICT begin /M {moveto} bind def /Z {gsave currentpoint lineto %g setlinewidth 1 setlinecap stroke grestore} bind def /D {M Z} bind def /K {0.5 0.5 setrgbcolor} bind def\n",rd);
745 		RSB_FPRINTF(fd,"/R {rlineto} bind def\n");
746 		RSB_FPRINTF(fd,"/N {newpath} bind def\n");
747 		RSB_FPRINTF(fd,"/L {lineto} bind def\n");
748 		RSB_FPRINTF(fd,"/C {closepath} bind def\n");
749 		RSB_FPRINTF(fd,"/SLW {setlinewidth} bind def\n");
750 		RSB_FPRINTF(fd,"/SRGB {setrgbcolor} bind def\n");
751 		RSB_FPRINTF(fd,"/SCF {scalefont} bind def\n");
752 		RSB_FPRINTF(fd,"/SF {setfont} bind def\n");
753 		rsb__util_find_max(&max[0],VA,typecode,nnz,1);
754 		rsb__util_find_min(&min[0],VA,typecode,nnz,1);
755 		// RSB_STDERR("%lf %lf\n", *(double*)(&min[0]), *(double*)(&max[0]));
756 		rsb__util_do_negate(&min[0],typecode,1);
757 		rsb__util_vector_add(&max[0],&min[0],typecode,1);
758 		// RSB_STDERR("%lf %lf\n", *(double*)(&min[0]), *(double*)(&max[0]));
759 		if(RSB_IS_ELEMENT_NONZERO(&max[0],typecode))
760 			rsb__vector_scale_inv(VA,&max[0],typecode,nnz); /* scale elements in [0,1] */
761 		else
762 			rsb__fill_with_ones(VA,typecode,nnz,1);
763 
764 		if(want_points_plot)
765 		{
766 		RSB_FPRINTF(fd,"%% dots plot\n");
767 		for(nzi=0;nzi<nnz;++nzi)
768 		{
769 			// RSB_FPRINTF(fd,"%d %d D\n",IA[nzi],JA[nzi]);
770 			// RSB_FPRINTF(fd,"%d %d D ",nr-1-IA[nzi],JA[nzi]);
771 			rsb_rf_t cv=0.0;
772 			RSB_NUMERICAL_TYPE_CAST_TO_ANY_P(rsb_rf_t,cv,typecode,VA,nzi);
773 			// cv=1.0f-cv;
774 			cv=0.5+cv/2.0; /* stronger */
775 			//cv=0.0+cv/2;
776 			// cv=0.5;
777 			// gray ... red
778 			// RSB_FPRINTF(fd,"%0.2f %0.2f %0.2f setrgbcolor\n",cv,0.5,0.5);
779 			RSB_FPRINTF(fd,"%.2f K ",cv);
780 			//RSB_FPRINTF(fd,"%d %d D ",nr-1-IA[nzi],JA[nzi]);
781 			RSB_FPRINTF(fd,"%d %d D ",JA[nzi],nr-1-IA[nzi]);
782 			if(nzi%32==0)
783 				RSB_FPRINTF(fd,"\n");
784 		}
785 		}
786 		// RSB_FPRINTF(fd,"gsave grestore showpage\n");
787 		RSB_FPRINTF(fd,"stroke\n");
788 		goto err;
789 	}
790 
791 	if(!all_nnz)
792 	{
793 		/* rsb__mtx_as_pixmap_resize is optional */
794 		if( RSB_SOME_ERROR(errval = rsb__mtx_as_pixmap_resize(VA, IA, JA, nnz, &nnz, m, k, height, width, typecode, flags)))
795 			goto err;
796 	}
797 	/*	if(m<=height)
798 			ys=1.0;
799 		else
800 			ys=((rsb_rf_t)height)/m;
801 		if(k<=width)
802 			xs=1.0;
803 		else*/
804 		ys=((rsb_rf_t)height)/m;
805 		xs=((rsb_rf_t)width)/k;
806 		csw=ys;
807 		csh=xs;
808 
809 //	{
810 //		ys=((rsb_rf_t)height)/m;
811 //		xs=((rsb_rf_t)width)/k;
812 //	}
813 	if(width>k)
814 		dx=.1*csw, csw*=.8;
815 	else
816 		xs=csw=1.0;
817 	if(height>m)
818 		dy=.1*csh, csh*=.8;
819 	else
820 		ys=csh=1.0;
821 /*
822 	if(height>m)
823 		yps=ys*.8;
824 	else
825 		yps=ys;
826 	if(width>m)
827 		xps=xs*.8;
828 	else
829 		xps=xs;
830 
831 	if(!all_nnz)
832 	{
833 		m=height;
834 		k=width;
835 	}*/
836 
837 	rsb__do_print_postscript_header(fd, width, height, csw, csh);
838 
839 	RSB_FPRINTF(fd,"%%%% nnz dump\n");
840 	RSB_FPRINTF(fd,"%%%% scales : %g %g\n",xs,ys);
841 
842 
843 	if(xs>1.0) xs=1.0;
844 	if(ys>1.0)ys=1.0;
845 
846 	for(n=0;n<nnz;++n)
847 	{
848 		RSB_FPRINTF(fd,"%%%% at : %d %d\n",(int)IA[n],(int)JA[n]);
849 		RSB_FPRINTF(fd,
850 			"%g %g translate\n"
851 			".85 .85 .85 csquare\n"
852 			"-%g -%g translate\n"
853 			, dx+((rsb_rf_t) (JA[n]))*xs, -dy+((rsb_rf_t)height)-((rsb_rf_t) (IA[n]))*ys
854 			, dx+((rsb_rf_t) (JA[n]))*xs, -dy+((rsb_rf_t)height)-((rsb_rf_t) (IA[n]))*ys);
855 	}
856 
857 	//RSB_FPRINTF(fd, "%%%%EOF\n");
858 
859 err:
860 	RSB_DO_ERR_RETURN(errval)
861 #else /* RSB_ALLOW_STDOUT */
862 	RSB_DO_ERR_RETURN(RSB_ERR_UNSUPPORTED_FEATURE);
863 #endif /* RSB_ALLOW_STDOUT */
864 }
865 
rsb__dump_postscript_recursion_from_matrix(const char * filename,rsb_blk_idx_t br,rsb_blk_idx_t bc,int width,int height,rsb_flags_t flags,rsb_bool_t want_blocks,rsb_bool_t z_dump,rsb_bool_t want_nonzeros,rsb_bool_t want_recursion,rsb_type_t typecode)866 rsb_err_t rsb__dump_postscript_recursion_from_matrix(const char * filename, rsb_blk_idx_t br, rsb_blk_idx_t bc, int width, int height, rsb_flags_t flags, rsb_bool_t want_blocks, rsb_bool_t z_dump , rsb_bool_t want_nonzeros, rsb_bool_t want_recursion, rsb_type_t typecode)
867 {
868 	/**
869 	 \ingroup gr_internals
870 	 */
871 #if RSB_ALLOW_STDOUT
872 	rsb_err_t errval = RSB_ERR_NO_ERROR;
873 	rsb_coo_idx_t *IA=NULL, *JA=NULL;
874 	void *VA=NULL;
875 	rsb_coo_idx_t m=0,k=0;
876        	rsb_nnz_idx_t nnz=0;
877 	struct rsb_mtx_t * mtxAp=NULL;
878 	FILE*fd = RSB_DEFAULT_FD;
879 
880 	if(!filename )
881 	{
882 		RSB_ERROR(RSB_ERRM_ES);
883 		return RSB_ERR_BADARGS;
884 	}
885 
886 	errval = rsb__util_mm_load_matrix_f(filename,&IA,&JA,&VA,&m,&k,&nnz,typecode,flags,NULL,NULL);
887 	if(RSB_SOME_ERROR(errval)) { RSB_PERR_GOTO(err,RSB_ERRM_ES) }
888 
889 	mtxAp = rsb__do_mtx_alloc_from_coo_const(VA,IA,JA,nnz,typecode,m,k,br,bc,flags,&errval);
890 	if(!mtxAp || RSB_SOME_ERROR(errval))
891 	{
892 		RSB_PERR_GOTO(err,RSB_ERRM_ES);
893 	}
894 
895 	if( want_nonzeros )
896 	{
897 		// RSB_POSTSCRIPT_DUMP_COMMENT(fd,"nonzeros structure dump");
898 		errval = rsb_dump_postscript_from_coo(fd, IA, JA, VA, m, k, nnz, br, bc, width, height, want_nonzeros, typecode);
899 		want_nonzeros = 0;
900 		if(RSB_SOME_ERROR(errval)) { RSB_PERR_GOTO(err,RSB_ERRM_ES) }
901 	}
902 
903 	RSB_CONDITIONAL_FREE(IA);
904        	RSB_CONDITIONAL_FREE(JA);
905        	RSB_CONDITIONAL_FREE(VA);
906 
907 	if(want_recursion)
908 	{
909 		errval = rsb__dump_postscript_recursion_from_mtx_t(fd, NULL, mtxAp, br, bc, width, height, RSB_FLAG_NOFLAGS/* FIXME */, want_blocks, z_dump , 0 /*want_nonzeros*/, NULL );
910 		if(RSB_SOME_ERROR(errval)) { RSB_PERR_GOTO(err,RSB_ERRM_ES) }
911 	}
912 
913 	RSB_MTX_FREE(mtxAp);/* we don't need it anymore here */
914 
915 	if( want_nonzeros )
916 	{
917 		RSB_POSTSCRIPT_DUMP_COMMENT(fd,"nonzeros structure dump");
918 		errval = rsb__dump_postscript_from_matrix(filename, br, bc, width, height, 1);
919 		if(RSB_SOME_ERROR(errval)) { RSB_PERR_GOTO(err,RSB_ERRM_ES) }
920 	}
921 
922 	errval = RSB_ERR_NO_ERROR;
923 	goto ret;
924 err:
925 	errval = RSB_ERR_GENERIC_ERROR;
926 ret:
927 	RSB_CONDITIONAL_FREE(IA); RSB_CONDITIONAL_FREE(JA); RSB_CONDITIONAL_FREE(VA);
928 	RSB_MTX_FREE(mtxAp);
929 	return errval;
930 #else  /* RSB_ALLOW_STDOUT */
931 	return RSB_ERR_UNSUPPORTED_FEATURE;
932 #endif /* RSB_ALLOW_STDOUT */
933 }
934 
rsb_dump_postscript_from_mtx_t(FILE * fd,const struct rsb_mtx_t * mtxAp,rsb_blk_idx_t br,rsb_blk_idx_t bc,int width,int height,rsb_bool_t all_nnz)935 static rsb_err_t rsb_dump_postscript_from_mtx_t(FILE*fd, const struct rsb_mtx_t*mtxAp, rsb_blk_idx_t br, rsb_blk_idx_t bc, int width, int height, rsb_bool_t all_nnz)
936 {
937 	struct rsb_coo_matrix_t coo;
938 	rsb_err_t errval = RSB_ERR_NO_ERROR;
939 
940 	RSB_INIT_COO_FROM_MTX(&coo,mtxAp);
941 	if(rsb__allocate_coo_matrix_t(&coo)!=&coo)
942        	{
943 	       	RSB_PERR_GOTO(err,RSB_ERRM_ES);
944 	}
945 	errval = rsb__do_get_coo(mtxAp,(rsb_byte_t**)(&coo.VA),&coo.IA,&coo.JA,RSB_FLAG_NOFLAGS);
946 	if(!RSB_SOME_ERROR(errval))
947 		errval = rsb_dump_postscript_from_coo(fd, coo.IA, coo.JA, coo.VA, coo.nr, coo.nc, coo.nnz, br, bc, width, height, all_nnz, mtxAp->typecode);
948 	if(RSB_SOME_ERROR(errval))
949 	{
950 		RSB_PERR_GOTO(merr,RSB_ERRM_ES);
951 	}
952 merr:
953 	rsb__destroy_coo_matrix_t(&coo);
954 err:
955 	return errval;
956 }
957 
rsb__dump_postscript_from_matrix(const char * filename,rsb_blk_idx_t br,rsb_blk_idx_t bc,int width,int height,rsb_bool_t all_nnz)958 rsb_err_t rsb__dump_postscript_from_matrix(const char * filename, rsb_blk_idx_t br, rsb_blk_idx_t bc, int width, int height, rsb_bool_t all_nnz)
959 {
960 	/**
961 	 \ingroup gr_internals
962 	 This function is experimentally used to render the sparse matrix.
963 	 Needs better error handling.
964 	 */
965 #if RSB_ALLOW_STDOUT
966 	rsb_err_t errval = RSB_ERR_NO_ERROR;
967 	rsb_coo_idx_t *IA=NULL, *JA=NULL;
968 	void *VA=NULL;
969 	rsb_coo_idx_t m=0,k=0;
970 	rsb_nnz_idx_t nnz=0;
971 #ifdef RSB_NUMERICAL_TYPE_DOUBLE
972 	rsb_type_t typecode = RSB_NUMERICAL_TYPE_DOUBLE ;
973 #else /* RSB_NUMERICAL_TYPE_DOUBLE */
974 	rsb_type_t typecode = RSB_NUMERICAL_TYPE_DEFAULT;
975 #endif /* RSB_NUMERICAL_TYPE_DOUBLE */
976 	rsb_flags_t flags = RSB_FLAG_NOFLAGS;
977 	rsb_time_t t=0;
978 
979 	RSB_DO_FLAG_ADD(flags,RSB_FLAG_WANT_BCSS_STORAGE) ;
980 	RSB_DO_FLAG_ADD(flags,RSB_FLAG_SORTED_INPUT) ;
981 
982 	if(!filename )
983 		return RSB_ERR_BADARGS;
984 
985 	t = - rsb_time();
986 	if( RSB_SOME_ERROR(errval = rsb__util_mm_load_matrix_f(filename, &IA, &JA,&VA , &m, &k, &nnz , typecode, flags, NULL, NULL)) )
987 		goto err;
988 	t += rsb_time();
989 
990 #if 1
991 	errval = rsb_dump_postscript_from_coo(/*fd*/RSB_DEFAULT_FD, IA, JA, VA, m, k, nnz, br, bc, width, height, all_nnz, typecode);
992 #else
993 #if 0
994 	{
995 		RSB_STDERR("%s","FIXME: this is functioning code to render PostScript raster spy plots; it just needs the right place to be employed ..\n");
996 		FILE*fd = RSB_DEFAULT_FD;
997 	       	rsb_coo_idx_t ri=0,ci=0,nr=m,nc=k;
998 	       	const rsb_coo_idx_t nnr=16/*0*2*/;
999 		const rsb_coo_idx_t nnc=nc/(nr/nnr);
1000 	       	rsb_nnz_idx_t nzi=0;
1001 		errval = rsb__mtx_as_pixmap_resize(VA,IA,JA,nnz,&nnz,nr,nc,nnr,nnc,typecode,RSB_FLAG_NOFLAGS);
1002 		if(RSB_SOME_ERROR(errval)) { RSB_PERR_GOTO(err,RSB_ERRM_ES) }
1003 		nc=nnc;
1004 		nr=nnr;
1005 		errval = rsb__util_sort_row_major_inner(VA,IA,JA,nnz,nr,nc, typecode,RSB_FLAG_NOFLAGS);
1006 		if(RSB_SOME_ERROR(errval)) { RSB_PERR_GOTO(err,RSB_ERRM_ES) }
1007 		errval = rsb__util_compress_to_row_pointers_array(NULL,nnz,nr,RSB_FLAG_NOFLAGS,RSB_FLAG_NOFLAGS,IA);
1008 		if(RSB_SOME_ERROR(errval)) { RSB_PERR_GOTO(err,RSB_ERRM_ES) }
1009 		// errval = rsb__do_switch_rsb_mtx_to_csr_sorted(mtxAp, &VA, &IA, &JA, RSB_FLAG_NOFLAGS);
1010 		if(RSB_SOME_ERROR(errval)) { RSB_PERR_GOTO(err,RSB_ERRM_ES) }
1011 		// RSB_POSTSCRIPT_DUMP_COMMENT(fd,"raster dump\n");
1012 		RSB_FPRINTF(fd,""
1013 			"%%!PS-Adobe-3.0 EPSF-3.0\n"
1014 			"%%%%Creator: "RSB_PACKAGE_STRING"\n"
1015 			"%%%%Title: matrix spy plot\n"
1016 			"%%%%CreationDate: \n"
1017 			"%%%%DocumentData: Clean7Bit\n"
1018 			"%%%%Origin: 0 0\n"
1019 			"%%%%BoundingBox: 0 0 %d %d\n"
1020 			"%%%%LanguageLevel: 2\n"
1021 			"%%%%Pages: 1\n"
1022 			"%%%%Page: 1 1\n"
1023 		,nc,nr);
1024 		RSB_FPRINTF(fd,"gsave\n""0 %d translate\n""%d %d scale\n""%d %d 8 [%d 0 0 -%d 0 0]\n"" {<",nr,nc,nr,nc,nr,nc,nr);
1025 		for(ri=0;ri<nr;++ri)
1026 		{
1027 	       		rsb_coo_idx_t fc=0,lc=0;
1028 	       		rsb_coo_idx_t crp=IA[ri],nrp=IA[ri+1];
1029 			if(nrp==crp)
1030 				lc=nc-1;
1031 			else
1032 				lc=JA[crp]-1;
1033 			for(ci=fc;ci<=lc;++ci)
1034 				RSB_FPRINTF(fd,"FF");
1035 			for(nzi=crp;nzi<nrp;++nzi)
1036 			{
1037 				RSB_FPRINTF(fd,"00");
1038 				fc=JA[nzi]+1;
1039 				lc=fc-1;
1040 				if(JA[nzi]==nc-1)
1041 					lc=nc-1;
1042 				else
1043 				{
1044 					if(nzi+1 < nrp)
1045 						lc=JA[nzi+1]-1;
1046 					else
1047 						lc=nc-1;
1048 				}
1049 				for(ci=fc;ci<=lc;++ci)
1050 					RSB_FPRINTF(fd,"FF");
1051 			}
1052 			RSB_FPRINTF(fd,"\n");
1053 		}
1054 		RSB_FPRINTF(fd,">}\n""image\n""grestore\n""showpage\n");
1055 	}
1056 #else
1057 		goto err;
1058 #endif
1059 #endif
1060 err:
1061 	RSB_CONDITIONAL_FREE(IA);
1062 	RSB_CONDITIONAL_FREE(JA);
1063 	RSB_CONDITIONAL_FREE(VA);
1064 	RSB_DO_ERR_RETURN(errval)
1065 #else /* RSB_ALLOW_STDOUT */
1066 	RSB_DO_ERR_RETURN(RSB_ERR_UNSUPPORTED_FEATURE);
1067 #endif /* RSB_ALLOW_STDOUT */
1068 }
1069 
rsb__do_mtx_render(const char * filename,const struct rsb_mtx_t * mtxAp,rsb_coo_idx_t pmWidth,rsb_coo_idx_t pmHeight,rsb_marf_t rflags)1070 rsb_err_t rsb__do_mtx_render(const char * filename, const struct rsb_mtx_t*mtxAp, rsb_coo_idx_t pmWidth, rsb_coo_idx_t pmHeight, rsb_marf_t rflags)
1071 {
1072 	rsb_err_t errval = RSB_ERR_NO_ERROR;
1073 
1074 	if(!mtxAp)
1075 	{
1076 		errval = RSB_ERR_BADARGS;
1077 		RSB_PERR_GOTO(err,RSB_ERRM_E_MTXAP);
1078 	}
1079 
1080 	switch(rflags)
1081 	{
1082 		case(RSB_MARF_RGB):
1083 		RSB_DO_ERROR_CUMULATE(errval,RSB_ERR_UNIMPLEMENTED_YET);
1084 		break;
1085 		case(RSB_MARF_EPS_L):
1086 		case(RSB_MARF_EPS_B):
1087 		case(RSB_MARF_EPS_S):
1088 		case(RSB_MARF_EPS):
1089 		{
1090 			FILE * fd = NULL;
1091 			rsb_time_t dt = rsb_time();
1092 			/* filename = filename ? filename : RSB_DEFAULT_DUMPFILENAME; */
1093 			if( ! filename )
1094 			{
1095 		       		fd = RSB_DEFAULT_FD;
1096 			}
1097 			else
1098 		       		fd = rsb__util_fopen(filename,"w");
1099 
1100 			if( rflags == RSB_MARF_EPS || rflags == RSB_MARF_EPS_S || rflags == RSB_MARF_EPS_L )
1101 				RSB_DO_ERROR_CUMULATE(errval,rsb_dump_postscript_from_mtx_t(fd,mtxAp,1,1,pmWidth,pmHeight,1));
1102 			if( rflags == RSB_MARF_EPS || rflags == RSB_MARF_EPS_B || rflags == RSB_MARF_EPS_L )
1103 				RSB_DO_ERROR_CUMULATE(errval,rsb__dump_postscript_recursion_from_mtx_t(fd,NULL,mtxAp,1,1,pmWidth,pmHeight,rflags,0,1,0,NULL));
1104 			if( fd )
1105 			{
1106 				dt = rsb_time() - dt;
1107 				RSB_FPRINTF(fd,"%% rendering time ~ %lg s\n",dt);
1108 			}
1109 
1110 			if( filename )
1111 				fclose(fd);
1112 		}
1113 		break;
1114 		default: {errval = RSB_ERR_UNIMPLEMENTED_YET; goto err;}
1115 	}
1116 err:
1117 	return errval;
1118 }
1119 
1120 /* @endcond */
1121