from typing import List, Tuple
import numpy as np
from numpy.typing import NDArray

class Matrix:
    def __init__(self, data: List[List[float]]) -> None: ...
    @staticmethod
    def zeros(rows: int, cols: int) -> Matrix: ...
    @staticmethod
    def ones(rows: int, cols: int) -> Matrix: ...
    @staticmethod
    def identity(size: int) -> Matrix: ...
    @staticmethod
    def from_numpy(array: NDArray[np.float64]) -> Matrix: ...
    @property
    def shape(self) -> Tuple[int, int]: ...
    @property
    def rows(self) -> int: ...
    @property
    def cols(self) -> int: ...
    def __repr__(self) -> str: ...
    def __str__(self) -> str: ...
    def __getitem__(self, idx: Tuple[int, int]) -> float: ...
    def __setitem__(self, idx: Tuple[int, int], value: float) -> None: ...
    def __add__(self, other: Matrix) -> Matrix: ...
    def __sub__(self, other: Matrix) -> Matrix: ...
    def __mul__(self, other: Matrix) -> Matrix: ...
    def __matmul__(self, other: Matrix) -> Matrix: ...
    def __rmul__(self, scalar: float) -> Matrix: ...
    def scale(self, scalar: float) -> Matrix: ...
    def transpose(self) -> Matrix: ...
    def inverse(self) -> Matrix: ...
    def determinant(self) -> float: ...
    def trace(self) -> float: ...
    def to_list(self) -> List[List[float]]: ...
    def to_numpy(self) -> NDArray[np.float64]: ...
    def matvec(self, vector: Vector) -> Vector: ...

class Vector:
    def __init__(self, data: List[float]) -> None: ...
    @staticmethod
    def zeros(size: int) -> Vector: ...
    @staticmethod
    def ones(size: int) -> Vector: ...
    @staticmethod
    def from_numpy(array: NDArray[np.float64]) -> Vector: ...
    def __len__(self) -> int: ...
    def __repr__(self) -> str: ...
    def __str__(self) -> str: ...
    def __getitem__(self, idx: int) -> float: ...
    def __setitem__(self, idx: int, value: float) -> None: ...
    def __add__(self, other: Vector) -> Vector: ...
    def __sub__(self, other: Vector) -> Vector: ...
    def __rmul__(self, scalar: float) -> Vector: ...
    def scale(self, scalar: float) -> Vector: ...
    def dot(self, other: Vector) -> float: ...
    def norm(self) -> float: ...
    def norm_squared(self) -> float: ...
    def normalize(self) -> Vector: ...
    def to_list(self) -> List[float]: ...
    def to_numpy(self) -> NDArray[np.float64]: ...

def matmul(a: Matrix, b: Matrix) -> Matrix: ...
def matvec(matrix: Matrix, vector: Vector) -> Vector: ...
