gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Merge
0 5 2
merge default
5 files changed with 186 insertions and 68 deletions:
↑ Collapse diff ↑
Ignore white space 6 line context
1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2
 *
3
 * This file is a part of LEMON, a generic C++ optimization library.
4
 *
5
 * Copyright (C) 2003-2009
6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8
 *
9
 * Permission to use, modify and distribute this software is granted
10
 * provided that this copyright notice appears in all copies. For
11
 * precise terms see the accompanying LICENSE file.
12
 *
13
 * This software is provided "AS IS" with no warranty of any kind,
14
 * express or implied, and with no claim as to its suitability for any
15
 * purpose.
16
 *
17
 */
18

	
19
///\file
20
///\brief Some basic non-inline functions and static global data.
21

	
22
#include<lemon/bits/windows.h>
23

	
24
#ifdef WIN32
25
#ifndef WIN32_LEAN_AND_MEAN
26
#define WIN32_LEAN_AND_MEAN
27
#endif
28
#ifndef NOMINMAX
29
#define NOMINMAX
30
#endif
31
#include <windows.h>
32
#else
33
#include <unistd.h>
34
#include <ctime>
35
#include <sys/times.h>
36
#include <sys/time.h>
37
#endif
38

	
39
#include <cmath>
40
#include <sstream>
41

	
42
namespace lemon {
43
  namespace bits {
44
    void getWinProcTimes(double &rtime,
45
                         double &utime, double &stime,
46
                         double &cutime, double &cstime)
47
    {
48
#ifdef WIN32
49
      static const double ch = 4294967296.0e-7;
50
      static const double cl = 1.0e-7;
51

	
52
      FILETIME system;
53
      GetSystemTimeAsFileTime(&system);
54
      rtime = ch * system.dwHighDateTime + cl * system.dwLowDateTime;
55

	
56
      FILETIME create, exit, kernel, user;
57
      if (GetProcessTimes(GetCurrentProcess(),&create, &exit, &kernel, &user)) {
58
        utime = ch * user.dwHighDateTime + cl * user.dwLowDateTime;
59
        stime = ch * kernel.dwHighDateTime + cl * kernel.dwLowDateTime;
60
        cutime = 0;
61
        cstime = 0;
62
      } else {
63
        rtime = 0;
64
        utime = 0;
65
        stime = 0;
66
        cutime = 0;
67
        cstime = 0;
68
      }
69
#else
70
      timeval tv;
71
      gettimeofday(&tv, 0);
72
      rtime=tv.tv_sec+double(tv.tv_usec)/1e6;
73

	
74
      tms ts;
75
      double tck=sysconf(_SC_CLK_TCK);
76
      times(&ts);
77
      utime=ts.tms_utime/tck;
78
      stime=ts.tms_stime/tck;
79
      cutime=ts.tms_cutime/tck;
80
      cstime=ts.tms_cstime/tck;
81
#endif
82
    }
83

	
84
    std::string getWinFormattedDate()
85
    {
86
      std::ostringstream os;
87
#ifdef WIN32
88
      SYSTEMTIME time;
89
      GetSystemTime(&time);
90
#if defined(_MSC_VER) && (_MSC_VER < 1500)
91
      LPWSTR buf1, buf2, buf3;
92
      if (GetDateFormat(LOCALE_USER_DEFAULT, 0, &time,
93
                        L"ddd MMM dd", buf1, 11) &&
94
          GetTimeFormat(LOCALE_USER_DEFAULT, 0, &time,
95
                        L"HH':'mm':'ss", buf2, 9) &&
96
          GetDateFormat(LOCALE_USER_DEFAULT, 0, &time,
97
                        L"yyyy", buf3, 5)) {
98
        os << buf1 << ' ' << buf2 << ' ' << buf3;
99
      }
100
#else
101
      char buf1[11], buf2[9], buf3[5];
102
      if (GetDateFormat(LOCALE_USER_DEFAULT, 0, &time,
103
                        "ddd MMM dd", buf1, 11) &&
104
          GetTimeFormat(LOCALE_USER_DEFAULT, 0, &time,
105
                        "HH':'mm':'ss", buf2, 9) &&
106
          GetDateFormat(LOCALE_USER_DEFAULT, 0, &time,
107
                        "yyyy", buf3, 5)) {
108
        os << buf1 << ' ' << buf2 << ' ' << buf3;
109
      }
110
#endif
111
      else os << "unknown";
112
#else
113
      timeval tv;
114
      gettimeofday(&tv, 0);
115

	
116
      char cbuf[26];
117
      ctime_r(&tv.tv_sec,cbuf);
118
      os << cbuf;
119
#endif
120
      return os.str();
121
    }
122

	
123
    int getWinRndSeed()
124
    {
125
#ifdef WIN32
126
      FILETIME time;
127
      GetSystemTimeAsFileTime(&time);
128
      return GetCurrentProcessId() + time.dwHighDateTime + time.dwLowDateTime;
129
#else
130
      timeval tv;
131
      gettimeofday(&tv, 0);
132
      return getpid() + tv.tv_sec + tv.tv_usec;
133
#endif
134
    }
135
  }
136
}
Ignore white space 6 line context
1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2
 *
3
 * This file is a part of LEMON, a generic C++ optimization library.
4
 *
5
 * Copyright (C) 2003-2009
6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8
 *
9
 * Permission to use, modify and distribute this software is granted
10
 * provided that this copyright notice appears in all copies. For
11
 * precise terms see the accompanying LICENSE file.
12
 *
13
 * This software is provided "AS IS" with no warranty of any kind,
14
 * express or implied, and with no claim as to its suitability for any
15
 * purpose.
16
 *
17
 */
18

	
19
#ifndef LEMON_WINDOWS_H
20
#define LEMON_WINDOWS_H
21

	
22
#include <string>
23

	
24
namespace lemon {
25
  namespace bits {
26
    void getWinProcTimes(double &rtime,
27
                         double &utime, double &stime,
28
                         double &cutime, double &cstime);
29
    std::string getWinFormattedDate();
30
    int getWinRndSeed();
31
  }
32
}
33

	
34
#endif
Ignore white space 6 line context
1 1
INCLUDE_DIRECTORIES(
2 2
  ${CMAKE_SOURCE_DIR}
3 3
  ${CMAKE_BINARY_DIR}
4 4
)
5 5

	
6 6
CONFIGURE_FILE(
7 7
  ${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake
8 8
  ${CMAKE_CURRENT_BINARY_DIR}/config.h
9 9
)
10 10

	
11 11
SET(LEMON_SOURCES
12 12
  arg_parser.cc
13 13
  base.cc
14 14
  color.cc
15 15
  lp_base.cc
16 16
  lp_skeleton.cc
17
  random.cc)
17
  random.cc
18
  bits/windows.cc
19
)
18 20

	
19 21
IF(HAVE_GLPK)
20 22
  SET(LEMON_SOURCES ${LEMON_SOURCES} glpk.cc)
21 23
  INCLUDE_DIRECTORIES(${GLPK_INCLUDE_DIR})
22 24
  IF(WIN32)
23 25
    INSTALL(FILES ${GLPK_BIN_DIR}/glpk.dll DESTINATION bin)
24 26
    INSTALL(FILES ${GLPK_BIN_DIR}/libltdl3.dll DESTINATION bin)
25 27
    INSTALL(FILES ${GLPK_BIN_DIR}/zlib1.dll DESTINATION bin)
26 28
  ENDIF(WIN32)
27 29
ENDIF(HAVE_GLPK)
28 30

	
29 31
ADD_LIBRARY(lemon ${LEMON_SOURCES})
30 32

	
31 33
INSTALL(
32 34
  TARGETS lemon
33 35
  ARCHIVE DESTINATION lib
34 36
  COMPONENT library)
35 37

	
36 38
INSTALL(
37 39
  DIRECTORY . bits concepts
38 40
  DESTINATION include/lemon
39 41
  COMPONENT headers
40 42
  FILES_MATCHING PATTERN "*.h")
Ignore white space 6 line context
1 1
EXTRA_DIST += \
2 2
	lemon/lemon.pc.in \
3 3
	lemon/CMakeLists.txt
4 4

	
5 5
pkgconfig_DATA += lemon/lemon.pc
6 6

	
7 7
lib_LTLIBRARIES += lemon/libemon.la
8 8

	
9 9
lemon_libemon_la_SOURCES = \
10 10
	lemon/arg_parser.cc \
11 11
	lemon/base.cc \
12 12
	lemon/color.cc \
13 13
	lemon/lp_base.cc \
14 14
	lemon/lp_skeleton.cc \
15
	lemon/random.cc
15
        lemon/random.cc \
16
	lemon/bits/windows.cc
16 17

	
17 18

	
18 19
lemon_libemon_la_CXXFLAGS = \
19 20
	$(GLPK_CFLAGS) \
20 21
	$(CPLEX_CFLAGS) \
21 22
	$(SOPLEX_CXXFLAGS) \
22 23
	$(CLP_CXXFLAGS)
23 24

	
24 25
lemon_libemon_la_LDFLAGS = \
25 26
	$(GLPK_LIBS) \
26 27
	$(CPLEX_LIBS) \
27 28
	$(SOPLEX_LIBS) \
28 29
	$(CLP_LIBS)
29 30

	
30 31
if HAVE_GLPK
31 32
lemon_libemon_la_SOURCES += lemon/glpk.cc
32 33
endif
33 34

	
34 35
if HAVE_CPLEX
35 36
lemon_libemon_la_SOURCES += lemon/cplex.cc
36 37
endif
37 38

	
38 39
if HAVE_SOPLEX
39 40
lemon_libemon_la_SOURCES += lemon/soplex.cc
40 41
endif
41 42

	
42 43
if HAVE_CLP
43 44
lemon_libemon_la_SOURCES += lemon/clp.cc
44 45
endif
45 46

	
46 47
lemon_HEADERS += \
47 48
	lemon/adaptors.h \
48 49
	lemon/arg_parser.h \
49 50
	lemon/assert.h \
50 51
	lemon/bfs.h \
51 52
	lemon/bin_heap.h \
52 53
	lemon/circulation.h \
53 54
	lemon/clp.h \
54 55
	lemon/color.h \
55 56
	lemon/concept_check.h \
56 57
	lemon/counter.h \
57 58
	lemon/core.h \
58 59
	lemon/cplex.h \
59 60
	lemon/dfs.h \
60 61
	lemon/dijkstra.h \
61 62
	lemon/dim2.h \
62 63
	lemon/dimacs.h \
63 64
	lemon/edge_set.h \
64 65
	lemon/elevator.h \
65 66
	lemon/error.h \
66 67
	lemon/full_graph.h \
67 68
	lemon/glpk.h \
68 69
	lemon/graph_to_eps.h \
69 70
	lemon/grid_graph.h \
70 71
	lemon/hypercube_graph.h \
71 72
	lemon/kruskal.h \
72 73
	lemon/hao_orlin.h \
73 74
	lemon/lgf_reader.h \
74 75
	lemon/lgf_writer.h \
75 76
	lemon/list_graph.h \
76 77
	lemon/lp.h \
77 78
	lemon/lp_base.h \
78 79
	lemon/lp_skeleton.h \
79 80
	lemon/list_graph.h \
80 81
	lemon/maps.h \
81 82
	lemon/math.h \
82 83
	lemon/max_matching.h \
83 84
	lemon/nauty_reader.h \
84 85
	lemon/path.h \
85 86
	lemon/preflow.h \
86 87
	lemon/radix_sort.h \
87 88
	lemon/random.h \
88 89
	lemon/smart_graph.h \
89 90
	lemon/soplex.h \
90 91
	lemon/suurballe.h \
91 92
	lemon/time_measure.h \
92 93
	lemon/tolerance.h \
93
	lemon/unionfind.h
94
	lemon/unionfind.h \
95
	lemon/bits/windows.h
94 96

	
95 97
bits_HEADERS += \
96 98
	lemon/bits/alteration_notifier.h \
97 99
	lemon/bits/array_map.h \
98 100
	lemon/bits/base_extender.h \
99 101
	lemon/bits/bezier.h \
100 102
	lemon/bits/default_map.h \
101 103
	lemon/bits/edge_set_extender.h \
102 104
	lemon/bits/enable_if.h \
103 105
	lemon/bits/graph_adaptor_extender.h \
104 106
	lemon/bits/graph_extender.h \
105 107
	lemon/bits/map_extender.h \
106 108
	lemon/bits/path_dump.h \
107 109
	lemon/bits/solver_bits.h \
108 110
	lemon/bits/traits.h \
109 111
	lemon/bits/variant.h \
110 112
	lemon/bits/vector_map.h
111 113

	
112 114
concept_HEADERS += \
113 115
	lemon/concepts/digraph.h \
114 116
	lemon/concepts/graph.h \
115 117
	lemon/concepts/graph_components.h \
116 118
	lemon/concepts/heap.h \
117 119
	lemon/concepts/maps.h \
118 120
	lemon/concepts/path.h
Ignore white space 6 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2009
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#ifndef LEMON_GRAPH_TO_EPS_H
20 20
#define LEMON_GRAPH_TO_EPS_H
21 21

	
22 22
#include<iostream>
23 23
#include<fstream>
24 24
#include<sstream>
25 25
#include<algorithm>
26 26
#include<vector>
27 27

	
28 28
#ifndef WIN32
29 29
#include<sys/time.h>
30 30
#include<ctime>
31 31
#else
32
#ifndef WIN32_LEAN_AND_MEAN
33
#define WIN32_LEAN_AND_MEAN
34
#endif
35
#ifndef NOMINMAX
36
#define NOMINMAX
37
#endif
38
#include<windows.h>
32
#include<lemon/bits/windows.h>
39 33
#endif
40 34

	
41 35
#include<lemon/math.h>
42 36
#include<lemon/core.h>
43 37
#include<lemon/dim2.h>
44 38
#include<lemon/maps.h>
45 39
#include<lemon/color.h>
46 40
#include<lemon/bits/bezier.h>
47 41
#include<lemon/error.h>
48 42

	
49 43

	
50 44
///\ingroup eps_io
51 45
///\file
52 46
///\brief A well configurable tool for visualizing graphs
53 47

	
54 48
namespace lemon {
55 49

	
56 50
  namespace _graph_to_eps_bits {
57 51
    template<class MT>
58 52
    class _NegY {
59 53
    public:
60 54
      typedef typename MT::Key Key;
61 55
      typedef typename MT::Value Value;
62 56
      const MT &map;
63 57
      int yscale;
64 58
      _NegY(const MT &m,bool b) : map(m), yscale(1-b*2) {}
65 59
      Value operator[](Key n) { return Value(map[n].x,map[n].y*yscale);}
66 60
    };
67 61
  }
68 62

	
69 63
///Default traits class of GraphToEps
70 64

	
71 65
///Default traits class of \ref GraphToEps.
72 66
///
73 67
///\c G is the type of the underlying graph.
74 68
template<class G>
75 69
struct DefaultGraphToEpsTraits
76 70
{
77 71
  typedef G Graph;
78 72
  typedef typename Graph::Node Node;
79 73
  typedef typename Graph::NodeIt NodeIt;
80 74
  typedef typename Graph::Arc Arc;
81 75
  typedef typename Graph::ArcIt ArcIt;
82 76
  typedef typename Graph::InArcIt InArcIt;
83 77
  typedef typename Graph::OutArcIt OutArcIt;
84 78

	
85 79

	
86 80
  const Graph &g;
87 81

	
88 82
  std::ostream& os;
89 83

	
90 84
  typedef ConstMap<typename Graph::Node,dim2::Point<double> > CoordsMapType;
91 85
  CoordsMapType _coords;
92 86
  ConstMap<typename Graph::Node,double > _nodeSizes;
93 87
  ConstMap<typename Graph::Node,int > _nodeShapes;
94 88

	
95 89
  ConstMap<typename Graph::Node,Color > _nodeColors;
96 90
  ConstMap<typename Graph::Arc,Color > _arcColors;
97 91

	
98 92
  ConstMap<typename Graph::Arc,double > _arcWidths;
99 93

	
100 94
  double _arcWidthScale;
101 95

	
102 96
  double _nodeScale;
103 97
  double _xBorder, _yBorder;
104 98
  double _scale;
105 99
  double _nodeBorderQuotient;
106 100

	
107 101
  bool _drawArrows;
108 102
  double _arrowLength, _arrowWidth;
109 103

	
110 104
  bool _showNodes, _showArcs;
111 105

	
112 106
  bool _enableParallel;
113 107
  double _parArcDist;
114 108

	
115 109
  bool _showNodeText;
116 110
  ConstMap<typename Graph::Node,bool > _nodeTexts;
117 111
  double _nodeTextSize;
118 112

	
119 113
  bool _showNodePsText;
120 114
  ConstMap<typename Graph::Node,bool > _nodePsTexts;
121 115
  char *_nodePsTextsPreamble;
122 116

	
123 117
  bool _undirected;
124 118

	
125 119
  bool _pleaseRemoveOsStream;
126 120

	
127 121
  bool _scaleToA4;
128 122

	
129 123
  std::string _title;
130 124
  std::string _copyright;
131 125

	
132 126
  enum NodeTextColorType
133 127
    { DIST_COL=0, DIST_BW=1, CUST_COL=2, SAME_COL=3 } _nodeTextColorType;
134 128
  ConstMap<typename Graph::Node,Color > _nodeTextColors;
135 129

	
136 130
  bool _autoNodeScale;
137 131
  bool _autoArcWidthScale;
138 132

	
139 133
  bool _absoluteNodeSizes;
140 134
  bool _absoluteArcWidths;
141 135

	
142 136
  bool _negY;
143 137

	
144 138
  bool _preScale;
145 139
  ///Constructor
146 140

	
147 141
  ///Constructor
148 142
  ///\param _g  Reference to the graph to be printed.
149 143
  ///\param _os Reference to the output stream.
150 144
  ///\param _os Reference to the output stream.
151 145
  ///By default it is <tt>std::cout</tt>.
152 146
  ///\param _pros If it is \c true, then the \c ostream referenced by \c _os
153 147
  ///will be explicitly deallocated by the destructor.
154 148
  DefaultGraphToEpsTraits(const G &_g,std::ostream& _os=std::cout,
155 149
                          bool _pros=false) :
156 150
    g(_g), os(_os),
157 151
    _coords(dim2::Point<double>(1,1)), _nodeSizes(1), _nodeShapes(0),
158 152
    _nodeColors(WHITE), _arcColors(BLACK),
159 153
    _arcWidths(1.0), _arcWidthScale(0.003),
160 154
    _nodeScale(.01), _xBorder(10), _yBorder(10), _scale(1.0),
161 155
    _nodeBorderQuotient(.1),
162 156
    _drawArrows(false), _arrowLength(1), _arrowWidth(0.3),
163 157
    _showNodes(true), _showArcs(true),
164 158
    _enableParallel(false), _parArcDist(1),
165 159
    _showNodeText(false), _nodeTexts(false), _nodeTextSize(1),
166 160
    _showNodePsText(false), _nodePsTexts(false), _nodePsTextsPreamble(0),
167 161
    _undirected(lemon::UndirectedTagIndicator<G>::value),
168 162
    _pleaseRemoveOsStream(_pros), _scaleToA4(false),
169 163
    _nodeTextColorType(SAME_COL), _nodeTextColors(BLACK),
170 164
    _autoNodeScale(false),
171 165
    _autoArcWidthScale(false),
172 166
    _absoluteNodeSizes(false),
173 167
    _absoluteArcWidths(false),
174 168
    _negY(false),
175 169
    _preScale(true)
176 170
  {}
177 171
};
178 172

	
179 173
///Auxiliary class to implement the named parameters of \ref graphToEps()
180 174

	
181 175
///Auxiliary class to implement the named parameters of \ref graphToEps().
182 176
///
183 177
///For detailed examples see the \ref graph_to_eps_demo.cc demo file.
184 178
template<class T> class GraphToEps : public T
185 179
{
186 180
  // Can't believe it is required by the C++ standard
187 181
  using T::g;
188 182
  using T::os;
189 183

	
190 184
  using T::_coords;
191 185
  using T::_nodeSizes;
192 186
  using T::_nodeShapes;
193 187
  using T::_nodeColors;
194 188
  using T::_arcColors;
195 189
  using T::_arcWidths;
196 190

	
197 191
  using T::_arcWidthScale;
198 192
  using T::_nodeScale;
199 193
  using T::_xBorder;
200 194
  using T::_yBorder;
201 195
  using T::_scale;
202 196
  using T::_nodeBorderQuotient;
203 197

	
204 198
  using T::_drawArrows;
205 199
  using T::_arrowLength;
206 200
  using T::_arrowWidth;
207 201

	
208 202
  using T::_showNodes;
209 203
  using T::_showArcs;
210 204

	
211 205
  using T::_enableParallel;
212 206
  using T::_parArcDist;
213 207

	
214 208
  using T::_showNodeText;
215 209
  using T::_nodeTexts;
216 210
  using T::_nodeTextSize;
217 211

	
218 212
  using T::_showNodePsText;
219 213
  using T::_nodePsTexts;
220 214
  using T::_nodePsTextsPreamble;
221 215

	
222 216
  using T::_undirected;
223 217

	
224 218
  using T::_pleaseRemoveOsStream;
225 219

	
226 220
  using T::_scaleToA4;
227 221

	
228 222
  using T::_title;
229 223
  using T::_copyright;
230 224

	
231 225
  using T::NodeTextColorType;
232 226
  using T::CUST_COL;
233 227
  using T::DIST_COL;
234 228
  using T::DIST_BW;
235 229
  using T::_nodeTextColorType;
236 230
  using T::_nodeTextColors;
237 231

	
238 232
  using T::_autoNodeScale;
239 233
  using T::_autoArcWidthScale;
240 234

	
241 235
  using T::_absoluteNodeSizes;
242 236
  using T::_absoluteArcWidths;
243 237

	
244 238

	
245 239
  using T::_negY;
246 240
  using T::_preScale;
247 241

	
248 242
  // dradnats ++C eht yb deriuqer si ti eveileb t'naC
249 243

	
250 244
  typedef typename T::Graph Graph;
251 245
  typedef typename Graph::Node Node;
252 246
  typedef typename Graph::NodeIt NodeIt;
253 247
  typedef typename Graph::Arc Arc;
254 248
  typedef typename Graph::ArcIt ArcIt;
255 249
  typedef typename Graph::InArcIt InArcIt;
256 250
  typedef typename Graph::OutArcIt OutArcIt;
257 251

	
258 252
  static const int INTERPOL_PREC;
259 253
  static const double A4HEIGHT;
260 254
  static const double A4WIDTH;
261 255
  static const double A4BORDER;
262 256

	
263 257
  bool dontPrint;
264 258

	
265 259
public:
266 260
  ///Node shapes
267 261

	
268 262
  ///Node shapes.
269 263
  ///
270 264
  enum NodeShapes {
271 265
    /// = 0
272 266
    ///\image html nodeshape_0.png
273 267
    ///\image latex nodeshape_0.eps "CIRCLE shape (0)" width=2cm
274 268
    CIRCLE=0,
275 269
    /// = 1
276 270
    ///\image html nodeshape_1.png
277 271
    ///\image latex nodeshape_1.eps "SQUARE shape (1)" width=2cm
278 272
    ///
279 273
    SQUARE=1,
280 274
    /// = 2
281 275
    ///\image html nodeshape_2.png
282 276
    ///\image latex nodeshape_2.eps "DIAMOND shape (2)" width=2cm
283 277
    ///
284 278
    DIAMOND=2,
285 279
    /// = 3
286 280
    ///\image html nodeshape_3.png
287 281
    ///\image latex nodeshape_2.eps "MALE shape (4)" width=2cm
288 282
    ///
289 283
    MALE=3,
290 284
    /// = 4
291 285
    ///\image html nodeshape_4.png
292 286
    ///\image latex nodeshape_2.eps "FEMALE shape (4)" width=2cm
293 287
    ///
294 288
    FEMALE=4
295 289
  };
296 290

	
297 291
private:
298 292
  class arcLess {
299 293
    const Graph &g;
300 294
  public:
301 295
    arcLess(const Graph &_g) : g(_g) {}
302 296
    bool operator()(Arc a,Arc b) const
303 297
    {
304 298
      Node ai=std::min(g.source(a),g.target(a));
305 299
      Node aa=std::max(g.source(a),g.target(a));
306 300
      Node bi=std::min(g.source(b),g.target(b));
307 301
      Node ba=std::max(g.source(b),g.target(b));
308 302
      return ai<bi ||
309 303
        (ai==bi && (aa < ba ||
310 304
                    (aa==ba && ai==g.source(a) && bi==g.target(b))));
311 305
    }
312 306
  };
313 307
  bool isParallel(Arc e,Arc f) const
314 308
  {
315 309
    return (g.source(e)==g.source(f)&&
316 310
            g.target(e)==g.target(f)) ||
317 311
      (g.source(e)==g.target(f)&&
318 312
       g.target(e)==g.source(f));
319 313
  }
320 314
  template<class TT>
321 315
  static std::string psOut(const dim2::Point<TT> &p)
322 316
    {
323 317
      std::ostringstream os;
324 318
      os << p.x << ' ' << p.y;
325 319
      return os.str();
326 320
    }
327 321
  static std::string psOut(const Color &c)
328 322
    {
329 323
      std::ostringstream os;
330 324
      os << c.red() << ' ' << c.green() << ' ' << c.blue();
331 325
      return os.str();
332 326
    }
333 327

	
334 328
public:
335 329
  GraphToEps(const T &t) : T(t), dontPrint(false) {};
336 330

	
337 331
  template<class X> struct CoordsTraits : public T {
338 332
  typedef X CoordsMapType;
339 333
    const X &_coords;
340 334
    CoordsTraits(const T &t,const X &x) : T(t), _coords(x) {}
341 335
  };
342 336
  ///Sets the map of the node coordinates
343 337

	
344 338
  ///Sets the map of the node coordinates.
345 339
  ///\param x must be a node map with \ref dim2::Point "dim2::Point<double>" or
346 340
  ///\ref dim2::Point "dim2::Point<int>" values.
347 341
  template<class X> GraphToEps<CoordsTraits<X> > coords(const X &x) {
348 342
    dontPrint=true;
349 343
    return GraphToEps<CoordsTraits<X> >(CoordsTraits<X>(*this,x));
350 344
  }
351 345
  template<class X> struct NodeSizesTraits : public T {
352 346
    const X &_nodeSizes;
353 347
    NodeSizesTraits(const T &t,const X &x) : T(t), _nodeSizes(x) {}
354 348
  };
355 349
  ///Sets the map of the node sizes
356 350

	
357 351
  ///Sets the map of the node sizes.
358 352
  ///\param x must be a node map with \c double (or convertible) values.
359 353
  template<class X> GraphToEps<NodeSizesTraits<X> > nodeSizes(const X &x)
360 354
  {
361 355
    dontPrint=true;
362 356
    return GraphToEps<NodeSizesTraits<X> >(NodeSizesTraits<X>(*this,x));
363 357
  }
364 358
  template<class X> struct NodeShapesTraits : public T {
365 359
    const X &_nodeShapes;
366 360
    NodeShapesTraits(const T &t,const X &x) : T(t), _nodeShapes(x) {}
367 361
  };
368 362
  ///Sets the map of the node shapes
369 363

	
370 364
  ///Sets the map of the node shapes.
371 365
  ///The available shape values
372 366
  ///can be found in \ref NodeShapes "enum NodeShapes".
373 367
  ///\param x must be a node map with \c int (or convertible) values.
374 368
  ///\sa NodeShapes
375 369
  template<class X> GraphToEps<NodeShapesTraits<X> > nodeShapes(const X &x)
376 370
  {
377 371
    dontPrint=true;
378 372
    return GraphToEps<NodeShapesTraits<X> >(NodeShapesTraits<X>(*this,x));
379 373
  }
380 374
  template<class X> struct NodeTextsTraits : public T {
381 375
    const X &_nodeTexts;
382 376
    NodeTextsTraits(const T &t,const X &x) : T(t), _nodeTexts(x) {}
383 377
  };
384 378
  ///Sets the text printed on the nodes
385 379

	
386 380
  ///Sets the text printed on the nodes.
387 381
  ///\param x must be a node map with type that can be pushed to a standard
388 382
  ///\c ostream.
389 383
  template<class X> GraphToEps<NodeTextsTraits<X> > nodeTexts(const X &x)
390 384
  {
391 385
    dontPrint=true;
392 386
    _showNodeText=true;
393 387
    return GraphToEps<NodeTextsTraits<X> >(NodeTextsTraits<X>(*this,x));
394 388
  }
395 389
  template<class X> struct NodePsTextsTraits : public T {
396 390
    const X &_nodePsTexts;
397 391
    NodePsTextsTraits(const T &t,const X &x) : T(t), _nodePsTexts(x) {}
398 392
  };
399 393
  ///Inserts a PostScript block to the nodes
400 394

	
401 395
  ///With this command it is possible to insert a verbatim PostScript
402 396
  ///block to the nodes.
403 397
  ///The PS current point will be moved to the center of the node before
404 398
  ///the PostScript block inserted.
405 399
  ///
406 400
  ///Before and after the block a newline character is inserted so you
407 401
  ///don't have to bother with the separators.
408 402
  ///
409 403
  ///\param x must be a node map with type that can be pushed to a standard
410 404
  ///\c ostream.
411 405
  ///
412 406
  ///\sa nodePsTextsPreamble()
413 407
  template<class X> GraphToEps<NodePsTextsTraits<X> > nodePsTexts(const X &x)
414 408
  {
415 409
    dontPrint=true;
416 410
    _showNodePsText=true;
417 411
    return GraphToEps<NodePsTextsTraits<X> >(NodePsTextsTraits<X>(*this,x));
418 412
  }
419 413
  template<class X> struct ArcWidthsTraits : public T {
420 414
    const X &_arcWidths;
421 415
    ArcWidthsTraits(const T &t,const X &x) : T(t), _arcWidths(x) {}
422 416
  };
423 417
  ///Sets the map of the arc widths
424 418

	
425 419
  ///Sets the map of the arc widths.
426 420
  ///\param x must be an arc map with \c double (or convertible) values.
427 421
  template<class X> GraphToEps<ArcWidthsTraits<X> > arcWidths(const X &x)
428 422
  {
429 423
    dontPrint=true;
430 424
    return GraphToEps<ArcWidthsTraits<X> >(ArcWidthsTraits<X>(*this,x));
431 425
  }
432 426

	
433 427
  template<class X> struct NodeColorsTraits : public T {
434 428
    const X &_nodeColors;
435 429
    NodeColorsTraits(const T &t,const X &x) : T(t), _nodeColors(x) {}
436 430
  };
437 431
  ///Sets the map of the node colors
438 432

	
439 433
  ///Sets the map of the node colors.
440 434
  ///\param x must be a node map with \ref Color values.
441 435
  ///
442 436
  ///\sa Palette
443 437
  template<class X> GraphToEps<NodeColorsTraits<X> >
444 438
  nodeColors(const X &x)
445 439
  {
446 440
    dontPrint=true;
447 441
    return GraphToEps<NodeColorsTraits<X> >(NodeColorsTraits<X>(*this,x));
448 442
  }
449 443
  template<class X> struct NodeTextColorsTraits : public T {
450 444
    const X &_nodeTextColors;
451 445
    NodeTextColorsTraits(const T &t,const X &x) : T(t), _nodeTextColors(x) {}
452 446
  };
453 447
  ///Sets the map of the node text colors
454 448

	
455 449
  ///Sets the map of the node text colors.
456 450
  ///\param x must be a node map with \ref Color values.
457 451
  ///
458 452
  ///\sa Palette
459 453
  template<class X> GraphToEps<NodeTextColorsTraits<X> >
460 454
  nodeTextColors(const X &x)
461 455
  {
462 456
    dontPrint=true;
463 457
    _nodeTextColorType=CUST_COL;
464 458
    return GraphToEps<NodeTextColorsTraits<X> >
465 459
      (NodeTextColorsTraits<X>(*this,x));
466 460
  }
467 461
  template<class X> struct ArcColorsTraits : public T {
468 462
    const X &_arcColors;
469 463
    ArcColorsTraits(const T &t,const X &x) : T(t), _arcColors(x) {}
470 464
  };
471 465
  ///Sets the map of the arc colors
472 466

	
473 467
  ///Sets the map of the arc colors.
474 468
  ///\param x must be an arc map with \ref Color values.
475 469
  ///
476 470
  ///\sa Palette
477 471
  template<class X> GraphToEps<ArcColorsTraits<X> >
478 472
  arcColors(const X &x)
479 473
  {
480 474
    dontPrint=true;
481 475
    return GraphToEps<ArcColorsTraits<X> >(ArcColorsTraits<X>(*this,x));
482 476
  }
483 477
  ///Sets a global scale factor for node sizes
484 478

	
485 479
  ///Sets a global scale factor for node sizes.
486 480
  ///
487 481
  /// If nodeSizes() is not given, this function simply sets the node
488 482
  /// sizes to \c d.  If nodeSizes() is given, but
489 483
  /// autoNodeScale() is not, then the node size given by
490 484
  /// nodeSizes() will be multiplied by the value \c d.
491 485
  /// If both nodeSizes() and autoNodeScale() are used, then the
492 486
  /// node sizes will be scaled in such a way that the greatest size will be
493 487
  /// equal to \c d.
494 488
  /// \sa nodeSizes()
495 489
  /// \sa autoNodeScale()
496 490
  GraphToEps<T> &nodeScale(double d=.01) {_nodeScale=d;return *this;}
497 491
  ///Turns on/off the automatic node size scaling.
498 492

	
499 493
  ///Turns on/off the automatic node size scaling.
500 494
  ///
501 495
  ///\sa nodeScale()
502 496
  ///
503 497
  GraphToEps<T> &autoNodeScale(bool b=true) {
504 498
    _autoNodeScale=b;return *this;
505 499
  }
506 500

	
507 501
  ///Turns on/off the absolutematic node size scaling.
508 502

	
509 503
  ///Turns on/off the absolutematic node size scaling.
510 504
  ///
511 505
  ///\sa nodeScale()
512 506
  ///
513 507
  GraphToEps<T> &absoluteNodeSizes(bool b=true) {
514 508
    _absoluteNodeSizes=b;return *this;
515 509
  }
516 510

	
517 511
  ///Negates the Y coordinates.
518 512
  GraphToEps<T> &negateY(bool b=true) {
519 513
    _negY=b;return *this;
520 514
  }
521 515

	
522 516
  ///Turn on/off pre-scaling
523 517

	
524 518
  ///By default graphToEps() rescales the whole image in order to avoid
525 519
  ///very big or very small bounding boxes.
526 520
  ///
527 521
  ///This (p)rescaling can be turned off with this function.
528 522
  ///
529 523
  GraphToEps<T> &preScale(bool b=true) {
530 524
    _preScale=b;return *this;
531 525
  }
532 526

	
533 527
  ///Sets a global scale factor for arc widths
534 528

	
535 529
  /// Sets a global scale factor for arc widths.
536 530
  ///
537 531
  /// If arcWidths() is not given, this function simply sets the arc
538 532
  /// widths to \c d.  If arcWidths() is given, but
539 533
  /// autoArcWidthScale() is not, then the arc withs given by
540 534
  /// arcWidths() will be multiplied by the value \c d.
541 535
  /// If both arcWidths() and autoArcWidthScale() are used, then the
542 536
  /// arc withs will be scaled in such a way that the greatest width will be
543 537
  /// equal to \c d.
544 538
  GraphToEps<T> &arcWidthScale(double d=.003) {_arcWidthScale=d;return *this;}
545 539
  ///Turns on/off the automatic arc width scaling.
546 540

	
547 541
  ///Turns on/off the automatic arc width scaling.
548 542
  ///
549 543
  ///\sa arcWidthScale()
550 544
  ///
551 545
  GraphToEps<T> &autoArcWidthScale(bool b=true) {
552 546
    _autoArcWidthScale=b;return *this;
553 547
  }
554 548
  ///Turns on/off the absolutematic arc width scaling.
555 549

	
556 550
  ///Turns on/off the absolutematic arc width scaling.
557 551
  ///
558 552
  ///\sa arcWidthScale()
559 553
  ///
560 554
  GraphToEps<T> &absoluteArcWidths(bool b=true) {
561 555
    _absoluteArcWidths=b;return *this;
562 556
  }
563 557
  ///Sets a global scale factor for the whole picture
564 558
  GraphToEps<T> &scale(double d) {_scale=d;return *this;}
565 559
  ///Sets the width of the border around the picture
566 560
  GraphToEps<T> &border(double b=10) {_xBorder=_yBorder=b;return *this;}
567 561
  ///Sets the width of the border around the picture
568 562
  GraphToEps<T> &border(double x, double y) {
569 563
    _xBorder=x;_yBorder=y;return *this;
570 564
  }
571 565
  ///Sets whether to draw arrows
572 566
  GraphToEps<T> &drawArrows(bool b=true) {_drawArrows=b;return *this;}
573 567
  ///Sets the length of the arrowheads
574 568
  GraphToEps<T> &arrowLength(double d=1.0) {_arrowLength*=d;return *this;}
575 569
  ///Sets the width of the arrowheads
576 570
  GraphToEps<T> &arrowWidth(double d=.3) {_arrowWidth*=d;return *this;}
577 571

	
578 572
  ///Scales the drawing to fit to A4 page
579 573
  GraphToEps<T> &scaleToA4() {_scaleToA4=true;return *this;}
580 574

	
581 575
  ///Enables parallel arcs
582 576
  GraphToEps<T> &enableParallel(bool b=true) {_enableParallel=b;return *this;}
583 577

	
584 578
  ///Sets the distance between parallel arcs
585 579
  GraphToEps<T> &parArcDist(double d) {_parArcDist*=d;return *this;}
586 580

	
587 581
  ///Hides the arcs
588 582
  GraphToEps<T> &hideArcs(bool b=true) {_showArcs=!b;return *this;}
589 583
  ///Hides the nodes
590 584
  GraphToEps<T> &hideNodes(bool b=true) {_showNodes=!b;return *this;}
591 585

	
592 586
  ///Sets the size of the node texts
593 587
  GraphToEps<T> &nodeTextSize(double d) {_nodeTextSize=d;return *this;}
594 588

	
595 589
  ///Sets the color of the node texts to be different from the node color
596 590

	
597 591
  ///Sets the color of the node texts to be as different from the node color
598 592
  ///as it is possible.
599 593
  GraphToEps<T> &distantColorNodeTexts()
600 594
  {_nodeTextColorType=DIST_COL;return *this;}
601 595
  ///Sets the color of the node texts to be black or white and always visible.
602 596

	
603 597
  ///Sets the color of the node texts to be black or white according to
604 598
  ///which is more different from the node color.
605 599
  GraphToEps<T> &distantBWNodeTexts()
606 600
  {_nodeTextColorType=DIST_BW;return *this;}
607 601

	
608 602
  ///Gives a preamble block for node Postscript block.
609 603

	
610 604
  ///Gives a preamble block for node Postscript block.
611 605
  ///
612 606
  ///\sa nodePsTexts()
613 607
  GraphToEps<T> & nodePsTextsPreamble(const char *str) {
614 608
    _nodePsTextsPreamble=str ;return *this;
615 609
  }
616 610
  ///Sets whether the graph is undirected
617 611

	
618 612
  ///Sets whether the graph is undirected.
619 613
  ///
620 614
  ///This setting is the default for undirected graphs.
621 615
  ///
622 616
  ///\sa directed()
623 617
   GraphToEps<T> &undirected(bool b=true) {_undirected=b;return *this;}
624 618

	
625 619
  ///Sets whether the graph is directed
626 620

	
627 621
  ///Sets whether the graph is directed.
628 622
  ///Use it to show the edges as a pair of directed ones.
629 623
  ///
630 624
  ///This setting is the default for digraphs.
631 625
  ///
632 626
  ///\sa undirected()
633 627
  GraphToEps<T> &directed(bool b=true) {_undirected=!b;return *this;}
634 628

	
635 629
  ///Sets the title.
636 630

	
637 631
  ///Sets the title of the generated image,
638 632
  ///namely it inserts a <tt>%%Title:</tt> DSC field to the header of
639 633
  ///the EPS file.
640 634
  GraphToEps<T> &title(const std::string &t) {_title=t;return *this;}
641 635
  ///Sets the copyright statement.
642 636

	
643 637
  ///Sets the copyright statement of the generated image,
644 638
  ///namely it inserts a <tt>%%Copyright:</tt> DSC field to the header of
645 639
  ///the EPS file.
646 640
  GraphToEps<T> &copyright(const std::string &t) {_copyright=t;return *this;}
647 641

	
648 642
protected:
649 643
  bool isInsideNode(dim2::Point<double> p, double r,int t)
650 644
  {
651 645
    switch(t) {
652 646
    case CIRCLE:
653 647
    case MALE:
654 648
    case FEMALE:
655 649
      return p.normSquare()<=r*r;
656 650
    case SQUARE:
657 651
      return p.x<=r&&p.x>=-r&&p.y<=r&&p.y>=-r;
658 652
    case DIAMOND:
659 653
      return p.x+p.y<=r && p.x-p.y<=r && -p.x+p.y<=r && -p.x-p.y<=r;
660 654
    }
661 655
    return false;
662 656
  }
663 657

	
664 658
public:
665 659
  ~GraphToEps() { }
666 660

	
667 661
  ///Draws the graph.
668 662

	
669 663
  ///Like other functions using
670 664
  ///\ref named-templ-func-param "named template parameters",
671 665
  ///this function calls the algorithm itself, i.e. in this case
672 666
  ///it draws the graph.
673 667
  void run() {
674 668
    const double EPSILON=1e-9;
675 669
    if(dontPrint) return;
676 670

	
677 671
    _graph_to_eps_bits::_NegY<typename T::CoordsMapType>
678 672
      mycoords(_coords,_negY);
679 673

	
680 674
    os << "%!PS-Adobe-2.0 EPSF-2.0\n";
681 675
    if(_title.size()>0) os << "%%Title: " << _title << '\n';
682 676
     if(_copyright.size()>0) os << "%%Copyright: " << _copyright << '\n';
683 677
    os << "%%Creator: LEMON, graphToEps()\n";
684 678

	
685 679
    {
680
      os << "%%CreationDate: ";
686 681
#ifndef WIN32
687 682
      timeval tv;
688 683
      gettimeofday(&tv, 0);
689 684

	
690 685
      char cbuf[26];
691 686
      ctime_r(&tv.tv_sec,cbuf);
692
      os << "%%CreationDate: " << cbuf;
687
      os << cbuf;
693 688
#else
694
      SYSTEMTIME time;
695
      GetSystemTime(&time);
696
#if defined(_MSC_VER) && (_MSC_VER < 1500)
697
      LPWSTR buf1, buf2, buf3;
698
      if (GetDateFormat(LOCALE_USER_DEFAULT, 0, &time,
699
                        L"ddd MMM dd", buf1, 11) &&
700
          GetTimeFormat(LOCALE_USER_DEFAULT, 0, &time,
701
                        L"HH':'mm':'ss", buf2, 9) &&
702
          GetDateFormat(LOCALE_USER_DEFAULT, 0, &time,
703
                        L"yyyy", buf3, 5)) {
704
        os << "%%CreationDate: " << buf1 << ' '
705
           << buf2 << ' ' << buf3 << std::endl;
706
      }
707
#else
708
        char buf1[11], buf2[9], buf3[5];
709
        if (GetDateFormat(LOCALE_USER_DEFAULT, 0, &time,
710
                          "ddd MMM dd", buf1, 11) &&
711
            GetTimeFormat(LOCALE_USER_DEFAULT, 0, &time,
712
                          "HH':'mm':'ss", buf2, 9) &&
713
            GetDateFormat(LOCALE_USER_DEFAULT, 0, &time,
714
                          "yyyy", buf3, 5)) {
715
          os << "%%CreationDate: " << buf1 << ' '
716
             << buf2 << ' ' << buf3 << std::endl;
717
        }
718
#endif
689
      os << bits::getWinFormattedDate();
719 690
#endif
720 691
    }
692
    os << std::endl;
721 693

	
722 694
    if (_autoArcWidthScale) {
723 695
      double max_w=0;
724 696
      for(ArcIt e(g);e!=INVALID;++e)
725 697
        max_w=std::max(double(_arcWidths[e]),max_w);
726 698
      if(max_w>EPSILON) {
727 699
        _arcWidthScale/=max_w;
728 700
      }
729 701
    }
730 702

	
731 703
    if (_autoNodeScale) {
732 704
      double max_s=0;
733 705
      for(NodeIt n(g);n!=INVALID;++n)
734 706
        max_s=std::max(double(_nodeSizes[n]),max_s);
735 707
      if(max_s>EPSILON) {
736 708
        _nodeScale/=max_s;
737 709
      }
738 710
    }
739 711

	
740 712
    double diag_len = 1;
741 713
    if(!(_absoluteNodeSizes&&_absoluteArcWidths)) {
742 714
      dim2::Box<double> bb;
743 715
      for(NodeIt n(g);n!=INVALID;++n) bb.add(mycoords[n]);
744 716
      if (bb.empty()) {
745 717
        bb = dim2::Box<double>(dim2::Point<double>(0,0));
746 718
      }
747 719
      diag_len = std::sqrt((bb.bottomLeft()-bb.topRight()).normSquare());
748 720
      if(diag_len<EPSILON) diag_len = 1;
749 721
      if(!_absoluteNodeSizes) _nodeScale*=diag_len;
750 722
      if(!_absoluteArcWidths) _arcWidthScale*=diag_len;
751 723
    }
752 724

	
753 725
    dim2::Box<double> bb;
754 726
    for(NodeIt n(g);n!=INVALID;++n) {
755 727
      double ns=_nodeSizes[n]*_nodeScale;
756 728
      dim2::Point<double> p(ns,ns);
757 729
      switch(_nodeShapes[n]) {
758 730
      case CIRCLE:
759 731
      case SQUARE:
760 732
      case DIAMOND:
761 733
        bb.add(p+mycoords[n]);
762 734
        bb.add(-p+mycoords[n]);
763 735
        break;
764 736
      case MALE:
765 737
        bb.add(-p+mycoords[n]);
766 738
        bb.add(dim2::Point<double>(1.5*ns,1.5*std::sqrt(3.0)*ns)+mycoords[n]);
767 739
        break;
768 740
      case FEMALE:
769 741
        bb.add(p+mycoords[n]);
770 742
        bb.add(dim2::Point<double>(-ns,-3.01*ns)+mycoords[n]);
771 743
        break;
772 744
      }
773 745
    }
774 746
    if (bb.empty()) {
775 747
      bb = dim2::Box<double>(dim2::Point<double>(0,0));
776 748
    }
777 749

	
778 750
    if(_scaleToA4)
779 751
      os <<"%%BoundingBox: 0 0 596 842\n%%DocumentPaperSizes: a4\n";
780 752
    else {
781 753
      if(_preScale) {
782 754
        //Rescale so that BoundingBox won't be neither to big nor too small.
783 755
        while(bb.height()*_scale>1000||bb.width()*_scale>1000) _scale/=10;
784 756
        while(bb.height()*_scale<100||bb.width()*_scale<100) _scale*=10;
785 757
      }
786 758

	
787 759
      os << "%%BoundingBox: "
788 760
         << int(floor(bb.left()   * _scale - _xBorder)) << ' '
789 761
         << int(floor(bb.bottom() * _scale - _yBorder)) << ' '
790 762
         << int(ceil(bb.right()  * _scale + _xBorder)) << ' '
791 763
         << int(ceil(bb.top()    * _scale + _yBorder)) << '\n';
792 764
    }
793 765

	
794 766
    os << "%%EndComments\n";
795 767

	
796 768
    //x1 y1 x2 y2 x3 y3 cr cg cb w
797 769
    os << "/lb { setlinewidth setrgbcolor newpath moveto\n"
798 770
       << "      4 2 roll 1 index 1 index curveto stroke } bind def\n";
799 771
    os << "/l { setlinewidth setrgbcolor newpath moveto lineto stroke }"
800 772
       << " bind def\n";
801 773
    //x y r
802 774
    os << "/c { newpath dup 3 index add 2 index moveto 0 360 arc closepath }"
803 775
       << " bind def\n";
804 776
    //x y r
805 777
    os << "/sq { newpath 2 index 1 index add 2 index 2 index add moveto\n"
806 778
       << "      2 index 1 index sub 2 index 2 index add lineto\n"
807 779
       << "      2 index 1 index sub 2 index 2 index sub lineto\n"
808 780
       << "      2 index 1 index add 2 index 2 index sub lineto\n"
809 781
       << "      closepath pop pop pop} bind def\n";
810 782
    //x y r
811 783
    os << "/di { newpath 2 index 1 index add 2 index moveto\n"
812 784
       << "      2 index             2 index 2 index add lineto\n"
813 785
       << "      2 index 1 index sub 2 index             lineto\n"
814 786
       << "      2 index             2 index 2 index sub lineto\n"
815 787
       << "      closepath pop pop pop} bind def\n";
816 788
    // x y r cr cg cb
817 789
    os << "/nc { 0 0 0 setrgbcolor 5 index 5 index 5 index c fill\n"
818 790
       << "     setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n"
819 791
       << "   } bind def\n";
820 792
    os << "/nsq { 0 0 0 setrgbcolor 5 index 5 index 5 index sq fill\n"
821 793
       << "     setrgbcolor " << 1+_nodeBorderQuotient << " div sq fill\n"
822 794
       << "   } bind def\n";
823 795
    os << "/ndi { 0 0 0 setrgbcolor 5 index 5 index 5 index di fill\n"
824 796
       << "     setrgbcolor " << 1+_nodeBorderQuotient << " div di fill\n"
825 797
       << "   } bind def\n";
826 798
    os << "/nfemale { 0 0 0 setrgbcolor 3 index "
827 799
       << _nodeBorderQuotient/(1+_nodeBorderQuotient)
828 800
       << " 1.5 mul mul setlinewidth\n"
829 801
       << "  newpath 5 index 5 index moveto "
830 802
       << "5 index 5 index 5 index 3.01 mul sub\n"
831 803
       << "  lineto 5 index 4 index .7 mul sub 5 index 5 index 2.2 mul sub"
832 804
       << " moveto\n"
833 805
       << "  5 index 4 index .7 mul add 5 index 5 index 2.2 mul sub lineto "
834 806
       << "stroke\n"
835 807
       << "  5 index 5 index 5 index c fill\n"
836 808
       << "  setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n"
837 809
       << "  } bind def\n";
838 810
    os << "/nmale {\n"
839 811
       << "  0 0 0 setrgbcolor 3 index "
840 812
       << _nodeBorderQuotient/(1+_nodeBorderQuotient)
841 813
       <<" 1.5 mul mul setlinewidth\n"
842 814
       << "  newpath 5 index 5 index moveto\n"
843 815
       << "  5 index 4 index 1 mul 1.5 mul add\n"
844 816
       << "  5 index 5 index 3 sqrt 1.5 mul mul add\n"
845 817
       << "  1 index 1 index lineto\n"
846 818
       << "  1 index 1 index 7 index sub moveto\n"
847 819
       << "  1 index 1 index lineto\n"
848 820
       << "  exch 5 index 3 sqrt .5 mul mul sub exch 5 index .5 mul sub"
849 821
       << " lineto\n"
850 822
       << "  stroke\n"
851 823
       << "  5 index 5 index 5 index c fill\n"
852 824
       << "  setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n"
853 825
       << "  } bind def\n";
854 826

	
855 827

	
856 828
    os << "/arrl " << _arrowLength << " def\n";
857 829
    os << "/arrw " << _arrowWidth << " def\n";
858 830
    // l dx_norm dy_norm
859 831
    os << "/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def\n";
860 832
    //len w dx_norm dy_norm x1 y1 cr cg cb
861 833
    os << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx "
862 834
       << "exch def\n"
863 835
       << "       /w exch def /len exch def\n"
864 836
      //<< "0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke"
865 837
       << "       newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n"
866 838
       << "       len w sub arrl sub dx dy lrl\n"
867 839
       << "       arrw dy dx neg lrl\n"
868 840
       << "       dx arrl w add mul dy w 2 div arrw add mul sub\n"
869 841
       << "       dy arrl w add mul dx w 2 div arrw add mul add rlineto\n"
870 842
       << "       dx arrl w add mul neg dy w 2 div arrw add mul sub\n"
871 843
       << "       dy arrl w add mul neg dx w 2 div arrw add mul add rlineto\n"
872 844
       << "       arrw dy dx neg lrl\n"
873 845
       << "       len w sub arrl sub neg dx dy lrl\n"
874 846
       << "       closepath fill } bind def\n";
875 847
    os << "/cshow { 2 index 2 index moveto dup stringwidth pop\n"
876 848
       << "         neg 2 div fosi .35 mul neg rmoveto show pop pop} def\n";
877 849

	
878 850
    os << "\ngsave\n";
879 851
    if(_scaleToA4)
880 852
      if(bb.height()>bb.width()) {
881 853
        double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.height(),
882 854
                  (A4WIDTH-2*A4BORDER)/bb.width());
883 855
        os << ((A4WIDTH -2*A4BORDER)-sc*bb.width())/2 + A4BORDER << ' '
884 856
           << ((A4HEIGHT-2*A4BORDER)-sc*bb.height())/2 + A4BORDER
885 857
           << " translate\n"
886 858
           << sc << " dup scale\n"
887 859
           << -bb.left() << ' ' << -bb.bottom() << " translate\n";
888 860
      }
889 861
      else {
890 862
        double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.width(),
891 863
                  (A4WIDTH-2*A4BORDER)/bb.height());
892 864
        os << ((A4WIDTH -2*A4BORDER)-sc*bb.height())/2 + A4BORDER << ' '
893 865
           << ((A4HEIGHT-2*A4BORDER)-sc*bb.width())/2 + A4BORDER
894 866
           << " translate\n"
895 867
           << sc << " dup scale\n90 rotate\n"
896 868
           << -bb.left() << ' ' << -bb.top() << " translate\n";
897 869
        }
898 870
    else if(_scale!=1.0) os << _scale << " dup scale\n";
899 871

	
900 872
    if(_showArcs) {
901 873
      os << "%Arcs:\ngsave\n";
902 874
      if(_enableParallel) {
903 875
        std::vector<Arc> el;
904 876
        for(ArcIt e(g);e!=INVALID;++e)
905 877
          if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0
906 878
             &&g.source(e)!=g.target(e))
907 879
            el.push_back(e);
908 880
        std::sort(el.begin(),el.end(),arcLess(g));
909 881

	
910 882
        typename std::vector<Arc>::iterator j;
911 883
        for(typename std::vector<Arc>::iterator i=el.begin();i!=el.end();i=j) {
912 884
          for(j=i+1;j!=el.end()&&isParallel(*i,*j);++j) ;
913 885

	
914 886
          double sw=0;
915 887
          for(typename std::vector<Arc>::iterator e=i;e!=j;++e)
916 888
            sw+=_arcWidths[*e]*_arcWidthScale+_parArcDist;
917 889
          sw-=_parArcDist;
918 890
          sw/=-2.0;
919 891
          dim2::Point<double>
920 892
            dvec(mycoords[g.target(*i)]-mycoords[g.source(*i)]);
921 893
          double l=std::sqrt(dvec.normSquare());
922 894
          dim2::Point<double> d(dvec/std::max(l,EPSILON));
923 895
          dim2::Point<double> m;
924 896
//           m=dim2::Point<double>(mycoords[g.target(*i)]+
925 897
//                                 mycoords[g.source(*i)])/2.0;
926 898

	
927 899
//            m=dim2::Point<double>(mycoords[g.source(*i)])+
928 900
//             dvec*(double(_nodeSizes[g.source(*i)])/
929 901
//                (_nodeSizes[g.source(*i)]+_nodeSizes[g.target(*i)]));
930 902

	
931 903
          m=dim2::Point<double>(mycoords[g.source(*i)])+
932 904
            d*(l+_nodeSizes[g.source(*i)]-_nodeSizes[g.target(*i)])/2.0;
933 905

	
934 906
          for(typename std::vector<Arc>::iterator e=i;e!=j;++e) {
935 907
            sw+=_arcWidths[*e]*_arcWidthScale/2.0;
936 908
            dim2::Point<double> mm=m+rot90(d)*sw/.75;
937 909
            if(_drawArrows) {
938 910
              int node_shape;
939 911
              dim2::Point<double> s=mycoords[g.source(*e)];
940 912
              dim2::Point<double> t=mycoords[g.target(*e)];
941 913
              double rn=_nodeSizes[g.target(*e)]*_nodeScale;
942 914
              node_shape=_nodeShapes[g.target(*e)];
943 915
              dim2::Bezier3 bez(s,mm,mm,t);
944 916
              double t1=0,t2=1;
945 917
              for(int ii=0;ii<INTERPOL_PREC;++ii)
946 918
                if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t2=(t1+t2)/2;
947 919
                else t1=(t1+t2)/2;
948 920
              dim2::Point<double> apoint=bez((t1+t2)/2);
949 921
              rn = _arrowLength+_arcWidths[*e]*_arcWidthScale;
950 922
              rn*=rn;
951 923
              t2=(t1+t2)/2;t1=0;
952 924
              for(int ii=0;ii<INTERPOL_PREC;++ii)
953 925
                if((bez((t1+t2)/2)-apoint).normSquare()>rn) t1=(t1+t2)/2;
954 926
                else t2=(t1+t2)/2;
955 927
              dim2::Point<double> linend=bez((t1+t2)/2);
956 928
              bez=bez.before((t1+t2)/2);
957 929
//               rn=_nodeSizes[g.source(*e)]*_nodeScale;
958 930
//               node_shape=_nodeShapes[g.source(*e)];
959 931
//               t1=0;t2=1;
960 932
//               for(int i=0;i<INTERPOL_PREC;++i)
961 933
//                 if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape))
962 934
//                   t1=(t1+t2)/2;
963 935
//                 else t2=(t1+t2)/2;
964 936
//               bez=bez.after((t1+t2)/2);
965 937
              os << _arcWidths[*e]*_arcWidthScale << " setlinewidth "
966 938
                 << _arcColors[*e].red() << ' '
967 939
                 << _arcColors[*e].green() << ' '
968 940
                 << _arcColors[*e].blue() << " setrgbcolor newpath\n"
969 941
                 << bez.p1.x << ' ' <<  bez.p1.y << " moveto\n"
970 942
                 << bez.p2.x << ' ' << bez.p2.y << ' '
971 943
                 << bez.p3.x << ' ' << bez.p3.y << ' '
972 944
                 << bez.p4.x << ' ' << bez.p4.y << " curveto stroke\n";
973 945
              dim2::Point<double> dd(rot90(linend-apoint));
974 946
              dd*=(.5*_arcWidths[*e]*_arcWidthScale+_arrowWidth)/
975 947
                std::sqrt(dd.normSquare());
976 948
              os << "newpath " << psOut(apoint) << " moveto "
977 949
                 << psOut(linend+dd) << " lineto "
978 950
                 << psOut(linend-dd) << " lineto closepath fill\n";
979 951
            }
980 952
            else {
981 953
              os << mycoords[g.source(*e)].x << ' '
982 954
                 << mycoords[g.source(*e)].y << ' '
983 955
                 << mm.x << ' ' << mm.y << ' '
984 956
                 << mycoords[g.target(*e)].x << ' '
985 957
                 << mycoords[g.target(*e)].y << ' '
986 958
                 << _arcColors[*e].red() << ' '
987 959
                 << _arcColors[*e].green() << ' '
988 960
                 << _arcColors[*e].blue() << ' '
989 961
                 << _arcWidths[*e]*_arcWidthScale << " lb\n";
990 962
            }
991 963
            sw+=_arcWidths[*e]*_arcWidthScale/2.0+_parArcDist;
992 964
          }
993 965
        }
994 966
      }
995 967
      else for(ArcIt e(g);e!=INVALID;++e)
996 968
        if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0
997 969
           &&g.source(e)!=g.target(e)) {
998 970
          if(_drawArrows) {
999 971
            dim2::Point<double> d(mycoords[g.target(e)]-mycoords[g.source(e)]);
1000 972
            double rn=_nodeSizes[g.target(e)]*_nodeScale;
1001 973
            int node_shape=_nodeShapes[g.target(e)];
1002 974
            double t1=0,t2=1;
1003 975
            for(int i=0;i<INTERPOL_PREC;++i)
1004 976
              if(isInsideNode((-(t1+t2)/2)*d,rn,node_shape)) t1=(t1+t2)/2;
1005 977
              else t2=(t1+t2)/2;
1006 978
            double l=std::sqrt(d.normSquare());
1007 979
            d/=l;
1008 980

	
1009 981
            os << l*(1-(t1+t2)/2) << ' '
1010 982
               << _arcWidths[e]*_arcWidthScale << ' '
1011 983
               << d.x << ' ' << d.y << ' '
1012 984
               << mycoords[g.source(e)].x << ' '
1013 985
               << mycoords[g.source(e)].y << ' '
1014 986
               << _arcColors[e].red() << ' '
1015 987
               << _arcColors[e].green() << ' '
1016 988
               << _arcColors[e].blue() << " arr\n";
1017 989
          }
1018 990
          else os << mycoords[g.source(e)].x << ' '
1019 991
                  << mycoords[g.source(e)].y << ' '
1020 992
                  << mycoords[g.target(e)].x << ' '
1021 993
                  << mycoords[g.target(e)].y << ' '
1022 994
                  << _arcColors[e].red() << ' '
1023 995
                  << _arcColors[e].green() << ' '
1024 996
                  << _arcColors[e].blue() << ' '
1025 997
                  << _arcWidths[e]*_arcWidthScale << " l\n";
1026 998
        }
1027 999
      os << "grestore\n";
1028 1000
    }
1029 1001
    if(_showNodes) {
1030 1002
      os << "%Nodes:\ngsave\n";
1031 1003
      for(NodeIt n(g);n!=INVALID;++n) {
1032 1004
        os << mycoords[n].x << ' ' << mycoords[n].y << ' '
1033 1005
           << _nodeSizes[n]*_nodeScale << ' '
1034 1006
           << _nodeColors[n].red() << ' '
1035 1007
           << _nodeColors[n].green() << ' '
1036 1008
           << _nodeColors[n].blue() << ' ';
1037 1009
        switch(_nodeShapes[n]) {
1038 1010
        case CIRCLE:
1039 1011
          os<< "nc";break;
1040 1012
        case SQUARE:
1041 1013
          os<< "nsq";break;
1042 1014
        case DIAMOND:
1043 1015
          os<< "ndi";break;
1044 1016
        case MALE:
1045 1017
          os<< "nmale";break;
1046 1018
        case FEMALE:
1047 1019
          os<< "nfemale";break;
1048 1020
        }
1049 1021
        os<<'\n';
1050 1022
      }
1051 1023
      os << "grestore\n";
1052 1024
    }
1053 1025
    if(_showNodeText) {
1054 1026
      os << "%Node texts:\ngsave\n";
1055 1027
      os << "/fosi " << _nodeTextSize << " def\n";
1056 1028
      os << "(Helvetica) findfont fosi scalefont setfont\n";
1057 1029
      for(NodeIt n(g);n!=INVALID;++n) {
1058 1030
        switch(_nodeTextColorType) {
1059 1031
        case DIST_COL:
1060 1032
          os << psOut(distantColor(_nodeColors[n])) << " setrgbcolor\n";
1061 1033
          break;
1062 1034
        case DIST_BW:
1063 1035
          os << psOut(distantBW(_nodeColors[n])) << " setrgbcolor\n";
1064 1036
          break;
1065 1037
        case CUST_COL:
1066 1038
          os << psOut(distantColor(_nodeTextColors[n])) << " setrgbcolor\n";
1067 1039
          break;
1068 1040
        default:
1069 1041
          os << "0 0 0 setrgbcolor\n";
1070 1042
        }
1071 1043
        os << mycoords[n].x << ' ' << mycoords[n].y
1072 1044
           << " (" << _nodeTexts[n] << ") cshow\n";
1073 1045
      }
1074 1046
      os << "grestore\n";
1075 1047
    }
1076 1048
    if(_showNodePsText) {
1077 1049
      os << "%Node PS blocks:\ngsave\n";
1078 1050
      for(NodeIt n(g);n!=INVALID;++n)
1079 1051
        os << mycoords[n].x << ' ' << mycoords[n].y
1080 1052
           << " moveto\n" << _nodePsTexts[n] << "\n";
1081 1053
      os << "grestore\n";
1082 1054
    }
1083 1055

	
1084 1056
    os << "grestore\nshowpage\n";
1085 1057

	
1086 1058
    //CleanUp:
1087 1059
    if(_pleaseRemoveOsStream) {delete &os;}
1088 1060
  }
1089 1061

	
1090 1062
  ///\name Aliases
1091 1063
  ///These are just some aliases to other parameter setting functions.
1092 1064

	
1093 1065
  ///@{
1094 1066

	
1095 1067
  ///An alias for arcWidths()
1096 1068
  template<class X> GraphToEps<ArcWidthsTraits<X> > edgeWidths(const X &x)
1097 1069
  {
1098 1070
    return arcWidths(x);
1099 1071
  }
1100 1072

	
1101 1073
  ///An alias for arcColors()
1102 1074
  template<class X> GraphToEps<ArcColorsTraits<X> >
1103 1075
  edgeColors(const X &x)
1104 1076
  {
1105 1077
    return arcColors(x);
1106 1078
  }
1107 1079

	
1108 1080
  ///An alias for arcWidthScale()
1109 1081
  GraphToEps<T> &edgeWidthScale(double d) {return arcWidthScale(d);}
1110 1082

	
1111 1083
  ///An alias for autoArcWidthScale()
1112 1084
  GraphToEps<T> &autoEdgeWidthScale(bool b=true)
1113 1085
  {
1114 1086
    return autoArcWidthScale(b);
1115 1087
  }
1116 1088

	
1117 1089
  ///An alias for absoluteArcWidths()
1118 1090
  GraphToEps<T> &absoluteEdgeWidths(bool b=true)
1119 1091
  {
1120 1092
    return absoluteArcWidths(b);
1121 1093
  }
1122 1094

	
1123 1095
  ///An alias for parArcDist()
1124 1096
  GraphToEps<T> &parEdgeDist(double d) {return parArcDist(d);}
1125 1097

	
1126 1098
  ///An alias for hideArcs()
1127 1099
  GraphToEps<T> &hideEdges(bool b=true) {return hideArcs(b);}
1128 1100

	
1129 1101
  ///@}
1130 1102
};
1131 1103

	
1132 1104
template<class T>
1133 1105
const int GraphToEps<T>::INTERPOL_PREC = 20;
1134 1106
template<class T>
1135 1107
const double GraphToEps<T>::A4HEIGHT = 841.8897637795276;
1136 1108
template<class T>
1137 1109
const double GraphToEps<T>::A4WIDTH  = 595.275590551181;
1138 1110
template<class T>
1139 1111
const double GraphToEps<T>::A4BORDER = 15;
1140 1112

	
1141 1113

	
1142 1114
///Generates an EPS file from a graph
1143 1115

	
1144 1116
///\ingroup eps_io
1145 1117
///Generates an EPS file from a graph.
1146 1118
///\param g Reference to the graph to be printed.
1147 1119
///\param os Reference to the output stream.
1148 1120
///By default it is <tt>std::cout</tt>.
1149 1121
///
1150 1122
///This function also has a lot of
1151 1123
///\ref named-templ-func-param "named parameters",
1152 1124
///they are declared as the members of class \ref GraphToEps. The following
1153 1125
///example shows how to use these parameters.
1154 1126
///\code
1155 1127
/// graphToEps(g,os).scale(10).coords(coords)
1156 1128
///              .nodeScale(2).nodeSizes(sizes)
1157 1129
///              .arcWidthScale(.4).run();
1158 1130
///\endcode
1159 1131
///
1160 1132
///For more detailed examples see the \ref graph_to_eps_demo.cc demo file.
1161 1133
///
1162 1134
///\warning Don't forget to put the \ref GraphToEps::run() "run()"
1163 1135
///to the end of the parameter list.
1164 1136
///\sa GraphToEps
1165 1137
///\sa graphToEps(G &g, const char *file_name)
1166 1138
template<class G>
1167 1139
GraphToEps<DefaultGraphToEpsTraits<G> >
1168 1140
graphToEps(G &g, std::ostream& os=std::cout)
1169 1141
{
1170 1142
  return
1171 1143
    GraphToEps<DefaultGraphToEpsTraits<G> >(DefaultGraphToEpsTraits<G>(g,os));
1172 1144
}
1173 1145

	
1174 1146
///Generates an EPS file from a graph
1175 1147

	
1176 1148
///\ingroup eps_io
1177 1149
///This function does the same as
1178 1150
///\ref graphToEps(G &g,std::ostream& os)
1179 1151
///but it writes its output into the file \c file_name
1180 1152
///instead of a stream.
1181 1153
///\sa graphToEps(G &g, std::ostream& os)
1182 1154
template<class G>
1183 1155
GraphToEps<DefaultGraphToEpsTraits<G> >
1184 1156
graphToEps(G &g,const char *file_name)
1185 1157
{
1186 1158
  std::ostream* os = new std::ofstream(file_name);
1187 1159
  if (!(*os)) {
1188 1160
    delete os;
1189 1161
    throw IoError("Cannot write file", file_name);
1190 1162
  }
1191 1163
  return GraphToEps<DefaultGraphToEpsTraits<G> >
1192 1164
    (DefaultGraphToEpsTraits<G>(g,*os,true));
1193 1165
}
1194 1166

	
1195 1167
///Generates an EPS file from a graph
1196 1168

	
1197 1169
///\ingroup eps_io
1198 1170
///This function does the same as
1199 1171
///\ref graphToEps(G &g,std::ostream& os)
1200 1172
///but it writes its output into the file \c file_name
1201 1173
///instead of a stream.
1202 1174
///\sa graphToEps(G &g, std::ostream& os)
1203 1175
template<class G>
1204 1176
GraphToEps<DefaultGraphToEpsTraits<G> >
1205 1177
graphToEps(G &g,const std::string& file_name)
1206 1178
{
1207 1179
  std::ostream* os = new std::ofstream(file_name.c_str());
1208 1180
  if (!(*os)) {
1209 1181
    delete os;
1210 1182
    throw IoError("Cannot write file", file_name);
1211 1183
  }
1212 1184
  return GraphToEps<DefaultGraphToEpsTraits<G> >
1213 1185
    (DefaultGraphToEpsTraits<G>(g,*os,true));
1214 1186
}
1215 1187

	
1216 1188
} //END OF NAMESPACE LEMON
1217 1189

	
1218 1190
#endif // LEMON_GRAPH_TO_EPS_H
Ignore white space 4194304 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2009
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
/*
20 20
 * This file contains the reimplemented version of the Mersenne Twister
21 21
 * Generator of Matsumoto and Nishimura.
22 22
 *
23 23
 * See the appropriate copyright notice below.
24 24
 *
25 25
 * Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
26 26
 * All rights reserved.
27 27
 *
28 28
 * Redistribution and use in source and binary forms, with or without
29 29
 * modification, are permitted provided that the following conditions
30 30
 * are met:
31 31
 *
32 32
 * 1. Redistributions of source code must retain the above copyright
33 33
 *    notice, this list of conditions and the following disclaimer.
34 34
 *
35 35
 * 2. Redistributions in binary form must reproduce the above copyright
36 36
 *    notice, this list of conditions and the following disclaimer in the
37 37
 *    documentation and/or other materials provided with the distribution.
38 38
 *
39 39
 * 3. The names of its contributors may not be used to endorse or promote
40 40
 *    products derived from this software without specific prior written
41 41
 *    permission.
42 42
 *
43 43
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
44 44
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
45 45
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
46 46
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
47 47
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
48 48
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
49 49
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
50 50
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 51
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
52 52
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
53 53
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
54 54
 * OF THE POSSIBILITY OF SUCH DAMAGE.
55 55
 *
56 56
 *
57 57
 * Any feedback is very welcome.
58 58
 * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
59 59
 * email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
60 60
 */
61 61

	
62 62
#ifndef LEMON_RANDOM_H
63 63
#define LEMON_RANDOM_H
64 64

	
65 65
#include <algorithm>
66 66
#include <iterator>
67 67
#include <vector>
68 68
#include <limits>
69 69
#include <fstream>
70 70

	
71 71
#include <lemon/math.h>
72 72
#include <lemon/dim2.h>
73 73

	
74 74
#ifndef WIN32
75 75
#include <sys/time.h>
76 76
#include <ctime>
77 77
#include <sys/types.h>
78 78
#include <unistd.h>
79 79
#else
80
#include <windows.h>
80
#include <lemon/bits/windows.h>
81 81
#endif
82 82

	
83 83
///\ingroup misc
84 84
///\file
85 85
///\brief Mersenne Twister random number generator
86 86

	
87 87
namespace lemon {
88 88

	
89 89
  namespace _random_bits {
90 90

	
91 91
    template <typename _Word, int _bits = std::numeric_limits<_Word>::digits>
92 92
    struct RandomTraits {};
93 93

	
94 94
    template <typename _Word>
95 95
    struct RandomTraits<_Word, 32> {
96 96

	
97 97
      typedef _Word Word;
98 98
      static const int bits = 32;
99 99

	
100 100
      static const int length = 624;
101 101
      static const int shift = 397;
102 102

	
103 103
      static const Word mul = 0x6c078965u;
104 104
      static const Word arrayInit = 0x012BD6AAu;
105 105
      static const Word arrayMul1 = 0x0019660Du;
106 106
      static const Word arrayMul2 = 0x5D588B65u;
107 107

	
108 108
      static const Word mask = 0x9908B0DFu;
109 109
      static const Word loMask = (1u << 31) - 1;
110 110
      static const Word hiMask = ~loMask;
111 111

	
112 112

	
113 113
      static Word tempering(Word rnd) {
114 114
        rnd ^= (rnd >> 11);
115 115
        rnd ^= (rnd << 7) & 0x9D2C5680u;
116 116
        rnd ^= (rnd << 15) & 0xEFC60000u;
117 117
        rnd ^= (rnd >> 18);
118 118
        return rnd;
119 119
      }
120 120

	
121 121
    };
122 122

	
123 123
    template <typename _Word>
124 124
    struct RandomTraits<_Word, 64> {
125 125

	
126 126
      typedef _Word Word;
127 127
      static const int bits = 64;
128 128

	
129 129
      static const int length = 312;
130 130
      static const int shift = 156;
131 131

	
132 132
      static const Word mul = Word(0x5851F42Du) << 32 | Word(0x4C957F2Du);
133 133
      static const Word arrayInit = Word(0x00000000u) << 32 |Word(0x012BD6AAu);
134 134
      static const Word arrayMul1 = Word(0x369DEA0Fu) << 32 |Word(0x31A53F85u);
135 135
      static const Word arrayMul2 = Word(0x27BB2EE6u) << 32 |Word(0x87B0B0FDu);
136 136

	
137 137
      static const Word mask = Word(0xB5026F5Au) << 32 | Word(0xA96619E9u);
138 138
      static const Word loMask = (Word(1u) << 31) - 1;
139 139
      static const Word hiMask = ~loMask;
140 140

	
141 141
      static Word tempering(Word rnd) {
142 142
        rnd ^= (rnd >> 29) & (Word(0x55555555u) << 32 | Word(0x55555555u));
143 143
        rnd ^= (rnd << 17) & (Word(0x71D67FFFu) << 32 | Word(0xEDA60000u));
144 144
        rnd ^= (rnd << 37) & (Word(0xFFF7EEE0u) << 32 | Word(0x00000000u));
145 145
        rnd ^= (rnd >> 43);
146 146
        return rnd;
147 147
      }
148 148

	
149 149
    };
150 150

	
151 151
    template <typename _Word>
152 152
    class RandomCore {
153 153
    public:
154 154

	
155 155
      typedef _Word Word;
156 156

	
157 157
    private:
158 158

	
159 159
      static const int bits = RandomTraits<Word>::bits;
160 160

	
161 161
      static const int length = RandomTraits<Word>::length;
162 162
      static const int shift = RandomTraits<Word>::shift;
163 163

	
164 164
    public:
165 165

	
166 166
      void initState() {
167 167
        static const Word seedArray[4] = {
168 168
          0x12345u, 0x23456u, 0x34567u, 0x45678u
169 169
        };
170 170

	
171 171
        initState(seedArray, seedArray + 4);
172 172
      }
173 173

	
174 174
      void initState(Word seed) {
175 175

	
176 176
        static const Word mul = RandomTraits<Word>::mul;
177 177

	
178 178
        current = state;
179 179

	
180 180
        Word *curr = state + length - 1;
181 181
        curr[0] = seed; --curr;
182 182
        for (int i = 1; i < length; ++i) {
183 183
          curr[0] = (mul * ( curr[1] ^ (curr[1] >> (bits - 2)) ) + i);
184 184
          --curr;
185 185
        }
186 186
      }
187 187

	
188 188
      template <typename Iterator>
189 189
      void initState(Iterator begin, Iterator end) {
190 190

	
191 191
        static const Word init = RandomTraits<Word>::arrayInit;
192 192
        static const Word mul1 = RandomTraits<Word>::arrayMul1;
193 193
        static const Word mul2 = RandomTraits<Word>::arrayMul2;
194 194

	
195 195

	
196 196
        Word *curr = state + length - 1; --curr;
197 197
        Iterator it = begin; int cnt = 0;
198 198
        int num;
199 199

	
200 200
        initState(init);
201 201

	
202 202
        num = length > end - begin ? length : end - begin;
203 203
        while (num--) {
204 204
          curr[0] = (curr[0] ^ ((curr[1] ^ (curr[1] >> (bits - 2))) * mul1))
205 205
            + *it + cnt;
206 206
          ++it; ++cnt;
207 207
          if (it == end) {
208 208
            it = begin; cnt = 0;
209 209
          }
210 210
          if (curr == state) {
211 211
            curr = state + length - 1; curr[0] = state[0];
212 212
          }
213 213
          --curr;
214 214
        }
215 215

	
216 216
        num = length - 1; cnt = length - (curr - state) - 1;
217 217
        while (num--) {
218 218
          curr[0] = (curr[0] ^ ((curr[1] ^ (curr[1] >> (bits - 2))) * mul2))
219 219
            - cnt;
220 220
          --curr; ++cnt;
221 221
          if (curr == state) {
222 222
            curr = state + length - 1; curr[0] = state[0]; --curr;
223 223
            cnt = 1;
224 224
          }
225 225
        }
226 226

	
227 227
        state[length - 1] = Word(1) << (bits - 1);
228 228
      }
229 229

	
230 230
      void copyState(const RandomCore& other) {
231 231
        std::copy(other.state, other.state + length, state);
232 232
        current = state + (other.current - other.state);
233 233
      }
234 234

	
235 235
      Word operator()() {
236 236
        if (current == state) fillState();
237 237
        --current;
238 238
        Word rnd = *current;
239 239
        return RandomTraits<Word>::tempering(rnd);
240 240
      }
241 241

	
242 242
    private:
243 243

	
244 244

	
245 245
      void fillState() {
246 246
        static const Word mask[2] = { 0x0ul, RandomTraits<Word>::mask };
247 247
        static const Word loMask = RandomTraits<Word>::loMask;
248 248
        static const Word hiMask = RandomTraits<Word>::hiMask;
249 249

	
250 250
        current = state + length;
251 251

	
252 252
        register Word *curr = state + length - 1;
253 253
        register long num;
254 254

	
255 255
        num = length - shift;
256 256
        while (num--) {
257 257
          curr[0] = (((curr[0] & hiMask) | (curr[-1] & loMask)) >> 1) ^
258 258
            curr[- shift] ^ mask[curr[-1] & 1ul];
259 259
          --curr;
260 260
        }
261 261
        num = shift - 1;
262 262
        while (num--) {
263 263
          curr[0] = (((curr[0] & hiMask) | (curr[-1] & loMask)) >> 1) ^
264 264
            curr[length - shift] ^ mask[curr[-1] & 1ul];
265 265
          --curr;
266 266
        }
267 267
        state[0] = (((state[0] & hiMask) | (curr[length - 1] & loMask)) >> 1) ^
268 268
          curr[length - shift] ^ mask[curr[length - 1] & 1ul];
269 269

	
270 270
      }
271 271

	
272 272

	
273 273
      Word *current;
274 274
      Word state[length];
275 275

	
276 276
    };
277 277

	
278 278

	
279 279
    template <typename Result,
280 280
              int shift = (std::numeric_limits<Result>::digits + 1) / 2>
281 281
    struct Masker {
282 282
      static Result mask(const Result& result) {
283 283
        return Masker<Result, (shift + 1) / 2>::
284 284
          mask(static_cast<Result>(result | (result >> shift)));
285 285
      }
286 286
    };
287 287

	
288 288
    template <typename Result>
289 289
    struct Masker<Result, 1> {
290 290
      static Result mask(const Result& result) {
291 291
        return static_cast<Result>(result | (result >> 1));
292 292
      }
293 293
    };
294 294

	
295 295
    template <typename Result, typename Word,
296 296
              int rest = std::numeric_limits<Result>::digits, int shift = 0,
297 297
              bool last = rest <= std::numeric_limits<Word>::digits>
298 298
    struct IntConversion {
299 299
      static const int bits = std::numeric_limits<Word>::digits;
300 300

	
301 301
      static Result convert(RandomCore<Word>& rnd) {
302 302
        return static_cast<Result>(rnd() >> (bits - rest)) << shift;
303 303
      }
304 304

	
305 305
    };
306 306

	
307 307
    template <typename Result, typename Word, int rest, int shift>
308 308
    struct IntConversion<Result, Word, rest, shift, false> {
309 309
      static const int bits = std::numeric_limits<Word>::digits;
310 310

	
311 311
      static Result convert(RandomCore<Word>& rnd) {
312 312
        return (static_cast<Result>(rnd()) << shift) |
313 313
          IntConversion<Result, Word, rest - bits, shift + bits>::convert(rnd);
314 314
      }
315 315
    };
316 316

	
317 317

	
318 318
    template <typename Result, typename Word,
319 319
              bool one_word = (std::numeric_limits<Word>::digits <
320 320
                               std::numeric_limits<Result>::digits) >
321 321
    struct Mapping {
322 322
      static Result map(RandomCore<Word>& rnd, const Result& bound) {
323 323
        Word max = Word(bound - 1);
324 324
        Result mask = Masker<Result>::mask(bound - 1);
325 325
        Result num;
326 326
        do {
327 327
          num = IntConversion<Result, Word>::convert(rnd) & mask;
328 328
        } while (num > max);
329 329
        return num;
330 330
      }
331 331
    };
332 332

	
333 333
    template <typename Result, typename Word>
334 334
    struct Mapping<Result, Word, false> {
335 335
      static Result map(RandomCore<Word>& rnd, const Result& bound) {
336 336
        Word max = Word(bound - 1);
337 337
        Word mask = Masker<Word, (std::numeric_limits<Result>::digits + 1) / 2>
338 338
          ::mask(max);
339 339
        Word num;
340 340
        do {
341 341
          num = rnd() & mask;
342 342
        } while (num > max);
343 343
        return num;
344 344
      }
345 345
    };
346 346

	
347 347
    template <typename Result, int exp, bool pos = (exp >= 0)>
348 348
    struct ShiftMultiplier {
349 349
      static const Result multiplier() {
350 350
        Result res = ShiftMultiplier<Result, exp / 2>::multiplier();
351 351
        res *= res;
352 352
        if ((exp & 1) == 1) res *= static_cast<Result>(2.0);
353 353
        return res;
354 354
      }
355 355
    };
356 356

	
357 357
    template <typename Result, int exp>
358 358
    struct ShiftMultiplier<Result, exp, false> {
359 359
      static const Result multiplier() {
360 360
        Result res = ShiftMultiplier<Result, exp / 2>::multiplier();
361 361
        res *= res;
362 362
        if ((exp & 1) == 1) res *= static_cast<Result>(0.5);
363 363
        return res;
364 364
      }
365 365
    };
366 366

	
367 367
    template <typename Result>
368 368
    struct ShiftMultiplier<Result, 0, true> {
369 369
      static const Result multiplier() {
370 370
        return static_cast<Result>(1.0);
371 371
      }
372 372
    };
373 373

	
374 374
    template <typename Result>
375 375
    struct ShiftMultiplier<Result, -20, true> {
376 376
      static const Result multiplier() {
377 377
        return static_cast<Result>(1.0/1048576.0);
378 378
      }
379 379
    };
380 380

	
381 381
    template <typename Result>
382 382
    struct ShiftMultiplier<Result, -32, true> {
383 383
      static const Result multiplier() {
384 384
        return static_cast<Result>(1.0/424967296.0);
385 385
      }
386 386
    };
387 387

	
388 388
    template <typename Result>
389 389
    struct ShiftMultiplier<Result, -53, true> {
390 390
      static const Result multiplier() {
391 391
        return static_cast<Result>(1.0/9007199254740992.0);
392 392
      }
393 393
    };
394 394

	
395 395
    template <typename Result>
396 396
    struct ShiftMultiplier<Result, -64, true> {
397 397
      static const Result multiplier() {
398 398
        return static_cast<Result>(1.0/18446744073709551616.0);
399 399
      }
400 400
    };
401 401

	
402 402
    template <typename Result, int exp>
403 403
    struct Shifting {
404 404
      static Result shift(const Result& result) {
405 405
        return result * ShiftMultiplier<Result, exp>::multiplier();
406 406
      }
407 407
    };
408 408

	
409 409
    template <typename Result, typename Word,
410 410
              int rest = std::numeric_limits<Result>::digits, int shift = 0,
411 411
              bool last = rest <= std::numeric_limits<Word>::digits>
412 412
    struct RealConversion{
413 413
      static const int bits = std::numeric_limits<Word>::digits;
414 414

	
415 415
      static Result convert(RandomCore<Word>& rnd) {
416 416
        return Shifting<Result, - shift - rest>::
417 417
          shift(static_cast<Result>(rnd() >> (bits - rest)));
418 418
      }
419 419
    };
420 420

	
421 421
    template <typename Result, typename Word, int rest, int shift>
422 422
    struct RealConversion<Result, Word, rest, shift, false> {
423 423
      static const int bits = std::numeric_limits<Word>::digits;
424 424

	
425 425
      static Result convert(RandomCore<Word>& rnd) {
426 426
        return Shifting<Result, - shift - bits>::
427 427
          shift(static_cast<Result>(rnd())) +
428 428
          RealConversion<Result, Word, rest-bits, shift + bits>::
429 429
          convert(rnd);
430 430
      }
431 431
    };
432 432

	
433 433
    template <typename Result, typename Word>
434 434
    struct Initializer {
435 435

	
436 436
      template <typename Iterator>
437 437
      static void init(RandomCore<Word>& rnd, Iterator begin, Iterator end) {
438 438
        std::vector<Word> ws;
439 439
        for (Iterator it = begin; it != end; ++it) {
440 440
          ws.push_back(Word(*it));
441 441
        }
442 442
        rnd.initState(ws.begin(), ws.end());
443 443
      }
444 444

	
445 445
      static void init(RandomCore<Word>& rnd, Result seed) {
446 446
        rnd.initState(seed);
447 447
      }
448 448
    };
449 449

	
450 450
    template <typename Word>
451 451
    struct BoolConversion {
452 452
      static bool convert(RandomCore<Word>& rnd) {
453 453
        return (rnd() & 1) == 1;
454 454
      }
455 455
    };
456 456

	
457 457
    template <typename Word>
458 458
    struct BoolProducer {
459 459
      Word buffer;
460 460
      int num;
461 461

	
462 462
      BoolProducer() : num(0) {}
463 463

	
464 464
      bool convert(RandomCore<Word>& rnd) {
465 465
        if (num == 0) {
466 466
          buffer = rnd();
467 467
          num = RandomTraits<Word>::bits;
468 468
        }
469 469
        bool r = (buffer & 1);
470 470
        buffer >>= 1;
471 471
        --num;
472 472
        return r;
473 473
      }
474 474
    };
475 475

	
476 476
  }
477 477

	
478 478
  /// \ingroup misc
479 479
  ///
480 480
  /// \brief Mersenne Twister random number generator
481 481
  ///
482 482
  /// The Mersenne Twister is a twisted generalized feedback
483 483
  /// shift-register generator of Matsumoto and Nishimura. The period
484 484
  /// of this generator is \f$ 2^{19937} - 1 \f$ and it is
485 485
  /// equi-distributed in 623 dimensions for 32-bit numbers. The time
486 486
  /// performance of this generator is comparable to the commonly used
487 487
  /// generators.
488 488
  ///
489 489
  /// This implementation is specialized for both 32-bit and 64-bit
490 490
  /// architectures. The generators differ sligthly in the
491 491
  /// initialization and generation phase so they produce two
492 492
  /// completly different sequences.
493 493
  ///
494 494
  /// The generator gives back random numbers of serveral types. To
495 495
  /// get a random number from a range of a floating point type you
496 496
  /// can use one form of the \c operator() or the \c real() member
497 497
  /// function. If you want to get random number from the {0, 1, ...,
498 498
  /// n-1} integer range use the \c operator[] or the \c integer()
499 499
  /// method. And to get random number from the whole range of an
500 500
  /// integer type you can use the argumentless \c integer() or \c
501 501
  /// uinteger() functions. After all you can get random bool with
502 502
  /// equal chance of true and false or given probability of true
503 503
  /// result with the \c boolean() member functions.
504 504
  ///
505 505
  ///\code
506 506
  /// // The commented code is identical to the other
507 507
  /// double a = rnd();                     // [0.0, 1.0)
508 508
  /// // double a = rnd.real();             // [0.0, 1.0)
509 509
  /// double b = rnd(100.0);                // [0.0, 100.0)
510 510
  /// // double b = rnd.real(100.0);        // [0.0, 100.0)
511 511
  /// double c = rnd(1.0, 2.0);             // [1.0, 2.0)
512 512
  /// // double c = rnd.real(1.0, 2.0);     // [1.0, 2.0)
513 513
  /// int d = rnd[100000];                  // 0..99999
514 514
  /// // int d = rnd.integer(100000);       // 0..99999
515 515
  /// int e = rnd[6] + 1;                   // 1..6
516 516
  /// // int e = rnd.integer(1, 1 + 6);     // 1..6
517 517
  /// int b = rnd.uinteger<int>();          // 0 .. 2^31 - 1
518 518
  /// int c = rnd.integer<int>();           // - 2^31 .. 2^31 - 1
519 519
  /// bool g = rnd.boolean();               // P(g = true) = 0.5
520 520
  /// bool h = rnd.boolean(0.8);            // P(h = true) = 0.8
521 521
  ///\endcode
522 522
  ///
523 523
  /// LEMON provides a global instance of the random number
524 524
  /// generator which name is \ref lemon::rnd "rnd". Usually it is a
525 525
  /// good programming convenience to use this global generator to get
526 526
  /// random numbers.
527 527
  class Random {
528 528
  private:
529 529

	
530 530
    // Architecture word
531 531
    typedef unsigned long Word;
532 532

	
533 533
    _random_bits::RandomCore<Word> core;
534 534
    _random_bits::BoolProducer<Word> bool_producer;
535 535

	
536 536

	
537 537
  public:
538 538

	
539 539
    ///\name Initialization
540 540
    ///
541 541
    /// @{
542 542

	
543 543
    /// \brief Default constructor
544 544
    ///
545 545
    /// Constructor with constant seeding.
546 546
    Random() { core.initState(); }
547 547

	
548 548
    /// \brief Constructor with seed
549 549
    ///
550 550
    /// Constructor with seed. The current number type will be converted
551 551
    /// to the architecture word type.
552 552
    template <typename Number>
553 553
    Random(Number seed) {
554 554
      _random_bits::Initializer<Number, Word>::init(core, seed);
555 555
    }
556 556

	
557 557
    /// \brief Constructor with array seeding
558 558
    ///
559 559
    /// Constructor with array seeding. The given range should contain
560 560
    /// any number type and the numbers will be converted to the
561 561
    /// architecture word type.
562 562
    template <typename Iterator>
563 563
    Random(Iterator begin, Iterator end) {
564 564
      typedef typename std::iterator_traits<Iterator>::value_type Number;
565 565
      _random_bits::Initializer<Number, Word>::init(core, begin, end);
566 566
    }
567 567

	
568 568
    /// \brief Copy constructor
569 569
    ///
570 570
    /// Copy constructor. The generated sequence will be identical to
571 571
    /// the other sequence. It can be used to save the current state
572 572
    /// of the generator and later use it to generate the same
573 573
    /// sequence.
574 574
    Random(const Random& other) {
575 575
      core.copyState(other.core);
576 576
    }
577 577

	
578 578
    /// \brief Assign operator
579 579
    ///
580 580
    /// Assign operator. The generated sequence will be identical to
581 581
    /// the other sequence. It can be used to save the current state
582 582
    /// of the generator and later use it to generate the same
583 583
    /// sequence.
584 584
    Random& operator=(const Random& other) {
585 585
      if (&other != this) {
586 586
        core.copyState(other.core);
587 587
      }
588 588
      return *this;
589 589
    }
590 590

	
591 591
    /// \brief Seeding random sequence
592 592
    ///
593 593
    /// Seeding the random sequence. The current number type will be
594 594
    /// converted to the architecture word type.
595 595
    template <typename Number>
596 596
    void seed(Number seed) {
597 597
      _random_bits::Initializer<Number, Word>::init(core, seed);
598 598
    }
599 599

	
600 600
    /// \brief Seeding random sequence
601 601
    ///
602 602
    /// Seeding the random sequence. The given range should contain
603 603
    /// any number type and the numbers will be converted to the
604 604
    /// architecture word type.
605 605
    template <typename Iterator>
606 606
    void seed(Iterator begin, Iterator end) {
607 607
      typedef typename std::iterator_traits<Iterator>::value_type Number;
608 608
      _random_bits::Initializer<Number, Word>::init(core, begin, end);
609 609
    }
610 610

	
611 611
    /// \brief Seeding from file or from process id and time
612 612
    ///
613 613
    /// By default, this function calls the \c seedFromFile() member
614 614
    /// function with the <tt>/dev/urandom</tt> file. If it does not success,
615 615
    /// it uses the \c seedFromTime().
616 616
    /// \return Currently always true.
617 617
    bool seed() {
618 618
#ifndef WIN32
619 619
      if (seedFromFile("/dev/urandom", 0)) return true;
620 620
#endif
621 621
      if (seedFromTime()) return true;
622 622
      return false;
623 623
    }
624 624

	
625 625
    /// \brief Seeding from file
626 626
    ///
627 627
    /// Seeding the random sequence from file. The linux kernel has two
628 628
    /// devices, <tt>/dev/random</tt> and <tt>/dev/urandom</tt> which
629 629
    /// could give good seed values for pseudo random generators (The
630 630
    /// difference between two devices is that the <tt>random</tt> may
631 631
    /// block the reading operation while the kernel can give good
632 632
    /// source of randomness, while the <tt>urandom</tt> does not
633 633
    /// block the input, but it could give back bytes with worse
634 634
    /// entropy).
635 635
    /// \param file The source file
636 636
    /// \param offset The offset, from the file read.
637 637
    /// \return True when the seeding successes.
638 638
#ifndef WIN32
639 639
    bool seedFromFile(const std::string& file = "/dev/urandom", int offset = 0)
640 640
#else
641 641
    bool seedFromFile(const std::string& file = "", int offset = 0)
642 642
#endif
643 643
    {
644 644
      std::ifstream rs(file.c_str());
645 645
      const int size = 4;
646 646
      Word buf[size];
647 647
      if (offset != 0 && !rs.seekg(offset)) return false;
648 648
      if (!rs.read(reinterpret_cast<char*>(buf), sizeof(buf))) return false;
649 649
      seed(buf, buf + size);
650 650
      return true;
651 651
    }
652 652

	
653 653
    /// \brief Seding from process id and time
654 654
    ///
655 655
    /// Seding from process id and time. This function uses the
656 656
    /// current process id and the current time for initialize the
657 657
    /// random sequence.
658 658
    /// \return Currently always true.
659 659
    bool seedFromTime() {
660 660
#ifndef WIN32
661 661
      timeval tv;
662 662
      gettimeofday(&tv, 0);
663 663
      seed(getpid() + tv.tv_sec + tv.tv_usec);
664 664
#else
665
      FILETIME time;
666
      GetSystemTimeAsFileTime(&time);
667
      seed(GetCurrentProcessId() + time.dwHighDateTime + time.dwLowDateTime);
665
      seed(bits::getWinRndSeed());
668 666
#endif
669 667
      return true;
670 668
    }
671 669

	
672 670
    /// @}
673 671

	
674 672
    ///\name Uniform distributions
675 673
    ///
676 674
    /// @{
677 675

	
678 676
    /// \brief Returns a random real number from the range [0, 1)
679 677
    ///
680 678
    /// It returns a random real number from the range [0, 1). The
681 679
    /// default Number type is \c double.
682 680
    template <typename Number>
683 681
    Number real() {
684 682
      return _random_bits::RealConversion<Number, Word>::convert(core);
685 683
    }
686 684

	
687 685
    double real() {
688 686
      return real<double>();
689 687
    }
690 688

	
691 689
    /// \brief Returns a random real number from the range [0, 1)
692 690
    ///
693 691
    /// It returns a random double from the range [0, 1).
694 692
    double operator()() {
695 693
      return real<double>();
696 694
    }
697 695

	
698 696
    /// \brief Returns a random real number from the range [0, b)
699 697
    ///
700 698
    /// It returns a random real number from the range [0, b).
701 699
    double operator()(double b) {
702 700
      return real<double>() * b;
703 701
    }
704 702

	
705 703
    /// \brief Returns a random real number from the range [a, b)
706 704
    ///
707 705
    /// It returns a random real number from the range [a, b).
708 706
    double operator()(double a, double b) {
709 707
      return real<double>() * (b - a) + a;
710 708
    }
711 709

	
712 710
    /// \brief Returns a random integer from a range
713 711
    ///
714 712
    /// It returns a random integer from the range {0, 1, ..., b - 1}.
715 713
    template <typename Number>
716 714
    Number integer(Number b) {
717 715
      return _random_bits::Mapping<Number, Word>::map(core, b);
718 716
    }
719 717

	
720 718
    /// \brief Returns a random integer from a range
721 719
    ///
722 720
    /// It returns a random integer from the range {a, a + 1, ..., b - 1}.
723 721
    template <typename Number>
724 722
    Number integer(Number a, Number b) {
725 723
      return _random_bits::Mapping<Number, Word>::map(core, b - a) + a;
726 724
    }
727 725

	
728 726
    /// \brief Returns a random integer from a range
729 727
    ///
730 728
    /// It returns a random integer from the range {0, 1, ..., b - 1}.
731 729
    template <typename Number>
732 730
    Number operator[](Number b) {
733 731
      return _random_bits::Mapping<Number, Word>::map(core, b);
734 732
    }
735 733

	
736 734
    /// \brief Returns a random non-negative integer
737 735
    ///
738 736
    /// It returns a random non-negative integer uniformly from the
739 737
    /// whole range of the current \c Number type. The default result
740 738
    /// type of this function is <tt>unsigned int</tt>.
741 739
    template <typename Number>
742 740
    Number uinteger() {
743 741
      return _random_bits::IntConversion<Number, Word>::convert(core);
744 742
    }
745 743

	
746 744
    unsigned int uinteger() {
747 745
      return uinteger<unsigned int>();
748 746
    }
749 747

	
750 748
    /// \brief Returns a random integer
751 749
    ///
752 750
    /// It returns a random integer uniformly from the whole range of
753 751
    /// the current \c Number type. The default result type of this
754 752
    /// function is \c int.
755 753
    template <typename Number>
756 754
    Number integer() {
757 755
      static const int nb = std::numeric_limits<Number>::digits +
758 756
        (std::numeric_limits<Number>::is_signed ? 1 : 0);
759 757
      return _random_bits::IntConversion<Number, Word, nb>::convert(core);
760 758
    }
761 759

	
762 760
    int integer() {
763 761
      return integer<int>();
764 762
    }
765 763

	
766 764
    /// \brief Returns a random bool
767 765
    ///
768 766
    /// It returns a random bool. The generator holds a buffer for
769 767
    /// random bits. Every time when it become empty the generator makes
770 768
    /// a new random word and fill the buffer up.
771 769
    bool boolean() {
772 770
      return bool_producer.convert(core);
773 771
    }
774 772

	
775 773
    /// @}
776 774

	
777 775
    ///\name Non-uniform distributions
778 776
    ///
779 777
    ///@{
780 778

	
781 779
    /// \brief Returns a random bool with given probability of true result.
782 780
    ///
783 781
    /// It returns a random bool with given probability of true result.
784 782
    bool boolean(double p) {
785 783
      return operator()() < p;
786 784
    }
787 785

	
788 786
    /// Standard normal (Gauss) distribution
789 787

	
790 788
    /// Standard normal (Gauss) distribution.
791 789
    /// \note The Cartesian form of the Box-Muller
792 790
    /// transformation is used to generate a random normal distribution.
793 791
    double gauss()
794 792
    {
795 793
      double V1,V2,S;
796 794
      do {
797 795
        V1=2*real<double>()-1;
798 796
        V2=2*real<double>()-1;
799 797
        S=V1*V1+V2*V2;
800 798
      } while(S>=1);
801 799
      return std::sqrt(-2*std::log(S)/S)*V1;
802 800
    }
803 801
    /// Normal (Gauss) distribution with given mean and standard deviation
804 802

	
805 803
    /// Normal (Gauss) distribution with given mean and standard deviation.
806 804
    /// \sa gauss()
807 805
    double gauss(double mean,double std_dev)
808 806
    {
809 807
      return gauss()*std_dev+mean;
810 808
    }
811 809

	
812 810
    /// Lognormal distribution
813 811

	
814 812
    /// Lognormal distribution. The parameters are the mean and the standard
815 813
    /// deviation of <tt>exp(X)</tt>.
816 814
    ///
817 815
    double lognormal(double n_mean,double n_std_dev)
818 816
    {
819 817
      return std::exp(gauss(n_mean,n_std_dev));
820 818
    }
821 819
    /// Lognormal distribution
822 820

	
823 821
    /// Lognormal distribution. The parameter is an <tt>std::pair</tt> of
824 822
    /// the mean and the standard deviation of <tt>exp(X)</tt>.
825 823
    ///
826 824
    double lognormal(const std::pair<double,double> &params)
827 825
    {
828 826
      return std::exp(gauss(params.first,params.second));
829 827
    }
830 828
    /// Compute the lognormal parameters from mean and standard deviation
831 829

	
832 830
    /// This function computes the lognormal parameters from mean and
833 831
    /// standard deviation. The return value can direcly be passed to
834 832
    /// lognormal().
835 833
    std::pair<double,double> lognormalParamsFromMD(double mean,
836 834
                                                   double std_dev)
837 835
    {
838 836
      double fr=std_dev/mean;
839 837
      fr*=fr;
840 838
      double lg=std::log(1+fr);
841 839
      return std::pair<double,double>(std::log(mean)-lg/2.0,std::sqrt(lg));
842 840
    }
843 841
    /// Lognormal distribution with given mean and standard deviation
844 842

	
845 843
    /// Lognormal distribution with given mean and standard deviation.
846 844
    ///
847 845
    double lognormalMD(double mean,double std_dev)
848 846
    {
849 847
      return lognormal(lognormalParamsFromMD(mean,std_dev));
850 848
    }
851 849

	
852 850
    /// Exponential distribution with given mean
853 851

	
854 852
    /// This function generates an exponential distribution random number
855 853
    /// with mean <tt>1/lambda</tt>.
856 854
    ///
857 855
    double exponential(double lambda=1.0)
858 856
    {
859 857
      return -std::log(1.0-real<double>())/lambda;
860 858
    }
861 859

	
862 860
    /// Gamma distribution with given integer shape
863 861

	
864 862
    /// This function generates a gamma distribution random number.
865 863
    ///
866 864
    ///\param k shape parameter (<tt>k>0</tt> integer)
867 865
    double gamma(int k)
868 866
    {
869 867
      double s = 0;
870 868
      for(int i=0;i<k;i++) s-=std::log(1.0-real<double>());
871 869
      return s;
872 870
    }
873 871

	
874 872
    /// Gamma distribution with given shape and scale parameter
875 873

	
876 874
    /// This function generates a gamma distribution random number.
877 875
    ///
878 876
    ///\param k shape parameter (<tt>k>0</tt>)
879 877
    ///\param theta scale parameter
880 878
    ///
881 879
    double gamma(double k,double theta=1.0)
882 880
    {
883 881
      double xi,nu;
884 882
      const double delta = k-std::floor(k);
885 883
      const double v0=E/(E-delta);
886 884
      do {
887 885
        double V0=1.0-real<double>();
888 886
        double V1=1.0-real<double>();
889 887
        double V2=1.0-real<double>();
890 888
        if(V2<=v0)
891 889
          {
892 890
            xi=std::pow(V1,1.0/delta);
893 891
            nu=V0*std::pow(xi,delta-1.0);
894 892
          }
895 893
        else
896 894
          {
897 895
            xi=1.0-std::log(V1);
898 896
            nu=V0*std::exp(-xi);
899 897
          }
900 898
      } while(nu>std::pow(xi,delta-1.0)*std::exp(-xi));
901 899
      return theta*(xi+gamma(int(std::floor(k))));
902 900
    }
903 901

	
904 902
    /// Weibull distribution
905 903

	
906 904
    /// This function generates a Weibull distribution random number.
907 905
    ///
908 906
    ///\param k shape parameter (<tt>k>0</tt>)
909 907
    ///\param lambda scale parameter (<tt>lambda>0</tt>)
910 908
    ///
911 909
    double weibull(double k,double lambda)
912 910
    {
913 911
      return lambda*pow(-std::log(1.0-real<double>()),1.0/k);
914 912
    }
915 913

	
916 914
    /// Pareto distribution
917 915

	
918 916
    /// This function generates a Pareto distribution random number.
919 917
    ///
920 918
    ///\param k shape parameter (<tt>k>0</tt>)
921 919
    ///\param x_min location parameter (<tt>x_min>0</tt>)
922 920
    ///
923 921
    double pareto(double k,double x_min)
924 922
    {
925 923
      return exponential(gamma(k,1.0/x_min))+x_min;
926 924
    }
927 925

	
928 926
    /// Poisson distribution
929 927

	
930 928
    /// This function generates a Poisson distribution random number with
931 929
    /// parameter \c lambda.
932 930
    ///
933 931
    /// The probability mass function of this distribusion is
934 932
    /// \f[ \frac{e^{-\lambda}\lambda^k}{k!} \f]
935 933
    /// \note The algorithm is taken from the book of Donald E. Knuth titled
936 934
    /// ''Seminumerical Algorithms'' (1969). Its running time is linear in the
937 935
    /// return value.
938 936

	
939 937
    int poisson(double lambda)
940 938
    {
941 939
      const double l = std::exp(-lambda);
942 940
      int k=0;
943 941
      double p = 1.0;
944 942
      do {
945 943
        k++;
946 944
        p*=real<double>();
947 945
      } while (p>=l);
948 946
      return k-1;
949 947
    }
950 948

	
951 949
    ///@}
952 950

	
953 951
    ///\name Two dimensional distributions
954 952
    ///
955 953
    ///@{
956 954

	
957 955
    /// Uniform distribution on the full unit circle
958 956

	
959 957
    /// Uniform distribution on the full unit circle.
960 958
    ///
961 959
    dim2::Point<double> disc()
962 960
    {
963 961
      double V1,V2;
964 962
      do {
965 963
        V1=2*real<double>()-1;
966 964
        V2=2*real<double>()-1;
967 965

	
968 966
      } while(V1*V1+V2*V2>=1);
969 967
      return dim2::Point<double>(V1,V2);
970 968
    }
971 969
    /// A kind of two dimensional normal (Gauss) distribution
972 970

	
973 971
    /// This function provides a turning symmetric two-dimensional distribution.
974 972
    /// Both coordinates are of standard normal distribution, but they are not
975 973
    /// independent.
976 974
    ///
977 975
    /// \note The coordinates are the two random variables provided by
978 976
    /// the Box-Muller method.
979 977
    dim2::Point<double> gauss2()
980 978
    {
981 979
      double V1,V2,S;
982 980
      do {
983 981
        V1=2*real<double>()-1;
984 982
        V2=2*real<double>()-1;
985 983
        S=V1*V1+V2*V2;
986 984
      } while(S>=1);
987 985
      double W=std::sqrt(-2*std::log(S)/S);
988 986
      return dim2::Point<double>(W*V1,W*V2);
989 987
    }
990 988
    /// A kind of two dimensional exponential distribution
991 989

	
992 990
    /// This function provides a turning symmetric two-dimensional distribution.
993 991
    /// The x-coordinate is of conditionally exponential distribution
994 992
    /// with the condition that x is positive and y=0. If x is negative and
995 993
    /// y=0 then, -x is of exponential distribution. The same is true for the
996 994
    /// y-coordinate.
997 995
    dim2::Point<double> exponential2()
998 996
    {
999 997
      double V1,V2,S;
1000 998
      do {
1001 999
        V1=2*real<double>()-1;
1002 1000
        V2=2*real<double>()-1;
1003 1001
        S=V1*V1+V2*V2;
1004 1002
      } while(S>=1);
1005 1003
      double W=-std::log(S)/S;
1006 1004
      return dim2::Point<double>(W*V1,W*V2);
1007 1005
    }
1008 1006

	
1009 1007
    ///@}
1010 1008
  };
1011 1009

	
1012 1010

	
1013 1011
  extern Random rnd;
1014 1012

	
1015 1013
}
1016 1014

	
1017 1015
#endif
Ignore white space 6 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2009
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#ifndef LEMON_TIME_MEASURE_H
20 20
#define LEMON_TIME_MEASURE_H
21 21

	
22 22
///\ingroup timecount
23 23
///\file
24 24
///\brief Tools for measuring cpu usage
25 25

	
26 26
#ifdef WIN32
27
#ifndef WIN32_LEAN_AND_MEAN
28
#define WIN32_LEAN_AND_MEAN
29
#endif
30
#ifndef NOMINMAX
31
#define NOMINMAX
32
#endif
33
#include <windows.h>
34
#include <cmath>
27
#include <lemon/bits/windows.h>
35 28
#else
36 29
#include <unistd.h>
37 30
#include <sys/times.h>
38 31
#include <sys/time.h>
39 32
#endif
40 33

	
41 34
#include <string>
42 35
#include <fstream>
43 36
#include <iostream>
44 37

	
45 38
namespace lemon {
46 39

	
47 40
  /// \addtogroup timecount
48 41
  /// @{
49 42

	
50 43
  /// A class to store (cpu)time instances.
51 44

	
52 45
  /// This class stores five time values.
53 46
  /// - a real time
54 47
  /// - a user cpu time
55 48
  /// - a system cpu time
56 49
  /// - a user cpu time of children
57 50
  /// - a system cpu time of children
58 51
  ///
59 52
  /// TimeStamp's can be added to or substracted from each other and
60 53
  /// they can be pushed to a stream.
61 54
  ///
62 55
  /// In most cases, perhaps the \ref Timer or the \ref TimeReport
63 56
  /// class is what you want to use instead.
64 57

	
65 58
  class TimeStamp
66 59
  {
67 60
    double utime;
68 61
    double stime;
69 62
    double cutime;
70 63
    double cstime;
71 64
    double rtime;
72 65

	
73 66
    void _reset() {
74 67
      utime = stime = cutime = cstime = rtime = 0;
75 68
    }
76 69

	
77 70
  public:
78 71

	
79 72
    ///Read the current time values of the process
80 73
    void stamp()
81 74
    {
82 75
#ifndef WIN32
83 76
      timeval tv;
84 77
      gettimeofday(&tv, 0);
85 78
      rtime=tv.tv_sec+double(tv.tv_usec)/1e6;
86 79

	
87 80
      tms ts;
88 81
      double tck=sysconf(_SC_CLK_TCK);
89 82
      times(&ts);
90 83
      utime=ts.tms_utime/tck;
91 84
      stime=ts.tms_stime/tck;
92 85
      cutime=ts.tms_cutime/tck;
93 86
      cstime=ts.tms_cstime/tck;
94 87
#else
95
      static const double ch = 4294967296.0e-7;
96
      static const double cl = 1.0e-7;
97

	
98
      FILETIME system;
99
      GetSystemTimeAsFileTime(&system);
100
      rtime = ch * system.dwHighDateTime + cl * system.dwLowDateTime;
101

	
102
      FILETIME create, exit, kernel, user;
103
      if (GetProcessTimes(GetCurrentProcess(),&create, &exit, &kernel, &user)) {
104
        utime = ch * user.dwHighDateTime + cl * user.dwLowDateTime;
105
        stime = ch * kernel.dwHighDateTime + cl * kernel.dwLowDateTime;
106
        cutime = 0;
107
        cstime = 0;
108
      } else {
109
        rtime = 0;
110
        utime = 0;
111
        stime = 0;
112
        cutime = 0;
113
        cstime = 0;
114
      }
88
      bits::getWinProcTimes(rtime, utime, stime, cutime, cstime);
115 89
#endif
116 90
    }
117 91

	
118 92
    /// Constructor initializing with zero
119 93
    TimeStamp()
120 94
    { _reset(); }
121 95
    ///Constructor initializing with the current time values of the process
122 96
    TimeStamp(void *) { stamp();}
123 97

	
124 98
    ///Set every time value to zero
125 99
    TimeStamp &reset() {_reset();return *this;}
126 100

	
127 101
    ///\e
128 102
    TimeStamp &operator+=(const TimeStamp &b)
129 103
    {
130 104
      utime+=b.utime;
131 105
      stime+=b.stime;
132 106
      cutime+=b.cutime;
133 107
      cstime+=b.cstime;
134 108
      rtime+=b.rtime;
135 109
      return *this;
136 110
    }
137 111
    ///\e
138 112
    TimeStamp operator+(const TimeStamp &b) const
139 113
    {
140 114
      TimeStamp t(*this);
141 115
      return t+=b;
142 116
    }
143 117
    ///\e
144 118
    TimeStamp &operator-=(const TimeStamp &b)
145 119
    {
146 120
      utime-=b.utime;
147 121
      stime-=b.stime;
148 122
      cutime-=b.cutime;
149 123
      cstime-=b.cstime;
150 124
      rtime-=b.rtime;
151 125
      return *this;
152 126
    }
153 127
    ///\e
154 128
    TimeStamp operator-(const TimeStamp &b) const
155 129
    {
156 130
      TimeStamp t(*this);
157 131
      return t-=b;
158 132
    }
159 133
    ///\e
160 134
    TimeStamp &operator*=(double b)
161 135
    {
162 136
      utime*=b;
163 137
      stime*=b;
164 138
      cutime*=b;
165 139
      cstime*=b;
166 140
      rtime*=b;
167 141
      return *this;
168 142
    }
169 143
    ///\e
170 144
    TimeStamp operator*(double b) const
171 145
    {
172 146
      TimeStamp t(*this);
173 147
      return t*=b;
174 148
    }
175 149
    friend TimeStamp operator*(double b,const TimeStamp &t);
176 150
    ///\e
177 151
    TimeStamp &operator/=(double b)
178 152
    {
179 153
      utime/=b;
180 154
      stime/=b;
181 155
      cutime/=b;
182 156
      cstime/=b;
183 157
      rtime/=b;
184 158
      return *this;
185 159
    }
186 160
    ///\e
187 161
    TimeStamp operator/(double b) const
188 162
    {
189 163
      TimeStamp t(*this);
190 164
      return t/=b;
191 165
    }
192 166
    ///The time ellapsed since the last call of stamp()
193 167
    TimeStamp ellapsed() const
194 168
    {
195 169
      TimeStamp t(NULL);
196 170
      return t-*this;
197 171
    }
198 172

	
199 173
    friend std::ostream& operator<<(std::ostream& os,const TimeStamp &t);
200 174

	
201 175
    ///Gives back the user time of the process
202 176
    double userTime() const
203 177
    {
204 178
      return utime;
205 179
    }
206 180
    ///Gives back the system time of the process
207 181
    double systemTime() const
208 182
    {
209 183
      return stime;
210 184
    }
211 185
    ///Gives back the user time of the process' children
212 186

	
213 187
    ///\note On <tt>WIN32</tt> platform this value is not calculated.
214 188
    ///
215 189
    double cUserTime() const
216 190
    {
217 191
      return cutime;
218 192
    }
219 193
    ///Gives back the user time of the process' children
220 194

	
221 195
    ///\note On <tt>WIN32</tt> platform this value is not calculated.
222 196
    ///
223 197
    double cSystemTime() const
224 198
    {
225 199
      return cstime;
226 200
    }
227 201
    ///Gives back the real time
228 202
    double realTime() const {return rtime;}
229 203
  };
230 204

	
231 205
  TimeStamp operator*(double b,const TimeStamp &t)
232 206
  {
233 207
    return t*b;
234 208
  }
235 209

	
236 210
  ///Prints the time counters
237 211

	
238 212
  ///Prints the time counters in the following form:
239 213
  ///
240 214
  /// <tt>u: XX.XXs s: XX.XXs cu: XX.XXs cs: XX.XXs real: XX.XXs</tt>
241 215
  ///
242 216
  /// where the values are the
243 217
  /// \li \c u: user cpu time,
244 218
  /// \li \c s: system cpu time,
245 219
  /// \li \c cu: user cpu time of children,
246 220
  /// \li \c cs: system cpu time of children,
247 221
  /// \li \c real: real time.
248 222
  /// \relates TimeStamp
249 223
  /// \note On <tt>WIN32</tt> platform the cummulative values are not
250 224
  /// calculated.
251 225
  inline std::ostream& operator<<(std::ostream& os,const TimeStamp &t)
252 226
  {
253 227
    os << "u: " << t.userTime() <<
254 228
      "s, s: " << t.systemTime() <<
255 229
      "s, cu: " << t.cUserTime() <<
256 230
      "s, cs: " << t.cSystemTime() <<
257 231
      "s, real: " << t.realTime() << "s";
258 232
    return os;
259 233
  }
260 234

	
261 235
  ///Class for measuring the cpu time and real time usage of the process
262 236

	
263 237
  ///Class for measuring the cpu time and real time usage of the process.
264 238
  ///It is quite easy-to-use, here is a short example.
265 239
  ///\code
266 240
  /// #include<lemon/time_measure.h>
267 241
  /// #include<iostream>
268 242
  ///
269 243
  /// int main()
270 244
  /// {
271 245
  ///
272 246
  ///   ...
273 247
  ///
274 248
  ///   Timer t;
275 249
  ///   doSomething();
276 250
  ///   std::cout << t << '\n';
277 251
  ///   t.restart();
278 252
  ///   doSomethingElse();
279 253
  ///   std::cout << t << '\n';
280 254
  ///
281 255
  ///   ...
282 256
  ///
283 257
  /// }
284 258
  ///\endcode
285 259
  ///
286 260
  ///The \ref Timer can also be \ref stop() "stopped" and
287 261
  ///\ref start() "started" again, so it is possible to compute collected
288 262
  ///running times.
289 263
  ///
290 264
  ///\warning Depending on the operation system and its actual configuration
291 265
  ///the time counters have a certain (10ms on a typical Linux system)
292 266
  ///granularity.
293 267
  ///Therefore this tool is not appropriate to measure very short times.
294 268
  ///Also, if you start and stop the timer very frequently, it could lead to
295 269
  ///distorted results.
296 270
  ///
297 271
  ///\note If you want to measure the running time of the execution of a certain
298 272
  ///function, consider the usage of \ref TimeReport instead.
299 273
  ///
300 274
  ///\sa TimeReport
301 275
  class Timer
302 276
  {
303 277
    int _running; //Timer is running iff _running>0; (_running>=0 always holds)
304 278
    TimeStamp start_time; //This is the relativ start-time if the timer
305 279
                          //is _running, the collected _running time otherwise.
306 280

	
307 281
    void _reset() {if(_running) start_time.stamp(); else start_time.reset();}
308 282

	
309 283
  public:
310 284
    ///Constructor.
311 285

	
312 286
    ///\param run indicates whether or not the timer starts immediately.
313 287
    ///
314 288
    Timer(bool run=true) :_running(run) {_reset();}
315 289

	
316 290
    ///\name Control the state of the timer
317 291
    ///Basically a Timer can be either running or stopped,
318 292
    ///but it provides a bit finer control on the execution.
319 293
    ///The \ref lemon::Timer "Timer" also counts the number of
320 294
    ///\ref lemon::Timer::start() "start()" executions, and it stops
321 295
    ///only after the same amount (or more) \ref lemon::Timer::stop()
322 296
    ///"stop()"s. This can be useful e.g. to compute the running time
323 297
    ///of recursive functions.
324 298

	
325 299
    ///@{
326 300

	
327 301
    ///Reset and stop the time counters
328 302

	
329 303
    ///This function resets and stops the time counters
330 304
    ///\sa restart()
331 305
    void reset()
332 306
    {
333 307
      _running=0;
334 308
      _reset();
335 309
    }
336 310

	
337 311
    ///Start the time counters
338 312

	
339 313
    ///This function starts the time counters.
340 314
    ///
341 315
    ///If the timer is started more than ones, it will remain running
342 316
    ///until the same amount of \ref stop() is called.
343 317
    ///\sa stop()
344 318
    void start()
345 319
    {
346 320
      if(_running) _running++;
347 321
      else {
348 322
        _running=1;
349 323
        TimeStamp t;
350 324
        t.stamp();
351 325
        start_time=t-start_time;
352 326
      }
353 327
    }
354 328

	
355 329

	
356 330
    ///Stop the time counters
357 331

	
358 332
    ///This function stops the time counters. If start() was executed more than
359 333
    ///once, then the same number of stop() execution is necessary the really
360 334
    ///stop the timer.
361 335
    ///
362 336
    ///\sa halt()
363 337
    ///\sa start()
364 338
    ///\sa restart()
365 339
    ///\sa reset()
366 340

	
367 341
    void stop()
368 342
    {
369 343
      if(_running && !--_running) {
370 344
        TimeStamp t;
371 345
        t.stamp();
372 346
        start_time=t-start_time;
373 347
      }
374 348
    }
375 349

	
376 350
    ///Halt (i.e stop immediately) the time counters
377 351

	
378 352
    ///This function stops immediately the time counters, i.e. <tt>t.halt()</tt>
379 353
    ///is a faster
380 354
    ///equivalent of the following.
381 355
    ///\code
382 356
    ///  while(t.running()) t.stop()
383 357
    ///\endcode
384 358
    ///
385 359
    ///
386 360
    ///\sa stop()
387 361
    ///\sa restart()
388 362
    ///\sa reset()
389 363

	
390 364
    void halt()
391 365
    {
392 366
      if(_running) {
393 367
        _running=0;
394 368
        TimeStamp t;
395 369
        t.stamp();
396 370
        start_time=t-start_time;
397 371
      }
398 372
    }
399 373

	
400 374
    ///Returns the running state of the timer
401 375

	
402 376
    ///This function returns the number of stop() exections that is
403 377
    ///necessary to really stop the timer.
404 378
    ///For example the timer
405 379
    ///is running if and only if the return value is \c true
406 380
    ///(i.e. greater than
407 381
    ///zero).
408 382
    int running()  { return _running; }
409 383

	
410 384

	
411 385
    ///Restart the time counters
412 386

	
413 387
    ///This function is a shorthand for
414 388
    ///a reset() and a start() calls.
415 389
    ///
416 390
    void restart()
417 391
    {
418 392
      reset();
419 393
      start();
420 394
    }
421 395

	
422 396
    ///@}
423 397

	
424 398
    ///\name Query Functions for the ellapsed time
425 399

	
426 400
    ///@{
427 401

	
428 402
    ///Gives back the ellapsed user time of the process
429 403
    double userTime() const
430 404
    {
431 405
      return operator TimeStamp().userTime();
432 406
    }
433 407
    ///Gives back the ellapsed system time of the process
434 408
    double systemTime() const
435 409
    {
436 410
      return operator TimeStamp().systemTime();
437 411
    }
438 412
    ///Gives back the ellapsed user time of the process' children
439 413

	
440 414
    ///\note On <tt>WIN32</tt> platform this value is not calculated.
441 415
    ///
442 416
    double cUserTime() const
443 417
    {
444 418
      return operator TimeStamp().cUserTime();
445 419
    }
446 420
    ///Gives back the ellapsed user time of the process' children
447 421

	
448 422
    ///\note On <tt>WIN32</tt> platform this value is not calculated.
449 423
    ///
450 424
    double cSystemTime() const
451 425
    {
452 426
      return operator TimeStamp().cSystemTime();
453 427
    }
454 428
    ///Gives back the ellapsed real time
455 429
    double realTime() const
456 430
    {
457 431
      return operator TimeStamp().realTime();
458 432
    }
459 433
    ///Computes the ellapsed time
460 434

	
461 435
    ///This conversion computes the ellapsed time, therefore you can print
462 436
    ///the ellapsed time like this.
463 437
    ///\code
464 438
    ///  Timer t;
465 439
    ///  doSomething();
466 440
    ///  std::cout << t << '\n';
467 441
    ///\endcode
468 442
    operator TimeStamp () const
469 443
    {
470 444
      TimeStamp t;
471 445
      t.stamp();
472 446
      return _running?t-start_time:start_time;
473 447
    }
474 448

	
475 449

	
476 450
    ///@}
477 451
  };
478 452

	
479 453
  ///Same as Timer but prints a report on destruction.
480 454

	
481 455
  ///Same as \ref Timer but prints a report on destruction.
482 456
  ///This example shows its usage.
483 457
  ///\code
484 458
  ///  void myAlg(ListGraph &g,int n)
485 459
  ///  {
486 460
  ///    TimeReport tr("Running time of myAlg: ");
487 461
  ///    ... //Here comes the algorithm
488 462
  ///  }
489 463
  ///\endcode
490 464
  ///
491 465
  ///\sa Timer
492 466
  ///\sa NoTimeReport
493 467
  class TimeReport : public Timer
494 468
  {
495 469
    std::string _title;
496 470
    std::ostream &_os;
497 471
  public:
498 472
    ///Constructor
499 473

	
500 474
    ///Constructor.
501 475
    ///\param title This text will be printed before the ellapsed time.
502 476
    ///\param os The stream to print the report to.
503 477
    ///\param run Sets whether the timer should start immediately.
504 478
    TimeReport(std::string title,std::ostream &os=std::cerr,bool run=true)
505 479
      : Timer(run), _title(title), _os(os){}
506 480
    ///Destructor that prints the ellapsed time
507 481
    ~TimeReport()
508 482
    {
509 483
      _os << _title << *this << std::endl;
510 484
    }
511 485
  };
512 486

	
513 487
  ///'Do nothing' version of TimeReport
514 488

	
515 489
  ///\sa TimeReport
516 490
  ///
517 491
  class NoTimeReport
518 492
  {
519 493
  public:
520 494
    ///\e
521 495
    NoTimeReport(std::string,std::ostream &,bool) {}
522 496
    ///\e
523 497
    NoTimeReport(std::string,std::ostream &) {}
524 498
    ///\e
525 499
    NoTimeReport(std::string) {}
526 500
    ///\e Do nothing.
527 501
    ~NoTimeReport() {}
528 502

	
529 503
    operator TimeStamp () const { return TimeStamp(); }
530 504
    void reset() {}
531 505
    void start() {}
532 506
    void stop() {}
533 507
    void halt() {}
534 508
    int running() { return 0; }
535 509
    void restart() {}
536 510
    double userTime() const { return 0; }
537 511
    double systemTime() const { return 0; }
538 512
    double cUserTime() const { return 0; }
539 513
    double cSystemTime() const { return 0; }
540 514
    double realTime() const { return 0; }
541 515
  };
542 516

	
543 517
  ///Tool to measure the running time more exactly.
544 518

	
545 519
  ///This function calls \c f several times and returns the average
546 520
  ///running time. The number of the executions will be choosen in such a way
547 521
  ///that the full real running time will be roughly between \c min_time
548 522
  ///and <tt>2*min_time</tt>.
549 523
  ///\param f the function object to be measured.
550 524
  ///\param min_time the minimum total running time.
551 525
  ///\retval num if it is not \c NULL, then the actual
552 526
  ///        number of execution of \c f will be written into <tt>*num</tt>.
553 527
  ///\retval full_time if it is not \c NULL, then the actual
554 528
  ///        total running time will be written into <tt>*full_time</tt>.
555 529
  ///\return The average running time of \c f.
556 530

	
557 531
  template<class F>
558 532
  TimeStamp runningTimeTest(F f,double min_time=10,unsigned int *num = NULL,
559 533
                            TimeStamp *full_time=NULL)
560 534
  {
561 535
    TimeStamp full;
562 536
    unsigned int total=0;
563 537
    Timer t;
564 538
    for(unsigned int tn=1;tn <= 1U<<31 && full.realTime()<=min_time; tn*=2) {
565 539
      for(;total<tn;total++) f();
566 540
      full=t;
567 541
    }
568 542
    if(num) *num=total;
569 543
    if(full_time) *full_time=full;
570 544
    return full/total;
571 545
  }
572 546

	
573 547
  /// @}
574 548

	
575 549

	
576 550
} //namespace lemon
577 551

	
578 552
#endif //LEMON_TIME_MEASURE_H
0 comments (0 inline)