with Globals;
use Globals;

pragma Elaborate_All (Globals);

package body Matrices.More is

  procedure Mult(R: in Flt; M: in out Matrix; Tmp: in out Scalar) is
  begin
    if R=Zero then
      SetZero(M);
    elsif R=One then
      null;
    elsif R=NegOne then
      Neg(M);
    else
      for I in M'Range(1) loop
        for J in M'Range(2) loop
          Mult(R,M(I,J),Tmp);
        end loop;
      end loop;
    end if;
  end Mult;

  procedure Prod(R: in Flt; M1: in Matrix; M2: in out Matrix) is
  begin
    if CheckRange and then not SameDim(M1,M2) then
      raise Dimension_Error with "Matrices.More.Prod error";
    end if;
    if R=Zero then
      SetZero(M2);
    elsif R=One then
      Copy(M1,M2);
    elsif R=NegOne then
      Neg(M1,M2);
    else
      for M in M1'Range(1) loop
        for N in M1'Range(2) loop
          Prod(R,M1(M,N),M2(M,N));
        end loop;
      end loop;
    end if;
  end Prod;

  procedure AddProd(R: in Flt; M1: in Matrix; M2: in out Matrix; Tmp: in out Scalar) is
  begin
    if CheckRange and then not SameDim(M1,M2) then
      raise Dimension_Error with "Matrices.More.Prod error";
    end if;
    if R=Zero then
      null;
    elsif R=One then
      Add(M1,M2);
    elsif R=NegOne then
      Sub(M1,M2);
    else
      for M in M1'Range(1) loop
        for N in M1'Range(2) loop
          AddProd(R,M1(M,N),M2(M,N),Tmp);
        end loop;
      end loop;
    end if;
  end AddProd;
  
  procedure AddProd(S: in Scalar; M1: in Matrix; M2: in out Matrix; Tmp: in out Scalar) is
  begin
    if CheckRange and then not SameDim(M1,M2) then
      raise Dimension_Error with "Matrices.More.AddProd error";
    end if;
    if not IsZero(S) then
      for I in M1'Range(1) loop
        for J in M1'Range(2) loop AddProd(S,M1(I,I),M2(I,J),Tmp); end loop;
      end loop;
    end if;
  end AddProd;
  
  procedure SubProd(S: in Scalar; M1: in Matrix; M2: in out Matrix; Tmp: in out Scalar) is
  begin
    if CheckRange and then not SameDim(M1,M2) then
      raise Dimension_Error with "Matrices.More.SubProd error";
    end if;
    if not IsZero(S) then
      for I in M1'Range(1) loop
        for J in M1'Range(2) loop SubProd(S,M1(I,I),M2(I,J),Tmp); end loop;
      end loop;
    end if;
  end SubProd;
  
  procedure Div(R: in Flt; M: in out Matrix; Tmp: in out Scalar) is
  begin
    if R=One then
      null;
    elsif R=NegOne then
      Neg(M);
    else
      for M1 in M'Range(1) loop
        for M2 in M'Range(2) loop
          Div(R,M(M1,M2),Tmp);
        end loop;
      end loop;
    end if;
  end Div;

  procedure Quot(M1: in Matrix; R: in Flt; M2: in out Matrix) is
  begin
    if CheckRange and then not SameDim(M1,M2) then
      raise Dimension_Error with "Matrices.More.Quot error";
    end if;
    if R=One then
      Copy(M1,M2);
    elsif R=NegOne then
      Neg(M1,M2);
    else
      for N in M1'Range(1) loop
        for M in M1'Range(2) loop
          Quot(M1(M,N),R,M2(M,N));
        end loop;
      end loop;
    end if;
  end Quot;

end Matrices.More;
