#include <print>
#include <iostream>
#include <cstdlib>

constexpr int SIZE = 3;

// Vorwaertsdeklaration
class Vector;

// Definition der Klasse Matrix
class Matrix
{
    short data[SIZE][SIZE]; // Datenfeld
public:
    // ctor, belegt Feld mit Zufallszahlen
    Matrix()
    {
        for (auto& row: data)
            for (auto& elem: row)
                elem = std::rand() % 100;
    };
    // dtor
    ~Matrix() = default;
    // Ausgabe Daten
    friend std::ostream& operator << (std::ostream& out, const Matrix& obj);
    // friend-Funktion fuer Matrix*Vector
    friend void MatVect(Matrix& mat, const Vector& vect);
};

std::ostream& operator << (std::ostream& out, const Matrix& obj)
{
    for (auto& row: obj.data)
    {
        for (auto& elem: row)
            std::print("{:4}, ",elem);
        std::println();
    }
    return out;
}

// Definition der Klasse Vector
class Vector
{
    short data[SIZE];
public:
    // ctor, belegt Feld mit Zufallszahlen
    Vector()
    {
        for (size_t index=0; index<SIZE; index++)
            data[index] = index+1;
    }
    // dtor
    virtual ~Vector() = default;
    // Ausgabe der Daten
    friend std::ostream& operator << (std::ostream& out, const Vector& obj);
    // friend-Funktion fuer Matrix*Vector
    friend void MatVect(Matrix& mat, const Vector& vect);
};
std::ostream& operator << (std::ostream& out, const Vector& obj)
{
    for (auto elem: obj.data)
        std::print("{:3}, ",elem);
    std::println();
    return out;
}

void MatVect(Matrix& mat, const Vector& vect)
{
    for (auto row=0; row<SIZE; row++)
    {
        for (auto col=0; col<SIZE; col++)
            mat.data[row][col] *= vect.data[row];
    }
}

int main()
{
    Matrix mat;     // Matrix Objekt und
    Vector vect;    // Vector Objekt definieren

    // Beide Objekte ausgeben
    std::println("Matrix: ");
    std::cout << mat;
    std::println("Vektor: ");
    std::cout << vect;
    std::println("Matrix *= Vektor:");
    MatVect(mat, vect);
    std::cout << mat;
}
