Does 'Reduce always return an Integer type rather than the base element?

I am playing around with some optimization things… I have the following code:

pragma Source_File_Name (Square, Body_File_Name => "example.adb");
pragma Ada_2022;

-- Type your code here, or load an example.
function Square(num : Integer) return Float is
    type My_Smol_Float is digits 6;
    Floaty1 : constant array (1..100) of My_Smol_Float := (others => My_Smol_Float(num));
    Floaty2 : constant array (1..100) of My_Smol_Float := (others => My_Smol_Float(num**2));
    Floaty_All : array (1..100) of My_Smol_Float;
    Accumul1, Accumul2, Accumul3 : My_Smol_Float;
begin
    for N of Floaty1 loop
        Accumul1 := @ + N;
    end loop;

    for I in Floaty1'Range loop
        Accumul2 := Floaty1(I) + Floaty2(I);
    end loop;

    for I in Floaty1'Range loop
        Floaty_All(I) := Floaty1(I) + Floaty2(I);
    end loop;

    return Float(Accumul1 + Accumul2 + Floaty_All'Reduce("+", 0));
end Square;

The compiler errors out with the following error:

gcc -c -I/app/ -g -fdiagnostics-color=always -S -fverbose-asm -masm=intel -O3 -march=znver4 -mtune=znver4 -gnatp -fopt-info-vec-all -o /app/example.s -I- <source>
gnatmake: "<source>" compilation error
example.adb:27:38: error: invalid operand types for operator "+"
example.adb:27:38: error: left operand has type "My_Smol_Float" defined at line 9
example.adb:27:38: error: right operand has type universal integer
Compiler returned: 4

It says that the return type of the 'Reduce is Universal Integer. However, Floaty_All is an array (indexed by Universal Integer) of My_Smol_Float. I would expect that the 'Reduce operation would return the result in the same base as the type. The Reference Manual does not say otherwise (though it is not too clear about it!) Reduction

Is this a compiler bug? @sttaft could you shed some light here?

Best regards,
Fer

EDIT: same issue happens if I try

    [...]
    Accumul3 := Floaty_All'Reduce("*", 0);

    return Float(Accumul1 + Accumul2 + Accumul3);

I think this is an example of a poor error message. I suspect that the problem is that you have supplied an integer literal as your initial value for the reduction, but the array has components of a real type. Supplying a real literal for the initial value succeeds.

1 Like

Indeed, this was the problem. Providing a real for the accumulator does make it work!

Thanks Jeff ^^

There are potentially two different types involved in a reduction, one the type of the “accumulator” and one the type of the “values” that provide the input. The initial expression determines the “accumulator type”, and the type of the reduction expression overall. The sequence of values being reduced determines the “value type”. The reducer subprogram takes a parameter of the accumulator type and a parameter of the value type, producing a value of the accumulator type. For example, you could reduce a sequence of individual characters to an unbounded string, where Character is the value type, and Unbounded_String is the accumulator type. But much more likely is that the accumulator and value types are the same, and a symmetric binary operator like “+” can be used.

2 Likes