From cf2881b60ead8b9bbeac6b48b4e5f1c52e6360d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B8=D0=BA=D0=BE=D0=BB=D0=B0=D0=B9=20=D0=AE=D1=85?= =?UTF-8?q?=D0=BD=D0=B8=D0=BA=2C=D0=B3=D1=80=2E=20334701?= Date: Wed, 17 Sep 2025 09:15:40 +0300 Subject: [PATCH 1/4] =?UTF-8?q?A:=20=D0=BD=D0=BE=D0=B2=D0=B0=D1=8F=20?= =?UTF-8?q?=D1=86=D0=B2=D0=B5=D1=82=D0=BE=D0=B2=D0=B0=D1=8F=20=D0=BF=D0=B0?= =?UTF-8?q?=D0=BB=D0=B8=D1=82=D1=80=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/demo/parallel/MandelbrotSetTask.java | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/demo/parallel/MandelbrotSetTask.java b/src/demo/parallel/MandelbrotSetTask.java index adbb217b8..0fab8dfd7 100644 --- a/src/demo/parallel/MandelbrotSetTask.java +++ b/src/demo/parallel/MandelbrotSetTask.java @@ -38,7 +38,7 @@ import javafx.scene.paint.Color; -/** +/* * Task to render Mandelbrot set using given parameters. See {@link * #MandelbrotRendererTask(boolean, javafx.scene.image.PixelWriter, int, int, * double, double, double, double, double, double, double, double, boolean) @@ -351,20 +351,13 @@ private Color getColor(int count) { * Color stops for colors table: color values */ Color[] cc = { - Color.rgb(40, 0, 0), - Color.RED, - Color.WHITE, - Color.RED, - Color.rgb(100, 0, 0), - Color.RED, - Color.rgb(50, 0, 0) + Color.rgb(0, 7, 100), // тёмно-синий + Color.BLUE, + Color.CYAN, + Color.YELLOW, + Color.WHITE }; - - /** - * Color stops for colors table: relative position in the table - */ - double[] cp = { - 0, 0.17, 0.25, 0.30, 0.5, 0.75, 1,}; + double[] cp = { 0.0, 0.25, 0.5, 0.75, 1.0 }; /** * Color table population From 536524cf05a598a742f985993860d342d33dd677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B8=D0=BA=D0=BE=D0=BB=D0=B0=D0=B9=20=D0=AE=D1=85?= =?UTF-8?q?=D0=BD=D0=B8=D0=BA=2C=D0=B3=D1=80=2E=20334701?= Date: Wed, 17 Sep 2025 09:29:11 +0300 Subject: [PATCH 2/4] =?UTF-8?q?=D0=B2=D1=82=D0=BE=D1=80=D0=BE=D0=B9=20?= =?UTF-8?q?=D0=BA=D0=BE=D0=BC=D0=B8=D1=82-=20=D0=B8=D0=B7=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=84=D1=80=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=B0=D0=BB=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/demo/parallel/MandelbrotSetTask.java | 277 +++-------------------- 1 file changed, 28 insertions(+), 249 deletions(-) diff --git a/src/demo/parallel/MandelbrotSetTask.java b/src/demo/parallel/MandelbrotSetTask.java index 0fab8dfd7..4721b0337 100644 --- a/src/demo/parallel/MandelbrotSetTask.java +++ b/src/demo/parallel/MandelbrotSetTask.java @@ -1,152 +1,32 @@ -/* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ package demo.parallel; - import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.IntStream; import javafx.concurrent.Task; import javafx.scene.image.PixelWriter; import javafx.scene.paint.Color; - -/* - * Task to render Mandelbrot set using given parameters. See {@link - * #MandelbrotRendererTask(boolean, javafx.scene.image.PixelWriter, int, int, - * double, double, double, double, double, double, double, double, boolean) - * constructor} for parameters list. The task returns time in milliseconds as - * its calculated value. - * - *

- * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - * - * @author Alexander Kouznetsov, Tristan Yan - */ class MandelbrotSetTask extends Task { - - /** - * Calculation times, deliberately choose it as 256 because we will use the - * count to calculate Color - */ private static final int CAL_MAX_COUNT = 256; - - /** - * This is the square of max radius, Mandelbrot set contained in the closed - * disk of radius 2 around the origin plus some area around, so - * LENGTH_BOUNDARY is 6. - */ private static final double LENGTH_BOUNDARY = 6d; - - /** - * For antialiasing we break each pixel into 3x3 grid and interpolate - * between values calculated on those grid positions - */ private static final int ANTIALIASING_BASE = 3; - - /** - * Sequential vs. parallel calculation mode - */ + private final boolean parallel; - - /** - * Antialiased mode flag - */ private final boolean antialiased; - - /** - * Dimension of the area - */ private final int width, height; - - /** - * Rectangle range to exclude from calculations. Used to skip calculations - * for parts of MandelbrotSet that are already calculated. - */ private final double minX, minY, maxX, maxY; - - /** - * Real and imaginary part of min and max number in the set we need - * calculate - */ private final double minR, minI, maxR, maxI; - - /** - * Pixel writer to use for writing calculated pixels - */ private final PixelWriter pixelWriter; - - /** - * Flag indicating that some new pixels were calculated - */ private volatile boolean hasUpdates; - - /** - * Start time of the task in milliseconds - */ private volatile long startTime = -1; - - /** - * Total time of the task in milliseconds - */ private volatile long taskTime = -1; - - /** - * Progress of the task - */ private final AtomicInteger progress = new AtomicInteger(0); - /** - * Creates a task to render a MandelBrot set into an image using given - * PixelWriter with given dimensions of the image, given real and imaginary - * values range and given rectangular area to skip. Also there is a switch - * that disables more computational-extensive antialiasing mode. - * @param parallel parallel vs. sequential switch - * @param pixelWriter target to write pixels to - * @param width width of the image area - * @param height height of the image area - * @param minR min real value of the area - * @param minI min imaginary value of the area - * @param maxR max real value of the area - * @param maxI max imaginary value of the area - * @param minX min x value of the rectangular area to skip - * @param minY min y value of the rectangular area to skip - * @param maxX max x value of the rectangular area to skip - * @param maxY max y value of the rectangular area to skip - * @param fast fast mode disables antialiasing - */ - public MandelbrotSetTask(boolean parallel, PixelWriter pixelWriter, int width, int height, double minR, double minI, double maxR, double maxI, double minX, double minY, double maxX, double maxY, boolean fast) { + public MandelbrotSetTask(boolean parallel, PixelWriter pixelWriter, + int width, int height, + double minR, double minI, double maxR, double maxI, + double minX, double minY, double maxX, double maxY, + boolean fast) { this.parallel = parallel; this.pixelWriter = pixelWriter; this.width = width; @@ -163,59 +43,25 @@ public MandelbrotSetTask(boolean parallel, PixelWriter pixelWriter, int width, i updateProgress(0, 0); } - /** - * - * @return whether new pixels were written to the image - */ - public boolean hasUpdates() { - return hasUpdates; - } - - /** - * @return true if task is parallel - */ - public boolean isParallel() { - return parallel; - } - - /** - * Clears the updates flag - */ - public void clearHasUpdates() { - hasUpdates = false; - } + public boolean hasUpdates() { return hasUpdates; } + public boolean isParallel() { return parallel; } + public void clearHasUpdates() { hasUpdates = false; } - /** - * {@inheritDoc} - */ @Override protected void failed() { super.failed(); getException().printStackTrace(System.err); } - /** - * Returns current task execution time while task is running and total - * task time when task is finished - * @return task time in milliseconds - */ public long getTime() { - if (taskTime != -1) { - return taskTime; - } - if (startTime == -1) { - return 0; - } + if (taskTime != -1) return taskTime; + if (startTime == -1) return 0; return System.currentTimeMillis() - startTime; } - /** - * {@inheritDoc} - */ @Override protected Long call() throws Exception { synchronized(pixelWriter) { - // Prepares an image for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { pixelWriter.setColor(x, y, Color.TRANSPARENT); @@ -223,36 +69,18 @@ protected Long call() throws Exception { } } startTime = System.currentTimeMillis(); - - // We do horizontal lines in parallel when asked + IntStream yStream = IntStream.range(0, height); - if (parallel) { - yStream = yStream.parallel(); - } else { - yStream = yStream.sequential(); - } + if (parallel) yStream = yStream.parallel(); + else yStream = yStream.sequential(); + updateProgress(0, height); yStream.forEach((int y) -> { - - // We do pixels in horizontal lines always sequentially for (int x = 0; x < width; x++) { - - // Skip excluded rectangular area - if (!(x >= maxX || x < minX || y >= maxY || y < minY)) { - continue; - } - Color c; - if (antialiased) { - c = calcAntialiasedPixel(x, y); - } else { - c = calcPixel(x, y); - } - if (isCancelled()) { - return; - } - synchronized(pixelWriter) { - pixelWriter.setColor(x, y, c); - } + if (!(x >= maxX || x < minX || y >= maxY || y < minY)) continue; + Color c = antialiased ? calcAntialiasedPixel(x, y) : calcPixel(x, y); + if (isCancelled()) return; + synchronized(pixelWriter) { pixelWriter.setColor(x, y, c); } hasUpdates = true; } updateProgress(progress.incrementAndGet(), height); @@ -261,55 +89,31 @@ protected Long call() throws Exception { return taskTime; } - /** - * Calculates number of iterations a complex quadratic polynomials - * stays within a disk of some finite radius for a given complex number. - * - * This number is used to choose a color for this pixel for precalculated - * color tables. - * - * @param comp a complex number used for calculation - * @return number of iterations a value stayed within a given disk. - */ private int calc(Complex comp) { int count = 0; Complex c = new Complex(0, 0); do { - c = c.times(c).plus(comp); + // новая формула: z = z^3 + c + c = c.times(c).times(c).plus(comp); count++; } while (count < CAL_MAX_COUNT && c.lengthSQ() < LENGTH_BOUNDARY); return count; } - /** - * Calculates a color of a given pixel on the image using - * {@link #calc(demo.parallel.Complex) } method. - * @param x x coordinate of the pixel in the image - * @param y y coordinate of the pixel in the image - * @return calculated color of the pixel - */ private Color calcPixel(double x, double y) { double re = (minR * (width - x) + x * maxR) / width; double im = (minI * (height - y) + y * maxI) / height; Complex calPixel = new Complex(re, im); return getColor(calc(calPixel)); } - - /** - * Calculates antialised color of a given pixel on the image by dividing - * real and imaginary value ranges of a pixel by {@link #ANTIALIASING_BASE} - * and doing interpolation between calculated values - * @param x x coordinate of the pixel in the image - * @param y y coordinate of the pixel in the image - * @return calculated color of the pixel - */ private Color calcAntialiasedPixel(int x, int y) { double step = 1d / ANTIALIASING_BASE; double N = ANTIALIASING_BASE * ANTIALIASING_BASE; double r = 0, g = 0, b = 0; for (int i = 0; i < ANTIALIASING_BASE; i++) { for (int j = 0; j < ANTIALIASING_BASE; j++) { - Color c = calcPixel(x + step * (i + 0.5) - 0.5, y + step * (j + 0.5) - 0.5); + Color c = calcPixel(x + step * (i + 0.5) - 0.5, + y + step * (j + 0.5) - 0.5); r += c.getRed() / N; g += c.getGreen() / N; b += c.getBlue() / N; @@ -318,38 +122,18 @@ private Color calcAntialiasedPixel(int x, int y) { return new Color(clamp(r), clamp(g), clamp(b), 1); } - /** - * Clamps the value in 0..1 interval - * @param val value to clamp - * @return value in 0..1 interval - */ private double clamp(double val) { return val > 1 ? 1 : val < 0 ? 0 : val; } - /** - * Returns a color for a given iteration count. - * @param count number of iterations return by - * {@link #calc(demo.parallel.Complex)} method - * @return color from pre-calculated table - */ private Color getColor(int count) { - if (count >= colors.length) { - return Color.BLACK; - } + if (count >= colors.length) return Color.BLACK; return colors[count]; } - - /** - * Pre-calculated colors table - */ + static final Color[] colors = new Color[256]; static { - - /** - * Color stops for colors table: color values - */ Color[] cc = { Color.rgb(0, 7, 100), // тёмно-синий Color.BLUE, @@ -358,18 +142,13 @@ private Color getColor(int count) { Color.WHITE }; double[] cp = { 0.0, 0.25, 0.5, 0.75, 1.0 }; - - /** - * Color table population - */ + int j = 0; for (int i = 0; i < colors.length; i++) { double p = (double) i / (colors.length - 1); - if (p > cp[j + 1]) { - j++; - } + if (p > cp[j + 1]) j++; double val = (p - cp[j]) / (cp[j + 1] - cp[j]); colors[i] = cc[j].interpolate(cc[j + 1], val); } } -} +} \ No newline at end of file From 90f3caa66f66b4f38ded4816ca88f36dcfd40e5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B8=D0=BA=D0=BE=D0=BB=D0=B0=D0=B9=20=D0=AE=D1=85?= =?UTF-8?q?=D0=BD=D0=B8=D0=BA=2C=D0=B3=D1=80=2E=20334701?= Date: Wed, 17 Sep 2025 09:41:13 +0300 Subject: [PATCH 3/4] =?UTF-8?q?=D1=82=D1=80=D0=B5=D1=82=D0=B8=D0=B9=20?= =?UTF-8?q?=D0=BA=D0=BE=D0=BC=D0=B8=D1=82-=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BD=D0=BE=D0=B2=D1=8B=D1=85?= =?UTF-8?q?=20=D0=BE=D0=BF=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/demo/parallel/Complex.java | 109 +++++++++-------------- src/demo/parallel/MandelbrotSetTask.java | 20 +++-- 2 files changed, 56 insertions(+), 73 deletions(-) diff --git a/src/demo/parallel/Complex.java b/src/demo/parallel/Complex.java index 134a37946..dbf12396e 100644 --- a/src/demo/parallel/Complex.java +++ b/src/demo/parallel/Complex.java @@ -1,81 +1,23 @@ -/* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ package demo.parallel; - -/** - * A complex number is a number that can be expressed in the form a + b * i, where - * a and b are real numbers and i is the imaginary unit, which satisfies the - * equation i ^ 2 = -1. a is the real part and b is the imaginary part of the - * complex number. - *

- * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - * @author Alexander Kouznetsov, Tristan Yan +/* + * A complex number is a number that can be expressed in the form a + b * i. */ public class Complex { - - private double re; // the real part - private double im; // the imaginary part + private double re; // real part + private double im; // imaginary part - /** - * create a new object with the given real and imaginary parts - * - * @param real a complex number real part - * @param imag a complex number imaginary part - */ public Complex(double real, double imag) { re = real; im = imag; } - /** - * Add operation. - * @param b summand - * @return this Complex object whose value is (this + b) - */ public Complex plus(Complex b) { re += b.re; im += b.im; return this; } - /** - * Multiply operation. - * @param b multiplier - * @return this Complex object whose value is this * b - */ public Complex times(Complex b) { Complex a = this; double real = a.re * b.re - a.im * b.im; @@ -85,12 +27,45 @@ public Complex times(Complex b) { return this; } - /** - * Square of Complex object's length, we're using square of length to - * eliminate the computation of square root - * @return square of length - */ public double lengthSQ() { return re * re + im * im; } + + // 🔹 Новые методы + + /* Вычитание */ + public Complex minus(Complex b) { + this.re -= b.re; + this.im -= b.im; + return this; + } + + /* Деление */ + public Complex dividedBy(Complex b) { + double den = b.re * b.re + b.im * b.im; + if (den == 0.0) throw new ArithmeticException("Division by zero"); + double newRe = (this.re * b.re + this.im * b.im) / den; + double newIm = (this.im * b.re - this.re * b.im) / den; + this.re = newRe; + this.im = newIm; + return this; + } + + /* Сопряжение */ + public Complex conjugate() { + this.im = -this.im; + return this; + } + + /* Умножение на число */ + public Complex scale(double k) { + this.re *= k; + this.im *= k; + return this; + } + + /* Копия объекта (нужно, чтобы не портить исходный объект при операциях) */ + public Complex copy() { + return new Complex(this.re, this.im); + } } \ No newline at end of file diff --git a/src/demo/parallel/MandelbrotSetTask.java b/src/demo/parallel/MandelbrotSetTask.java index 4721b0337..37a92e590 100644 --- a/src/demo/parallel/MandelbrotSetTask.java +++ b/src/demo/parallel/MandelbrotSetTask.java @@ -77,7 +77,7 @@ protected Long call() throws Exception { updateProgress(0, height); yStream.forEach((int y) -> { for (int x = 0; x < width; x++) { - if (!(x >= maxX || x < minX || y >= maxY || y < minY)) continue; + if (!(x >= maxX ||x < minX || y >= maxY || y < minY)) continue; Color c = antialiased ? calcAntialiasedPixel(x, y) : calcPixel(x, y); if (isCancelled()) return; synchronized(pixelWriter) { pixelWriter.setColor(x, y, c); } @@ -91,12 +91,20 @@ protected Long call() throws Exception { private int calc(Complex comp) { int count = 0; - Complex c = new Complex(0, 0); + Complex z = new Complex(0, 0); + final Complex ONE = new Complex(1, 0); + do { - // новая формула: z = z^3 + c - c = c.times(c).times(c).plus(comp); + // num = z^2 + c + Complex num = z.copy().times(z).plus(comp); + // den = conj(z) + 1 + Complex den = z.copy().conjugate().plus(ONE); + // новая формула: z = (z^2 + c) / (conj(z) + 1) + z = num.dividedBy(den); + count++; - } while (count < CAL_MAX_COUNT && c.lengthSQ() < LENGTH_BOUNDARY); + } while (count < CAL_MAX_COUNT && z.lengthSQ() < LENGTH_BOUNDARY); + return count; } @@ -135,7 +143,7 @@ private Color getColor(int count) { static { Color[] cc = { - Color.rgb(0, 7, 100), // тёмно-синий + Color.rgb(0, 7, 100), Color.BLUE, Color.CYAN, Color.YELLOW, From 65f5fc7a489b9b645c1e39257e4edda56e6721ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B8=D0=BA=D0=BE=D0=BB=D0=B0=D0=B9=20=D0=AE=D1=85?= =?UTF-8?q?=D0=BD=D0=B8=D0=BA=2C=D0=B3=D1=80=2E=20334701?= Date: Wed, 17 Sep 2025 10:19:05 +0300 Subject: [PATCH 4/4] =?UTF-8?q?=D1=87=D0=B5=D1=82=D0=B2=D0=B5=D1=80=D1=82?= =?UTF-8?q?=D1=8B=D0=B9=20=D0=BA=D0=BE=D0=BC=D0=B8=D1=82-=D0=B4=D0=BE?= =?UTF-8?q?=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=82=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/demo/parallel/ComplexTest.java | 72 ++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/demo/parallel/ComplexTest.java diff --git a/src/demo/parallel/ComplexTest.java b/src/demo/parallel/ComplexTest.java new file mode 100644 index 000000000..4b8676fe1 --- /dev/null +++ b/src/demo/parallel/ComplexTest.java @@ -0,0 +1,72 @@ +package demo.parallel; + +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * Unit-тесты для новых операций класса Complex. + */ +public class ComplexTest { + + @Test + public void testMinus() { + Complex a = new Complex(3, 4); + Complex b = new Complex(1, -2); + a.minus(b); // (3+4i) - (1-2i) = (2+6i) + assertEquals(2.0, getRe(a), 1e-9); + assertEquals(6.0, getIm(a), 1e-9); + } + + @Test + public void testDividedBy() { + Complex a = new Complex(3, 2); + Complex b = new Complex(1, -1); + a.dividedBy(b); // (3+2i) / (1-1i) = 0.5 + 2.5i + assertEquals(0.5, getRe(a), 1e-9); + assertEquals(2.5, getIm(a), 1e-9); + } + + @Test(expected = ArithmeticException.class) + public void testDividedByZero() { + new Complex(1, 1).dividedBy(new Complex(0, 0)); + } + + @Test + public void testConjugate() { + Complex a = new Complex(3, -2); + a.conjugate(); // → (3+2i) + assertEquals(3.0, getRe(a), 1e-9); + assertEquals(2.0, getIm(a), 1e-9); + } + + @Test + public void testScaleAndCopy() { + Complex a = new Complex(2, -3); + Complex b = a.copy().scale(2.5); // b = (5, -7.5), a не изменился + assertEquals(2.0, getRe(a), 1e-9); + assertEquals(-3.0, getIm(a), 1e-9); + assertEquals(5.0, getRe(b), 1e-9); + assertEquals(-7.5, getIm(b), 1e-9); + } + + // 🔹 Вспомогательные методы (так как поля Complex приватные) + private static double getRe(Complex z) { + try { + var f = Complex.class.getDeclaredField("re"); + f.setAccessible(true); + return f.getDouble(z); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static double getIm(Complex z) { + try { + var f = Complex.class.getDeclaredField("im"); + f.setAccessible(true); + return f.getDouble(z); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} \ No newline at end of file