- /*
- * MIT License
- *
- * Copyright (c) 2026 Roland Mainz <roland.mainz@nrubsig.org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
- /*
- * rov_int_mandelbrot_test1.c - math test module for |template <typename T> class rov_int_template|
- *
- * WARNING: This module must be compileable with ISO C and ISO C++ compilers
- * for benchmarking and testing purposes!
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdint.h>
- #include <iostream>
- #define USE_ROV_INT_TEMPLATE002_TYPES 1
- #ifdef USE_ROV_INT_TEMPLATE002_TYPES
- /*
- * Compile with ISO C++ integer wrapper class
- */
- #include "rov_int_template002.h"
- typedef rov_int_template<int32_t> test_int32_t;
- typedef rov_int_template<int64_t> test_int64_t;
- #else
- /*
- * Compile with ISO C99/C11 compiler
- */
- #error XXX
- typedef int32_t test_int32_t;
- typedef int64_t test_int64_t;
- #endif /* USE_ROV_INT_TEMPLATE002_TYPES */
- /* Mandelbrot parameters */
- #define MANDELBROT_VIEW_WIDTH (132LL) /*72*/
- #define MANDELBROT_VIEW_HEIGHT (3*25LL)
- #define MANDELBROT_VIEW_MAX_ITER (75)
- /* Fixed-point math (fpx) scale */
- #define FPX_SCALE (1000LL) /* fpx scale: 1000 <--> 1.0 */
- /*
- * |fpx_mul()| - fpx multiply: (a*b)/FPX_SCALE using 64-bit
- */
- static inline
- test_int32_t fpx_mul(test_int32_t a, test_int32_t b)
- {
- return (test_int32_t)(((test_int64_t)a * (test_int64_t)b) / FPX_SCALE);
- }
- /*
- * Iterations && ASCII "palette"
- * - FIXME: Make this a cmdline argument
- */
- static const char mandelbrot_palette[] =
- " .':;-~=+*0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ%&$#";
- const size_t mandelbrot_palette_len = sizeof(mandelbrot_palette) - 1;
- static
- void do_fxmath_mandelbrot(void)
- {
- /*
- * Mandelbrot view window:
- * fpx: x in [-2, 1], y range adjusted for aspect
- */
- const test_int32_t x_min = -2000; /* was: -2.000 * FPX_SCALE */
- const test_int32_t x_max = 1000; /* was: 1.000 * FPX_SCALE */
- const test_int32_t x_range = x_max - x_min;
- /* y_range = x_range * MANDELBROT_VIEW_HEIGHT / MANDELBROT_VIEW_WIDTH, centered around 0 */
- const test_int32_t y_range =
- (test_int32_t)(((test_int64_t)x_range * MANDELBROT_VIEW_HEIGHT) / MANDELBROT_VIEW_WIDTH);
- const test_int32_t y_min = -(y_range / 2);
- const test_int32_t y_max = (y_range - y_range / 2);
- /* Precompute escape radius squared, scaled: (2*FPX_SCALE)^2 */
- const test_int64_t esc2 = (test_int64_t)((2LL * FPX_SCALE) * (2LL * FPX_SCALE));
- for (int j = 0; j < MANDELBROT_VIEW_HEIGHT; j++) {
- /* cy = y_min + j * (y_max - y_min) / (MANDELBROT_VIEW_HEIGHT-1) */
- test_int32_t cy = y_min;
- test_int64_t t = (test_int64_t)(y_max - y_min);
- t = (t * (test_int64_t)j) / (test_int64_t)(MANDELBROT_VIEW_HEIGHT - 1);
- cy = (test_int32_t)((test_int64_t)y_min + t);
- for (int i = 0; i < MANDELBROT_VIEW_WIDTH; i++) {
- /* cx = x_min + i * x_range / (MANDELBROT_VIEW_WIDTH-1) */
- test_int32_t cx = x_min;
- test_int64_t t = (test_int64_t)x_range;
- t = (t * (test_int64_t)i) / (test_int64_t)(MANDELBROT_VIEW_WIDTH - 1);
- cx = (test_int32_t)((test_int64_t)x_min + t);
- test_int32_t zx = 0, zy = 0;
- int iter = 0;
- /* Loop in fpx: z_{n+1} = z_n^2 + c */
- for (;;) {
- test_int64_t sumsq = (test_int64_t)zx * (test_int64_t)zx + (test_int64_t)zy * (test_int64_t)zy;
- if (sumsq > esc2)
- break;
- if (iter >= MANDELBROT_VIEW_MAX_ITER)
- break;
- test_int32_t zx2 = fpx_mul(zx, zx);
- test_int32_t zy2 = fpx_mul(zy, zy);
- test_int32_t xy = fpx_mul(zx, zy);
- test_int32_t nx = (zx2 - zy2) + cx;
- test_int32_t ny = (test_int32_t)((test_int64_t)xy * 2) + cy;
- zx = nx;
- zy = ny;
- iter++;
- }
- /* Map mandelbrot iterations to palette index */
- size_t idx = (iter >= MANDELBROT_VIEW_MAX_ITER)
- ? (mandelbrot_palette_len - 1)
- : (int)(((test_int64_t)iter * (mandelbrot_palette_len - 1)) / MANDELBROT_VIEW_MAX_ITER);
- (void)putchar(mandelbrot_palette[idx]);
- }
- (void)putchar('\n');
- }
- }
- static
- void do_unit_tests1(void)
- {
- /*
- * FIXME: clang++ throws SIGFPE on Debian Bulleye, we need to add code to catch this
- */
- {
- rov_int_template<int32_t> x = 0;
- rov_int_template<int32_t> y = 0;
- try {
- (void)printf("res (x/y)=%d\n", (int)(x/y));
- std::cerr << "Test FAILED for " << "(x/y)\n";
- }
- catch (const std::exception& e) {
- std::cerr << "Caught exception: " << e.what() << " (expected - test OK)\n";
- }
- }
- {
- rov_int_template<int32_t> x = 0;
- try {
- (void)printf("res (x/0)=%d\n", (int)(x/0));
- std::cerr << "Test FAILED for " << "(x/0)\n";
- }
- catch (const std::exception& e) {
- std::cerr << "Caught exception: " << e.what() << " (expected - test OK)\n";
- }
- }
- {
- rov_int_template<int32_t> x = 0;
- rov_int_template<int32_t> y = 0;
- try {
- (void)printf("res (x/=y)=%d\n", (int)(x/=y));
- std::cerr << "Test FAILED for " << "(x/=y)\n";
- }
- catch (const std::exception& e) {
- std::cerr << "Caught exception: " << e.what() << " (expected - test OK)\n";
- }
- }
- }
- static
- void do_unit_tests2_template_nesting(void)
- {
- #ifdef DISABLED_FOR_NOW
- {
- /*
- * Nested template testcase
- * We use this for:
- * 1. compiler testing (some compilers like g++ and clang++ have
- * issues with this
- * 2. benchmarking, because we can get extra levels of
- * indirection easily over all affected components, except if we hit [1]
- */
- rov_int_template<rov_int_template<rov_int_template<rov_int_template<int32_t>>>> x = 1;
- rov_int_template<rov_int_template<rov_int_template<rov_int_template<int32_t>>>> y = 2;
- (void)printf("res (x+y)=%d\n", int((x+y).get().get().get()));
- }
- #endif /* DISABLED_FOR_NOW */
- }
- int main(int ac, char *av[])
- {
- #if 1
- do_unit_tests1();
- do_unit_tests2_template_nesting();
- #endif
- #if 1
- do_fxmath_mandelbrot();
- #endif
- return EXIT_SUCCESS;
- }
rov_int_mandelbrot_test1.c - math test module for |template <typename T> class rov_int_template|
Posted by Anonymous on Fri 27th Mar 2026 13:22
raw | new post
modification of post by Anonymous (view diff)
Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.
rovema.kpaste.net RSS