Search code examples
matrixada

matrix function not able to compile ada "declarations must come before "begin"


Hi so I'm very new to ada but it doesn't seem to like this code that I wrote, I keep having this error even though it looks fine.

Compile
   [Ada]          main.adb
main.adb:17:09: error: declarations must come before "begin"
gprbuild: *** compilation phase failed

here is the code:

with Ada.Text_IO;  use Ada.Text_IO;
with Ada.Numerics.Linear_Algebra;

procedure main is

  type Square_Matrix is array(Integer range <>, Integer range <>) of Float;
  
  function Determinant(matrix : in Square_Matrix) return Float is
    (Ada.Numerics.Linear_Algebra.Determinant(matrix));

  function Adjoint(matrix : in Square_Matrix) return Square_Matrix is
    result : Square_Matrix := matrix;
    dimension : Integer := matrix'Length;
  begin
    for i in 1 .. dimension loop
      for j in 1 .. dimension loop
        temp : Square_Matrix(dimension - 1, dimension - 1);
        for m in 1 .. dimension - 1 loop
          for n in 1 .. dimension - 1 loop
            if m < i and n < j then
              temp(m, n) := matrix(m, n);
            elsif m < i and n >= j then
              temp(m, n) := matrix(m, n + 1);
            elsif m >= i and n < j then
              temp(m, n) := matrix(m + 1, n);
            else
              temp(m, n) := matrix(m + 1, n + 1);
            end if;
          end loop;
        end loop;
        sign : Integer := (if (i + j) mod 2 = 0 then 1 else -1);
        result(j, i) := sign * Determinant(temp);
      end loop;
    end loop;
    return result;
  end Adjoint;

  matrix : Square_Matrix(1 .. 6, 1 .. 6) := ((2.0, -2.0, 4.0, -2.0, 0.0, 2.0),
                                             (1.0, 0.0, 4.0, -3.0, 0.0, 0.0),
                                             (1.0, 1.0, 1.0, 1.0, 1.0, 1.0),
                                             (1.0, 0.0, 0.0, -1.0, 0.0, 0.0),
                                             (3.0, 0.0, 0.0, -3.0, 0.0, 2.0),
                                             (1.0, 0.0, 0.0, -2.0, 0.0, 4.0));
  adjoint_matrix : Square_Matrix(1 .. 6, 1 .. 6);

begin
  adjoint_matrix := Adjoint(matrix);
  
  Put_Line("Original Matrix:");
  for i in matrix'Range(1) loop
    for j in matrix'Range(2) loop
      Put(Float'Image(matrix(i, j)), 4, 2);
    end loop;
    New_Line;
  end loop;
  
  Put_Line("Adjoint Matrix:");
  for i in adjoint_matrix'Range(1) loop
    for j in adjoint_matrix'Range(2) loop
      Put(Float'Image(adjoint_matrix(i, j)), 6, 2);
    end loop;
    New_Line;
  end loop;
  
end main;

Solution

  • Just looking at the problem with sign - which you would have come across as soon as you’d fixed the code in line with @Zerte’s answer - you have

    sign : Integer := (if (i + j) mod 2 = 0 then 1 else -1);
    result(j, i) := sign * Determinant(temp);
    

    You’re not allowed to declare something (here, sign) in the middle of code; the structure you would use would be a declare block,

    declare
       sign : Integer := (if (i + j) mod 2 = 0 then 1 else -1);
    begin
       result(j, i) := sign * Determinant(temp);
    end;
    

    What I was suggesting (and, apologies for not noticing that you were already using a conditional expression) was

    result(j, i) := Determinant(temp)
       * (if (i + j) mod 2 = 0 then 1 else -1);
    

    or maybe

    result(j, i) := (if (i + j) mod 2 = 0 
                     then Determinant(temp)
                     else -Determinant(temp));
    

    Personally, I’d probably just have used an if statement.