Jump to content

File:Mandelbrot Set Image 113.png

This is a Quality image. Click here for more information.
From Wikimedia Commons, the free media repository
Original file (10,000 × 10,000 pixels, file size: 95.38 MB, MIME type: image/png)

Captions

Captions

Mandelbrot set, Re = -1.028457781372052547774824579171003431968291180173, Im = 0.361463930751890432883338309925137437795829478445, Width = 1.54e-44

Summary

[edit]
Description
English: Mandelbrot set, Re = -1.028457781372052547774824579171003431968291180173, Im = 0.361463930751890432883338309925137437795829478445, Width = 1.54e-44
Русский: Множества Мандельброта, Re = -1.028457781372052547774824579171003431968291180173, Im = 0.361463930751890432883338309925137437795829478445, Ширина = 1.54e-44
Беларуская: Мноства Мандэльброта, Re = -1.028457781372052547774824579171003431968291180173, Im = 0.361463930751890432883338309925137437795829478445, Шырыня = 1.54e-44
Date
Source Own work
Author Aokoroko
Other versions
Source code (C++)
InfoField
#include <atomic>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <vector>
#include <mpfr.h>
#include <omp.h>

using std::vector;

const char * CENTER_RE = "-1.028457781372052547774824579171003431968291180173";
const char * CENTER_IM = "0.361463930751890432883338309925137437795829478445";
const char * VIEW_SIZE = "1.54e-44";

const int WIDTH = 10000;
const int HEIGHT = 10000;
const int AA = 8;
const int MAX_ITER = 50000;
const double ESCAPE_RADIUS_SQUARED = 40000.0;
const int PALETTE_FRAME = 155;
const char * OUTPUT_FILE = "Mandelbrot Set Image 113.bmp";
const mpfr_prec_t PRECISION_BITS = 350;

struct Complex {
  double re;
  double im;
};

#pragma pack(push, 1)
struct BMPHeader {
  uint16_t type {
    0x4D42
  };
  uint32_t size {
    0
  };
  uint32_t reserved {
    0
  };
  uint32_t offBits {
    54
  };
  uint32_t structSize {
    40
  };
  int32_t width {
    0
  };
  int32_t height {
    0
  };
  uint16_t planes {
    1
  };
  uint16_t bitCount {
    24
  };
  uint32_t compression {
    0
  };
  uint32_t sizeImage {
    0
  };
  int32_t xPixelsPerMeter {
    2834
  };
  int32_t yPixelsPerMeter {
    2834
  };
  uint32_t colorsUsed {
    0
  };
  uint32_t colorsImportant {
    0
  };
};
#pragma pack(pop)

int main() {
  const double startTime = omp_get_wtime();
  const long rawWidth = static_cast < long > (WIDTH) * AA;
  const long rawHeight = static_cast < long > (HEIGHT) * AA;

  mpfr_t centerRe, centerIm, zReMp, zImMp, tmp1, tmp2, viewSizeMp;
  mpfr_inits2(
    PRECISION_BITS,
    centerRe,
    centerIm,
    zReMp,
    zImMp,
    tmp1,
    tmp2,
    viewSizeMp,
    static_cast < mpfr_ptr > (nullptr)
  );

  mpfr_set_str(centerRe, CENTER_RE, 10, MPFR_RNDN);
  mpfr_set_str(centerIm, CENTER_IM, 10, MPFR_RNDN);
  mpfr_set_str(viewSizeMp, VIEW_SIZE, 10, MPFR_RNDN);

  const double sampleStep = mpfr_get_d(viewSizeMp, MPFR_RNDN) / rawWidth;

  vector < Complex > referenceOrbit;
  referenceOrbit.reserve(MAX_ITER + 1);

  mpfr_set_ui(zReMp, 0, MPFR_RNDN);
  mpfr_set_ui(zImMp, 0, MPFR_RNDN);

  for (int iter = 0; iter <= MAX_ITER; ++iter) {
    Complex z {
      mpfr_get_d(zReMp, MPFR_RNDN),
        mpfr_get_d(zImMp, MPFR_RNDN)
    };

    referenceOrbit.push_back(z);

    if (z.re * z.re + z.im * z.im > ESCAPE_RADIUS_SQUARED) {
      break;
    }

    mpfr_mul(tmp1, zReMp, zImMp, MPFR_RNDN);
    mpfr_sqr(tmp2, zReMp, MPFR_RNDN);
    mpfr_sqr(zReMp, zImMp, MPFR_RNDN);
    mpfr_sub(zReMp, tmp2, zReMp, MPFR_RNDN);
    mpfr_add(zReMp, zReMp, centerRe, MPFR_RNDN);
    mpfr_mul_2ui(tmp1, tmp1, 1, MPFR_RNDN);
    mpfr_add(zImMp, tmp1, centerIm, MPFR_RNDN);
  }

  const int referenceLength = static_cast < int > (referenceOrbit.size());

  mpfr_clears(
    centerRe,
    centerIm,
    zReMp,
    zImMp,
    tmp1,
    tmp2,
    viewSizeMp,
    static_cast < mpfr_ptr > (nullptr)
  );

  std::fprintf(stderr, "Reference orbit: %d points\n", referenceLength);

  const double PI = 3.14159265358979323846;
  uint8_t palette[256][3];

  for (int i = 0; i < 255; ++i) {
    palette[i][0] = static_cast < uint8_t > (
      std::lround(127.0 + 127.0 * std::cos(2.0 * PI * i / 255.0))
    );
    palette[i][1] = static_cast < uint8_t > (
      std::lround(127.0 + 127.0 * std::sin(2.0 * PI * i / 255.0))
    );
    palette[i][2] = palette[i][1];
  }

  palette[255][0] = 255;
  palette[255][1] = 255;
  palette[255][2] = 255;

  const int rowBytes = (WIDTH * 3 + 3) & ~3;
  vector < uint8_t > image(static_cast < size_t > (rowBytes) * HEIGHT, 0);

  std::atomic < int > completedRows {
    0
  };
  const Complex * reference = referenceOrbit.data();

  #pragma omp parallel for schedule(dynamic)
  for (int y = 0; y < HEIGHT; ++y) {
    uint8_t * row = image.data() + static_cast < size_t > (y) * rowBytes;

    for (int x = 0; x < WIDTH; ++x) {
      unsigned blueSum = 0;
      unsigned greenSum = 0;
      unsigned redSum = 0;

      for (int sampleY = 0; sampleY < AA; ++sampleY) {
        const double deltaCIm =
          (static_cast < long > (y) * AA + sampleY - rawHeight / 2) * sampleStep;

        for (int sampleX = 0; sampleX < AA; ++sampleX) {
          const double deltaCRe =
            (static_cast < long > (x) * AA + sampleX - rawWidth / 2) * sampleStep;

          double deltaRe = 0.0;
          double deltaIm = 0.0;
          double zRe = 0.0;
          double zIm = 0.0;

          int referenceIndex = 0;
          int iter = 0;

          while (
            iter < MAX_ITER &&
            zRe * zRe + zIm * zIm < ESCAPE_RADIUS_SQUARED
          ) {
            const double a = 2.0 * reference[referenceIndex].re + deltaRe;
            const double b = 2.0 * reference[referenceIndex].im + deltaIm;

            const double nextDeltaRe =
              a * deltaRe - b * deltaIm + deltaCRe;

            deltaIm = a * deltaIm + b * deltaRe + deltaCIm;
            deltaRe = nextDeltaRe;

            ++referenceIndex;
            ++iter;

            zRe = reference[referenceIndex].re + deltaRe;
            zIm = reference[referenceIndex].im + deltaIm;

            if (
              zRe * zRe + zIm * zIm <
              deltaRe * deltaRe + deltaIm * deltaIm ||
              referenceIndex == referenceLength - 1
            ) {
              deltaRe = zRe;
              deltaIm = zIm;
              referenceIndex = 0;
            }
          }

          const int remaining = MAX_ITER - iter;
          const uint8_t colorIndex =
            (remaining == 0) ?
            255 :
            static_cast < uint8_t > (remaining % 254);

          const int paletteIndex =
            (colorIndex == 255) ?
            255 :
            (colorIndex - PALETTE_FRAME + 255) % 255;

          blueSum += palette[paletteIndex][0];
          greenSum += palette[paletteIndex][1];
          redSum += palette[paletteIndex][2];
        }
      }

      const int samples = AA * AA;
      row[x * 3 + 0] = static_cast < uint8_t > (blueSum / samples);
      row[x * 3 + 1] = static_cast < uint8_t > (greenSum / samples);
      row[x * 3 + 2] = static_cast < uint8_t > (redSum / samples);
    }

    const int done = ++completedRows;

    if (done % 50 == 0 || done == HEIGHT) {
      std::fprintf(
        stderr,
        "\rProgress: %d/%d rows (%.1f%%)",
        done,
        HEIGHT,
        100.0 * done / HEIGHT
      );
    }
  }

  BMPHeader header;
  header.width = WIDTH;
  header.height = HEIGHT;
  header.sizeImage = static_cast < uint32_t > (image.size());
  header.size = header.sizeImage + 54;

  FILE * file = std::fopen(OUTPUT_FILE, "wb");

  if (!file) {
    std::perror(OUTPUT_FILE);
    return 1;
  }

  std::fwrite( & header, sizeof header, 1, file);
  std::fwrite(image.data(), 1, image.size(), file);
  std::fclose(file);

  std::fprintf(
    stderr,
    "\nDone: \"%s\" saved in %.1f s\n",
    OUTPUT_FILE,
    omp_get_wtime() - startTime
  );

  return 0;
}

Technical details

[edit]
  • High-Precision Reference: The 5000-bit reference trajectory is computed exactly once per zoom layer.
  • Hardware-Native Performance: Blazing-fast math for billions of pixels utilizing hardware-native double registers.
  • When using double-precision floating-point numbers (on the order of 10-15, perturbation theory only allows you to zoom down to the 10-308 level-no further.
  • Innovative Algorithm: Revolutionary Reference Reset to Zero implementation.
  • True 8x8 SSAA: Pristine, anti-aliased image quality with 64 independent samples per pixel.
  • OpenMP Multi-threading: High-speed parallel computing to maximize CPU utilization.
  • Software: C++ (compiled with g++), GNU C++ Compiler.
[edit]

Notes

[edit]

Licensing

[edit]
I, the copyright holder of this work, hereby publish it under the following license:
Creative Commons CC-Zero This file is made available under the Creative Commons CC0 1.0 Universal Public Domain Dedication.
The person who associated a work with this deed has dedicated the work to the public domain by waiving all of their rights to the work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law. You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission.

This image has been assessed using the Quality image guidelines and is considered a Quality image.

العربية  جازايرية  беларуская  беларуская (тарашкевіца)  български  বাংলা  català  čeština  Cymraeg  Deutsch  Schweizer Hochdeutsch  Zazaki  Ελληνικά  English  Esperanto  español  eesti  euskara  فارسی  suomi  français  galego  עברית  हिन्दी  hrvatski  magyar  հայերեն  Bahasa Indonesia  italiano  日本語  Jawa  ქართული  Qaraqalpaqsha  한국어  kurdî  кыргызча  Latina  Lëtzebuergesch  lietuvių  македонски  മലയാളം  मराठी  Bahasa Melayu  Nederlands  ਪੰਜਾਬੀ  Norfuk / Pitkern  polski  português  português do Brasil  rumantsch  română  русский  sicilianu  slovenčina  slovenščina  shqip  српски / srpski  svenska  தமிழ்  తెలుగు  ไทย  Tagalog  toki pona  Türkçe  українська  oʻzbekcha / ўзбекча  vèneto  Tiếng Việt  中文  中文(简体)  中文(繁體)  +/−

File history

Click on a date/time to view the file as it appeared at that time.

Date/TimeThumbnailDimensionsUserComment
current08:55, 1 August 2026Thumbnail for version as of 08:55, 1 August 202610,000 × 10,000 (95.38 MB)Aokoroko (talk | contribs)Fragment of the Mandelbrot set. 100 Megapixels (10,000 x 10,000 px) with 8x SSAA. The source code included.
12:56, 20 July 2026Thumbnail for version as of 12:56, 20 July 20262,160 × 2,160 (7.01 MB)Aokoroko (talk | contribs)Uploaded own work with UploadWizard

The following 92 pages use this file:

File usage on other wikis

The following other wikis use this file:

Metadata