21 #define BOOST_TEST_MODULE libjmmcg_tests
22 #include <boost/test/included/unit_test.hpp>
24 #include "core/thread_pool_workers.hpp"
29 #include <boost/mpl/assert.hpp>
30 #include <boost/static_assert.hpp>
31 #include <boost/type_traits.hpp>
32 #include <boost/scoped_ptr.hpp>
33 #include <boost/shared_ptr.hpp>
34 #include <boost/tr1/array.hpp>
44 using namespace libjmmcg;
62 template<
class V,
unsigned int W,
unsigned int H, V Init>
77 friend std::ostream &
__fastcall operator<<(
std::ostream &os,
element_type const &e)
noexcept(
false) {
78 os<<
std::hex<<e.value<<
std::dec;
111 return f.element->value>s.element->value;
118 return ((screen.begin()+pt.x)->begin()+pt.y);
121 return ((screen.begin()+pt.x)->begin()+pt.y);
125 return screen.begin()->begin();
129 return ((screen.end()-1)->end()-1);
137 const const_neighbourhood_type ret={
138 (inside(point_type(p.x, p.y+1)) ?
typename const_neighbourhood_type::value_type(point_type(p.x, p.y+1), find(point_type(p.x, p.y+1))) :
typename const_neighbourhood_type::value_type(screen.begin()->end())),
139 (inside(point_type(p.x+1, p.y+1)) ?
typename const_neighbourhood_type::value_type(point_type(p.x+1, p.y+1), find(point_type(p.x+1, p.y+1))) :
typename const_neighbourhood_type::value_type(screen.begin()->end())),
140 (inside(point_type(p.x+1, p.y)) ?
typename const_neighbourhood_type::value_type(point_type(p.x+1, p.y), find(point_type(p.x+1, p.y))) :
typename const_neighbourhood_type::value_type(screen.begin()->end())),
141 (inside(point_type(p.x+1, p.y-1)) ?
typename const_neighbourhood_type::value_type(point_type(p.x+1, p.y-1), find(point_type(p.x+1, p.y-1))) :
typename const_neighbourhood_type::value_type(screen.begin()->end())),
142 (inside(point_type(p.x, p.y-1)) ?
typename const_neighbourhood_type::value_type(point_type(p.x, p.y-1), find(point_type(p.x, p.y-1))) :
typename const_neighbourhood_type::value_type(screen.begin()->end())),
143 (inside(point_type(p.x-1, p.y-1)) ?
typename const_neighbourhood_type::value_type(point_type(p.x-1, p.y-1), find(point_type(p.x-1, p.y-1))) :
typename const_neighbourhood_type::value_type(screen.begin()->end())),
144 (inside(point_type(p.x-1, p.y)) ?
typename const_neighbourhood_type::value_type(point_type(p.x-1, p.y), find(point_type(p.x-1, p.y))) :
typename const_neighbourhood_type::value_type(screen.begin()->end())),
145 (inside(point_type(p.x-1, p.y+1)) ?
typename const_neighbourhood_type::value_type(point_type(p.x-1, p.y+1), find(point_type(p.x-1, p.y+1))) :
typename const_neighbourhood_type::value_type(screen.begin()->end()))
150 const neighbourhood_type ret={{
151 (inside(point_type(p.x, p.y+1)) ?
typename neighbourhood_type::value_type(point_type(p.x, p.y+1), find(point_type(p.x, p.y+1))) :
typename neighbourhood_type::value_type(screen.begin()->end())),
152 (inside(point_type(p.x+1, p.y+1)) ?
typename neighbourhood_type::value_type(point_type(p.x+1, p.y+1), find(point_type(p.x+1, p.y+1))) :
typename neighbourhood_type::value_type(screen.begin()->end())),
153 (inside(point_type(p.x+1, p.y)) ?
typename neighbourhood_type::value_type(point_type(p.x+1, p.y), find(point_type(p.x+1, p.y))) :
typename neighbourhood_type::value_type(screen.begin()->end())),
154 (inside(point_type(p.x+1, p.y-1)) ?
typename neighbourhood_type::value_type(point_type(p.x+1, p.y-1), find(point_type(p.x+1, p.y-1))) :
typename neighbourhood_type::value_type(screen.begin()->end())),
155 (inside(point_type(p.x, p.y-1)) ?
typename neighbourhood_type::value_type(point_type(p.x, p.y-1), find(point_type(p.x, p.y-1))) :
typename neighbourhood_type::value_type(screen.begin()->end())),
156 (inside(point_type(p.x-1, p.y-1)) ?
typename neighbourhood_type::value_type(point_type(p.x-1, p.y-1), find(point_type(p.x-1, p.y-1))) :
typename neighbourhood_type::value_type(screen.begin()->end())),
157 (inside(point_type(p.x-1, p.y)) ?
typename neighbourhood_type::value_type(point_type(p.x-1, p.y), find(point_type(p.x-1, p.y))) :
typename neighbourhood_type::value_type(screen.begin()->end())),
158 (inside(point_type(p.x-1, p.y+1)) ?
typename neighbourhood_type::value_type(point_type(p.x-1, p.y+1), find(point_type(p.x-1, p.y+1))) :
typename neighbourhood_type::value_type(screen.begin()->end()))
163 friend std::ostream &
__fastcall operator<<(
std::ostream &os,
bitmap const &b)
noexcept(
false) {
164 os<<
"Width="<<b.width
165 <<
", height="<<b.height
166 <<
", initial value="<<
static_cast<V>(b.initial_value)
168 for (
typename container_type::size_type y=0; y<b.height; ++y) {
169 for (
typename container_type::size_type x=0; x<b.width; ++x) {
199 os<<cp.bottom_left<<cp.top_right;
204 template<
class Op,
class WkQ>
220 : screen(scr), work_queue(wk), fn(op), pt(p) {
224 void __fastcall start()
noexcept(
true) {
230 assert(pt_to_compute.element);
231 if (!pt_to_compute.element->computed) {
232 pt_to_compute.element->value=fn.operator()(pt_to_compute.pt);
233 pt_to_compute.element->computed=
true;
234 add_neighbours(pt_to_compute);
239 return typename screen_type::lower_iterations().operator()(pt, gr.pt);
251 void __fastcall add_neighbours(
result_type const &cur_pt)
noexcept(
true) {
252 const typename screen_type::neighbourhood_type neighbours(screen.neighbours(cur_pt.pt));
256 [&screen, &work_queue, &fn, &cur_pt](
typename screen_type::neighbourhood_type::const_iterator i) {
258 if (i->element!=screen.screen.begin()->end() && !i->element->computed && i->element->value==screen.initial_value) {
259 auto const &computed_pt=work_queue<<
typename work_queue_type::joinable()<<greedy_render_t<Op, WkQ>(screen, work_queue, fn, *i);
267 template<
class CP,
class Scr>
280 :
max_iters(mi),
bailout_sqrd(b*b), plane(cp), d_x(plane.width()/sc.width), d_y(plane.height()/sc.height) {
293 friend std::ostream &
__fastcall operator<<(
std::ostream &os,
Mandelbrot const &m)
noexcept(
false) {
294 os<<
"Max. iterations="<<m.max_iters
295 <<
", bailout="<<
std::sqrt(m.bailout_sqrd)
308 plane.bottom_left.real()+d_x*p.x,
309 plane.bottom_left.imag()+d_y*p.y
314 return typename complex_plane_type::element_type(c.real()*c.real()-c.imag()*c.imag(), 2*c.real()*c.imag());
318 BOOST_AUTO_TEST_SUITE(fractals)
320 BOOST_AUTO_TEST_CASE(mandelbrot)
322 typedef bitmap<
unsigned long, 170, 170, -1> screen_t;
324 typedef Mandelbrot<plane_t, screen_t> Mandelbrot_t;
325 typedef std::priority_queue<screen_t::lower_iterations::first_argument_type, std::vector<screen_t::lower_iterations::first_argument_type>, screen_t::lower_iterations> work_queue_type;
327 typedef ppd::thread_pool<
328 ppd::pool_traits::work_distribution_mode_t::worker_threads_get_work<pool_traits::work_distribution_mode_t::queue_model_t::pool_owns_queue>,
329 ppd::pool_traits::size_mode_t::fixed_size,
331 ppd::generic_traits::return_data::joinable,
333 ppd::heavyweight_threading,
334 ppd::pool_traits::prioritised_queue,
337 ppd::basic_statistics
341 typedef greedy_render_t<Mandelbrot_t, pool_type> renderer_t;
344 plane_t complex_plane(plane_t::element_type(-2.0, -1.5), plane_t::element_type(0.9, 1.5));
345 std::cout<<complex_plane<<std::endl;
348 const screen_t::lower_iterations::first_argument_type pt(start, screen.find(start));
349 renderer_t renderer(screen, pool, Mandelbrot_t(complex_plane, screen, 15), pt);
350 std::cout<<renderer<<
std::endl;
352 std::cout<<screen<<
std::endl;
355 BOOST_AUTO_TEST_SUITE_END()