Advertisement
ms_shnits

Бассейны Ньютона для уравнения z^4 - 1 = 0

Apr 11th, 2018
347
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.26 KB | None | 0 0
  1. /*
  2.  
  3.     Бассейны Ньютона для уравнения z^4 - 1 = 0
  4.  
  5. */
  6.  
  7. #include <math.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10.  
  11.  
  12.  
  13. /* всякие функции, эмулирующие работу с комплексными числами */
  14. struct Complex
  15.     {
  16.         float x;
  17.         float y;
  18.     };
  19.  
  20. typedef struct Complex   ComplexType;
  21. typedef struct Complex * ComplexRef;
  22.  
  23. ComplexType Complex_number (float x, float y)
  24. {
  25.     ComplexType result;
  26.     result.x = x;
  27.     result.y = y;
  28.     return result;
  29. }
  30.  
  31. ComplexType Complex_sum (ComplexType u, ComplexType v)
  32. {
  33.     ComplexType result;
  34.     result.x = u.x + v.x;
  35.     result.y = u.y + v.y;
  36.     return result;
  37. }
  38.  
  39. ComplexType Complex_sub (ComplexType u, ComplexType v)
  40. {
  41.     ComplexType result;
  42.     result.x = u.x - v.x;
  43.     result.y = u.y - v.y;
  44.     return result;
  45. }
  46.  
  47. ComplexType Complex_prod (ComplexType u, ComplexType v)
  48. {
  49.     ComplexType result;
  50.     result.x = u.x*v.x - u.y*v.y,
  51.     result.y = u.x*v.y + u.y*v.x;
  52.     return result;
  53. }
  54.  
  55. float Complex_abs2 (ComplexType u)
  56. {
  57.     return u.x*u.x + u.y*u.y;
  58. }
  59.  
  60. ComplexType Complex_conj (ComplexType u)
  61. {
  62.     return Complex_number (u.x, -u.y);
  63. }
  64.  
  65. ComplexType Complex_div (ComplexType u, ComplexType v, int *error)
  66. {
  67.     *error = 0;
  68.     float
  69.         r = Complex_abs2(v);
  70.     if (r == 0)
  71.         *error = 1;
  72.     ComplexType result = Complex_prod(u, Complex_conj(v));
  73.     if (!(*error))
  74.     {
  75.         result.x /= r;
  76.         result.y /= r;
  77.     }
  78.     return result;
  79. }
  80.  
  81. ComplexType Complex_pown(ComplexType z, int n)
  82. {
  83.     ComplexType result = Complex_number(1, 0);
  84.     while(n > 0)
  85.     {
  86.         if (n & 1)
  87.             result = Complex_prod(result, z);
  88.         n >>= 1;
  89.         z = Complex_prod(z, z);
  90.     }
  91.     return result;
  92. }
  93. /* end of всякие функции, эмулирующие работу с комплексными числами */
  94.  
  95.  
  96.  
  97. /* функция, определяющая, к какому из четырех корней {1, -1, i, -i} уравнения z^4 - 1 = 0
  98.    сходится итерационный процесс метода Ньютона от начальной точки z0 = x + iy */
  99. int newton (float x, float y)
  100. {
  101.     ComplexType
  102.         z = Complex_number(x, y),
  103.         prev_z = Complex_number(1000, 1000);
  104.  
  105.     int error;
  106.  
  107.     /* пока очередное приближение не стало слишком большим (процесс расходится) и
  108.     очередное приближение заметно отличается от предыдущего (процесс сошелся), считаем итерации
  109.     */
  110.     while ((Complex_abs2(z) < 1e6) && (Complex_abs2(Complex_sub(z, prev_z)) > 1e-6))
  111.     {
  112.         // запоминаем предыдущее приближение
  113.         prev_z = z;
  114.  
  115.         // считаем новое приближение по формуле z - (z^4 - 1) / (4 z^3)
  116.         z = Complex_sub(z, Complex_div(Complex_sub(Complex_pown(z, 4), Complex_number(1,0)), Complex_prod(Complex_number(4,0), Complex_pown(z, 3)), &error));
  117.  
  118.         // если на (4 z^3) поделить нельза, заплакали и вышли
  119.         if (error)
  120.             return 0;
  121.     }
  122.     /* end of пока очередное приближение ... считаем итерации*/
  123.  
  124.     /* анализируем результат: */
  125.  
  126.     // процесс разошелся
  127.     if (Complex_abs2(z) > 1e6)
  128.         return 0;
  129.  
  130.     // нас прибило к корню 1
  131.     if (Complex_abs2(Complex_sub(z, Complex_number(1,0))) < 1e-3)
  132.         return 1;
  133.  
  134.     // нас прибило к корню -1
  135.     if (Complex_abs2(Complex_sub(z, Complex_number(-1,0))) < 1e-3)
  136.         return 2;
  137.  
  138.     // нас прибило к корню i
  139.     if (Complex_abs2(Complex_sub(z, Complex_number(0,1))) < 1e-3)
  140.         return 3;
  141.  
  142.     // нас прибило к корню -i
  143.     if (Complex_abs2(Complex_sub(z, Complex_number(0,-1))) < 1e-3)
  144.         return 4;
  145.  
  146.     // нас занесло неведомо куда
  147.     return 0;
  148. }
  149.  
  150.  
  151. int main(void)
  152. {
  153.     // задаем размеры картинки
  154.     int Xpixels = 500, Ypixels = 500;
  155.  
  156.     // задаем размеры области комплексной плоскости
  157.     float Xmin = -10.0, Xmax = 10.0, Ymin = -10.0, Ymax = 10.0;
  158.  
  159.     /* рисуем картинку */
  160.     FILE *f = fopen("result.ppm", "w");
  161.     fprintf(f, "P3\n");
  162.     fprintf(f, "%d %d 255\n", Xpixels, Ypixels);
  163.  
  164.     for (int y = 0; y < Ypixels; y++)
  165.     {
  166.         for (int x = 0; x < Xpixels; x++)
  167.         {
  168.             switch (newton(Xmin + (Xmax - Xmin) / Xpixels * x, Ymin + (Ymax - Ymin) / Ypixels * y))
  169.             {
  170.                 case 1: fprintf(f, "%d %d %d  ", 255,   0,   0); break;
  171.                 case 2: fprintf(f, "%d %d %d  ",   0, 255,   0); break;
  172.                 case 3: fprintf(f, "%d %d %d  ",   0,   0, 255); break;
  173.                 case 4: fprintf(f, "%d %d %d  ", 255, 255,   0); break;
  174.                 default:
  175.                         fprintf(f, "%d %d %d  ",   0,   0,   0); break;
  176.             }
  177.         }
  178.         fprintf(f, "\n");
  179.     }
  180.  
  181.     fclose(f);
  182.     /* end of рисуем картинку */
  183.  
  184.     return 0;
  185. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement