with Globals;
use Globals;

pragma Elaborate_All (Globals);

package body MGeneric is

  procedure MP_Modify1(M: in out Matrix) is
  begin
    for I in M'Range(1) loop
      for J in M'Range(2) loop Modify1(M(I,J)); end loop;
    end loop;
  end MP_Modify1;

  procedure MP_Modify2(M1,M2: in out Matrix) is
  begin
    if CheckRange and then ((M1'First(1) /= M2'First(1)) or (M1'Last(1) /= M2'Last(1))
                              or (M1'First(2) /= M2'First(2)) or (M1'Last(2) /= M2'Last(2))) then
      raise Dimension_Error with "MGeneric.MP_Modify2 error";
    end if;
    for I in M2'Range(1) loop
      for J in M2'Range(2) loop Modify2(M1(I,J),M2(I,J)); end loop;
    end loop;
  end MP_Modify2;

  procedure MP_Map1(M1: in Matrix; M2: in out Matrix) is
  begin
    if CheckRange and then ((M1'First(1) /= M2'First(1)) or (M1'Last(1) /= M2'Last(1))
                              or (M1'First(2) /= M2'First(2)) or (M1'Last(2) /= M2'Last(2))) then
      raise Dimension_Error with "MGeneric.MP_Map1 error";
    end if;
    for I in M2'Range(1) loop
      for J in M2'Range(2) loop Map1(M1(I,J),M2(I,J)); end loop;
    end loop;
  end MP_Map1;

  function MF_Map1(M: Matrix) return Matrix is
    W: Matrix(M'Range(1),M'Range(2));
  begin
    for I in M'Range(1) loop
      for J in M'Range(2) loop Map1(M(I,J),W(I,J)); end loop;
    end loop;
    return W;
  end MF_Map1;

  procedure MP_Map2(M1,M2: in Matrix; M3: in out Matrix) is
  begin
    if CheckRange and then ((M1'First(1) /= M3'First(1)) or (M1'Last(1) /= M3'Last(1))
                              or (M1'First(2) /= M3'First(2)) or (M1'Last(2) /= M3'Last(2))
                              or (M2'First(1) /= M3'First(1)) or (M2'Last(1) /= M3'Last(1))
                              or (M2'First(2) /= M3'First(2)) or (M2'Last(2) /= M3'Last(2))) then
      raise Dimension_Error with "MGeneric.MP_Map2 error";
    end if;
    for I in M3'Range(1) loop
      for J in M3'Range(2) loop Map2(M1(I,J),M2(I,J),M3(I,J)); end loop;
    end loop;
  end MP_Map2;

  function MF_Map2(M1,M2: Matrix) return Matrix is
    M3: Matrix(M2'Range(1),M2'Range(2));
  begin
    if CheckRange and then ((M1'First(1) /= M2'First(1)) or (M1'Last(1) /= M2'Last(1))
                              or (M1'First(2) /= M2'First(2)) or (M1'Last(2) /= M2'Last(2))) then
      raise Dimension_Error with "MGeneric.MF_Map2 error";
    end if;
    for I in M3'Range(1) loop
      for J in M3'Range(2) loop Map2(M1(I,J),M2(I,J),M3(I,J)); end loop;
    end loop;
    return M3;
  end MF_Map2;

  function MF_BProperty(M: Matrix) return Boolean is
  begin
    for I in M'Range(1) loop
      for J in M'Range(2) loop
        if not BProperty(M(I,J)) then return False; end if;
      end loop;
    end loop;
    return True;
  end MF_BProperty;

  function MF_LProperty(M: Matrix) return Logical is
    L: Logical := True;
    LIJ: Logical;
  begin
    for I in M'Range(1) loop
      for J in M'Range(2) loop
        LIJ := LProperty(M(I,J));
        if LIJ=False then return False; end if;
        if LIJ=Uncertain then L := Uncertain; end if;
      end loop;
    end loop;
    return L;
  end MF_LProperty;

  function MF_BSimilar(M1,M2: Matrix) return Boolean is
  begin
    if CheckRange and then ((M1'First(1) /= M2'First(1)) or (M1'Last(1) /= M2'Last(1))
                              or (M1'First(2) /= M2'First(2)) or (M1'Last(2) /= M2'Last(2))) then
      raise Dimension_Error with "MGeneric.MF_BSimilar error";
    end if;
    for I in M2'Range(1) loop
      for J in M2'Range(2) loop
        if not BSimilar(M1(I,J),M2(I,J)) then return False; end if;
      end loop;
    end loop;
    return True;
  end MF_BSimilar;

  function MF_LSimilar(M1,M2: Matrix) return Logical is
    L: Logical := True;
    LIJ: Logical;
  begin
    if CheckRange and then ((M1'First(1) /= M2'First(1)) or (M1'Last(1) /= M2'Last(1))
                              or (M1'First(2) /= M2'First(2)) or (M1'Last(2) /= M2'Last(2))) then
      raise Dimension_Error with "MGeneric.MF_LSimilar error";
    end if;
    for I in M2'Range(1) loop
      for J in M2'Range(2) loop
        LIJ := LSimilar(M1(I,J),M2(I,J));
        if LIJ=False then return False; end if;
        if LIJ=Uncertain then L := Uncertain; end if;
      end loop;
    end loop;
    return L;
  end MF_LSimilar;

end MGeneric;
