-
Notifications
You must be signed in to change notification settings - Fork 2
/
MCFgen.hpp
158 lines (123 loc) · 4.32 KB
/
MCFgen.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/***** Useful, non-bio-specific C++ functions *****/
/* Written by Martin C Frith */
/* I intend that anyone who finds this code useful be free to use,
modify, or redistribute it without any restrictions. Naturally, I
hope it will not be used for evil purposes. */
// Basically, these are functions that I think should be
// in the standard library but aren't
// Better versions of many of these functions probably
// exist in libraries such as boost
#ifndef MCF_GEN_H
#define MCF_GEN_H
#include <cassert>
#include <cstdlib>
#include <iostream> // die
#include <iterator>
#include <numeric> // accumulate
#include <sstream>
#include <string>
#include <vector>
namespace mcf {
// convert any type to a string, with default formatting
template <class T> std::string tostring(T x);
// perl-style die
void die(const std::string &message);
// return x to the power of y
// only use this when S, T are integral types and y >= 0
// doesn't check for overflow!!
// pow() is dangerous for integers because it uses floats
template <class S, class T> S int_pow(S x, T y);
template <class T> void reserve_or_die(std::vector<T> &v, unsigned n);
// return true if the range equals its reverse
template <class It> bool is_reverse(It start, It end);
// normalize a range (make it sum to 1)
// no guarantee that the answer will be exactly 1
// the range had better contain floating-point values!
template <class It> void normalize(It start, It end);
}
template <class T> inline std::string mcf::tostring(T x) {
std::ostringstream temp;
temp << x;
return temp.str();
}
inline void mcf::die(const std::string &message) {
std::cerr << message << std::endl;
exit(EXIT_FAILURE);
}
template <class S, class T> inline S mcf::int_pow(S x, T y) {
S ans = 1;
for (; y > 0; --y)
ans *= x;
return ans;
}
template <class T>
inline void mcf::reserve_or_die(std::vector<T> &v, unsigned n) {
v.reserve(n);
if (v.capacity() < n)
die("Out of memory: couldn't reserve " + tostring(n) +
" vector elements of size " + tostring(sizeof(T)));
}
template <class It> bool mcf::is_reverse(It start, It end) {
while (end > start)
if (*(start++) != *(--end))
return false;
return true;
}
template <class It> void mcf::normalize(It start, It end) {
typename std::iterator_traits<It>::value_type tot =
std::accumulate(start, end, // added typename 16-2-2005:
typename std::iterator_traits<It>::value_type(0));
assert(tot != 0); // doesn't like being prefixed by std::
tot = 1 / tot;
for (; start < end; ++start)
*start *= tot;
}
/* Functions below here deprecated */
#include <cstdlib> // malloc, rand, RAND_MAX
// use my matrix class instead!!
// allocate an x by y matrix:
// allocates just 1 chunk of memory, so can free it with free()
// (appalling low-level hackery!)
// is it possible to use new instead of malloc ???
template <class T> T **new_matrix(unsigned x, unsigned y) {
T **mat = (T **)malloc(x * (sizeof(void *) + y * sizeof(T)));
T *p = (T *)(mat + x);
for (unsigned i = 0u; i < x; ++i, p += y)
mat[i] = p;
return mat;
}
/*** functions for making random choices ***/
// random stuff is tricky!!! Use boost instead(?)
// return a random double between 0 (inclusive) and n (exclusive)
inline double rand(double n) { return rand() / (RAND_MAX + 1.0) * n; }
// return a random float between 0 (inclusive) and n (exclusive)
// the loop seems to be needed for float, but not double
inline float rand(float n) {
float r;
do {
r = float(rand(double(n)));
} while (r == n);
return r;
}
// return a random unsigned int between 0 (inclusive) and n (exclusive)
// from C FAQ, 13.16
inline unsigned rand(unsigned n) { return unsigned(rand(double(n))); }
// randomly choose an element in the range [start end)
// weighted by the values of the elements
// the total of the element values is passed in & assumed to be correct
// the "end" is theoretically redundant, but if T is a floating type,
// the "total" might be slightly imprecise
template <class It, class T> It random_choice(It start, It end, T total) {
// choose a random number between 0 (inclusive) and total (exclusive):
T choice = rand(total);
T x = T(0);
--end; // if we get to the last element, we will choose it for sure
while (start < end) {
x += *start;
if (x > choice)
break;
++start;
}
return start;
}
#endif