Wikiversity betawikiversity https://beta.wikiversity.org/wiki/Main_Page MediaWiki 1.47.0-wmf.14 first-letter Media Special Talk User User talk Wikiversity Wikiversity talk File File talk MediaWiki MediaWiki talk Template Template talk Help Help talk Category Category talk TimedText TimedText talk Module Module talk Translations Translations talk Event Event talk Talk:Halaman Utama 1 55680 385940 385933 2026-08-06T00:39:56Z Satya Rambana 55705 /* Dukungan dan Komentar */ Reply 385940 wikitext text/x-wiki == Dukungan dan Komentar == Hi hi! Rencananya Halaman Utama ini akan menjadi halaman utama pengembangan proyek Wikiversitas bahasa Indonesia. Apabila berkenan, boleh memberikan dukungan atau komentar di bawah. Terima kasih! <small>Saya rencananya ingin membuat pertemuan daring untuk membahas proyek ini.</small> [[User:OwlyKnight|OwlyKnight]] ([[User talk:OwlyKnight|talk]]) 11:09, 6 June 2026 (UTC) :Halo OwlyKnight! :Terima kasih sudah merintis Halaman Utama ini. Saya sangat mendukung penuh pengembangan Wikiversitas bahasa Indonesia. :Saat ini saya sedang menyusun beberapa modul dan materi pembelajaran terbuka untuk Matematika Keuangan. Semoga kontribusi ini bisa membantu menambah beberapa bacaan. Kapan saja ada rencana diskusi atau koordinasi lebih lanjut maupun informasi aturan-aturan khusus lainnya dalam penulisan, saya siap menyimak dan mendukung. :Salam hangat! :[[User:Satya Rambana|Satya Rambana]] ([[User talk:Satya Rambana|talk]]) 01:27, 28 July 2026 (UTC) :Halo OwlyKnight! :Saya sedang mencoba untuk menuliskan persamaan matematika, menggunakan referensi yang ada seperti di Wikipedia bahasa Indonesia (https://id.wikipedia.org/wiki/Bantuan:Menampilkan_rumus) menggunakan penulisan Sintaks HTML. Namun, saya mendapati bahwa kemudian teks {{math}} menghasilkan tampilan teks dengan warna merah dan menunjukkan Template:Math (pages does not exist). Apakah terdapat cara tertentu untuk menuliskan persamaan matematika di Wikiversitas bahasa Indonesia? Terima kasih. [[User:Satya Rambana|Satya Rambana]] ([[User talk:Satya Rambana|talk]]) 03:00, 28 July 2026 (UTC) ::Halo, @[[User:Satya Rambana|Satya Rambana]]! Terima kasih banyak untuk antusiasmenya. Mohon maaf karena saya terlambat membalas pesan Anda di sini. Untuk Template:Math sepertinya belum ada di situs ini. Akan saya coba migrasi ke sini (bersama dengan templat-templat yang mungkin diperlukan) dan mungkin terjemahkan beberapa menjadi bahasa Indonesia, misalnya Template:Math menjadi Template:Matematika / Templat:Mat. Terima kasih! [[User:OwlyKnight|OwlyKnight]] ([[User talk:OwlyKnight|talk]]) 03:58, 5 August 2026 (UTC) ::Halo, @[[User:Satya Rambana|Satya Rambana]]! Saya sudah membuat beberapa templat matematika yang bisa dicek di sini: [[:Category:Templat format matematika]]. Secara umum, saya mengubah beberapa nama templat menjadi seperti berikut: ::* <nowiki>{{math}} → {{</nowiki>[[Template:matematika|matematika]]}} ::* <nowiki>{{mvar}} → {{</nowiki>[[Template:mvar|mvar]]}} (tidak berubah) ::* <nowiki>{{sfrac}} → {{</nowiki>[[Template:pecahan|pecahan]]}} ::* <nowiki>{{sub}} → {{</nowiki>[[Template:subskrip|subskrip]]}} ::* <nowiki>{{sup}} → {{</nowiki>[[Template:superskrip|superskrip]]}} ::* <nowiki>{{su}} → {{</nowiki>[[Template:subsup|subsup]]}} ::* <nowiki>{{overline}} → {{</nowiki>[[Template:garis atas|garis atas]]}} ::* <nowiki>{{overset}} → {{</nowiki>[[Template:set atas|set atas]]}} ::* <nowiki>{{underset}} → {{</nowiki>[[Template:set bawah|set bawah]]}} ::Terima kasih banyak! :D [[User:OwlyKnight|OwlyKnight]] ([[User talk:OwlyKnight|talk]]) 09:01, 5 August 2026 (UTC) :::Terima kasih atas bantuan Anda, @[[User:OwlyKnight|OwlyKnight]]! Templat-templat yang telah dibuat berfungsi dengan baik dalam proses penyuntingan di Wikiversitas bahasa Indonesia. Saya juga mengucapkan terima kasih atas waktu, tenaga, dan dedikasi yang telah Anda curahkan untuk membuat templat-templat tersebut. [[User:Satya Rambana|Satya Rambana]] ([[User talk:Satya Rambana|talk]]) 00:39, 6 August 2026 (UTC) 0duphvu4hhfcggr3crbrf4uam4vhpt7 385941 385940 2026-08-06T05:04:33Z OwlyKnight 53456 /* Dukungan dan Komentar */ Reply 385941 wikitext text/x-wiki == Dukungan dan Komentar == Hi hi! Rencananya Halaman Utama ini akan menjadi halaman utama pengembangan proyek Wikiversitas bahasa Indonesia. Apabila berkenan, boleh memberikan dukungan atau komentar di bawah. Terima kasih! <small>Saya rencananya ingin membuat pertemuan daring untuk membahas proyek ini.</small> [[User:OwlyKnight|OwlyKnight]] ([[User talk:OwlyKnight|talk]]) 11:09, 6 June 2026 (UTC) :Halo OwlyKnight! :Terima kasih sudah merintis Halaman Utama ini. Saya sangat mendukung penuh pengembangan Wikiversitas bahasa Indonesia. :Saat ini saya sedang menyusun beberapa modul dan materi pembelajaran terbuka untuk Matematika Keuangan. Semoga kontribusi ini bisa membantu menambah beberapa bacaan. Kapan saja ada rencana diskusi atau koordinasi lebih lanjut maupun informasi aturan-aturan khusus lainnya dalam penulisan, saya siap menyimak dan mendukung. :Salam hangat! :[[User:Satya Rambana|Satya Rambana]] ([[User talk:Satya Rambana|talk]]) 01:27, 28 July 2026 (UTC) :Halo OwlyKnight! :Saya sedang mencoba untuk menuliskan persamaan matematika, menggunakan referensi yang ada seperti di Wikipedia bahasa Indonesia (https://id.wikipedia.org/wiki/Bantuan:Menampilkan_rumus) menggunakan penulisan Sintaks HTML. Namun, saya mendapati bahwa kemudian teks {{math}} menghasilkan tampilan teks dengan warna merah dan menunjukkan Template:Math (pages does not exist). Apakah terdapat cara tertentu untuk menuliskan persamaan matematika di Wikiversitas bahasa Indonesia? Terima kasih. [[User:Satya Rambana|Satya Rambana]] ([[User talk:Satya Rambana|talk]]) 03:00, 28 July 2026 (UTC) ::Halo, @[[User:Satya Rambana|Satya Rambana]]! Terima kasih banyak untuk antusiasmenya. Mohon maaf karena saya terlambat membalas pesan Anda di sini. Untuk Template:Math sepertinya belum ada di situs ini. Akan saya coba migrasi ke sini (bersama dengan templat-templat yang mungkin diperlukan) dan mungkin terjemahkan beberapa menjadi bahasa Indonesia, misalnya Template:Math menjadi Template:Matematika / Templat:Mat. Terima kasih! [[User:OwlyKnight|OwlyKnight]] ([[User talk:OwlyKnight|talk]]) 03:58, 5 August 2026 (UTC) ::Halo, @[[User:Satya Rambana|Satya Rambana]]! Saya sudah membuat beberapa templat matematika yang bisa dicek di sini: [[:Category:Templat format matematika]]. Secara umum, saya mengubah beberapa nama templat menjadi seperti berikut: ::* <nowiki>{{math}} → {{</nowiki>[[Template:matematika|matematika]]}} ::* <nowiki>{{mvar}} → {{</nowiki>[[Template:mvar|mvar]]}} (tidak berubah) ::* <nowiki>{{sfrac}} → {{</nowiki>[[Template:pecahan|pecahan]]}} ::* <nowiki>{{sub}} → {{</nowiki>[[Template:subskrip|subskrip]]}} ::* <nowiki>{{sup}} → {{</nowiki>[[Template:superskrip|superskrip]]}} ::* <nowiki>{{su}} → {{</nowiki>[[Template:subsup|subsup]]}} ::* <nowiki>{{overline}} → {{</nowiki>[[Template:garis atas|garis atas]]}} ::* <nowiki>{{overset}} → {{</nowiki>[[Template:set atas|set atas]]}} ::* <nowiki>{{underset}} → {{</nowiki>[[Template:set bawah|set bawah]]}} ::Terima kasih banyak! :D [[User:OwlyKnight|OwlyKnight]] ([[User talk:OwlyKnight|talk]]) 09:01, 5 August 2026 (UTC) :::Terima kasih atas bantuan Anda, @[[User:OwlyKnight|OwlyKnight]]! Templat-templat yang telah dibuat berfungsi dengan baik dalam proses penyuntingan di Wikiversitas bahasa Indonesia. Saya juga mengucapkan terima kasih atas waktu, tenaga, dan dedikasi yang telah Anda curahkan untuk membuat templat-templat tersebut. [[User:Satya Rambana|Satya Rambana]] ([[User talk:Satya Rambana|talk]]) 00:39, 6 August 2026 (UTC) ::::@[[User:Satya Rambana|Satya Rambana]]: Terima kasih kembali dan senang untuk berkontribusi bersama :D ::::Untuk draft panduan dan kebijakan akan saya coba buat secepatnya. Semoga bisa sebelum Agustus akhir atau sebelum mulai semester. Catatan: Panduan dan kebijakan ini tentu dapat berubah sesuai dengan diskusi kita kontributor :D [[User:OwlyKnight|OwlyKnight]] ([[User talk:OwlyKnight|talk]]) 05:04, 6 August 2026 (UTC) e8pd8v5invqoywfewh7qlrebjz8wkdj Рэндэрынг мноства Мандэльброта на C++ 0 55805 385939 385916 2026-08-05T17:26:37Z Aokoroko 55658 /* Зыходны код C++ */ 385939 wikitext text/x-wiki {{Language|be}} <span style="font-size:90%; color:#54595d;">Мовы курса:</span> [https://ru.wikiversity.org/wiki/Рендеринг_множества_Мандельброта_на_C%2B%2B 🇷🇺 Русский] • '''🇧🇾 Беларуская''' • [[Рендеринг множини Мандельброта на C++|🇺🇦 Українська]] {| class="wikitable" style="float: right; margin: 0 0 1em 1em; width: 300px;" |- ! colspan="2" | Курс «Рэндэрынг мноства Мандэльброта на C++» |- | '''Факультэт:''' || Інфармацыйныя тэхналогіі |- | '''Прэрэквізіты:''' || Веданне сінтаксісу C++ і камплексных лікаў |- | '''Патрабаванні пасля:''' || Навыкі аптымізацыі рэндэрынгу фракталаў |- | '''Выкладчык:''' || [[User:Aokoroko]] |} == Уводзіны == Дадзены практыкум змяшчае арыгінальны зыходны код на C++ для высокадакладнага рэндэрынгу фрагментаў мноства Мандэльброта з выкарыстаннем алгарытмаў аптымізацыі (уключаючы тэорыю абурэнняў) і глыбокага згладжвання (8x8 SSAA). Аўтар алгарытму і выяў: [[User:Aokoroko]]. == Ключавыя асаблівасці == * Разлік апорнай траекторыі на 1000 біт усяго адзін раз. * Рэактыўны разлік мільярда пікселяў на апаратным double. * Разлік можна выканаць істотна хутчэй, калі выкарыстоўваць білінейную апраксімацыю. * Пры выкарыстанні лікаў з плаваючай коскай двайной дакладнасці (парадку 10⁻¹⁵) тэорыя абурэнняў дазваляе наблізіцца да ўзроўню 10⁻³⁰⁸ - не далей. * Рэвалюцыйны алгарытм Reference Reset to Zero. * Сапраўдны SSAA 8x8 для ідэальна згладжанага малюнка без аліасінгу. * Паралелізм OpenMP для высокахуткаснага шматпаточнага рэндэрынгу. == Зыходны код C++ == Ніжэй прадстаўлены зыходны код праграмы, які выкарыстоўваўся для генерацыі 100-мегапіксельных выбраных выяў на Вікісховішчы. <syntaxhighlight lang="cpp"> #include <atomic> #include <cmath> #include <cstdint> #include <cstdio> #include <vector> #include <algorithm> #include <mpfr.h> #include <omp.h> using std::vector; using std::min; const char * CENTER_RE = "-1.99999543561201124623198345433951143502785679245726844745821388800402678499411681518036306219179273434395557574279985918047221291197081186140687781560831995"; const char * CENTER_IM = "-0.00000000000000000000000026198152173811047783694060060607013913873144250985383083459221663448338433592617272786772587281530484110756597337683912309313885172"; const char * VIEW_SIZE = "1.15e-119"; const int WIDTH = 2160; const int HEIGHT = 2160; const int AA = 8; const int MAX_ITER = 50000; const double ESCAPE_RADIUS_SQUARED = 50000.0; const int PALETTE_FRAME = 200; const char * OUTPUT_FILE = "Mandelbrot Set Image 112.bmp"; const mpfr_prec_t PRECISION_BITS = 1000; const int REF_SIZE = MAX_ITER + 200; 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(REF_SIZE); mpfr_set_ui(zReMp, 0, MPFR_RNDN); mpfr_set_ui(zImMp, 0, MPFR_RNDN); for (int iter = 0; iter < REF_SIZE - 1; ++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); std::fprintf(stderr, "Precomputing skip100 matrices...\n"); vector<Complex> coeff_A(REF_SIZE, {1.0, 0.0}); vector<Complex> coeff_B(REF_SIZE, {0.0, 0.0}); vector<double> rad_R(REF_SIZE, 2.0); vector<double> aS_squared(REF_SIZE, 0.0); for (int i = 0; i < referenceLength; ++i) { double r2 = referenceOrbit[i].re * referenceOrbit[i].re + referenceOrbit[i].im * referenceOrbit[i].im; aS_squared[i] = (r2 < ESCAPE_RADIUS_SQUARED) ? r2 : 0.0; } const int loop_limit = min(static_cast<int>(MAX_ITER), referenceLength - 105); #pragma omp parallel for for (int i = 0; i < loop_limit; ++i) { double min_r2 = ESCAPE_RADIUS_SQUARED; for (int k = 0; k < 100; ++k) { if (i + k >= referenceLength) break; if (aS_squared[i + k] < min_r2) min_r2 = aS_squared[i + k]; } rad_R[i] = std::sqrt(min_r2); for (int k = 0; k < 100; ++k) { if (i + k >= referenceLength) break; double r_re = referenceOrbit[i + k].re; double r_im = referenceOrbit[i + k].im; double next_A_re = 2.0 * (r_re * coeff_A[i].re - r_im * coeff_A[i].im); double next_A_im = 2.0 * (r_re * coeff_A[i].im + r_im * coeff_A[i].re); double next_B_re = 2.0 * (r_re * coeff_B[i].re - r_im * coeff_B[i].im) + 1.0; double next_B_im = 2.0 * (r_re * coeff_B[i].im + r_im * coeff_B[i].re); coeff_A[i].re = next_A_re; coeff_A[i].im = next_A_im; coeff_B[i].re = next_B_re; coeff_B[i].im = next_B_im; } } 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) { if (zRe * zRe + zIm * zIm >= ESCAPE_RADIUS_SQUARED) { break; } double eps_abs2 = deltaRe * deltaRe + deltaIm * deltaIm; double limit_r2 = 1e-60 * rad_R[referenceIndex] * rad_R[referenceIndex]; if (eps_abs2 < limit_r2 && (referenceIndex + 100 < loop_limit) && (iter + 100 < MAX_ITER)) { double backup_deltaRe = deltaRe; double backup_deltaIm = deltaIm; int backup_refIdx = referenceIndex; int backup_iter = iter; double next_eps_re = (coeff_A[referenceIndex].re * deltaRe - coeff_A[referenceIndex].im * deltaIm) + (coeff_B[referenceIndex].re * deltaCRe - coeff_B[referenceIndex].im * deltaCIm); double next_eps_im = (coeff_A[referenceIndex].re * deltaIm + coeff_A[referenceIndex].im * deltaRe) + (coeff_B[referenceIndex].re * deltaCIm + coeff_B[referenceIndex].im * deltaCRe); deltaRe = next_eps_re; deltaIm = next_eps_im; referenceIndex += 100; iter += 100; zRe = reference[referenceIndex].re + deltaRe; zIm = reference[referenceIndex].im + deltaIm; if (zRe * zRe + zIm * zIm >= ESCAPE_RADIUS_SQUARED) { deltaRe = backup_deltaRe; deltaIm = backup_deltaIm; referenceIndex = backup_refIdx; iter = backup_iter; } else { continue; } } 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 >= loop_limit) { 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! Saved to %s in %.2f seconds.\n", OUTPUT_FILE, omp_get_wtime() - startTime); return 0; } </syntaxhighlight> == Прыклады выяў == <gallery mode="packed" heights="200"> File:Mandelbrot Set Image 107.png|Фрагмент мноства, тэорыя абурэнняў. Адрознівальная здольнасць 10000 x 10000 пікселяў. File:Mandelbrot Set Image 108.png|Фрагмент мноства, тэорыя абурэнняў. Адрознівальная здольнасць 10000 x 10000 пікселяў. File:Mandelbrot Set Image 109.png|Фрагмент мноства, тэорыя абурэнняў. Адрознівальная здольнасць 10000 x 10000 пікселяў. File:Mandelbrot Set Image 110.png|Фрагмент мноства, тэорыя абурэнняў. Адрознівальная здольнасць 10000 x 10000 пікселяў. </gallery> == Спасылкі == * [https://github.com/Divetoxx/Mandelbrot Афіцыйны рэпазіторый праекта Mandelbrot CLI на GitHub] — зыходны код, дакументацыя і гатовыя рэлізы праграмы рэндэрынгу. * [https://rosettacode.org/wiki/Mandelbrot_set#Perturbation_Theory Прыклады аптымізацыі на Rosetta Code] — рэалізацыя тэорыі абурэнняў на C++ у глабальнай базе праграмных рашэнняў. [[Category:be:Computer science]] [[Category:BE]] o2tezev0qzh5fb4006iw7sbbu7prmvq Рендеринг множини Мандельброта на C++ 0 55806 385938 385914 2026-08-05T17:25:58Z Aokoroko 55658 /* Вихідний код C++ */ 385938 wikitext text/x-wiki {{Language|uk}} <span style="font-size:90%; color:#54595d;">Мови курсу:</span> [https://ru.wikiversity.org/wiki/Рендеринг_множества_Мандельброта_на_C%2B%2B 🇷🇺 Русский] • [[Рэндэрынг мноства Мандэльброта на C++|🇧🇾 Беларуская]] • '''🇺🇦 Українська''' {| class="wikitable" style="float: right; margin: 0 0 1em 1em; width: 300px;" |- ! colspan="2" | Курс «Рендеринг множини Мандельброта на C++» |- | '''Факультет:''' || Інформаційні технології |- | '''Пререквізити:''' || Знання синтаксису C++ та комплексних чисел |- | '''Постреквізити:''' || Навички оптимізації рендерингу фракталів |- | '''Викладач:''' || [[User:Aokoroko]] |} == Вступ == Даний практикум містить оригінальний вихідний код на C++ для високоточного рендерингу фрагментів множини Мандельброта з використанням алгоритмів оптимізації (включаючи теорію збурень) та глибокого згладжування (8x8 SSAA). Автор алгоритму та зображень: [[User:Aokoroko]]. == Ключові особливості == * Розрахунок опорної траєкторії на 1000 біт усього один раз. * Реактивний розрахунок мільярда пікселів на апаратному double. * Розрахунок можна виконати суттєво швидше, якщо використовувати білінійну апроксимацію. * При використанні чисел із плаваючою комою подвійної точності (порядку 10⁻¹⁵) теорія збурень дозволяє наблизитися до рівня 10⁻³⁰⁸ - не далі. * Революційний алгоритм Reference Reset to Zero. * Справжній SSAA 8x8 для ідеально згладженого зображення без аліасингу. * Паралелізм OpenMP для високошвидкісного багатопотокового рендерингу. == Вихідний код C++ == Ниже представлений вихідний код програми, що використовувався для генерації 100-мегапіксельних вибраних зображень на Вікісховищі. <syntaxhighlight lang="cpp"> #include <atomic> #include <cmath> #include <cstdint> #include <cstdio> #include <vector> #include <algorithm> #include <mpfr.h> #include <omp.h> using std::vector; using std::min; const char * CENTER_RE = "-1.99999543561201124623198345433951143502785679245726844745821388800402678499411681518036306219179273434395557574279985918047221291197081186140687781560831995"; const char * CENTER_IM = "-0.00000000000000000000000026198152173811047783694060060607013913873144250985383083459221663448338433592617272786772587281530484110756597337683912309313885172"; const char * VIEW_SIZE = "1.15e-119"; const int WIDTH = 2160; const int HEIGHT = 2160; const int AA = 8; const int MAX_ITER = 50000; const double ESCAPE_RADIUS_SQUARED = 50000.0; const int PALETTE_FRAME = 200; const char * OUTPUT_FILE = "Mandelbrot Set Image 112.bmp"; const mpfr_prec_t PRECISION_BITS = 1000; const int REF_SIZE = MAX_ITER + 200; 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(REF_SIZE); mpfr_set_ui(zReMp, 0, MPFR_RNDN); mpfr_set_ui(zImMp, 0, MPFR_RNDN); for (int iter = 0; iter < REF_SIZE - 1; ++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); std::fprintf(stderr, "Precomputing skip100 matrices...\n"); vector<Complex> coeff_A(REF_SIZE, {1.0, 0.0}); vector<Complex> coeff_B(REF_SIZE, {0.0, 0.0}); vector<double> rad_R(REF_SIZE, 2.0); vector<double> aS_squared(REF_SIZE, 0.0); for (int i = 0; i < referenceLength; ++i) { double r2 = referenceOrbit[i].re * referenceOrbit[i].re + referenceOrbit[i].im * referenceOrbit[i].im; aS_squared[i] = (r2 < ESCAPE_RADIUS_SQUARED) ? r2 : 0.0; } const int loop_limit = min(static_cast<int>(MAX_ITER), referenceLength - 105); #pragma omp parallel for for (int i = 0; i < loop_limit; ++i) { double min_r2 = ESCAPE_RADIUS_SQUARED; for (int k = 0; k < 100; ++k) { if (i + k >= referenceLength) break; if (aS_squared[i + k] < min_r2) min_r2 = aS_squared[i + k]; } rad_R[i] = std::sqrt(min_r2); for (int k = 0; k < 100; ++k) { if (i + k >= referenceLength) break; double r_re = referenceOrbit[i + k].re; double r_im = referenceOrbit[i + k].im; double next_A_re = 2.0 * (r_re * coeff_A[i].re - r_im * coeff_A[i].im); double next_A_im = 2.0 * (r_re * coeff_A[i].im + r_im * coeff_A[i].re); double next_B_re = 2.0 * (r_re * coeff_B[i].re - r_im * coeff_B[i].im) + 1.0; double next_B_im = 2.0 * (r_re * coeff_B[i].im + r_im * coeff_B[i].re); coeff_A[i].re = next_A_re; coeff_A[i].im = next_A_im; coeff_B[i].re = next_B_re; coeff_B[i].im = next_B_im; } } 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) { if (zRe * zRe + zIm * zIm >= ESCAPE_RADIUS_SQUARED) { break; } double eps_abs2 = deltaRe * deltaRe + deltaIm * deltaIm; double limit_r2 = 1e-60 * rad_R[referenceIndex] * rad_R[referenceIndex]; if (eps_abs2 < limit_r2 && (referenceIndex + 100 < loop_limit) && (iter + 100 < MAX_ITER)) { double backup_deltaRe = deltaRe; double backup_deltaIm = deltaIm; int backup_refIdx = referenceIndex; int backup_iter = iter; double next_eps_re = (coeff_A[referenceIndex].re * deltaRe - coeff_A[referenceIndex].im * deltaIm) + (coeff_B[referenceIndex].re * deltaCRe - coeff_B[referenceIndex].im * deltaCIm); double next_eps_im = (coeff_A[referenceIndex].re * deltaIm + coeff_A[referenceIndex].im * deltaRe) + (coeff_B[referenceIndex].re * deltaCIm + coeff_B[referenceIndex].im * deltaCRe); deltaRe = next_eps_re; deltaIm = next_eps_im; referenceIndex += 100; iter += 100; zRe = reference[referenceIndex].re + deltaRe; zIm = reference[referenceIndex].im + deltaIm; if (zRe * zRe + zIm * zIm >= ESCAPE_RADIUS_SQUARED) { deltaRe = backup_deltaRe; deltaIm = backup_deltaIm; referenceIndex = backup_refIdx; iter = backup_iter; } else { continue; } } 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 >= loop_limit) { 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! Saved to %s in %.2f seconds.\n", OUTPUT_FILE, omp_get_wtime() - startTime); return 0; } </syntaxhighlight> == Приклади зображень == <gallery mode="packed" heights="200"> File:Mandelbrot Set Image 107.png|Фрагмент множини, теорія збурень. Роздільна здатність 10000 x 10000 пікселів. File:Mandelbrot Set Image 108.png|Фрагмент множини, теорія збурень. Роздільна здатність 10000 x 10000 пікселів. File:Mandelbrot Set Image 109.png|Фрагмент множини, теорія збурень. Роздільна здатність 10000 x 10000 пікселів. File:Mandelbrot Set Image 110.png|Фрагмент множини, теорія збурень. Роздільна здатність 10000 x 10000 пікселів. </gallery> == Посилання == * [https://github.com/Divetoxx/Mandelbrot Офіційний репозиторій проєкту Mandelbrot CLI на GitHub] — вихідний код, документація та готові релізи програми рендерингу. * [https://rosettacode.org/wiki/Mandelbrot_set#Perturbation_Theory Приклади оптимізації на Rosetta Code] — реалізацыя теорії збурень на C++ у глобальній базі програмних рішень. [[Category:uk:Computer science]] [[Category:UK]] rxr99z4qr3brswfgqzu5edvo2g9yi1e User:KuddA88161 2 56042 385936 2026-08-05T14:02:42Z KuddA88161 55776 Created page with "<div style="max-width: 900px; margin: auto; font-family: Georgia, 'Times New Roman', serif;"> <div style="text-align:center; padding:35px 20px; border:1px solid #aaa; background:#f8f6f0;"> ’’‘KUDDA88161’’’ <div style="font-size:110%; letter-spacing:3px; margin-top:8px;"> ''STUDERE · CREARE · DOCERE'' </div> <div style="margin-top:18px; font-size:120%;"> ''“I am here to learn and create.”'' </div> </div> <div style="margin-top:25px; padding:20px; borde..." 385936 wikitext text/x-wiki <div style="max-width: 900px; margin: auto; font-family: Georgia, 'Times New Roman', serif;"> <div style="text-align:center; padding:35px 20px; border:1px solid #aaa; background:#f8f6f0;"> ’’‘KUDDA88161’’’ <div style="font-size:110%; letter-spacing:3px; margin-top:8px;"> ''STUDERE · CREARE · DOCERE'' </div> <div style="margin-top:18px; font-size:120%;"> ''“I am here to learn and create.”'' </div> </div> <div style="margin-top:25px; padding:20px; border-left:4px solid #777; background:#f8f8f8;"> == 📖 MY LIBRARY == I am interested in knowledge, learning, and the many ideas that can be studied, explored, and developed. </div> <div style="display:flex; gap:15px; flex-wrap:wrap; margin-top:20px;"> <div style="flex:1; min-width:250px; padding:20px; border:1px solid #bbb; background:#faf9f5;"> === 📚 READING === Books, texts, and works I am currently exploring. </div> <div style="flex:1; min-width:250px; padding:20px; border:1px solid #bbb; background:#faf9f5;"> === 🔬 LEARNING === Subjects and ideas that I am currently studying. </div> </div> <div style="display:flex; gap:15px; flex-wrap:wrap; margin-top:15px;"> <div style="flex:1; min-width:250px; padding:20px; border:1px solid #bbb; background:#faf9f5;"> === ✒️ WRITING === Pages, notes, and ideas that I create. </div> <div style="flex:1; min-width:250px; padding:20px; border:1px solid #bbb; background:#faf9f5;"> === 🏛️ WIKIVERSITY === A place where I learn, write, explore, and share knowledge. </div> </div> <div style="margin-top:25px; padding:20px; background:#f4f1e8; border:1px solid #aaa;"> == 📜 MY INTERESTS == <div style="text-align:center; font-size:110%;"> ‘’‘History · Science · Philosophy · Technology · Languages · Education’’’ </div> </div> <div style="margin-top:25px; padding:20px; border:1px solid #aaa;"> == 🖋️ MY NOTES == <div style="font-family:Georgia,serif; font-size:115%; text-align:center; padding:15px;"> ‘’“Knowledge is not merely something to possess, but something to explore, develop, and share.”’’ </div> </div> <div style="margin-top:25px; padding:20px; border:1px solid #aaa;"> == 📚 MY WORKS == * [[Wikiversity:Sekolah]] * [[Wikiversity:Sekolah/Sekolah Dasar]] * [[User:KuddA88161/Sandbox|My Sandbox]] </div> <div style="margin-top:30px; text-align:center; padding:20px; border-top:1px solid #aaa; color:#666;"> ‘’‘❦’’’ ‘‘Kudd Asahara · Wikiversity · 2026’’ </div> </div> b1z054ziupqc26tfenajxnvqhm3ftp8 User:KuddA88161/Sandbox 2 56043 385937 2026-08-05T14:04:49Z KuddA88161 55776 Created page with "<div style="max-width:900px; margin:auto; font-family:Georgia, 'Times New Roman', serif;"> <div style="text-align:center; padding:35px 20px; border:1px solid #aaa; background:#f8f6f0;"> ’’‘KUDDA88161’S SANDBOX’’’ <div style="font-size:110%; letter-spacing:2px; margin-top:10px;"> ''TABULA EXPERIMENTORUM'' </div> <div style="margin-top:15px;"> ''A personal workspace for drafts, experiments, notes, and unfinished ideas.'' </div> </div> <div style="margin-top..." 385937 wikitext text/x-wiki <div style="max-width:900px; margin:auto; font-family:Georgia, 'Times New Roman', serif;"> <div style="text-align:center; padding:35px 20px; border:1px solid #aaa; background:#f8f6f0;"> ’’‘KUDDA88161’S SANDBOX’’’ <div style="font-size:110%; letter-spacing:2px; margin-top:10px;"> ''TABULA EXPERIMENTORUM'' </div> <div style="margin-top:15px;"> ''A personal workspace for drafts, experiments, notes, and unfinished ideas.'' </div> </div> <div style="margin-top:25px; padding:20px; border-left:4px solid #777; background:#f8f8f8;"> == 🧪 THE WORKBENCH == This is my personal workspace on Wikiversity. I use this page to experiment with wiki markup, develop ideas, write drafts, organize notes, and test things before they become finished work. ‘’‘Nothing here has to be perfect.’’’ It is a place to learn by doing. </div> <div style="display:flex; gap:15px; flex-wrap:wrap; margin-top:20px;"> <div style="flex:1; min-width:250px; padding:20px; border:1px solid #bbb; background:#faf9f5;"> === ✒️ DRAFTS === Pages and writings that are still being developed. * ‘‘Draft 01 —’’ * ‘‘Draft 02 —’’ * ‘‘Draft 03 —’’ </div> <div style="flex:1; min-width:250px; padding:20px; border:1px solid #bbb; background:#faf9f5;"> === 🔬 EXPERIMENTS === Things I am testing or learning. * Wiki markup * Templates * Page layouts * New ideas </div> </div> <div style="margin-top:20px; padding:20px; background:#f4f1e8; border:1px solid #aaa;"> == 📓 NOTES == <div style="padding:10px;"> ‘’‘Current notes’’’ ‘’‘Questions to explore’’’ </div> </div> <div style="margin-top:20px; padding:20px; border:1px solid #aaa;"> </div> <div style="margin-top:20px; padding:20px; border:1px solid #aaa;"> == 🗃️ ARCHIVE == Old drafts and experiments may be kept here for reference. * [[/Archive|Archive]] </div> <div style="margin-top:30px; padding:20px; text-align:center; border-top:1px solid #aaa; color:#666;"> ‘’‘❦’’’ ‘’“Every finished work begins as an unfinished idea.”’’ </div> </div> [[Category:Wikiversity user pages]] 01ynh93n52tiw5n0s1cgteai6ij9atk