Codebase list libhpptools / e3d2bb3
Imported Upstream version 1.1.1 Andreas Tille 7 years ago
10 changed file(s) with 304 addition(s) and 80 deletion(s). Raw diff Collapse all Expand all
3838
3939 - =for_each[_it][_advance]=: Apply functor to elements in range. Options: take iterator pair or range as input; pass iterator instead of element to functor; store next iterator prior to applying functor (e.g. use: remove elements from a list in one pass.)
4040
41 - =(min|max|minmax)[_value]_of=: Find min and/or max in range. Options: take iterator pair or range as input; optionally use functor to extract key; return iterator or value.
41 - =(min|max|minmax)[_value]_of=: Find min and/or max in range. Options: take iterator pair or range as input; optionally use functor to extract key; return iterator(s) or value(s).
4242
4343 - =mean_stdv_of=: Find mean and sample stdv of elements in range. Options: take iterator pair or range as input; optionally use functor to extract key.
4444
45 - =(equal|all|any)_of=: Check range of elements are equal, or that all are true, or that at least one is true. Options: take iterator pair or range as input; optionally use functor to extract key.
45 - =(equal|all|any)_of=: Check that all elements in a range are equal, or that all are true, or that at least one is true. Options: take iterator pair or range as input; optionally use functor to extract key.
4646
4747 - =os_join=: Use =operator <<= overloads to print range or to convert it to string using a custom separator. Options: take iterator pair or range as input; optionally use functor to extract key.
4848
4949 #+BEGIN_EXAMPLE
5050 #include "alg.hpp"
5151 ...
52 std::vector< int > v{3, 6, 18};
53 bool equal_mod_3 = alg::equal_of(v, [] (int i) { return i%3; }); // true
54 std::cout << "v: " << alg::os_join(v, ", ") << std::endl; // prints "v: 3, 6, 18"
52 std::list<int> l{3, 6, 10, 18};
53 // erase elements == 0 mod 5 => l == {3, 6, 18}
54 alg::for_each_it_advance(l, [&l] (std::list<int>::iterator it) { if (*it%5 == 0) l.erase(it); });
55 // iterator to minimum value mod 5 => iterator to 6
56 auto it_min_val_mod_5 = alg::min_of(l, [] (int i) { return i%5; });
57 // all equal mod 3 => true
58 bool equal_mod_3 = alg::equal_of(l, [] (int i) { return i%3; });
59 // to ostream => "l: 3, 6, 18"
60 std::cout << "l: " << alg::os_join(l, ", ") << std::endl;
5561 #+END_EXAMPLE
5662
5763 ***** logsum
00 SHELL := /bin/bash
1
2 DIR =
31
42 .PHONY: all sample clean
53
64 all: benchmark-logsum
75
8 benchmark-logsum: ../include/logsum.hpp ${DIR}/logsum.h ${DIR}/logsum.cpp
9 g++ -std=c++11 -O2 -Wall -Wextra -pedantic -I ${DIR} -DBENCHMARK_p7LOGSUM -x c++ ../include/logsum.hpp ${DIR}/logsum.cpp -o $@
6 benchmark-logsum: ../include/logsum.hpp
7 g++ -std=c++11 -O2 -Wall -Wextra -pedantic -DBENCHMARK_p7LOGSUM -x c++ ../include/logsum.hpp -o $@
108
119 run: benchmark-logsum
1210 ./benchmark-logsum 42 0
0 SHELL := /bin/bash
1
2 .PHONY: all sample clean
3
4 all: sample-logdiff
5
6 sample-logdiff: ../include/logdiff.hpp
7 g++ -std=c++11 -O0 -g3 -ggdb -fno-eliminate-unused-debug-types -Wall -Wextra -pedantic -DSAMPLE_LOGDIFF -x c++ $< -o $@
8
9 sample: sample-logdiff
10 ./sample-logdiff .5 .2
11
12 clean:
13 rm -rf sample-logdiff
44 all: test-alg
55
66 %: %.cpp
7 g++ -std=c++11 -O0 -g3 -ggdb -fno-eliminate-unused-debug-types -Wall -Wextra -pedantic -I../include -o $@ $^ -lz
7 ${DOCKER_CMD} ${CXX} -std=c++11 -O0 -g3 -ggdb -fno-eliminate-unused-debug-types -Wall -Wextra -pedantic -I../include -o $@ $^ -lz
88
99 test: test-alg
10 ./test-alg
10 ${DOCKER_CMD} ./test-alg
1111
1212 clean:
1313 rm -rf test-alg
44 all: test-strict_fstream ztxtpipe zpipe zc
55
66 %: %.cpp
7 g++ -std=c++11 -O0 -g3 -ggdb -fno-eliminate-unused-debug-types -Wall -Wextra -pedantic -I../include -o $@ $^ -lz
7 ${DOCKER_CMD} ${CXX} -std=c++11 -O0 -g3 -ggdb -fno-eliminate-unused-debug-types -Wall -Wextra -pedantic -I../include -o $@ $^ -lz
88
99 test: ztxtpipe zpipe zc
10 diff -q ztxtpipe.cpp <(./ztxtpipe <ztxtpipe.cpp)
11 diff -q ztxtpipe.cpp <(gzip <ztxtpipe.cpp | ./ztxtpipe)
12 diff -q ztxtpipe.cpp <(gzip -9 <ztxtpipe.cpp | ./ztxtpipe)
13 diff -q <(cat ztxtpipe.cpp ztxtpipe.cpp) <(cat ztxtpipe.cpp ztxtpipe.cpp | gzip | ./ztxtpipe)
14 diff -q <(cat ztxtpipe.cpp ztxtpipe.cpp) <({ gzip <ztxtpipe.cpp; gzip <ztxtpipe.cpp; } | ./ztxtpipe)
15 diff -q zpipe.cpp <(./zpipe <zpipe.cpp)
16 diff -q zpipe.cpp <(gzip <zpipe.cpp | ./zpipe)
17 diff -q zpipe.cpp <(gzip -9 <zpipe.cpp | ./zpipe)
18 diff -q <(cat zpipe.cpp zpipe.cpp) <(cat zpipe.cpp zpipe.cpp | gzip | ./zpipe)
19 diff -q <(cat zpipe.cpp zpipe.cpp) <({ gzip <zpipe.cpp; gzip <zpipe.cpp; } | ./zpipe)
20 diff -q <(<zpipe.cpp | gzip) <(<zpipe.cpp | gzip | gzip | ./zpipe)
21 diff -q zc.cpp <(./zc <zc.cpp)
22 diff -q zc.cpp <(./zc - <zc.cpp)
23 diff -q zc.cpp <(./zc - - <zc.cpp)
24 diff -q zc.cpp <(./zc zc.cpp)
25 diff -q zc.cpp <(<zc.cpp gzip | ./zc)
26 diff -q zc.cpp <(<zc.cpp gzip | ./zc -)
27 diff -q zc.cpp <(<zc.cpp gzip | ./zc - -)
28 diff -q zc.cpp <(./zc <(<zc.cpp gzip))
29 diff -q zc.cpp <(<zc.cpp ./zc -c | zcat)
30 diff -q zc.cpp <(<zc.cpp ./zc -c - | zcat)
31 diff -q zc.cpp <(<zc.cpp ./zc -c - - | zcat)
32 diff -q zc.cpp <(./zc -c zc.cpp | zcat)
33 diff -q <(cat zc.cpp zc.cpp) <(./zc -c zc.cpp - <zc.cpp | zcat)
34 diff -q <(cat zc.cpp zc.cpp) <(./zc -c - zc.cpp <zc.cpp | zcat)
35 diff -q <(cat zc.cpp zc.cpp) <(./zc -c zc.cpp zc.cpp | zcat)
36 diff -q <(cat zc.cpp zc.cpp) <({ ./zc -c zc.cpp; ./zc -c zc.cpp; } | zcat)
37 diff -q <(cat zc.cpp zc.cpp) <({ gzip <zc.cpp; ./zc -c zc.cpp; } | zcat)
38 diff -q <(cat zc.cpp zc.cpp) <({ ./zc -c zc.cpp; gzip <zc.cpp; } | zcat)
10 cat ztxtpipe.cpp | ${DOCKER_CMD} ./ztxtpipe | diff -q - ztxtpipe.cpp
11 cat ztxtpipe.cpp | gzip | ${DOCKER_CMD} ./ztxtpipe | diff -q - ztxtpipe.cpp
12 cat ztxtpipe.cpp ztxtpipe.cpp | gzip | ${DOCKER_CMD} ./ztxtpipe | diff -q - <(cat ztxtpipe.cpp ztxtpipe.cpp)
13 { gzip <ztxtpipe.cpp; gzip <ztxtpipe.cpp; } | ${DOCKER_CMD} ./ztxtpipe | diff -q - <(cat ztxtpipe.cpp ztxtpipe.cpp)
14
15 cat zpipe.cpp | ${DOCKER_CMD} ./zpipe | diff -q - zpipe.cpp
16 cat zpipe.cpp | gzip | ${DOCKER_CMD} ./zpipe | diff -q - zpipe.cpp
17 cat zpipe.cpp zpipe.cpp | gzip | ${DOCKER_CMD} ./zpipe | diff -q - <(cat zpipe.cpp zpipe.cpp)
18 { gzip <zpipe.cpp; gzip <zpipe.cpp; } | ${DOCKER_CMD} ./zpipe | diff -q - <(cat zpipe.cpp zpipe.cpp)
19 cat zpipe.cpp | gzip | gzip | ${DOCKER_CMD} ./zpipe | diff -q - <(cat zpipe.cpp | gzip)
20
21 cat zc.cpp | ${DOCKER_CMD} ./zc | diff -q - zc.cpp
22 cat zc.cpp | ${DOCKER_CMD} ./zc - | diff -q - zc.cpp
23 cat zc.cpp | ${DOCKER_CMD} ./zc - - | diff -q - zc.cpp
24 ${DOCKER_CMD} ./zc zc.cpp | diff -q - zc.cpp
25 cat zc.cpp | gzip | ${DOCKER_CMD} ./zc | diff -q - zc.cpp
26 cat zc.cpp | gzip | ${DOCKER_CMD} ./zc - | diff -q - zc.cpp
27 cat zc.cpp | gzip | ${DOCKER_CMD} ./zc - - | diff -q - zc.cpp
28
29 cat zc.cpp | ${DOCKER_CMD} ./zc -c | zcat | diff -q - zc.cpp
30 cat zc.cpp | ${DOCKER_CMD} ./zc -c - | zcat | diff -q - zc.cpp
31 cat zc.cpp | ${DOCKER_CMD} ./zc -c - - | zcat | diff -q - zc.cpp
32 ${DOCKER_CMD} ./zc -c zc.cpp | zcat | diff -q - zc.cpp
33
34 cat zc.cpp | ${DOCKER_CMD} ./zc -c zc.cpp - | zcat | diff -q - <(cat zc.cpp zc.cpp)
35 cat zc.cpp | ${DOCKER_CMD} ./zc -c - zc.cpp | zcat | diff -q - <(cat zc.cpp zc.cpp)
36 ${DOCKER_CMD} ./zc -c zc.cpp zc.cpp | zcat | diff -q - <(cat zc.cpp zc.cpp)
37 { ${DOCKER_CMD} ./zc -c zc.cpp; ${DOCKER_CMD} ./zc -c zc.cpp; } | zcat | diff -q - <(cat zc.cpp zc.cpp)
38 { ${DOCKER_CMD} ./zc -c zc.cpp; gzip <zc.cpp; } | zcat | diff -q - <(cat zc.cpp zc.cpp)
39 { gzip <zc.cpp; ${DOCKER_CMD} ./zc -c zc.cpp; } | zcat | diff -q - <(cat zc.cpp zc.cpp)
3940 @echo "all passed"
4041
4142 clean:
6767 #define __ALG_HPP
6868
6969 #include <algorithm>
70 #include <cmath>
7071 #include <iostream>
72 #include <iterator>
73 #include <numeric>
7174 #include <sstream>
7275 #include <type_traits>
7376
289292 * @param fn Functor used to obtain key from value.
290293 */
291294 template < class Forward_Iterator, class Unary_Function = detail::Identity >
292 typename std::result_of< Unary_Function(typename Forward_Iterator::value_type) >::type
295 typename std::result_of< Unary_Function(typename std::iterator_traits< Forward_Iterator >::value_type) >::type
293296 min_value_of(Forward_Iterator first, Forward_Iterator last, Unary_Function&& fn = Unary_Function())
294297 {
295298 auto it = min_of(first, last, std::forward< Unary_Function >(fn));
296299 return it != last
297300 ? fn(*it)
298 : typename std::result_of< Unary_Function(typename Forward_Iterator::value_type) >::type();
301 : typename std::result_of< Unary_Function(typename std::iterator_traits< Forward_Iterator >::value_type) >::type();
299302 }
300303
301304 /**
306309 template < class Forward_Range, class Unary_Function = detail::Identity >
307310 auto
308311 min_value_of(Forward_Range&& rg, Unary_Function&& fn = Unary_Function())
309 -> typename std::result_of< Unary_Function(typename decltype(rg.begin())::value_type) >::type
312 -> typename std::result_of< Unary_Function(typename std::iterator_traits< decltype(rg.begin()) >::value_type) >::type
310313 {
311314 return min_value_of(rg.begin(), rg.end(), std::forward< Unary_Function >(fn));
312315 }
356359 * @param fn Functor used to obtain key from value.
357360 */
358361 template < class Forward_Iterator, class Unary_Function = detail::Identity >
359 typename std::result_of< Unary_Function(typename Forward_Iterator::value_type) >::type
362 typename std::result_of< Unary_Function(typename std::iterator_traits< Forward_Iterator >::value_type) >::type
360363 max_value_of(Forward_Iterator first, Forward_Iterator last, Unary_Function&& fn = Unary_Function())
361364 {
362365 auto it = max_of(first, last, std::forward< Unary_Function >(fn));
363366 return it != last
364367 ? fn(*it)
365 : typename std::result_of< Unary_Function(typename Forward_Iterator::value_type) >::type();
368 : typename std::result_of< Unary_Function(typename std::iterator_traits< Forward_Iterator >::value_type) >::type();
366369 }
367370
368371 /**
373376 template < class Forward_Range, class Unary_Function = detail::Identity >
374377 auto
375378 max_value_of(Forward_Range&& rg, Unary_Function&& fn = Unary_Function())
376 -> typename std::result_of< Unary_Function(typename decltype(rg.begin())::value_type) >::type
379 -> typename std::result_of< Unary_Function(typename std::iterator_traits< decltype(rg.begin()) >::value_type) >::type
377380 {
378381 return max_value_of(rg.begin(), rg.end(), std::forward< Unary_Function >(fn));
379382 }
427430 * @param fn Functor used to obtain key from value.
428431 */
429432 template < class Forward_Iterator, class Unary_Function = detail::Identity >
430 std::pair< typename std::result_of< Unary_Function(typename Forward_Iterator::value_type) >::type,
431 typename std::result_of< Unary_Function(typename Forward_Iterator::value_type) >::type >
433 std::pair< typename std::result_of< Unary_Function(typename std::iterator_traits< Forward_Iterator >::value_type) >::type,
434 typename std::result_of< Unary_Function(typename std::iterator_traits< Forward_Iterator >::value_type) >::type >
432435 minmax_value_of(Forward_Iterator first, Forward_Iterator last, Unary_Function&& fn = Unary_Function())
433436 {
434437 auto p = minmax_of(first, last, std::forward< Unary_Function >(fn));
435438 return p.first != last
436439 ? std::make_pair(fn(*p.first), fn(*p.second))
437 : std::make_pair(typename std::result_of< Unary_Function(typename Forward_Iterator::value_type) >::type(),
438 typename std::result_of< Unary_Function(typename Forward_Iterator::value_type) >::type());
440 : std::make_pair(typename std::result_of< Unary_Function(typename std::iterator_traits< Forward_Iterator >::value_type) >::type(),
441 typename std::result_of< Unary_Function(typename std::iterator_traits< Forward_Iterator >::value_type) >::type());
439442 }
440443
441444 /**
446449 template < class Forward_Range, class Unary_Function = detail::Identity >
447450 auto
448451 minmax_value_of(Forward_Range&& rg, Unary_Function&& fn = Unary_Function())
449 -> std::pair< typename std::result_of< Unary_Function(typename decltype(rg.begin())::value_type) >::type,
450 typename std::result_of< Unary_Function(typename decltype(rg.begin())::value_type) >::type >
452 -> std::pair< typename std::result_of< Unary_Function(typename std::iterator_traits< decltype(rg.begin()) >::value_type) >::type,
453 typename std::result_of< Unary_Function(typename std::iterator_traits< decltype(rg.begin()) >::value_type) >::type >
451454 {
452455 return minmax_value_of(rg.begin(), rg.end(), std::forward< Unary_Function >(fn));
453456 }
623626 */
624627
625628 #include <vector>
629 #include <array>
626630
627631 using namespace std;
628632 using namespace alg;
629633
630634 int main()
631635 {
632 vector< unsigned > v{ 42, 1, 15 };
636 array< array< unsigned, 3 >, 3 > v2 = {{ {{ 42, 1, 15 }}, {{1, 2, 3}}, {{4, 5, 6}} }};
637 array< unsigned, 3 >& v = v2[0];
633638 cout << "v: " << os_join(v.begin(), v.end(), ", ") << endl;
634639 cout << "v[0]: " << os_join(v.begin(), v.begin() + 1, ", ") << endl;
635640 cout << "v+1: " << os_join(v.begin(), v.end(), ", ", [] (unsigned i) { return i + 1; }) << endl;
638643 cout << "u: " << os_join(vector< int >{ 5, 17, 6 }, ";") << endl;
639644 string s = os_join(vector< char >{ 'a', 'b', 'c' }, "-");
640645 cout << "s: " << s << endl;
646 cout << "min: " << min_value_of(v) << endl;
647 cout << "max: " << max_value_of(v) << endl;
648 cout << "minmax: " << minmax_value_of(v).first << "," << minmax_value_of(v).second << endl;
641649 }
642650
643651 #endif
0 //
1 // logdiff -- inspired by Sean Eddy's fast table-driven log sum
2 //
3 // The MIT License (MIT)
4 //
5 // (C) Matei David, Ontario Institute for Cancer Research, 2015
6 //
7
8 #ifndef __LOGDIFF_HPP
9 #define __LOGDIFF_HPP
10
11 #include <algorithm>
12 #include <cassert>
13 #include <cmath>
14
15 /*
16 * LOGDIFF_SCALE defines the precision of the calculation; the
17 * default of 1000.0 means rounding differences to the nearest 0.001
18 * nat. LOGDIFF_TBL defines the size of the lookup table; the
19 * default of 16000 means entries are calculated for differences of 0
20 * to 16.000 nats (when LOGDIFF_SCALE is 1000.0).
21 */
22 #define LOGDIFF_TBL 16000
23 #define LOGDIFF_SCALE 1000.0f
24
25 namespace logdiff
26 {
27
28 namespace detail
29 {
30
31 struct LogDiff_Helper
32 {
33 /* Function: table()
34 * Synposis: Holds the main lookup table used in logspace diff computations.
35 *
36 * Purpose: Encapsulate static array inside a function to avoid the need for a separate definition.
37 */
38 static inline float* table(void)
39 {
40 static float _table[LOGDIFF_TBL]; /* LOGDIFF_TBL=16000: (A-B) = 0..16 nats, steps of 0.001 */
41 return _table;
42 }
43
44 /* Function: init()
45 * Synopsis: Initialize the logdiff table.
46 *
47 * Purpose: Initialize the logdiff lookup table for logdiff().
48 * This function must be called once before any
49 * call to logdiff().
50 *
51 * Note: The precision of the lookup table is determined
52 * by the compile-time <LOGDIFF_TBL> constant.
53 *
54 * Returns: true on success.
55 */
56 static bool init()
57 {
58 static bool first_time = true;
59 if (not first_time)
60 {
61 return true;
62 }
63 first_time = false;
64
65 for (unsigned i = 0; i < LOGDIFF_TBL; i++)
66 {
67 auto x = -((double) i / LOGDIFF_SCALE);
68 auto e_x = std::exp(x);
69 table()[i] = std::log(1.0 - e_x);
70 }
71
72 return true;
73 }
74
75 /* Function: logdiff()
76 * Synopsis: Approximate $\log(e^a - e^b)$.
77 *
78 * Purpose: Returns a fast table-driven approximation to
79 * $\log(e^a - e^b)$.
80 *
81 * Either <a> or <b> (or both) may be $-\infty$,
82 * but neither may be $+\infty$ or <NaN>.
83 *
84 * Note: This function is a critical optimization target, because
85 * it's in the inner loop of generic Forward() algorithms.
86 */
87 static inline float logdiff(float a, float b)
88 {
89 if (a < b) std::swap(a, b);
90 return logdiff_nocomp(a, b);
91 }
92 static inline float logdiff_nocomp(float a, float b)
93 {
94 // static object whose constructor initializes the lookup table
95 static Table_Initializer _init;
96 (void)_init;
97
98 return (b == -INFINITY or a - b >= (float)(LOGDIFF_TBL - 1) / LOGDIFF_SCALE)
99 ? a
100 : a + table()[(int)((a - b) * LOGDIFF_SCALE)];
101 }
102
103 /* Function: logdiff_error()
104 * Synopsis: Compute absolute error in probability from logdiff.
105 *
106 * Purpose: Compute the absolute error in probability space
107 * resulting from logdiff()'s table lookup:
108 * approximation result - exact result.
109 */
110 static float logdiff_error(float a, float b)
111 {
112 if (a < b) std::swap(a, b);
113 return logdiff_error_nocomp(a, b);
114 }
115 static float logdiff_error_nocomp(float a, float b)
116 {
117 assert(a >= b);
118 if (a == b) return 0.0;
119 float approx = logdiff_nocomp(a, b);
120 float exact = std::log(std::exp(a) - std::exp(b));
121 return std::exp(approx) - std::exp(exact);
122 }
123
124 /* Struct: Table_Initializer
125 * Purpose: Initialize the lookup table on construction.
126 */
127 struct Table_Initializer
128 {
129 Table_Initializer()
130 {
131 init();
132 }
133 }; // struct Table_Initializer
134 }; // struct LogDiff_Helper
135
136 } // namespace detail
137
138 /*
139 * Publish main methods outside of the helper struct.
140 */
141 inline float LogDiff(float a, float b) { return detail::LogDiff_Helper::logdiff(a, b); }
142 inline float LogDiffError(float a, float b) { return detail::LogDiff_Helper::logdiff_error(a, b); }
143
144 } // namespace logdiff
145
146 #endif
147
148 #ifdef SAMPLE_LOGDIFF
149
150 /*
151
152 g++ -std=c++11 -DSAMPLE_LOGDIFF -x c++ logdiff.hpp -o sample-logdiff
153
154 */
155
156 #include <iostream>
157 #include <sstream>
158
159 using namespace std;
160 using namespace logdiff;
161
162 int main(int argc, char* argv[])
163 {
164 if (argc != 3)
165 {
166 cerr << "use: " << argv[0] << " <a> <b>" << endl;
167 return EXIT_FAILURE;
168 }
169
170 float a;
171 float b;
172 float result;
173
174 istringstream(argv[1]) >> a;
175 istringstream(argv[2]) >> b;
176
177 result = LogDiff(a, b);
178 cout << "logdiff(" << a << ", " << b << ") = " << result << endl;
179
180 result = log(exp(a) - exp(b));
181 cout << "log(exp(" << a << ") - exp(" << b << ")) = " << result << endl;
182
183 cout << "Absolute error in probability: " << LogDiffError(a, b) << endl;
184 }
185
186 #endif
252252 // we need 2-level indirection in order to trigger expansion after token pasting
253253 // http://stackoverflow.com/questions/1597007/creating-c-macro-with-and-line-token-concatenation-with-positioning-macr
254254 // http://stackoverflow.com/a/11763196/717706
255 #ifdef WIN32
256 #define __EXPAND(...) __VA_ARGS__
257 #define __LOG_aux2(N, ...) __EXPAND(__LOG_ ## N (__VA_ARGS__))
258 #else
255259 #define __LOG_aux2(N, ...) __LOG_ ## N (__VA_ARGS__)
260 #endif
261
256262 #define __LOG_aux1(N, ...) __LOG_aux2(N, __VA_ARGS__)
257263
258264 #define __NARGS_AUX(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, ...) _9
265
266 #ifdef WIN32
267 #define __NARGS(...) __EXPAND(__NARGS_AUX(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0))
268 #else
259269 #define __NARGS(...) __NARGS_AUX(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0)
270 #endif
260271
261272 #ifndef LOG_FACILITY
262273 #define LOG_FACILITY "main"
142142 {
143143 // static object whose constructor initializes the lookup table
144144 static Table_Initializer _init;
145 (void)_init;
145146
146147 const float max = ESL_MAX(a, b);
147148 const float min = ESL_MIN(a, b);
148149
149 return (min == -eslINFINITY || (max-min) >= 15.7f)
150 return (min == -eslINFINITY or max - min >= (float)(p7_LOGSUM_TBL - 1) / p7_LOGSUM_SCALE)
150151 ? max
151 : max + flogsum_lookup()[(int)((max-min)*p7_LOGSUM_SCALE)];
152 : max + flogsum_lookup()[(int)((max - min) * p7_LOGSUM_SCALE)];
152153 }
153154
154155 /* Function: p7_FLogsumError()
258259 #include <chrono>
259260 #include <iostream>
260261 #include <random>
261 #include <set>
262 #include <deque>
262263 #include <sstream>
263264 #include <vector>
264265
265 #include "logsum.h"
266
267266 using namespace std;
267 using namespace logsum;
268268
269269 int main(int argc, char* argv[])
270270 {
271271 if (argc < 3)
272272 {
273273 cerr << "use: " << argv[0] << " <seed> <version>" << endl
274 << "where <version> is 0 for old, 1 for new" << endl;
274 << "where <version> means:" << endl
275 << " 0: use exp&log" << endl
276 << " 1: use table lookup" << endl;
275277 return EXIT_FAILURE;
276278 }
277279 size_t seed = 0;
284286 }
285287 clog << "seed: " << seed << endl;
286288 clog << "version: " << version << endl;
287 const unsigned n = 1000000;
288 set< float > s;
289 const unsigned n = 100000000;
290 std::deque< std::pair< float, float > > s;
289291 mt19937 rg(seed);
290292 uniform_real_distribution< float > unif;
291293 for (unsigned i = 0; i < n; ++i)
292294 {
293 s.insert(unif(rg));
294 }
295 p7_FLogsumInit();
295 s.emplace_back(unif(rg), unif(rg));
296 }
297 float res = 0.0;
296298
297299 // start timer
298300 auto start_time = chrono::high_resolution_clock::now();
299301
300302 if (version == 0)
301303 {
302 while (s.size() > 1)
304 for (unsigned i = 0; i < s.size(); ++i)
303305 {
304 float a = *s.begin();
305 s.erase(s.begin());
306 float b = *s.begin();
307 s.erase(s.begin());
308 s.insert(::p7_FLogsum(a, b));
306 float& a = s[i].first;
307 float& b = s[i].second;
308 res = std::log(std::exp(a) + std::exp(b));
309 (void)res;
309310 }
310311 }
311312 else if (version == 1)
312313 {
313 while (s.size() > 1)
314 for (unsigned i = 0; i < s.size(); ++i)
314315 {
315 float a = *s.begin();
316 s.erase(s.begin());
317 float b = *s.begin();
318 s.erase(s.begin());
319 s.insert(logsum::p7_FLogsum(a, b));
316 float& a = s[i].first;
317 float& b = s[i].second;
318 res = logsum::p7_FLogsum(a, b);
319 (void)res;
320320 }
321321 }
322322
323323 // end timer
324324 auto end_time = chrono::high_resolution_clock::now();
325325
326 cout << "time: " << chrono::duration_cast< chrono::milliseconds >(end_time - start_time).count() << endl
327 << "result: " << *s.begin() << endl;
326 cout << "time: " << chrono::duration_cast< chrono::milliseconds >(end_time - start_time).count() << endl;
328327 }
329328
330329 #endif
6666 assert(not std::isnan(b));
6767 _val_set.erase(_val_set.begin());
6868 #ifdef LOG
69 if (b - a > 15.7 and b > -80)
69 if (not std::isinf(a) and b - a > 15.7 and b > -80)
7070 {
7171 LOG("logsumset", warning)
7272 << "precision loss: a=" << a << " b=" << b << std::endl;