-- This program does some simple analysis of the values found in an array.
-- It makes use of user-defined procedures.
-- It finds the sum of all of the values, and it
-- counts the number of positive, zero, and negative values
-- It displays the sum and the counts.
-- It also does a little very simple simple error checking.
-- For testing purposes, we fill up the array with some dummy values.
-- It would also be interesting to fill the array with random values,
-- but we'll skip that for now.
--
-- Author: Ned Okie
-- Date: 8/24/2009

with ada.text_io; use ada.text_io; 
with ada.integer_text_io; use ada.integer_text_io; 
 
procedure sumCountProcs is

    ----------------------------------
    ------ Declare constants and types
    
    Num_Ints: 
        constant Natural := 10;   -- Number of elements in the array

    -- A type for our array
    type Int_Array is array (1 .. Num_Ints) of Integer;

    ---------------------------------------
    ------ Declare functions and procedures

    -- returns sum of elements in array a
    function sumArray(a: Int_Array) return integer is

        s: Integer := 0;  -- holds the sum
    begin
        for i in a'range loop
            s := s + a(i);
        end loop;
        return s;
    end sumArray;
    
    -- Analyzes integer array a
    -- Returns the following out parameters:
        -- np: number of positive integers in a
        -- nz: number of zero integers in a
        -- nn: number of negative integers in a
    procedure doCounts(a: Int_Array; np, nz, nn: out Natural) is
    begin
        np := 0;
        nz := 0;
        nn := 0;
        for i in a'range loop
            if a(i) > 0 then
                np := np + 1;

            -- Zeros
            elsif a(i) = 0 then
                nz := nz + 1;

            -- Negatives
            else -- a(i) < 0  must be true
                nn := nn + 1;

            end if;
        end loop;
    end doCounts;

    -- Outputs s and i on a single line, followed by a newline
    procedure put_line(s: String; i: Integer) is
    begin
        put(s);
        put(i, width => 0);
        new_line;
    end put_line;

    -- Outputs results of analysis:
    -- s: sum of array
    -- np, nz, nn: number of positives, zeros, negatives, respectively
    procedure putResults(s: in Integer; np, nz, nn: in Natural) is
    begin
        put_line("Sum of all: ", s);
        put_line("Number of positives: ", np);
        put_line("Number of zeros: ", nz);
        put_line("Number of negatives: ", nn);
    end putResults;


    -----------------------------------------
    ------ Declare variables for main routine

    theNums: Int_Array;           -- Array to hold the numbers

    sum: Integer := 0;            -- Sum of all values in the array

    -- Number of positives, zeros, and negatives in the array
    numPositives, numZeros, numNegatives: Natural := 0;

begin  -- main
    -- Put some values into the array
    theNums := (5, 0, -4, 9, 0, 3, -9, -77, 22, 11); 

    -- Do the calculations
    sum := sumArray(theNums);

    doCounts(theNums, numPositives, numZeros, numNegatives);

    -- Error Checking
    if numPositives + numZeros + numNegatives /= Num_Ints then
        put_line("ERROR IN COUNTS!!!");
    end if;
    
    -- Print sum and counts
    putResults(sum, numPositives, numZeros, numNegatives);

end sumCountProcs;