1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2021 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not visit scipopt.org. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15
16 /**@file disp.c
17 * @ingroup OTHER_CFILES
18 * @brief methods and datastructures for displaying runtime statistics
19 * @author Tobias Achterberg
20 * @author Timo Berthold
21 */
22
23 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
24
25 #include <stdio.h>
26 #include <assert.h>
27 #include <string.h>
28
29 #include "scip/def.h"
30 #include "blockmemshell/memory.h"
31 #include "scip/set.h"
32 #include "scip/stat.h"
33 #include "scip/scip.h"
34 #include "scip/disp.h"
35 #include "scip/pub_message.h"
36 #include "scip/pub_misc.h"
37 #include "scip/syncstore.h"
38 #include "scip/struct_disp.h"
39
40
41
42 /*
43 * display column methods
44 */
45
46 /** parameter change information method to autoselect display columns again */
SCIP_DECL_PARAMCHGD(SCIPparamChgdDispActive)47 SCIP_DECL_PARAMCHGD(SCIPparamChgdDispActive)
48 { /*lint --e{715}*/
49 /* automatically select the now active display columns */
50 SCIP_CALL( SCIPautoselectDisps(scip) );
51
52 return SCIP_OKAY;
53 }
54
55 /** copies the given display to a new scip */
SCIPdispCopyInclude(SCIP_DISP * disp,SCIP_SET * set)56 SCIP_RETCODE SCIPdispCopyInclude(
57 SCIP_DISP* disp, /**< display column */
58 SCIP_SET* set /**< SCIP_SET of SCIP to copy to */
59 )
60 {
61 assert(disp != NULL);
62 assert(set != NULL);
63 assert(set->scip != NULL);
64
65 if( disp->dispcopy != NULL )
66 {
67 SCIPsetDebugMsg(set, "including display column %s in subscip %p\n", SCIPdispGetName(disp), (void*)set->scip);
68 SCIP_CALL( disp->dispcopy(set->scip, disp) );
69 }
70 return SCIP_OKAY;
71 }
72
73 /** internal method for creating a display column */
74 static
doDispCreate(SCIP_DISP ** disp,SCIP_SET * set,SCIP_MESSAGEHDLR * messagehdlr,BMS_BLKMEM * blkmem,const char * name,const char * desc,const char * header,SCIP_DISPSTATUS dispstatus,SCIP_DECL_DISPCOPY ((* dispcopy)),SCIP_DECL_DISPFREE ((* dispfree)),SCIP_DECL_DISPINIT ((* dispinit)),SCIP_DECL_DISPEXIT ((* dispexit)),SCIP_DECL_DISPINITSOL ((* dispinitsol)),SCIP_DECL_DISPEXITSOL ((* dispexitsol)),SCIP_DECL_DISPOUTPUT ((* dispoutput)),SCIP_DISPDATA * dispdata,int width,int priority,int position,SCIP_Bool stripline)75 SCIP_RETCODE doDispCreate(
76 SCIP_DISP** disp, /**< pointer to store display column */
77 SCIP_SET* set, /**< global SCIP settings */
78 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
79 BMS_BLKMEM* blkmem, /**< block memory for parameter settings */
80 const char* name, /**< name of display column */
81 const char* desc, /**< description of display column */
82 const char* header, /**< head line of display column */
83 SCIP_DISPSTATUS dispstatus, /**< display activation status of display column */
84 SCIP_DECL_DISPCOPY ((*dispcopy)), /**< copy method of display column or NULL if you don't want to copy your plugin into sub-SCIPs */
85 SCIP_DECL_DISPFREE ((*dispfree)), /**< destructor of display column */
86 SCIP_DECL_DISPINIT ((*dispinit)), /**< initialize display column */
87 SCIP_DECL_DISPEXIT ((*dispexit)), /**< deinitialize display column */
88 SCIP_DECL_DISPINITSOL ((*dispinitsol)), /**< solving process initialization method of display column */
89 SCIP_DECL_DISPEXITSOL ((*dispexitsol)), /**< solving process deinitialization method of display column */
90 SCIP_DECL_DISPOUTPUT ((*dispoutput)), /**< output method */
91 SCIP_DISPDATA* dispdata, /**< display column data */
92 int width, /**< width of display column (no. of chars used) */
93 int priority, /**< priority of display column */
94 int position, /**< relative position of display column */
95 SCIP_Bool stripline /**< should the column be separated with a line from its right neighbor? */
96 )
97 {
98 char paramname[SCIP_MAXSTRLEN];
99 char paramdesc[SCIP_MAXSTRLEN];
100
101 assert(disp != NULL);
102 assert(name != NULL);
103 assert(desc != NULL);
104 assert(header != NULL);
105 assert(dispoutput != NULL);
106 assert(width >= 0);
107
108 SCIP_ALLOC( BMSallocMemory(disp) );
109 BMSclearMemory(*disp);
110
111 SCIP_ALLOC( BMSduplicateMemoryArray(&(*disp)->name, name, strlen(name)+1) );
112 SCIP_ALLOC( BMSduplicateMemoryArray(&(*disp)->desc, desc, strlen(desc)+1) );
113 SCIP_ALLOC( BMSduplicateMemoryArray(&(*disp)->header, header, strlen(header)+1) );
114 (*disp)->dispstatus = dispstatus;
115 (*disp)->dispcopy = dispcopy;
116 (*disp)->dispfree = dispfree;
117 (*disp)->dispinit = dispinit;
118 (*disp)->dispexit = dispexit;
119 (*disp)->dispinitsol = dispinitsol;
120 (*disp)->dispexitsol = dispexitsol;
121 (*disp)->dispoutput = dispoutput;
122 (*disp)->dispdata = dispdata;
123 (*disp)->width = width;
124 (*disp)->priority = priority;
125 (*disp)->position = position;
126 (*disp)->stripline = stripline;
127 (*disp)->initialized = FALSE;
128 (*disp)->active = (dispstatus == SCIP_DISPSTATUS_ON);
129 (*disp)->mode = SCIP_DISPMODE_DEFAULT;
130
131 /* add parameters */
132 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "display/%s/active", name);
133 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "display activation status of display column <%s> (0: off, 1: auto, 2:on)", name);
134 SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc,
135 (int*)(&(*disp)->dispstatus), FALSE, (int)dispstatus, 0, 2, SCIPparamChgdDispActive, NULL) );
136
137 return SCIP_OKAY;
138 }
139
140 /** creates a display column */
SCIPdispCreate(SCIP_DISP ** disp,SCIP_SET * set,SCIP_MESSAGEHDLR * messagehdlr,BMS_BLKMEM * blkmem,const char * name,const char * desc,const char * header,SCIP_DISPSTATUS dispstatus,SCIP_DECL_DISPCOPY ((* dispcopy)),SCIP_DECL_DISPFREE ((* dispfree)),SCIP_DECL_DISPINIT ((* dispinit)),SCIP_DECL_DISPEXIT ((* dispexit)),SCIP_DECL_DISPINITSOL ((* dispinitsol)),SCIP_DECL_DISPEXITSOL ((* dispexitsol)),SCIP_DECL_DISPOUTPUT ((* dispoutput)),SCIP_DISPDATA * dispdata,int width,int priority,int position,SCIP_Bool stripline)141 SCIP_RETCODE SCIPdispCreate(
142 SCIP_DISP** disp, /**< pointer to store display column */
143 SCIP_SET* set, /**< global SCIP settings */
144 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
145 BMS_BLKMEM* blkmem, /**< block memory for parameter settings */
146 const char* name, /**< name of display column */
147 const char* desc, /**< description of display column */
148 const char* header, /**< head line of display column */
149 SCIP_DISPSTATUS dispstatus, /**< display activation status of display column */
150 SCIP_DECL_DISPCOPY ((*dispcopy)), /**< copy method of display column or NULL if you don't want to copy your plugin into sub-SCIPs */
151 SCIP_DECL_DISPFREE ((*dispfree)), /**< destructor of display column */
152 SCIP_DECL_DISPINIT ((*dispinit)), /**< initialize display column */
153 SCIP_DECL_DISPEXIT ((*dispexit)), /**< deinitialize display column */
154 SCIP_DECL_DISPINITSOL ((*dispinitsol)), /**< solving process initialization method of display column */
155 SCIP_DECL_DISPEXITSOL ((*dispexitsol)), /**< solving process deinitialization method of display column */
156 SCIP_DECL_DISPOUTPUT ((*dispoutput)), /**< output method */
157 SCIP_DISPDATA* dispdata, /**< display column data */
158 int width, /**< width of display column (no. of chars used) */
159 int priority, /**< priority of display column */
160 int position, /**< relative position of display column */
161 SCIP_Bool stripline /**< should the column be separated with a line from its right neighbor? */
162 )
163 {
164 assert(disp != NULL);
165 assert(name != NULL);
166 assert(desc != NULL);
167 assert(header != NULL);
168 assert(dispoutput != NULL);
169 assert(width >= 0);
170
171 SCIP_CALL_FINALLY( doDispCreate(disp, set, messagehdlr, blkmem, name, desc, header, dispstatus, dispcopy,
172 dispfree, dispinit, dispexit, dispinitsol, dispexitsol, dispoutput, dispdata, width, priority, position,
173 stripline), (void) SCIPdispFree(disp, set) );
174
175 return SCIP_OKAY;
176 }
177
178 /** frees memory of display column */
SCIPdispFree(SCIP_DISP ** disp,SCIP_SET * set)179 SCIP_RETCODE SCIPdispFree(
180 SCIP_DISP** disp, /**< pointer to display column data structure */
181 SCIP_SET* set /**< global SCIP settings */
182 )
183 {
184 assert(disp != NULL);
185 if( *disp == NULL )
186 return SCIP_OKAY;
187 assert(!(*disp)->initialized);
188 assert(set != NULL);
189
190 /* call destructor of display column */
191 if( (*disp)->dispfree != NULL )
192 {
193 SCIP_CALL( (*disp)->dispfree(set->scip, *disp) );
194 }
195
196 BMSfreeMemoryArrayNull(&(*disp)->name);
197 BMSfreeMemoryArrayNull(&(*disp)->desc);
198 BMSfreeMemoryArrayNull(&(*disp)->header);
199 BMSfreeMemory(disp);
200
201 return SCIP_OKAY;
202 }
203
204 /** initializes display column */
SCIPdispInit(SCIP_DISP * disp,SCIP_SET * set)205 SCIP_RETCODE SCIPdispInit(
206 SCIP_DISP* disp, /**< display column */
207 SCIP_SET* set /**< global SCIP settings */
208 )
209 {
210 assert(disp != NULL);
211 assert(set != NULL);
212
213 if( disp->initialized )
214 {
215 SCIPerrorMessage("display column <%s> already initialized\n", disp->name);
216 return SCIP_INVALIDCALL;
217 }
218
219 if( disp->dispinit != NULL )
220 {
221 SCIP_CALL( disp->dispinit(set->scip, disp) );
222 }
223 disp->initialized = TRUE;
224
225 return SCIP_OKAY;
226 }
227
228 /** deinitializes display column */
SCIPdispExit(SCIP_DISP * disp,SCIP_SET * set)229 SCIP_RETCODE SCIPdispExit(
230 SCIP_DISP* disp, /**< display column */
231 SCIP_SET* set /**< global SCIP settings */
232 )
233 {
234 assert(disp != NULL);
235 assert(set != NULL);
236
237 if( !disp->initialized )
238 {
239 SCIPerrorMessage("display column <%s> not initialized\n", disp->name);
240 return SCIP_INVALIDCALL;
241 }
242
243 if( disp->dispexit != NULL )
244 {
245 SCIP_CALL( disp->dispexit(set->scip, disp) );
246 }
247 disp->initialized = FALSE;
248
249 return SCIP_OKAY;
250 }
251
252 /** informs display column that the branch and bound process is being started */
SCIPdispInitsol(SCIP_DISP * disp,SCIP_SET * set)253 SCIP_RETCODE SCIPdispInitsol(
254 SCIP_DISP* disp, /**< display column */
255 SCIP_SET* set /**< global SCIP settings */
256 )
257 {
258 assert(disp != NULL);
259 assert(set != NULL);
260
261 /* call solving process initialization method of display column */
262 if( disp->dispinitsol != NULL )
263 {
264 SCIP_CALL( disp->dispinitsol(set->scip, disp) );
265 }
266
267 return SCIP_OKAY;
268 }
269
270 /** informs display column that the branch and bound process data is being freed */
SCIPdispExitsol(SCIP_DISP * disp,SCIP_SET * set)271 SCIP_RETCODE SCIPdispExitsol(
272 SCIP_DISP* disp, /**< display column */
273 SCIP_SET* set /**< global SCIP settings */
274 )
275 {
276 assert(disp != NULL);
277 assert(set != NULL);
278
279 /* call solving process deinitialization method of display column */
280 if( disp->dispexitsol != NULL )
281 {
282 SCIP_CALL( disp->dispexitsol(set->scip, disp) );
283 }
284
285 return SCIP_OKAY;
286 }
287
288 /** output display column to screen */
SCIPdispOutput(SCIP_DISP * disp,SCIP_SET * set,FILE * file)289 SCIP_RETCODE SCIPdispOutput(
290 SCIP_DISP* disp, /**< display column */
291 SCIP_SET* set, /**< global SCIP settings */
292 FILE* file /**< output file (or NULL for standard output) */
293 )
294 {
295 assert(disp != NULL);
296 assert(disp->dispoutput != NULL);
297 assert(set != NULL);
298
299 SCIP_CALL( disp->dispoutput(set->scip, disp, file) );
300
301 return SCIP_OKAY;
302 }
303
304 /** gets user data of display column */
SCIPdispGetData(SCIP_DISP * disp)305 SCIP_DISPDATA* SCIPdispGetData(
306 SCIP_DISP* disp /**< display column */
307 )
308 {
309 assert(disp != NULL);
310
311 return disp->dispdata;
312 }
313
314 /** sets user data of display column; user has to free old data in advance! */
SCIPdispSetData(SCIP_DISP * disp,SCIP_DISPDATA * dispdata)315 void SCIPdispSetData(
316 SCIP_DISP* disp, /**< display column */
317 SCIP_DISPDATA* dispdata /**< new display column user data */
318 )
319 {
320 assert(disp != NULL);
321
322 disp->dispdata = dispdata;
323 }
324
325 /** gets name of display column */
SCIPdispGetName(SCIP_DISP * disp)326 const char* SCIPdispGetName(
327 SCIP_DISP* disp /**< display column */
328 )
329 {
330 assert(disp != NULL);
331
332 return disp->name;
333 }
334
335 /** gets description of display column */
SCIPdispGetDesc(SCIP_DISP * disp)336 const char* SCIPdispGetDesc(
337 SCIP_DISP* disp /**< display column */
338 )
339 {
340 assert(disp != NULL);
341
342 return disp->desc;
343 }
344
345 /** gets head line of display column */
SCIPdispGetHeader(SCIP_DISP * disp)346 const char* SCIPdispGetHeader(
347 SCIP_DISP* disp /**< display column */
348 )
349 {
350 assert(disp != NULL);
351
352 return disp->header;
353 }
354
355 /** gets width of display column */
SCIPdispGetWidth(SCIP_DISP * disp)356 int SCIPdispGetWidth(
357 SCIP_DISP* disp /**< display column */
358 )
359 {
360 assert(disp != NULL);
361
362 return disp->width;
363 }
364
365 /** gets priority of display column */
SCIPdispGetPriority(SCIP_DISP * disp)366 int SCIPdispGetPriority(
367 SCIP_DISP* disp /**< display column */
368 )
369 {
370 assert(disp != NULL);
371
372 return disp->priority;
373 }
374
375 /** gets position of display column */
SCIPdispGetPosition(SCIP_DISP * disp)376 int SCIPdispGetPosition(
377 SCIP_DISP* disp /**< display column */
378 )
379 {
380 assert(disp != NULL);
381
382 return disp->position;
383 }
384
385 /** gets status of display column */
SCIPdispGetStatus(SCIP_DISP * disp)386 SCIP_DISPSTATUS SCIPdispGetStatus(
387 SCIP_DISP* disp /**< display column */
388 )
389 {
390 assert(disp != NULL);
391
392 return disp->dispstatus;
393 }
394
395 /** is display column initialized? */
SCIPdispIsInitialized(SCIP_DISP * disp)396 SCIP_Bool SCIPdispIsInitialized(
397 SCIP_DISP* disp /**< display column */
398 )
399 {
400 assert(disp != NULL);
401
402 return disp->initialized;
403 }
404
405 /** prints one line of output with the active display columns */
SCIPdispPrintLine(SCIP_SET * set,SCIP_MESSAGEHDLR * messagehdlr,SCIP_STAT * stat,FILE * file,SCIP_Bool forcedisplay,SCIP_Bool endline)406 SCIP_RETCODE SCIPdispPrintLine(
407 SCIP_SET* set, /**< global SCIP settings */
408 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
409 SCIP_STAT* stat, /**< problem statistics data */
410 FILE* file, /**< output file (or NULL for standard output) */
411 SCIP_Bool forcedisplay, /**< should the line be printed without regarding frequency? */
412 SCIP_Bool endline /**< should the line be terminated with a newline symbol? */
413 )
414 {
415 assert(set != NULL);
416 assert(set->disp_freq >= -1);
417 assert(set->disp_headerfreq >= -1);
418 assert(stat != NULL);
419
420 if( (SCIP_VERBLEVEL)set->disp_verblevel < SCIP_VERBLEVEL_NORMAL || set->disp_freq == -1 )
421 return SCIP_OKAY;
422
423 if( forcedisplay
424 || (stat->nnodes != stat->lastdispnode
425 && set->disp_freq > 0
426 && (stat->nnodes % set->disp_freq == 0 || stat->nnodes == 1)) )
427 {
428 int i;
429 int j;
430 SCIP_Bool stripline;
431
432 /* display header line */
433 if( (set->disp_headerfreq == 0 && stat->ndisplines == 0)
434 || (set->disp_headerfreq > 0 && stat->ndisplines % set->disp_headerfreq == 0) )
435 {
436 int fillspace;
437
438 stripline = FALSE;
439 for( i = 0; i < set->ndisps; ++i )
440 {
441 assert(set->disps[i] != NULL);
442 if( set->disps[i]->active )
443 {
444 if( stripline )
445 SCIPmessageFPrintInfo(messagehdlr, file, "|");
446 fillspace = set->disps[i]->width - (int)strlen(set->disps[i]->header);
447 for( j = 0; j < (fillspace)/2; ++j )
448 SCIPmessageFPrintInfo(messagehdlr, file, " ");
449 SCIPmessageFPrintInfo(messagehdlr, file, "%s", (const char*)set->disps[i]->header);
450 for( j = 0; j < (fillspace+1)/2; ++j )
451 SCIPmessageFPrintInfo(messagehdlr, file, " ");
452 stripline = set->disps[i]->stripline;
453 }
454 }
455 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
456 }
457
458 /* display node information line */
459 stripline = FALSE;
460 for( i = 0; i < set->ndisps; ++i )
461 {
462 assert(set->disps[i] != NULL);
463 if( set->disps[i]->active )
464 {
465 if( stripline )
466 SCIPmessageFPrintInfo(messagehdlr, file, "|");
467 SCIP_CALL( SCIPdispOutput(set->disps[i], set, file) );
468 stripline = set->disps[i]->stripline;
469 }
470 }
471 if( endline )
472 {
473 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
474 }
475 fflush(stdout);
476
477 stat->lastdispnode = stat->nnodes;
478 stat->ndisplines++;
479 }
480
481 return SCIP_OKAY;
482 }
483
484 /** comparison method for display columns */
485 static
SCIP_DECL_SORTPTRCOMP(dispComp)486 SCIP_DECL_SORTPTRCOMP(dispComp)
487 { /*lint --e{715}*/
488 return ((SCIP_DISP*)elem2)->priority - ((SCIP_DISP*)elem1)->priority;
489 }
490
491 /** activates all display lines fitting in the display w.r. to priority */
SCIPdispAutoActivate(SCIP_SET * set)492 SCIP_RETCODE SCIPdispAutoActivate(
493 SCIP_SET* set /**< global SCIP settings */
494 )
495 {
496 SCIP_DISP** disps;
497 SCIP_SYNCSTORE* syncstore;
498 SCIP_DISPMODE mode;
499 int totalwidth;
500 int width;
501 int i;
502
503 assert(set != NULL);
504
505 syncstore = SCIPgetSyncstore(set->scip);
506 assert(syncstore != NULL);
507
508 /* sort display columns w.r. to their priority */
509 SCIP_ALLOC( BMSduplicateMemoryArray(&disps, set->disps, set->ndisps) );
510 SCIPsortPtr((void**)disps, dispComp, set->ndisps);
511
512 totalwidth = 0;
513
514 if( SCIPsyncstoreIsInitialized(syncstore) )
515 mode = SCIP_DISPMODE_CONCURRENT;
516 else
517 mode = SCIP_DISPMODE_DEFAULT;
518
519 /* first activate all columns with display status ON */
520 for( i = 0; i < set->ndisps; ++i )
521 {
522 width = disps[i]->width;
523 if( disps[i]->stripline )
524 width++;
525 if( disps[i]->dispstatus == SCIP_DISPSTATUS_ON && (disps[i]->mode & mode) )
526 {
527 disps[i]->active = TRUE;
528 totalwidth += width;
529 }
530 else
531 disps[i]->active = FALSE;
532 }
533
534 /* beginning with highest priority display column, activate AUTO columns as long as it fits into display width */
535 for( i = 0; i < set->ndisps; ++i )
536 {
537 if( disps[i]->dispstatus == SCIP_DISPSTATUS_AUTO )
538 {
539 assert(!disps[i]->active);
540
541 width = disps[i]->width;
542 if( disps[i]->stripline )
543 width++;
544 if( totalwidth + width <= set->disp_width && (disps[i]->mode & mode) )
545 {
546 disps[i]->active = TRUE;
547 totalwidth += width;
548 }
549 }
550 }
551
552 /* free temporary memory */
553 BMSfreeMemoryArray(&disps);
554
555 return SCIP_OKAY;
556 }
557
558 /** changes the display column mode */
SCIPdispChgMode(SCIP_DISP * disp,SCIP_DISPMODE mode)559 void SCIPdispChgMode(
560 SCIP_DISP* disp, /**< display column */
561 SCIP_DISPMODE mode /**< the display column mode */
562 )
563 {
564 disp->mode = mode;
565 }
566
567 static
568 const char decpowerchar[] = {' ', 'k', 'M', 'G', 'T', 'P', 'E'};
569 #define MAXDECPOWER 6
570
571 /** displays a long integer in decimal form fitting in a given width */
SCIPdispLongint(SCIP_MESSAGEHDLR * messagehdlr,FILE * file,SCIP_Longint val,int width)572 void SCIPdispLongint(
573 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
574 FILE* file, /**< output stream */
575 SCIP_Longint val, /**< value to display */
576 int width /**< width to fit into */
577 )
578 {
579 assert(width >= 1);
580
581 if( width == 1 )
582 {
583 if( val < 0 )
584 SCIPmessageFPrintInfo(messagehdlr, file, "-");
585 else if( val < 10 )
586 SCIPmessageFPrintInfo(messagehdlr, file, "%" SCIP_LONGINT_FORMAT, val);
587 else
588 SCIPmessageFPrintInfo(messagehdlr, file, "+");
589 }
590 else
591 {
592 char format[SCIP_MAXSTRLEN];
593 SCIP_Longint maxval;
594 int decpower;
595 int i;
596
597 maxval = 1;
598 for( i = 0; i < width-1; ++i )
599 maxval *= 10;
600 if( val < 0 )
601 maxval /= 10;
602 decpower = 0;
603 while( ABS(val) >= maxval && decpower < MAXDECPOWER )
604 {
605 decpower++;
606 val /= 1000;
607 }
608 (void) SCIPsnprintf(format, SCIP_MAXSTRLEN, "%%%d" SCIP_LONGINT_FORMAT "%c", width-1, decpowerchar[decpower]);
609
610 if( width == 2 && val < 0 )
611 SCIPmessageFPrintInfo(messagehdlr, file, "-%c", decpowerchar[decpower]);
612 else
613 SCIPmessageFPrintInfo(messagehdlr, file, (const char*)format, val);
614 }
615 }
616
617 /** displays an integer in decimal form fitting in a given width */
SCIPdispInt(SCIP_MESSAGEHDLR * messagehdlr,FILE * file,int val,int width)618 void SCIPdispInt(
619 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
620 FILE* file, /**< output stream */
621 int val, /**< value to display */
622 int width /**< width to fit into */
623 )
624 {
625 SCIPdispLongint(messagehdlr, file, (SCIP_Longint)val, width);
626 }
627
628
629 static const char timepowerchar[] = {'s', 'm', 'h', 'd', 'y'};
630 static const SCIP_Real timepowerval[] = {1.0, 60.0, 60.0, 24.0, 365.0};
631 #define MAXTIMEPOWER 4
632
633 /** displays a time value fitting in a given width */
SCIPdispTime(SCIP_MESSAGEHDLR * messagehdlr,FILE * file,SCIP_Real val,int width)634 void SCIPdispTime(
635 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
636 FILE* file, /**< output stream */
637 SCIP_Real val, /**< value in seconds to display */
638 int width /**< width to fit into */
639 )
640 {
641 assert(width >= 1);
642
643 if( width == 1 )
644 {
645 if( val < 0.0 )
646 SCIPmessageFPrintInfo(messagehdlr, file, "-");
647 else if( val < 10.0 )
648 SCIPmessageFPrintInfo(messagehdlr, file, "%.0f", val);
649 else
650 SCIPmessageFPrintInfo(messagehdlr, file, "+");
651 }
652 else
653 {
654 char format[SCIP_MAXSTRLEN];
655 SCIP_Longint maxval;
656 int timepower;
657 int i;
658
659 maxval = 1;
660 for( i = 0; i < width-1; ++i )
661 maxval *= 10;
662 if( val < 0.0 )
663 maxval /= 10;
664 timepower = 0;
665 while( REALABS(val) + 0.5 >= maxval && timepower < MAXTIMEPOWER )
666 {
667 timepower++;
668 val /= timepowerval[timepower];
669 }
670 if( REALABS(val) + 0.05 < maxval/100.0 )
671 (void) SCIPsnprintf(format, SCIP_MAXSTRLEN, "%%%d.1f%c", width-1, timepowerchar[timepower]);
672 else
673 (void) SCIPsnprintf(format, SCIP_MAXSTRLEN, "%%%d.0f%c", width-1, timepowerchar[timepower]);
674
675 if( width == 2 && val < 0.0 )
676 SCIPmessageFPrintInfo(messagehdlr, file, "-%c", timepowerchar[timepower]);
677 else
678 SCIPmessageFPrintInfo(messagehdlr, file, (const char*)format, val);
679 }
680 }
681