package org.example.Math;

import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;

public class Vector2D extends Vector {

    public Vector2D(double x, double y) {
        super( new double[]{x, y});
    }

    @Override
    public double length() {
        return Math.sqrt(A[0] * A[0] + A[1] * A[1]);
    }

    @Override
    public Vector normalize() {
        double len = length();
        return new Vector2D(A[0] / len, A[1] / len);
    }

    public static Vector2D add(Vector v1, Vector v2) {
        return new Vector2D(v1.A[0] + v2.A[0], v1.A[1] + v2.A[1]);
    }

    public static Vector2D subtract(Vector v1, Vector v2) {
        return new Vector2D(v1.A[0] - v2.A[0], v1.A[1] - v2.A[1]);
    }

    public static Vector2D multiply(Vector first, double scalar) {
        if (!(first instanceof Vector2D)) throw new IllegalArgumentException("Vectors must be of the same type");
        Vector2D v = (Vector2D) first;
        return new Vector2D(v.A[0] * scalar, v.A[1] * scalar);
    }


    public static Vector2D divide(Vector v, double scalar) {
        if (!(v instanceof Vector2D)) throw new IllegalArgumentException("Vectors must be of the same type");
        Vector2D other = (Vector2D) v;
        if (scalar == 0) throw new ArithmeticException("Division by zero");
        return new Vector2D(other.A[0] / scalar, other.A[1] / scalar);
    }

    public static double dotProduct(Vector v1, Vector v2) {
        if (!(v1 instanceof Vector2D) || !(v2 instanceof Vector2D)) throw new IllegalArgumentException("Vectors must be of the same type");
        v1 = (Vector2D) v1;
        v2 = (Vector2D) v2;
        return v2.A[0] * v1.A[0] + v2.A[1] * v1.A[1];
    }
}

package org.example.Math;

public abstract class Vector {
    protected double[] A;

    public Vector(double[] a) {
        this.A = a;
    }

    public abstract double length();

    public abstract Vector normalize();


}
package org.example.Math;

public class Vector3D extends Vector {

    public Vector3D(double x, double y, double z) {
        super(new double[]{x, y, z});
    }

    @Override
    public double length() {
        return Math.sqrt(A[0] * A[0] + A[1] * A[1] + A[2] * A[2]);
    }

    @Override
    public Vector normalize() {
        double len = length();
        return new Vector3D(A[0] / len, A[1] / len, A[2] / len);
    }

    public static Vector3D add(Vector v1, Vector v2) {
        return new Vector3D(v1.A[0] + v2.A[0], v1.A[1] + v2.A[1], v1.A[2] + v2.A[2]);
    }

    public static Vector3D subtract(Vector v1, Vector v2) {
        return new Vector3D(v1.A[0] - v2.A[0], v1.A[1] - v2.A[1], v1.A[2] - v2.A[2]);
    }

    public static Vector3D multiply(Vector v, double scalar) {
        return new Vector3D(v.A[0] * scalar, v.A[1] * scalar, v.A[2] * scalar);
    }

    public static Vector3D divide(Vector v, double scalar) {
        if (scalar == 0) throw new ArithmeticException("Division by zero");
        return new Vector3D(v.A[0] / scalar, v.A[1] / scalar, v.A[2] / scalar);
    }

    public static double dotProduct(Vector v1, Vector v2) {
        return v1.A[0] * v2.A[0] + v1.A[1] * v2.A[1] + v1.A[2] * v2.A[2];
    }

    public static Vector3D crossProduct(Vector v1, Vector v2) {
        return new Vector3D(
            v1.A[1] * v2.A[2] - v1.A[2] * v2.A[1],
            v1.A[2] * v2.A[0] - v1.A[0] * v2.A[2],
            v1.A[0] * v2.A[1] - v1.A[1] * v2.A[0]
        );
    }
}package org.example.Math;

public class Vector4D extends Vector {

    public Vector4D(double x, double y, double z, double w) {
        super(new double[]{x, y, z, w});
    }

    @Override
    public double length() {
        return Math.sqrt(A[0] * A[0] + A[1] * A[1] + A[2] * A[2] + A[3] * A[3]);
    }

    @Override
    public Vector normalize() {
        double len = length();
        return new Vector4D(A[0] / len, A[1] / len, A[2] / len, A[3] / len);
    }

    public static Vector4D add(Vector v1, Vector v2) {
        return new Vector4D(v1.A[0] + v2.A[0], v1.A[1] + v2.A[1], v1.A[2] + v2.A[2], v1.A[3] + v2.A[3]);
    }

    public static Vector4D subtract(Vector v1, Vector v2) {
        return new Vector4D(v1.A[0] - v2.A[0], v1.A[1] - v2.A[1], v1.A[2] - v2.A[2], v1.A[3] - v2.A[3]);
    }

    public static Vector4D multiply(Vector v, double scalar) {
        return new Vector4D(v.A[0] * scalar, v.A[1] * scalar, v.A[2] * scalar, v.A[3] * scalar);
    }

    public static Vector4D divide(Vector v, double scalar) {
        if (scalar == 0) throw new ArithmeticException("Division by zero");
        return new Vector4D(v.A[0] / scalar, v.A[1] / scalar, v.A[2] / scalar, v.A[3] / scalar);
    }

    public static double dotProduct(Vector v1, Vector v2) {
        return v1.A[0] * v2.A[0] + v1.A[1] * v2.A[1] + v1.A[2] * v2.A[2] + v1.A[3] * v2.A[3];
    }
}
пропиши тесты для каждого открытого метода