threaded dla, _very_ naive, interest test 0...

Discussion in 'C++' started by Chris M. Thomasson, Jun 10, 2014.

  1. An initial attempt at a threaded dla:

    https://plus.google.com/101799841244447089430/posts/Pmm7Qsh9W2t

    ___________________________________________________________

    #include <cstdio>
    #include <cstdlib>
    #include <ctime>
    #include <cmath>
    #include <random>
    #include <functional>
    #include <thread>
    #include "bitmaplib.h" /* Paul Bourke's C bitmap library
    http://paulbourke.net/fractals/
    */


    #define WIDTH 1024U
    #define HEIGHT ((unsigned int)(WIDTH * (9.0 / 16.0)))
    #define POINTS 66666


    static double
    prv_round(
    double norigin
    ){
    return static_cast<double>(
    (norigin > 0.0) ?
    static_cast<long>(norigin + 0.5) :
    static_cast<long>(norigin - 0.5));
    }


    BITMAP4
    prv_color_gradient(
    BITMAP4 cmin,
    BITMAP4 cmax,
    double cscale
    ){
    BITMAP4 cwidth;

    cwidth.r = cmax.r - cmin.r;
    cwidth.g = cmax.g - cmin.g;
    cwidth.b = cmax.b - cmin.b;
    cwidth.a = cmax.a - cmin.a;

    BITMAP4 cresult;

    cresult.r = (unsigned char)(cmin.r + ((double)cwidth.r * cscale));
    cresult.g = (unsigned char)(cmin.g + ((double)cwidth.g * cscale));
    cresult.b = (unsigned char)(cmin.b + ((double)cwidth.b * cscale));
    cresult.a = (unsigned char)(cmin.a + ((double)cwidth.a * cscale));

    return cresult;
    }


    class simple_rand
    {
    unsigned int const m_seed;
    mutable std::mt19937 m_engine;
    mutable std::uniform_real_distribution<double> m_rdist;


    public:
    simple_rand(
    unsigned int seed
    ): m_seed(seed),
    m_engine(seed),
    m_rdist(0.0, 1.0)
    {

    }


    public:
    double
    get() const {
    return m_rdist(m_engine);
    }


    double
    get(double nmin, double nmax) const
    {
    double random = get();
    return nmin + ((nmax - nmin) * random);
    }


    double
    get_round(double nmin, double nmax) const
    {
    double random = get();
    return prv_round(get(nmin, nmax));
    }
    };


    class x_bitmap
    {
    public:
    BITMAP4* const m_bitmap;
    unsigned int const m_width;
    unsigned int const m_height;

    public:
    x_bitmap(unsigned int width, unsigned int height)
    : m_bitmap(Create_Bitmap(width, height)),
    m_width(width),
    m_height(height)
    {
    if (! m_bitmap) throw;
    BITMAP4 color_bgrnd = { 0x00, 0x00, 0x00, 0x00 };
    Erase_Bitmap(m_bitmap, m_width, m_height, color_bgrnd);
    }


    ~x_bitmap() throw()
    {
    Destroy_Bitmap(m_bitmap);
    }


    public:
    bool
    set_pixel(int px, int py, BITMAP4 color)
    {
    return Draw_Pixel(m_bitmap, m_width, m_height, px, py, color);
    }


    BITMAP4
    get_pixel(int px, int py) const
    {
    return Get_Pixel(m_bitmap, m_width, m_height, px, py);
    }


    void erase(BITMAP4 color)
    {
    Erase_Bitmap(m_bitmap, m_width, m_height, color);
    }


    bool
    save(const char* fname)
    {
    FILE* fptr = std::fopen(fname,"wb");

    if (! fptr) {
    fprintf(stderr,"Failed to open output file\n");
    return false;
    } else {
    Write_Bitmap(fptr, m_bitmap, m_width, m_height, 9);
    fclose(fptr);
    }
    return true;
    }
    };


    class dla_walker
    {
    public:
    simple_rand m_rand;
    x_bitmap& m_bitmap;


    public:
    dla_walker(x_bitmap& bitmap_)
    : m_rand(((unsigned int)this) * 1331U),
    m_bitmap(bitmap_)
    {

    }


    public:
    bool
    check_point(int cpx, int cpy, int ximin, int ximax, int yimin, int
    yimax)
    {
    BITMAP4 color_check;

    for (int xi = ximin; xi < ximax; ++xi)
    {
    for (int yi = yimin; yi < yimax; ++yi)
    {
    int px = cpx + xi;
    int py = cpy + yi;

    if (px < 0) px = px * -1;
    if (py < 0) py = py * -1;
    if (px > m_bitmap.m_width - 1) px = px - (px - (m_bitmap.m_width - 1));
    if (py > m_bitmap.m_height - 1) py = py - (py - (m_bitmap.m_height - 1));

    color_check = m_bitmap.get_pixel(px, py);

    if (color_check.a == 0xFF)
    {
    return true;
    }
    }
    }

    return false;
    }

    void walk_point(unsigned int imax, int cpx, int cpy, BITMAP4
    color_origin)
    {
    unsigned int px = cpx;
    unsigned int py = cpy;

    for (unsigned int i = 0; i < imax; ++i)
    {
    int r1 = m_rand.get_round(-2, 2);
    int r2 = m_rand.get_round(-2, 2);

    int r3 = m_rand.get_round(-2, -1);
    int r4 = m_rand.get_round(1, 2);
    int r5 = m_rand.get_round(-2, -1);
    int r6 = m_rand.get_round(1, 2);

    px += r1;
    py += r2;

    if (px < 0) px = m_bitmap.m_width - 1;
    if (py < 0) py = m_bitmap.m_height - 1;
    if (px > m_bitmap.m_width - 1) px = 0;
    if (py > m_bitmap.m_height - 1) py = 0;

    if (check_point(px, py, r3, r4, r5, r6))
    {
    color_origin.a = 0xFF;
    m_bitmap.set_pixel(px, py, color_origin);

    return;
    }
    }
    }


    void walk_points(unsigned int imax, int cpx, int cpy)
    {
    BITMAP4 color_min = { 0xFF, 0x00, 0x00, 0x00 };
    BITMAP4 color_max = { 0xFF, 0xFF, 0x00, 0x00 };
    BITMAP4 color_result;
    double cscale;

    for (unsigned int i = 0; i < imax; ++i)
    {
    cscale = 1.0 - ((double)i / (double)(imax - 1));

    cpx = m_rand.get_round(0, m_bitmap.m_width - 1);
    cpy = m_rand.get_round(0, m_bitmap.m_height - 1);

    color_result = prv_color_gradient(color_min, color_max, cscale);

    walk_point(m_rand.get_round(33, 33313), cpx, cpy, color_result);

    if (! (i % 8192 * 2))
    {
    std::printf("%p::dla_walker: plotted %d of %d\r", (void*)this, i + 1,
    imax);
    }
    }
    }


    static void
    seed_point(x_bitmap& bmp, int cpx, int cpy)
    {
    BITMAP4 color_origin = { 0xFF, 0x00, 0x00, 0xFF };

    bmp.set_pixel(cpx, cpy, color_origin);
    }
    };


    class dla_thread
    {
    dla_walker m_walker;

    public:
    dla_thread(x_bitmap& bmp)
    : m_walker(bmp)
    {
    std::printf("%p::dla_thread::dla_thread()\n", (void*)this);
    }

    public:
    void operator()()
    {
    std::printf("%p::dla_thread::eek:perator()\n", (void*)this);

    int px = m_walker.m_rand.get(10, m_walker.m_bitmap.m_width - 11);
    int py = m_walker.m_rand.get(10, m_walker.m_bitmap.m_width - 11);

    m_walker.walk_points(POINTS, px, py);
    }
    };


    int
    main()
    {
    {
    {
    simple_rand rand_(std::time(nullptr));
    x_bitmap bmp(WIDTH, HEIGHT);

    // Seed our initial growth points
    {
    #define ASEED_MAX 11.0

    double aseed = (3.14 * 2.0) / ASEED_MAX;
    double acur = .6;
    double r = 50.0;
    double cpx = bmp.m_width / 2.0;
    double cpy = bmp.m_height / 2.0;

    for (unsigned int i = 0; i < ASEED_MAX * 97; ++i)
    {
    acur = aseed * (i * 3.14);
    r += 1.28;

    r *= .9953;

    double px = std::cos(acur) * r + cpx;
    double py = std::sin(acur) * r + cpy;

    dla_walker::seed_point(bmp, px , py);
    }
    }

    // Spawn threads and wait...
    {
    dla_thread dlat1(bmp);
    dla_thread dlat2(bmp);
    dla_thread dlat3(bmp);
    dla_thread dlat4(bmp);

    {
    std::thread t1(std::ref(dlat1));
    std::thread t2(std::ref(dlat2));
    std::thread t3(std::ref(dlat3));
    std::thread t4(std::ref(dlat4));

    t1.join();
    t2.join();
    t3.join();
    t4.join();
    }
    }

    // That's all folks! ;^)
    bmp.save("dlax.bmp");
    }

    std::system("dlax.bmp");
    }

    std::puts("\n\nProgram Complete!");
    std::fflush(stdout);
    std::getchar();

    return 0;
    }
    _____________________________________________________________


    Enjoy?


    Yikes!
     
    Chris M. Thomasson, Jun 10, 2014
    #1
    1. Advertisements

  2. Chris M. Thomasson, Jun 10, 2014
    #2
    1. Advertisements

  3. Chris M. Thomasson

    Öö Tiib Guest

    It seems that he wrote C++ code that uses several
    'std::thread's to draw some sort of diffusion fractals in that
    code.

    Some people like fractals as decorative; some use these for
    solving some technical problems. Lot of things in nature
    (including life) seem to work primarily on Brown movement
    and diffusion. It is hard to tell why (and if at all) it is noteworthy.
     
    Öö Tiib, Jun 10, 2014
    #3
  4. "Öö Tiib" wrote in message
    Öö Tiib: Exactly!

    I am trying to visualize a random aspect generated by
    race-conditions by relating them to Brownian motion
    and diffusion. I thought DLA and no synchronization
    between threads would be interesting wrt detecting,
    and ultimately graphing encounters with seed points.
     
    Chris M. Thomasson, Jun 14, 2014
    #4
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.