17db96d56Sopenharmony_ci/*
27db96d56Sopenharmony_ci * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
37db96d56Sopenharmony_ci *
47db96d56Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
57db96d56Sopenharmony_ci * modification, are permitted provided that the following conditions
67db96d56Sopenharmony_ci * are met:
77db96d56Sopenharmony_ci *
87db96d56Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright
97db96d56Sopenharmony_ci *    notice, this list of conditions and the following disclaimer.
107db96d56Sopenharmony_ci *
117db96d56Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright
127db96d56Sopenharmony_ci *    notice, this list of conditions and the following disclaimer in the
137db96d56Sopenharmony_ci *    documentation and/or other materials provided with the distribution.
147db96d56Sopenharmony_ci *
157db96d56Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
167db96d56Sopenharmony_ci * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
177db96d56Sopenharmony_ci * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
187db96d56Sopenharmony_ci * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
197db96d56Sopenharmony_ci * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
207db96d56Sopenharmony_ci * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
217db96d56Sopenharmony_ci * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
227db96d56Sopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
237db96d56Sopenharmony_ci * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
247db96d56Sopenharmony_ci * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
257db96d56Sopenharmony_ci * SUCH DAMAGE.
267db96d56Sopenharmony_ci */
277db96d56Sopenharmony_ci
287db96d56Sopenharmony_ci
297db96d56Sopenharmony_ci#include "mpdecimal.h"
307db96d56Sopenharmony_ci
317db96d56Sopenharmony_ci#include <stdint.h>
327db96d56Sopenharmony_ci#include <stdio.h>
337db96d56Sopenharmony_ci#include <stdlib.h>
347db96d56Sopenharmony_ci#include <time.h>
357db96d56Sopenharmony_ci
367db96d56Sopenharmony_ci
377db96d56Sopenharmony_cistatic void
387db96d56Sopenharmony_cierr_exit(const char *msg)
397db96d56Sopenharmony_ci{
407db96d56Sopenharmony_ci    fprintf(stderr, "%s\n", msg);
417db96d56Sopenharmony_ci    exit(1);
427db96d56Sopenharmony_ci}
437db96d56Sopenharmony_ci
447db96d56Sopenharmony_cistatic mpd_t *
457db96d56Sopenharmony_cinew_mpd(void)
467db96d56Sopenharmony_ci{
477db96d56Sopenharmony_ci    mpd_t *x = mpd_qnew();
487db96d56Sopenharmony_ci    if (x == NULL) {
497db96d56Sopenharmony_ci        err_exit("out of memory");
507db96d56Sopenharmony_ci    }
517db96d56Sopenharmony_ci
527db96d56Sopenharmony_ci    return x;
537db96d56Sopenharmony_ci}
547db96d56Sopenharmony_ci
557db96d56Sopenharmony_ci/*
567db96d56Sopenharmony_ci * Example from: http://en.wikipedia.org/wiki/Mandelbrot_set
577db96d56Sopenharmony_ci *
587db96d56Sopenharmony_ci * Escape time algorithm for drawing the set:
597db96d56Sopenharmony_ci *
607db96d56Sopenharmony_ci * Point x0, y0 is deemed to be in the Mandelbrot set if the return
617db96d56Sopenharmony_ci * value is maxiter. Lower return values indicate how quickly points
627db96d56Sopenharmony_ci * escaped and can be used for coloring.
637db96d56Sopenharmony_ci */
647db96d56Sopenharmony_cistatic int
657db96d56Sopenharmony_cicolor_point(const mpd_t *x0, const mpd_t *y0, const long maxiter, mpd_context_t *ctx)
667db96d56Sopenharmony_ci{
677db96d56Sopenharmony_ci    mpd_t *x, *y, *sq_x, *sq_y;
687db96d56Sopenharmony_ci    mpd_t *two, *four, *c;
697db96d56Sopenharmony_ci    long i;
707db96d56Sopenharmony_ci
717db96d56Sopenharmony_ci    x = new_mpd();
727db96d56Sopenharmony_ci    y = new_mpd();
737db96d56Sopenharmony_ci    mpd_set_u32(x, 0, ctx);
747db96d56Sopenharmony_ci    mpd_set_u32(y, 0, ctx);
757db96d56Sopenharmony_ci
767db96d56Sopenharmony_ci    sq_x = new_mpd();
777db96d56Sopenharmony_ci    sq_y = new_mpd();
787db96d56Sopenharmony_ci    mpd_set_u32(sq_x, 0, ctx);
797db96d56Sopenharmony_ci    mpd_set_u32(sq_y, 0, ctx);
807db96d56Sopenharmony_ci
817db96d56Sopenharmony_ci    two = new_mpd();
827db96d56Sopenharmony_ci    four = new_mpd();
837db96d56Sopenharmony_ci    mpd_set_u32(two, 2, ctx);
847db96d56Sopenharmony_ci    mpd_set_u32(four, 4, ctx);
857db96d56Sopenharmony_ci
867db96d56Sopenharmony_ci    c = new_mpd();
877db96d56Sopenharmony_ci    mpd_set_u32(c, 0, ctx);
887db96d56Sopenharmony_ci
897db96d56Sopenharmony_ci    for (i = 0; i < maxiter && mpd_cmp(c, four, ctx) <= 0; i++) {
907db96d56Sopenharmony_ci        mpd_mul(y, x, y, ctx);
917db96d56Sopenharmony_ci        mpd_mul(y, y, two, ctx);
927db96d56Sopenharmony_ci        mpd_add(y, y, y0, ctx);
937db96d56Sopenharmony_ci
947db96d56Sopenharmony_ci        mpd_sub(x, sq_x, sq_y, ctx);
957db96d56Sopenharmony_ci        mpd_add(x, x, x0, ctx);
967db96d56Sopenharmony_ci
977db96d56Sopenharmony_ci        mpd_mul(sq_x, x, x, ctx);
987db96d56Sopenharmony_ci        mpd_mul(sq_y, y, y, ctx);
997db96d56Sopenharmony_ci        mpd_add(c, sq_x, sq_y, ctx);
1007db96d56Sopenharmony_ci    }
1017db96d56Sopenharmony_ci
1027db96d56Sopenharmony_ci    mpd_del(c);
1037db96d56Sopenharmony_ci    mpd_del(four);
1047db96d56Sopenharmony_ci    mpd_del(two);
1057db96d56Sopenharmony_ci    mpd_del(sq_y);
1067db96d56Sopenharmony_ci    mpd_del(sq_x);
1077db96d56Sopenharmony_ci    mpd_del(y);
1087db96d56Sopenharmony_ci    mpd_del(x);
1097db96d56Sopenharmony_ci
1107db96d56Sopenharmony_ci    return i;
1117db96d56Sopenharmony_ci}
1127db96d56Sopenharmony_ci
1137db96d56Sopenharmony_ciint
1147db96d56Sopenharmony_cimain(int argc, char **argv)
1157db96d56Sopenharmony_ci{
1167db96d56Sopenharmony_ci    mpd_context_t ctx;
1177db96d56Sopenharmony_ci    mpd_t *x0, *y0;
1187db96d56Sopenharmony_ci    mpd_t *sqrt_2, *xstep, *ystep;
1197db96d56Sopenharmony_ci    mpd_ssize_t prec = 19;
1207db96d56Sopenharmony_ci
1217db96d56Sopenharmony_ci    long iter = 1000;
1227db96d56Sopenharmony_ci    int points[40][80];
1237db96d56Sopenharmony_ci    int i, j;
1247db96d56Sopenharmony_ci    clock_t start_clock, end_clock;
1257db96d56Sopenharmony_ci
1267db96d56Sopenharmony_ci
1277db96d56Sopenharmony_ci    if (argc != 3) {
1287db96d56Sopenharmony_ci        fprintf(stderr, "usage: ./bench prec iter\n");
1297db96d56Sopenharmony_ci        exit(1);
1307db96d56Sopenharmony_ci    }
1317db96d56Sopenharmony_ci    prec = strtoll(argv[1], NULL, 10);
1327db96d56Sopenharmony_ci    iter = strtol(argv[2], NULL, 10);
1337db96d56Sopenharmony_ci
1347db96d56Sopenharmony_ci    mpd_init(&ctx, prec);
1357db96d56Sopenharmony_ci    /* no more MPD_MINALLOC changes after here */
1367db96d56Sopenharmony_ci
1377db96d56Sopenharmony_ci    sqrt_2 = new_mpd();
1387db96d56Sopenharmony_ci    xstep = new_mpd();
1397db96d56Sopenharmony_ci    ystep = new_mpd();
1407db96d56Sopenharmony_ci    x0 = new_mpd();
1417db96d56Sopenharmony_ci    y0 = new_mpd();
1427db96d56Sopenharmony_ci
1437db96d56Sopenharmony_ci    mpd_set_u32(sqrt_2, 2, &ctx);
1447db96d56Sopenharmony_ci    mpd_sqrt(sqrt_2, sqrt_2, &ctx);
1457db96d56Sopenharmony_ci    mpd_div_u32(xstep, sqrt_2, 40, &ctx);
1467db96d56Sopenharmony_ci    mpd_div_u32(ystep, sqrt_2, 20, &ctx);
1477db96d56Sopenharmony_ci
1487db96d56Sopenharmony_ci    start_clock = clock();
1497db96d56Sopenharmony_ci    mpd_copy(y0, sqrt_2, &ctx);
1507db96d56Sopenharmony_ci    for (i = 0; i < 40; i++) {
1517db96d56Sopenharmony_ci        mpd_copy(x0, sqrt_2, &ctx);
1527db96d56Sopenharmony_ci        mpd_set_negative(x0);
1537db96d56Sopenharmony_ci        for (j = 0; j < 80; j++) {
1547db96d56Sopenharmony_ci            points[i][j] = color_point(x0, y0, iter, &ctx);
1557db96d56Sopenharmony_ci            mpd_add(x0, x0, xstep, &ctx);
1567db96d56Sopenharmony_ci        }
1577db96d56Sopenharmony_ci        mpd_sub(y0, y0, ystep, &ctx);
1587db96d56Sopenharmony_ci    }
1597db96d56Sopenharmony_ci    end_clock = clock();
1607db96d56Sopenharmony_ci
1617db96d56Sopenharmony_ci#ifdef BENCH_VERBOSE
1627db96d56Sopenharmony_ci    for (i = 0; i < 40; i++) {
1637db96d56Sopenharmony_ci        for (j = 0; j < 80; j++) {
1647db96d56Sopenharmony_ci            if (points[i][j] == iter) {
1657db96d56Sopenharmony_ci                putchar('*');
1667db96d56Sopenharmony_ci            }
1677db96d56Sopenharmony_ci            else if (points[i][j] >= 10) {
1687db96d56Sopenharmony_ci                putchar('+');
1697db96d56Sopenharmony_ci            }
1707db96d56Sopenharmony_ci            else if (points[i][j] >= 5) {
1717db96d56Sopenharmony_ci                putchar('.');
1727db96d56Sopenharmony_ci            }
1737db96d56Sopenharmony_ci            else {
1747db96d56Sopenharmony_ci                putchar(' ');
1757db96d56Sopenharmony_ci            }
1767db96d56Sopenharmony_ci        }
1777db96d56Sopenharmony_ci        putchar('\n');
1787db96d56Sopenharmony_ci    }
1797db96d56Sopenharmony_ci    putchar('\n');
1807db96d56Sopenharmony_ci#else
1817db96d56Sopenharmony_ci    (void)points; /* suppress gcc warning */
1827db96d56Sopenharmony_ci#endif
1837db96d56Sopenharmony_ci
1847db96d56Sopenharmony_ci    printf("time: %f\n\n", (double)(end_clock-start_clock)/(double)CLOCKS_PER_SEC);
1857db96d56Sopenharmony_ci
1867db96d56Sopenharmony_ci    mpd_del(y0);
1877db96d56Sopenharmony_ci    mpd_del(x0);
1887db96d56Sopenharmony_ci    mpd_del(ystep);
1897db96d56Sopenharmony_ci    mpd_del(xstep);
1907db96d56Sopenharmony_ci    mpd_del(sqrt_2);
1917db96d56Sopenharmony_ci
1927db96d56Sopenharmony_ci    return 0;
1937db96d56Sopenharmony_ci}
194