1 /* Copyright (C) 2011 LinBox 2 * Written by Brice Boyer (briceboyer) <boyer.brice@gmail.com> 3 * 4 * 5 * 6 * ========LICENCE======== 7 * This file is part of the library LinBox. 8 * 9 * LinBox is free software: you can redistribute it and/or modify 10 * it under the terms of the GNU Lesser General Public 11 * License as published by the Free Software Foundation; either 12 * version 2.1 of the License, or (at your option) any later version. 13 * 14 * This library is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Lesser General Public License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public 20 * License along with this library; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22 * ========LICENCE======== 23 */ 24 25 /*! @file benchmarks/benchmark.h 26 * @ingroup benchmarks 27 * @brief Common header to ease benchmarking routines. 28 * We provide a class to easily populate and plot files that represent 29 * benchmarks. 30 * 31 * We use <a href="http://www.gnuplot.info/">gnuplot</a> for the plotting part 32 * or LaTeX to provide tables. A minimum knowledge of \c Gnuplot is a plus but 33 * the \c benchmark-* files should provide enough examples for creating 34 * standard (not too fancy) plots. 35 * 36 * We fall back to plain latex tabulars when gnuplot is not available. We plot 37 * graphs in files whose name is extended by a random 8-char string to avoid 38 * écraser files. 39 * 40 */ 41 42 #ifndef __LINBOX_benchmarks_benchmark_H 43 #define __LINBOX_benchmarks_benchmark_H 44 // here classes TimeWatcher, PlotStyle, PlotData are declared 45 46 #include "linbox/linbox-config.h" 47 #include <stdlib.h> 48 #include "linbox/integer.h" 49 #include "linbox/util/debug.h" 50 #include "tests/test-common.h" 51 #include "linbox/util/timer.h" 52 #include <string> 53 #include <fstream> 54 #include <iomanip> // setprecision 55 56 #include <sys/utsname.h> 57 #include <ctime> 58 #ifdef __LINBOX_HAVE_TINYXML2 59 #include <tinyxml2.h> 60 #endif 61 62 #include "benchmark-utils.h" 63 #include "benchmark-metadata.h" 64 65 66 // 67 // TimeWatcher 68 // 69 70 namespace LinBox { 71 /*! Helper. 72 * This helper has several functions : 73 * - Records the timings 74 * - predict the execution time for the next experiment 75 * - helps producing enough experiments (but not too much and not too time consuming) for producing a valid measure. 76 * . 77 * @warning if the timings are too short, this may not be accurate. 78 * 79 * See member function help for more information. 80 */ 81 class TimeWatcher { 82 private : 83 dvector_t * Points_; //!< Points data. If <code>Points_[i] = x</code>, then <code>Values_[i]=f(x)<code>. 84 dvector_t * Values_; //!< Time data. See \p Points_ . 85 86 size_t MaxRepet_; //!< Maximum number of repetitions of timings 87 size_t MinRepet_; //!< Minimum number of repetitions of timings 88 double MaxTime_; //!< Maximum time to be spent on repetitions (after MinRepet_ iters have been done) 89 double AbortTime_; //!< Time to abort a series of computation. 90 bool aborted_; //!< abort any subsequent computation 91 92 93 public: 94 /*! constructor. 95 * Inits the time watcher with a pair of points/values 96 * @param pts vector of points 97 * @param vals vector of times 98 */ 99 TimeWatcher (dvector_t & pts, dvector_t & vals) ; 100 101 //! Null Constructor. The pointers are intialised to NULL 102 TimeWatcher () ; 103 104 void init(dvector_t & pts, dvector_t & vals); 105 106 //! returns the vector of abscissa (points) 107 dvector_t & refX() ; 108 109 //! returns the vector of ordiantes (values) 110 dvector_t & refY() ; 111 112 /** Prediction for the next experiment time. 113 * It is assumed that \c predict(0)=0. If Curent_<3, a linear, 114 * then quadratic fit is done. Other wise, a cubic fit is 115 * performed. 116 * @param x the next evaluation point. 117 * @return f(x) where f tries to fit the points : \f$ f(\mathtt{Data\_}[0][0..\mathtt{Current\_}-1]) \approx refY()[0..\mathtt{Current\_}-1]\f$ 118 */ 119 double predict(double x) ; 120 121 /*! @brief Watches a timer and a number and repet and signals if over. 122 * 123 * We want at least 2 repetions but not more than maxtime spent on timing. 124 * 125 * @param repet number of previous repetitions. Should be 0 on the first time \c keepon is called. 126 * @param tim timer to watch 127 * @param maxtime maximum time (in seconds) until \c watchon tells stop. 128 * @return \c true if we conditions are not met to stop, \c false otherwise. 129 * @pre \c tim should have been started previously ! 130 * 131 */ 132 bool keepon(size_t & repet, double tim, bool usePrediction = false) ; 133 134 //! size 135 size_t size() const; 136 137 //! clear the pointers (not the settings) 138 void clear(); 139 140 } ; // TimeWatcher 141 } // LinBox 142 143 // 144 // DataSeries 145 // 146 147 namespace LinBox { 148 /** @brief this structure holds a bunch of timings. 149 * It collects the points, the time spent at each point and a measure 150 * (for instance mflops). 151 * @todo Times and Values could be dmatrix_t (and mergeable) 152 */ 153 struct DataSeries { 154 svector_t PointLabels ; //!< points abscisa, values for the x axis. Used in legend for the X axis. 155 dvector_t Points ; //!< points abscisa, values for the x axis. Used in TimeWatcher (for instance, if PointLabels are the names of sparse matrices, Points would be their number of non zeros, or 1,2,3,... or whatever relevant for predicting time) 156 dvector_t Times ; //!< actual computation times. 157 dvector_t Values ; //!< actual data to be plotted (for instance mflops) 158 svector_t UID ; //!< unique id of a point. 159 160 //! Constructor 161 DataSeries() ; 162 163 ~DataSeries() ; 164 165 #if 0 166 /** @brief resize 167 * @param n new size 168 * @pre the size before was n-1 169 */ 170 void resize(const size_t & n); 171 #endif 172 173 //! Size of the series of measurements. 174 size_t size() const; 175 176 //! add some new data. 177 void push_back(const std::string & nam, const double & val, const double & x = NAN, const double &y = NAN); 178 179 // use it but change time 180 // void useMetadata(const MetaData & m) ; 181 }; // DataSeries 182 183 } // LinBox 184 185 /* ********************** */ 186 /* Plot structures */ 187 /* ********************** */ 188 189 // 190 // PlotStyle 191 // 192 193 namespace LinBox { 194 195 /*! @brief Represents a table of values to plot (2D). 196 * list of values are reprensented by vectors. the table is a vector 197 * of these vectors. 198 * 199 * @warning NaN, inf are used as missing data. More genenally 200 * we could store data in strings. 201 * @todo Allow for 'speed up against col X' style 202 * @todo make depend on PlotData 203 */ 204 //!@todo setUsingSeries(const svector_t &) 205 class PlotStyle { 206 public: 207 //! What format the plot should be in? 208 struct Term { 209 //! Term type 210 enum Type { 211 png = 100, //!< png. Portable Network Graphics file. 212 pdf = 101, //!< pdf. Portable Document Format actually, this is eps converted to pdf. 213 eps = 102, //!< eps. Encapsulated PostScript. Cool for inclusion in LaTex files. This is the default. 214 epstex = 107, //!< epslatex. Encapsulated PostScript. Cool for inclusion in LaTex files with latex formulas. 215 svg = 103, //!< sgv. Scalable Vector Graphics. 216 tex = 104, //!< tex. Simple tabular. 217 html = 105, //!< html. HTML table. 218 other= 106 //!< don't know yet... 219 } ; 220 }; 221 222 // enum NoType { other = 0 } ; 223 //! What style of graphic : histogram ? graph ? 224 struct Plot { 225 //! Plot type 226 enum Type { 227 histo = 200, //! histogram plot. This is the default. x ticks are evenly spaced, whatever there value and are labelled with their value. 228 graph = 201, //! standard plot. Plots y_i=f(x) with x in the first colum and y_i in ith column. x-ticks are well spaced. This will not work if the X are not numbers (but strings). 229 other = 202 //! other (ie user supplied). 230 } ; 231 }; 232 233 struct Line { 234 enum Type { 235 lines = 300, //! lines. 236 histogram = 301, //! histogram (boxes). 237 linespoints= 302, //! lines with points. (default) 238 points = 303, //! only the points. 239 other = 304 //! rien. 240 } ; 241 }; 242 243 struct Options { 244 enum Type { 245 oblique = 400, 246 other = 401 247 }; 248 }; 249 250 /*! @brief Constructor. 251 * By default, creates an histogram representing the data in an eps plot. 252 */ 253 PlotStyle() ; 254 255 /*! @brief sets the titles in the graph. 256 * @param titre Title of the graph 257 * @param titre_y Title of the y-axis (series) 258 * @param titre_x Title of the x-axis (data points) 259 */ 260 void setTitle ( const std::string & titre 261 , const std::string & titre_y 262 , const std::string & titre_x); 263 264 /*! @brief Gets the title of the graph. 265 * @return a gnuplot command to set the title of the graph. 266 */ 267 std::string getTitle() const ; 268 269 /*! @brief Gets the title of points abscissa. 270 * @return a gnuplot command to set the title of the abscissa. 271 */ 272 std::string getTitleX() const ; 273 274 /*! @brief Gets the title of the series. 275 * @return a gnuplot command to set the title of the ordinate (series). 276 */ 277 std::string getTitleY() const ; 278 279 /*! @brief get the title string. 280 * @param index can be (0,1,2) 281 */ 282 std::string getRawTitle(int index=0) const ; 283 284 /*! @brief Sets the output format. 285 * @sa TermType 286 * @param term type 287 */ 288 void setTerm( enum Term::Type term) ; 289 290 291 /*! @brief Gets the output format. 292 * @return string for setting the expected output format in gnuplot. 293 * @warning noenhanced allows underscores while enhanced does subscripts. 294 * if we add a (no) enhanced option, we'll have to add a safeFormat(std::string) that replaces \c _ with <code>\_</code> . 295 * This is tricky and can be done at "post production" stage :-) 296 */ 297 std::string getTerm() const ; 298 299 /*! @brief Gets the graph output extension. 300 * By default, this is ".eps". 301 * @return a string for this extension, including the sepatating dot. 302 * 303 */ 304 std::string getExt() const ; 305 306 #if 0 307 /*! @brief gets the style of the graph. 308 * This is very user-tweakable !! 309 * @return the style for gnuplot. 310 */ 311 const std::string & getStyle() 312 { 313 return "#style\n"+_styleopts_ ; 314 } 315 316 /*! @brief sets the style of the graph. 317 * This is very user-tweakable !! 318 * @param style the style for gnuplot as a gnuplot command. 319 */ 320 void setStyle(const std::string & style) 321 { 322 _styleopts_ = style ; 323 } 324 #endif 325 326 /*! @brief sets the legend position. 327 * @param keypos the arguments to key (where the legend should be put) 328 * can be : 329 * <code> 330 * set key {on|off} {default} 331 * {{inside | outside} | {lmargin | rmargin | tmargin | bmargin} | {at <position>}} 332 * {left | right | center} {top | bottom | center} 333 * {vertical | horizontal} {Left | Right} 334 * {{no}reverse} {{no}invert} 335 * {samplen <sample_length>} {spacing <vertical_spacing>} 336 * {width <width_increment>} 337 * {height <height_increment>} 338 * {{no}autotitle {columnheader}} 339 * {title "<text>"} {{no}enhanced} 340 * {{no}box { {linestyle | ls <line_style>} | {linetype | lt <line_type>} {linewidth | lw <line_width>}}} 341 * </code> 342 */ 343 void setKeyPos(const std::string & keypos) ; 344 345 346 /*! @brief Gets the legend position. 347 * by default, it is "under". 348 */ 349 std::string getKeyPos() const ; 350 351 /*! @brief sets the position of the labels on the X absciss. 352 * @param opt 353 * @param more more stuff 354 */ 355 void setXtics ( enum Options::Type opt, const std::string & more="") ; 356 357 /*! @brief Gets the legend position. 358 * by default, it is 45° inclined (use in on long tics legends). 359 */ 360 const std::string & getXtics() const ; 361 362 /*! @brief Gets the name of the output graph. 363 * @param basnam the raw name for the output. 364 * @return basnam+extenstion. 365 */ 366 std::string getOutput(const std::string & basnam) const ; 367 368 /*! @brief Sets the type of plot. 369 * @param type the type. 370 * @sa PlotType 371 * 372 */ 373 void setPlotType(enum Plot::Type type) ; 374 375 /*! @brief Sets the way dots are linked. 376 * @sa LineType 377 * @param type type 378 */ 379 void setLineType( enum Line::Type type) ; 380 381 /*! @brief Gets the type of plot. 382 * default is histogram, or if graph is supplied, then the default is linespoints. 383 * Can be totally customized. 384 * @return a string for gnuplot to set the plot type. 385 * @sa PlotType 386 * 387 */ 388 std::string getPlotType(const std::string & extraargs ="") ; 389 390 /*! @brief adds some style line to the graph. 391 * This is very user-tweakable !! 392 * @param style a style line for gnuplot as a gnuplot command. 393 */ 394 void addPlotType(const std::string & style) ; 395 396 /*! @brief tells which columns to use. 397 * @param col a column to use. 398 * @param moreargs more stuff 399 */ 400 void setUsingSeries(size_t col, const std::string & moreargs= "") ; 401 402 /*! @brief adds a column to use 403 * @param col a column to use. 404 * @param moreargs more stuff 405 * @pre \p _usingcols_ is not empty, ie \c setUsingSeries has already been called. 406 */ 407 void addUsingSeries(size_t col, const std::string & moreargs= "") ; 408 409 /*! @brief tells which columns to use. 410 * @param cols a list of column to use. 411 * @param moreargs more stuff 412 */ 413 void setUsingSeries(std::list<size_t> cols, const std::string & moreargs= "") ; 414 415 /*! @brief adds a set of columns to use. 416 * @param cols a list of column to use. 417 * @param moreargs more stuff 418 * @pre \p _usingcols_ is not empty, ie \c setUsingSeries has already been called. 419 */ 420 void addUsingSeries(std::list<size_t> cols, const std::string & moreargs= "") ; 421 422 /*! @brief tells which columns to use. 423 * @param cols all colums between \c cols.first and \c cols.second (included) 424 * will be used. 425 * @param moreargs more stuff 426 * 427 */ 428 void setUsingSeries(std::pair<size_t,size_t> cols, const std::string & moreargs= "") ; 429 430 /*! @brief adds contiguous columns to use. 431 * @param cols all colums between \c cols.first and \c 432 * cols.second will be used. 433 * @param moreargs more stuff 434 * @pre \p _usingcols_ is not empty, ie \c setUsingSeries has 435 * already been called. 436 * 437 */ 438 void addUsingSeries(std::pair<size_t,size_t> cols, const std::string & moreargs= "") ; 439 440 const std::string & getUsingSeries() const ; 441 442 private : 443 // int _precision_ ; //!< precision of the output. by default 2. 444 /* Legend. */ 445 std::string _legend_pos_; //!< legend position 446 /* titles */ 447 std::string _title_ ; //!< name of the graph 448 std::string _title_x_ ; //!< title for the points 449 std::string _title_y_ ; //!< title for the series 450 std::string _xtics_ ; //!< format for the x tics. 451 /* units */ 452 // std::string _unit_ ; 453 /* terminal output */ 454 enum Term::Type _term_ ; //!< output data format. 455 // std::string _termopts_ ; 456 /* plotting style */ 457 enum Plot::Type _plot_type_ ; //!< histogram/graph style 458 // std::string _plot_extra_; //!< extra specification for the plot style. default empty. 459 enum Line::Type _line_type_ ; //!< style for the representation of points 460 std::string _styleopts_ ; //!< gp style command. 461 /* columns to use */ 462 std::string _usingcols_ ; //!< columns to be used (gp command) 463 464 465 } ; // PlotStyle 466 467 } // LinBox 468 469 // 470 // PlotData 471 // 472 473 namespace LinBox { 474 475 struct Point { 476 //! x 477 struct Labels { 478 typedef std::string type; 479 }; 480 481 //! y 482 struct Values { 483 typedef double type; 484 } ; 485 486 //! numerical value for x 487 struct Points { 488 typedef double type; 489 }; 490 491 //! y time 492 struct Times { 493 typedef double type; 494 }; 495 } ; 496 497 /*! @brief The raw data to plot. 498 * Represents the labels for the points (X axis) and the values for 499 * each series of measures (Y axis). 500 * 501 * Members that set/get are named as follows : 502 * - getX(nom,j) return the j'th element of series named nom 503 * - getX(i,j) return the j'th element of series number i 504 * - getCurrentSeriesX(j) return the j'th element of current series 505 * - getCurrentEntryX() return the current element of current series (ie the last one) 506 * - . 507 * 508 * Members are also named as follows : 509 * - getXXX is a const member 510 * - selectXXX is non const and may create/update stuff 511 * - refXXX returns a reference 512 * - setXXX sets something 513 * 514 * @internal The internal representation is a 515 * vector of vector, each series of point being a vector of double. 516 * 517 * @tparam Xkind the X axis is parametrised by \p Xkind (string, int, double...) 518 * The Y axis is always represented by double. 519 * @todo put the legend (title, x, y) in there 520 */ 521 class PlotData { 522 private : 523 std::vector<DataSeries > _tableau_ ; //!< data. \c _tableau_[i] represents a series of measurements. A data series is augmented only via the \c push_back method. A series may be accessed by its name, its number or it is the current working series. 524 svector_t _series_label_ ; //!< label for each series of measures. Used in the legend of the plots/tables of points. 525 mutable size_t _curr_series_ ; //!< index of the current series of measurements. 526 mutable TimeWatcher _time_watch_ ; //!< time predictor, helper. See \c TimeWatcher. 527 MetaData _plot_data_ ; //!< information abouth the benchmark 528 MetaDataSeries _meta_data_ ; //!< information about each point 529 private: 530 531 #ifdef __LINBOX_HAVE_TINYXML2 532 //! @internal data part of the XML output 533 tinyxml2::XMLElement * saveData(tinyxml2::XMLDocument & doc) ; 534 #endif 535 536 /** Finds the index of a series by its name. 537 * @param nom name of the series 538 * @return its index 539 */ 540 size_t getIndex(const std::string & nom) const ; 541 542 /** Finds the index of a series by its name. 543 * @param nom name of the series 544 * @return its index 545 */ 546 size_t selectIndex(const std::string & nom) ; 547 548 public : 549 550 /*! Returns the ith series of measurements. 551 * @param i ith series to be returned 552 */ 553 const DataSeries & getSeries(const size_t &i) const ; 554 555 /*! Returns the ith series of measurements. 556 * @param i ith series to be returned 557 */ 558 const DataSeries & selectSeries(const size_t &i) ; 559 560 /*! Returns the series of measurements after its name. 561 * @param nom name of series to be returned 562 */ 563 const DataSeries & selectSeries(const std::string &name) ; 564 565 /*! Returns the current series of measurements. 566 */ 567 const DataSeries & getCurrentSeries() const; 568 569 /*! Returns the ith series of measurements. 570 * @param i ith series to be returned 571 */ 572 DataSeries & refSeries(const size_t &i) ; 573 574 /*! Returns the ith series of measurements. 575 * @param i ith series to be returned 576 */ 577 DataSeries & refSeries(const std::string & nom) ; 578 579 /*! Returns the current series of measurements. 580 */ 581 DataSeries & refCurrentSeries() ; 582 583 /*! Inits a plot with series of data. 584 * @param nb_pts number of points in each series. 585 * @param nb_srs number of series of points. Default is 1. 586 */ 587 PlotData() ; 588 /*! destructor. 589 */ 590 ~PlotData() ; 591 592 /*! copy constructor. 593 * @param PD a PlotData to copy. 594 */ 595 PlotData(const PlotData & PD); 596 597 /** @brief initialize to empty 598 */ 599 void clear() ; 600 601 /*! merges another plot data to the current one. 602 * (just adds to the end, does not merge series by name yet) 603 */ 604 void merge(const PlotData &PD) ; 605 606 /*! @brief get the number of series. 607 * @return number of series. 608 */ 609 size_t size() const ; 610 611 /** @brief gets the current series number. 612 */ 613 size_t getCurrentSeriesNumber() const ; 614 615 /*! @brief Sets the name of a series. 616 * @param i index of the series 617 * @param nom name of the series 618 */ 619 void setSeriesName(const size_t & i, const std::string & nom) ; 620 621 // ref Series 622 623 template<class Pt> 624 std::vector<typename Pt::type> & refSeries(const size_t & i, Pt kind) ; 625 626 template<class Pt> refSeries(const std::string & name,Pt kind)627 std::vector<typename Pt::type> & refSeries(const std::string & name, Pt kind) 628 { 629 return refSeries(getIndex(name ), kind ); 630 } 631 632 // get Series 633 634 template<class Pt> 635 const std::vector<typename Pt::type> & getSeries(const size_t & i, Pt kind) const ; 636 637 template<class Pt> getSeries(const std::string & name,Pt kind)638 const std::vector<typename Pt::type> & getSeries(const std::string & name, Pt kind) const 639 { 640 return getSeries(getIndex(name),kind); 641 } 642 643 template<class Pt> getCurrentSeries(Pt kind)644 const std::vector<typename Pt::type> & getCurrentSeries( Pt kind) const 645 { 646 return getSeries(_curr_series_, kind); 647 } 648 649 template<class Pt> getSeriesEntry(const size_t & i,const size_t & j,Pt kind)650 const typename Pt::type & getSeriesEntry(const size_t & i, const size_t & j, Pt kind) const 651 { 652 linbox_check(j<getSeriesSize(i)); 653 return (getSeries(i,kind)[j]) ; 654 } 655 656 template<class Pt> getSeriesEntry(const std::string & name,const size_t & j,Pt kind)657 const typename Pt::type & getSeriesEntry(const std::string & name, const size_t & j, Pt kind) const 658 { 659 return getSeriesEntry(getIndex(name),j,kind); 660 } 661 662 template<class Pt> getSeriesEntry(const size_t & i,Pt kind)663 const typename Pt::type & getSeriesEntry(const size_t & i, Pt kind) const 664 { 665 return ( getSeries(i,kind).back() ) ; 666 } 667 668 template<class Pt> getSeriesEntry(const std::string & name,Pt kind)669 const typename Pt::type & getSeriesEntry(const std::string & name, Pt kind) const 670 { 671 return getSeriesEntry(getIndex(name),kind); 672 } 673 674 template<class Pt> getCurrentSeriesEntry(const size_t & j,Pt kind)675 const typename Pt::type & getCurrentSeriesEntry(const size_t & j, Pt kind) const 676 { 677 return getSeriesEntry(_curr_series_, j, kind); 678 } 679 680 template<class Pt> getCurrentSeriesEntry(Pt kind)681 const typename Pt::type & getCurrentSeriesEntry( Pt kind) const 682 { 683 return getSeriesEntry(_curr_series_, kind); 684 } 685 686 687 // set Series 688 689 /** Gets the name of a series. 690 * @param i index of the series 691 */ 692 const std::string & getSeriesName(const size_t & i) const ; 693 694 /** Gets the name of the current series. 695 */ 696 const std::string & getCurrentSeriesName() const ; 697 698 /*! @brief Sets the name of the current series. 699 * @param nom name of the series 700 */ 701 void setCurrentSeriesName(const std::string & nom) ; 702 703 /** Inits the watch on a series 704 * @param i index of a series 705 */ 706 void initWatch ( const size_t & i) ; 707 708 /** Inits the watch to current series 709 */ 710 void initCurrentSeriesWatch () ; 711 712 /** Creates a new series. 713 * It is created after the last series. 714 * \c getCurrentSeries() points to it. 715 * @param nom name of the new series 716 */ 717 void newSeries(const std::string & nom = "") ; 718 719 /** Finish a series of measurements. 720 * Nothing is done for the moment. 721 */ 722 void finishSeries() ; 723 724 /** @brief size of a series. 725 * @param i index of the series 726 */ 727 size_t getSeriesSize(const size_t & i) const ; 728 729 /** @brief size of the current series. 730 */ 731 size_t getCurrentSeriesSize() const ; 732 733 /*! goes to the next series of points 734 */ 735 bool selectNextSeries() ; 736 737 /** selects the first series 738 */ 739 void selectFirstSeries() ; 740 741 /*! @brief Sets the name of a point. 742 * @param i series number 743 * @param j index for the the point 744 * @param nom name of the point 745 */ 746 template<class T> setSeriesPointLabel(const size_t & i,const size_t & j,const T & nom)747 void setSeriesPointLabel(const size_t & i, const size_t & j, const T & nom) 748 { 749 std::string nom_s = fortifyString(toString(nom)); 750 linbox_check(j<getSeriesSize(i) ); 751 refSeries(i).PointLabels[j] = nom_s ; 752 753 return; 754 } 755 756 /*! @brief Sets the name of a point. 757 * @param j index for the the point 758 * @param nom name of the point 759 */ 760 void setCurrentSeriesPointLabel(const size_t & j, const std::string & nom) ; 761 762 763 764 /*! @brief gets the name of a series. 765 * Defaults to \c "series.i" 766 * @param i its index. 767 * @return its name. 768 */ 769 std::string getSeriesLabel(const size_t & i) const ; 770 771 /*! @brief gets the name of a series. 772 * Defaults to \c "series.i" 773 * @param i its index. 774 * @return its name. 775 */ 776 std::string getCurrentSeriesLabel() const; 777 778 /*! @brief gets all the names in the series. 779 * @return a vector of names. 780 */ 781 const svector_t & getSeriesLabels() const ; 782 783 784 785 786 787 /*! @brief sets a new entry. 788 * @param i index of the series 789 * @param j index of the point 790 * @param nam name of the point (eg size of the matrix, name of a sparse matrix,...) 791 * @param val value to be inserted (eg mflops, sec,...). 792 * @param xval x value of the point (eg size of the matrix, of a sparse matrix,...) 793 * @param yval time for this computation (seconds) 794 */ 795 void setSeriesEntry(const size_t &i, const std::string & nam, const double & val 796 , const double & xval = NAN, const double & yval = NAN) ; 797 798 /*! @brief sets a new entry. 799 * @param name name of the series 800 * @param j index of the point 801 * @param nam name of the point (eg size of the matrix, name of a sparse matrix,...) 802 * @param val value to be inserted (eg mflops, sec,...). 803 * @param xval x value of the point (eg size of the matrix, of a sparse matrix,...) 804 * @param yval time for this computation (seconds) 805 */ 806 void setSeriesEntry(const std::string & nom, const std::string & nam, const double & val 807 , const double & xval = NAN, const double & yval = NAN) ; 808 809 /*! @brief sets a new entry. 810 * @param j index of the point 811 * @param nam name of the point (eg size of the matrix, name of a sparse matrix,...) 812 * @param val value to be inserted (eg mflops, sec,...). 813 */ 814 template<class T> 815 void setCurrentSeriesEntry(const T & nam, const double & val 816 , const double & xval = NAN, const double & yval = NAN) 817 { 818 std::string nam_s = fortifyString(toString(nam)); 819 return setSeriesEntry(_curr_series_,nam_s,val,xval,yval) ; 820 } 821 822 823 824 /*! gets a reference to the array of data. 825 * @return a reference to the member \c _tableau_ representing the data. 826 */ 827 const std::vector<DataSeries > & getTable() const ; 828 829 /*! gets a reference to the array of data. 830 * @return a reference to the member \c _tableau_ representing the data. 831 */ 832 std::vector<DataSeries > & refTable() ; 833 834 835 /** @brief Continue for another time measure ? 836 * @see TimeWatcher::keepon 837 * @param repet current number of repetitions for this new measure 838 * @param tim time previously spent on the measures. 839 * @return true if one more measure can be done 840 */ 841 bool keepon(size_t & repet, double tim, bool usePrediction=false) ; 842 843 void load( const std::string & filename) ; 844 845 /** @brief saves the data in XML format. 846 * @param filename file name 847 * @param title titles of the data 848 * @param xtitle legend of the X axis 849 * @param ytitle legend of the Y axis. 850 */ 851 void save( const std::string & filename 852 , const std::string & title = "" 853 , const std::string & xtitle = "" 854 , const std::string & ytitle = "") ; 855 addCurrentEntryMetaData(const MetaData & m)856 void addCurrentEntryMetaData(const MetaData & m) 857 { 858 _meta_data_.push_back(getCurrentEntryId(),m); 859 } 860 861 /** returns the unique ID of the current series last entry 862 */ getCurrentEntryId()863 const std::string & getCurrentEntryId() const 864 { 865 return (getCurrentSeries().UID).back(); 866 } 867 868 /** @brief returns the unique ID of the current series j'th entry. 869 * @param j index of the entry. 870 */ getCurrentSeriesId(const size_t & j)871 const std::string & getCurrentSeriesId(const size_t & j) const 872 { 873 return (getCurrentSeries().UID[j]); 874 } 875 876 /** @brief returns the unique ID of the i'th series j'th entry. 877 * @param i index of the series. 878 * @param j index of the entry. 879 */ getId(const size_t & i,const size_t & j)880 const std::string & getId(const size_t & i, const size_t & j) 881 { 882 return (selectSeries(i).UID[j]); 883 } 884 885 /** @brief returns the unique ID of the i'th series j'th entry. 886 * @param i index of the series. 887 * @param j index of the entry. 888 */ getId(const std::string & name,const size_t & j)889 const std::string & getId(const std::string & name, const size_t & j) 890 { 891 return (selectSeries(name).UID[j]); 892 } 893 894 }; // PlotData 895 896 } // LinBox 897 898 // 899 // PlotGraph 900 // 901 902 namespace LinBox { 903 904 /*! @brief The graph (2D). 905 * This class joins a PlotStyle and a PlotData to build up a graph. A 906 * filename should be provided as well, indicating where the output 907 * graph and scripts will be generated. 908 * 909 * @warning the filename will get a random suffix before the extension 910 * so as not to overwrite files "par inadvertance". 911 * @warning don't name anything else than a folder "data" in your working directory. You've been warned. 912 * @todo make depend on PlotStyle (that owns data) 913 */ 914 //!@todo use getUsingSeries in latex/html/csv/xml 915 class PlotGraph { 916 private : 917 PlotData & _data_ ; //!< reference to the data points 918 PlotStyle & _style_ ; //!< reference to a plotting style 919 std::string _filename_ ; //!< name for the output file (without extension). a random \c _XXXXXX suffix will be added to make it unique. 920 std::string _printname_ ; //!< name for the output file (without extension) to be printed. a random \c _XXXXXX suffix makes it unique. 921 dmatrix_t _merge_data_ ; 922 svector_t _merge_points_ ; 923 924 private : 925 926 /*! @internal 927 * @brief Appends random suffix. 928 * Appends to \p _filename_ a random string constituted of an 929 * underscore followed by 8 random alnum chars. 930 * @return the concatenation of \c _filename_ and this suffix. 931 */ 932 void _randomName(); 933 934 //! @internal returns the file name (without extension and uid) 935 const std::string & getFileName() ; 936 937 //! @bug this supposes the two series have unique measurements for one point. 938 void mergeTwoSeries( svector_t & merge_points 939 , dmatrix_t & merge_data 940 , const svector_t & pts 941 , const dvector_t & dat 942 , const size_t & idx) const ; 943 944 //! merge all series of points into a vector of absissa points and a vector of vector of data points 945 void mergeSeries(); 946 947 void print_csv(); 948 949 void print_dat(); 950 951 void print_xml(); 952 953 void print_html() ; 954 955 /*! @brief Prints data in a latex tabular. 956 */ 957 void print_latex(); 958 959 /*!@brief Plots the data with gnuplot. 960 * Produces data in a .dat file, creates a .gp gnuplot script and 961 * outputs a graph calling gnuplot. 962 * @warning If gnuplot is not available, fall back to the latex method. 963 */ 964 void print_gnuplot(bool only_data=false); 965 966 public : 967 968 /*! @brief Sets a new data structure. 969 * @param data a reference to a PlotData class. 970 */ 971 void setData( PlotData & data ); 972 973 /*! @brief Gets the data. 974 * @param[in,out] data a reference to a PlotData class. 975 */ 976 PlotData & refData( PlotData & data); 977 978 /*! @brief Sets a new style structure. 979 * @param style a reference to a PlotStyle class. 980 */ 981 void setStyle( PlotStyle & style ) ; 982 983 /*! @brief Gets the style. 984 * @param[in,out] style a reference to a PlotStyle class. 985 */ 986 PlotStyle & refStyle( PlotStyle & style) ; 987 refStyle()988 PlotStyle & refStyle( ) 989 { return _style_ ; } 990 991 992 // not implemented yet 993 void sortSeries() ; 994 995 // not implemented yet 996 void unique() ; 997 998 /*! @brief Constructor for the PlotGraph class. 999 * Plots a series of data according to a style. 1000 * @param data data to be plot, will be processed by the style 1001 * @param style sets parameters to gnuplot to achieve a nice 1002 * plot. 1003 */ 1004 PlotGraph( PlotData & data, PlotStyle & style ); 1005 1006 /*! @brief sets the ouput file name. 1007 * All output is put in a "data" subfolder. 1008 * @warning Since no file is overwritten, this 1009 * directory can rapidly get very populated. 1010 */ 1011 void setOutFilename( const std::string & filename ) ; 1012 1013 const std::string & getUsingSeries() ; 1014 1015 /*! @brief Gets the plot command line. 1016 * @param File the name of/path to the data file (with extension) 1017 * @return a gnuplot "plot" command stream. 1018 */ 1019 std::string getPlotCommand(const std::string & File) ; 1020 1021 void print( Tag::Printer pt = Tag::Printer::xml) ; 1022 1023 void save() ; 1024 1025 void load(const std::string & filename) ; 1026 1027 }; // PlotGraph 1028 1029 } // LinBox 1030 1031 // 1032 // Least Squares 1033 // 1034 1035 #ifdef __LINBOX_HAVE_LAPACK 1036 extern "C" { 1037 #if 1 // from lapack (not clapack) 1038 1039 void dgels_(char *trans, int *m, int *n, int *nrhs, double *a, int *lda, 1040 double *b, int *ldb, double *work, int *lwork, int *info); 1041 1042 void dgelsy_(int *m, int *n, int *nrhs, double *a, int *lda, 1043 double *b, int *ldb, int *JPVT, double *RCOND, int *RANK, 1044 double *work, int *lwork, int *info); 1045 1046 void dgelss_(int *m, int *n, int *nrhs, double *a, int *lda, 1047 double *b, int *ldb, double *s, double *RCOND, int *RANK, 1048 double *work, int *lwork, int *info); 1049 #endif 1050 1051 #if 0 1052 int clapack_dgels (const enum CBLAS_ORDER Order, 1053 const enum CBLAS_TRANSPOSE TA, 1054 int M, 1055 int N, 1056 int NRHS, 1057 double * A, 1058 int lda, 1059 double * B, 1060 const int ldb 1061 ); 1062 #endif 1063 } 1064 #endif // __LINBOX_HAVE_LAPACK 1065 1066 // 1067 // Curve fitting 1068 // 1069 1070 namespace LinBox { 1071 1072 //! fit X[n-1,n],Y[n-1,n] and return evaluation at x. 1073 double fit2(const dvector_t & X, const dvector_t & Y, int n, double x); 1074 1075 #ifdef __LINBOX_HAVE_LAPACK 1076 //! fits with a degree 3 polynomial and return evaluation at x. 1077 double fit_lapack3(const dvector_t &X, const dvector_t &Z, double x); 1078 #endif // __LINBOX_HAVE_LAPACK 1079 1080 1081 //! fit X[n-2,n],Y[n-2,n] and return evaluation at x. 1082 double fit3(const dvector_t & X, const dvector_t & Y,int n, double x); 1083 1084 } // LinBox 1085 1086 1087 #ifdef LinBoxSrcOnly 1088 #include "benchmarks/benchmark.C" 1089 #endif 1090 1091 #include "benchmarks/benchmark.inl" 1092 1093 #endif // __LINBOX_benchmarks_benchmark_H 1094 1095 // Local Variables: 1096 // mode: C++ 1097 // tab-width: 4 1098 // indent-tabs-mode: nil 1099 // c-basic-offset: 4 1100 // End: 1101 // vim:sts=4:sw=4:ts=4:et:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s 1102