comp.lang.ada
 help / color / mirror / Atom feed
Search results ordered by [date|relevance]  view[summary|nested|Atom feed]
thread overview below | download mbox.gz: |
* Re: basic question on Ada programming
  2019-01-24  3:59  9% basic question on Ada programming Nasser M. Abbasi
@ 2019-01-24  7:58  7% ` Niklas Holsti
  0 siblings, 0 replies; 61+ results
From: Niklas Holsti @ 2019-01-24  7:58 UTC (permalink / raw)


On 19-01-24 05:59 , Nasser M. Abbasi wrote:
> I forgot these since I did not program in Ada for long time.
>
> Very basic question. In this
>
> ---------------------------
> with Ada.Text_Io;
> with Ada.Numerics.Real_Arrays;
>
> procedure main is
>   A : constant Ada.Numerics.Real_Arrays.Real_Matrix :=
>            (( 1.0,  2.0,  3.0),
>            ( 4.0,  5.0,  6.0),
>            ( 7.0,  8.0,  9.0));
>
>   v : constant Ada.Numerics.Real_Arrays.Real_Vector := (1.0,2.0,3.0);
>   procedure put (x : Ada.Numerics.Real_Arrays.Real_Vector) is
>     begin
>          FOR e of x LOOP
>              Ada.Text_Io.put_line(float'image(e));
>          END LOOP;
>    end put;
>    --use Ada.Numerics.Real_Arrays;
> begin
>     put(A*v); -- error here, since it does not see *
> end main;
> ------------------
>
> How can I write put(A*v) above, without having to do
>
>      use Ada.Numerics.Real_Arrays;
>
> above it?

Ada.Numerics.Real_Arrays."*" (A,v)

Or do "use type Ada.Numerics.Real_Arrays.Real_Matrix".

Or rename the operator "*" locally. But "use type" is better.

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .


^ permalink raw reply	[relevance 7%]

* basic question on Ada programming
@ 2019-01-24  3:59  9% Nasser M. Abbasi
  2019-01-24  7:58  7% ` Niklas Holsti
  0 siblings, 1 reply; 61+ results
From: Nasser M. Abbasi @ 2019-01-24  3:59 UTC (permalink / raw)


I forgot these since I did not program in Ada for long time.

Very basic question. In this

---------------------------
with Ada.Text_Io;
with Ada.Numerics.Real_Arrays;

procedure main is
   A : constant Ada.Numerics.Real_Arrays.Real_Matrix :=
            (( 1.0,  2.0,  3.0),
            ( 4.0,  5.0,  6.0),
            ( 7.0,  8.0,  9.0));

   v : constant Ada.Numerics.Real_Arrays.Real_Vector := (1.0,2.0,3.0);
   procedure put (x : Ada.Numerics.Real_Arrays.Real_Vector) is
     begin
          FOR e of x LOOP
              Ada.Text_Io.put_line(float'image(e));
          END LOOP;
    end put;
    --use Ada.Numerics.Real_Arrays;
begin
     put(A*v); -- error here, since it does not see *
end main;
------------------

How can I write put(A*v) above, without having to do

      use Ada.Numerics.Real_Arrays;

above it?

I am trying to see if I can avoid doing use Ada.Numerics.Real_Arrays
so that I can explicitly add Ada.Numerics.Real_Arrays.something every
where, so I know where the something is coming from when looking at
the code.

But what about the *?  How to tell Ada it is coming from
Ada.Numerics.Real_Arrays without doing an explicit use? What
would the syntax be?

Using gnat community 2018.

Thanks
--Nasser


^ permalink raw reply	[relevance 9%]

* Re: overloading operators
  2018-11-26 18:03  0%           ` Simon Wright
@ 2018-11-26 18:24  0%             ` Dmitry A. Kazakov
  0 siblings, 0 replies; 61+ results
From: Dmitry A. Kazakov @ 2018-11-26 18:24 UTC (permalink / raw)


On 2018-11-26 19:03, Simon Wright wrote:
> Anh Vo <anhvofrcaus@gmail.com> writes:
> 
>> On Thursday, November 22, 2018 at 12:18:06 AM UTC-8, briot.e...@gmail.com wrote:
>>>> You can always say e.g. Ada.Numerics.Real_Arrays."*" (A, B) but it is
>>>> rather clumsy compared to A * B!
>>>
>>>
>>> The main use I have for that notation is in expression functions in specs,
>>> since we try to avoid use clauses in specs. So for instance:
>>>
>>>      function Greater (A, B : Some_Package.My_Type)  return Some_Package.My_Type
>>>          is (Some_Package.">" (A, B));
>>
>> What is wrong with "use type clause"?
> 
> Nothing, but OP was asking about what qualifications are available

Then I think one forgot qualification of the arguments:

   ...
   is (Some_Package.">" (Some_Package.Greater.A, Some_Package.Greater.B));

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


^ permalink raw reply	[relevance 0%]

* Re: overloading operators
  2018-11-26 17:47  0%         ` Anh Vo
@ 2018-11-26 18:03  0%           ` Simon Wright
  2018-11-26 18:24  0%             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 61+ results
From: Simon Wright @ 2018-11-26 18:03 UTC (permalink / raw)


Anh Vo <anhvofrcaus@gmail.com> writes:

> On Thursday, November 22, 2018 at 12:18:06 AM UTC-8, briot.e...@gmail.com wrote:
>> > You can always say e.g. Ada.Numerics.Real_Arrays."*" (A, B) but it is
>> > rather clumsy compared to A * B!
>> 
>> 
>> The main use I have for that notation is in expression functions in specs,
>> since we try to avoid use clauses in specs. So for instance:
>> 
>>     function Greater (A, B : Some_Package.My_Type)  return Some_Package.My_Type
>>         is (Some_Package.">" (A, B));
>
> What is wrong with "use type clause"?

Nothing, but OP was asking about what qualifications are available

^ permalink raw reply	[relevance 0%]

* Re: overloading operators
  2018-11-22  8:18  0%       ` briot.emmanuel
  2018-11-22 11:39  0%         ` Simon Wright
@ 2018-11-26 17:47  0%         ` Anh Vo
  2018-11-26 18:03  0%           ` Simon Wright
  1 sibling, 1 reply; 61+ results
From: Anh Vo @ 2018-11-26 17:47 UTC (permalink / raw)


On Thursday, November 22, 2018 at 12:18:06 AM UTC-8, briot.e...@gmail.com wrote:
> > You can always say e.g. Ada.Numerics.Real_Arrays."*" (A, B) but it is
> > rather clumsy compared to A * B!
> 
> 
> The main use I have for that notation is in expression functions in specs,
> since we try to avoid use clauses in specs. So for instance:
> 
>     function Greater (A, B : Some_Package.My_Type)  return Some_Package.My_Type
>         is (Some_Package.">" (A, B));

What is wrong with "use type clause"?

Anh Vo


^ permalink raw reply	[relevance 0%]

* Re: overloading operators
  2018-11-22  8:18  0%       ` briot.emmanuel
@ 2018-11-22 11:39  0%         ` Simon Wright
  2018-11-26 17:47  0%         ` Anh Vo
  1 sibling, 0 replies; 61+ results
From: Simon Wright @ 2018-11-22 11:39 UTC (permalink / raw)


briot.emmanuel@gmail.com writes:

>> You can always say e.g. Ada.Numerics.Real_Arrays."*" (A, B) but it is
>> rather clumsy compared to A * B!
>
> The main use I have for that notation is in expression functions in specs,
> since we try to avoid use clauses in specs. So for instance:
>
>     function Greater (A, B : Some_Package.My_Type)  return Some_Package.My_Type
>         is (Some_Package.">" (A, B));

Good point (though return Boolean would be better :-)

Personally I try to avoid use clauses in body context clauses, too.

^ permalink raw reply	[relevance 0%]

* Re: overloading operators
  2018-11-21 17:37  5%     ` Simon Wright
@ 2018-11-22  8:18  0%       ` briot.emmanuel
  2018-11-22 11:39  0%         ` Simon Wright
  2018-11-26 17:47  0%         ` Anh Vo
  0 siblings, 2 replies; 61+ results
From: briot.emmanuel @ 2018-11-22  8:18 UTC (permalink / raw)


> You can always say e.g. Ada.Numerics.Real_Arrays."*" (A, B) but it is
> rather clumsy compared to A * B!


The main use I have for that notation is in expression functions in specs,
since we try to avoid use clauses in specs. So for instance:

    function Greater (A, B : Some_Package.My_Type)  return Some_Package.My_Type
        is (Some_Package.">" (A, B));


       

^ permalink raw reply	[relevance 0%]

* Re: overloading operators
  @ 2018-11-21 17:37  5%     ` Simon Wright
  2018-11-22  8:18  0%       ` briot.emmanuel
  0 siblings, 1 reply; 61+ results
From: Simon Wright @ 2018-11-21 17:37 UTC (permalink / raw)


hnptz@yahoo.de writes:

> On Wednesday, November 21, 2018 at 2:50:05 PM UTC+1, AdaMagica wrote:
>> Am Mittwoch, 21. November 2018 10:56:09 UTC+1 schrieb hn...@yahoo.de:
>> > How can I use the old and the overloaded operator at the same time
>> > in the same program for the same type?
>> > For example: Overloaded "*" defined by user for type Real_Matrix
>> > and "*" defined in package Numerics.Real_Arrays for Real_Matrix.
>> 
>> For the nomenclature:
>> If I understand correctly what you're saying, it's not overloading,
>> but overriding what you're doing.
>> If you defined a function "*" for type Real_Matrix in a package of
>> your own, say Pack, the corresponding operation in the package where
>> Real_Matrix is defined, here Ada.Numerics, is hidden from direct and
>> use visibility in Pack. You can make it visible again via an
>> extended name.
>> So which "*" is visible at certain place depends on the kind of
>> visibility of Pack and Ada.Numerics. With proper name qualification,
>> both are callable at the same place in code.
>
> what would be a proper name qualification? Extended name for pack
> defined "*" in Ada.Numerics like pack."*"?

You can always say e.g. Ada.Numerics.Real_Arrays."*" (A, B) but it is
rather clumsy compared to A * B!


^ permalink raw reply	[relevance 5%]

* Re: GNAT can't vectorize Real_Matrix multiplication from Ada.Numerics.Real_Arrays. What a surprise!
  2018-02-20  2:31  5%               ` Bojan Bozovic
@ 2018-02-26  6:58  5%                 ` Robert Eachus
  0 siblings, 0 replies; 61+ results
From: Robert Eachus @ 2018-02-26  6:58 UTC (permalink / raw)


On Monday, February 19, 2018 at 9:31:26 PM UTC-5, Bojan Bozovic 

> I have looked at ATLAS, however it can't spawn more threads than specified at compile time, so there's lots of possibility to optimize there, by spawning as many threads as supported at run-time.

Aarrg!  Yes, there is a lot of work that needs to be done.  The intent is that you run ATLAS on your target environment, then use the best result as your blas library.

But the problem I am fighting with right now is that on the most recent (high-end) processors from Intel and AMD, you never want to use as many threads as the hardware tells you are available at run-time.  In fact, it is common that if you have a processor which supports 8-threads, you want to run four threads on all even or odd numbered threads.  The recent Threadripper and EPYC CPUs from AMD make it even more complex, as do any multisocket systems.  Usually you want to split the problem up completely and duplicate the data on each hardware CPU chip.


^ permalink raw reply	[relevance 5%]

* Re: GNAT can't vectorize Real_Matrix multiplication from Ada.Numerics.Real_Arrays. What a surprise!
  2018-02-19 21:08  5%             ` Robert Eachus
@ 2018-02-20  2:31  5%               ` Bojan Bozovic
  2018-02-26  6:58  5%                 ` Robert Eachus
  0 siblings, 1 reply; 61+ results
From: Bojan Bozovic @ 2018-02-20  2:31 UTC (permalink / raw)


On Monday, February 19, 2018 at 10:08:41 PM UTC+1, Robert Eachus wrote:
> On Sunday, February 18, 2018 at 4:48:42 PM UTC-5, Nasser M. Abbasi wrote:
> > On 2/18/2018 1:38 PM, Bojan Bozovic wrote:
> > 
> > If you are doing A*B by hand, then you are doing something
> > wrong. Almost all languages end up calling Blas
> > Fortran libraries for these operations. Your code and
> > the Ada code can't be faster.
> > 
> > http://www.netlib.org/blas/
> > 
> > Intel Math Kernel Library has all these.
> > 
> > https://en.wikipedia.org/wiki/Math_Kernel_Library
> 
> For multiplying two small matrices, blas is overkill and will be slower.  If you have say, 1000x1000 matrices, then you should be using blas.  But which BLAS?  Intel and AMD both have math libraries optimized for their CPUs.  However, I tend to use ATLAS.  ATLAS will build a blas targeted at your specific hardware.  This is not just about instruction set additions like SIMD2.  It will tailor the implementation to your number of cores and supported threads, cache sizes, and memory speeds.  I've also used the goto blas, but ATLAS even though not perfect, builds all of blas3 using matrix multiplication and blas2, such that all operations slower than O(n^2) have their speed determined by matrix multiplication.  (Then use multiple matrix multiplication codes with different parameters to find the fastest.)
> 
> Usually hardware vendor libraries catch up to and surpass ATLAS, but by then the hardware is obsolete. :-(   The other problem right now is that blas libraries are pretty dumb when it comes to multiprocessor systems.  I'm working on fixing that. ;-)

I have looked at ATLAS, however it can't spawn more threads than specified at compile time, so there's lots of possibility to optimize there, by spawning as many threads as supported at run-time. Ada would do much better here than C, because you could make portable code without resorting to ugly hacks of C, and using parallelism no matter whats the underlying processor architecture. That are my $0.02, worthless or not (and if you want to use assembler to "optimize" further in C, that can be done in any language, which I fear Intel MKL library and other vendor libraries do).


^ permalink raw reply	[relevance 5%]

* Re: GNAT can't vectorize Real_Matrix multiplication from Ada.Numerics.Real_Arrays. What a surprise!
  2018-02-18 21:48  6%           ` Nasser M. Abbasi
  2018-02-18 22:50  5%             ` Bojan Bozovic
@ 2018-02-19 21:08  5%             ` Robert Eachus
  2018-02-20  2:31  5%               ` Bojan Bozovic
  1 sibling, 1 reply; 61+ results
From: Robert Eachus @ 2018-02-19 21:08 UTC (permalink / raw)


On Sunday, February 18, 2018 at 4:48:42 PM UTC-5, Nasser M. Abbasi wrote:
> On 2/18/2018 1:38 PM, Bojan Bozovic wrote:
> 
> If you are doing A*B by hand, then you are doing something
> wrong. Almost all languages end up calling Blas
> Fortran libraries for these operations. Your code and
> the Ada code can't be faster.
> 
> http://www.netlib.org/blas/
> 
> Intel Math Kernel Library has all these.
> 
> https://en.wikipedia.org/wiki/Math_Kernel_Library

For multiplying two small matrices, blas is overkill and will be slower.  If you have say, 1000x1000 matrices, then you should be using blas.  But which BLAS?  Intel and AMD both have math libraries optimized for their CPUs.  However, I tend to use ATLAS.  ATLAS will build a blas targeted at your specific hardware.  This is not just about instruction set additions like SIMD2.  It will tailor the implementation to your number of cores and supported threads, cache sizes, and memory speeds.  I've also used the goto blas, but ATLAS even though not perfect, builds all of blas3 using matrix multiplication and blas2, such that all operations slower than O(n^2) have their speed determined by matrix multiplication.  (Then use multiple matrix multiplication codes with different parameters to find the fastest.)

Usually hardware vendor libraries catch up to and surpass ATLAS, but by then the hardware is obsolete. :-(   The other problem right now is that blas libraries are pretty dumb when it comes to multiprocessor systems.  I'm working on fixing that. ;-)

^ permalink raw reply	[relevance 5%]

* Re: GNAT can't vectorize Real_Matrix multiplication from Ada.Numerics.Real_Arrays. What a surprise!
  2018-02-18 21:48  6%           ` Nasser M. Abbasi
@ 2018-02-18 22:50  5%             ` Bojan Bozovic
  2018-02-19 21:08  5%             ` Robert Eachus
  1 sibling, 0 replies; 61+ results
From: Bojan Bozovic @ 2018-02-18 22:50 UTC (permalink / raw)


On Sunday, February 18, 2018 at 10:48:42 PM UTC+1, Nasser M. Abbasi wrote:
> On 2/18/2018 1:38 PM, Bojan Bozovic wrote:
> 
> If you are doing A*B by hand, then you are doing something
> wrong. Almost all languages end up calling Blas
> Fortran libraries for these operations. Your code and
> the Ada code can't be faster.
> 
> http://www.netlib.org/blas/
> 
> Intel Math Kernel Library has all these.
> 
> https://en.wikipedia.org/wiki/Math_Kernel_Library
> 
> --Nasser

Well I wanted to compare how Ada would do against C simply in 4x4 matrix multiplication, and I was surprised to see several times slower results, so I tried then to code 'by hand' to attempt to achieve the same speed with Ada (and the speed is comparable). I'm just learning the language and so I was unaware of it's finesses (such as making new instance of Ada.Numerics.Generic_Real_Arrays). Thanks for the links. I will have to bookmark them.


^ permalink raw reply	[relevance 5%]

* Re: GNAT can't vectorize Real_Matrix multiplication from Ada.Numerics.Real_Arrays. What a surprise!
  2018-02-18 19:38  5%         ` Bojan Bozovic
@ 2018-02-18 21:48  6%           ` Nasser M. Abbasi
  2018-02-18 22:50  5%             ` Bojan Bozovic
  2018-02-19 21:08  5%             ` Robert Eachus
  0 siblings, 2 replies; 61+ results
From: Nasser M. Abbasi @ 2018-02-18 21:48 UTC (permalink / raw)


On 2/18/2018 1:38 PM, Bojan Bozovic wrote:

If you are doing A*B by hand, then you are doing something
wrong. Almost all languages end up calling Blas
Fortran libraries for these operations. Your code and
the Ada code can't be faster.

http://www.netlib.org/blas/

Intel Math Kernel Library has all these.

https://en.wikipedia.org/wiki/Math_Kernel_Library

--Nasser


^ permalink raw reply	[relevance 6%]

* Re: GNAT can't vectorize Real_Matrix multiplication from Ada.Numerics.Real_Arrays. What a surprise!
  2018-02-18 13:31 11%       ` Jeffrey R. Carter
@ 2018-02-18 19:38  5%         ` Bojan Bozovic
  2018-02-18 21:48  6%           ` Nasser M. Abbasi
  0 siblings, 1 reply; 61+ results
From: Bojan Bozovic @ 2018-02-18 19:38 UTC (permalink / raw)


On Sunday, February 18, 2018 at 2:31:18 PM UTC+1, Jeffrey R. Carter wrote:
> On 02/18/2018 01:05 PM, Bojan Bozovic wrote:
> > Thanks very much for clarification! It's always good to learn something new, I suppose.
> 
> The real optimization in your example seems to be that the compiler optimizes 
> away the 10E6 loop around the in-line code, but not around the call to "*". 
> Removing both loops gives similar times for both multiplications. The call to 
> "*" will never be as fast because it copies its result into your variable. 
> Replacing Ada.Numerics.Real_Arrays with an instantiation of 
> Ada.Numerics.Generic_Real_Arrays gives an additional factor of 2 reduction.
> 
> -- 
> Jeff Carter
> Just as Khan was hindered by two-dimensional thinking in a
> three-dimensional situation, so many developers are hindered
> by sequential thinking in concurrent situations.
> 118

And indeed, now everything is in its place, as I don't see matrix multiplication several times slower than doing things 'by hand'. I have used aggressive optimization because in this day its custom a program to manipulate over gigabytes or even terabytes of data, while being at most megabytes in size - so compiling for various processors of the same family and using launcher program which will query processor capability and run optimally optimized program is nothing new - one might say most computation now is done on GPU but then also exact capabilities of GPU must be known. Thanks for making my Ada learning experience an enjoyment!

^ permalink raw reply	[relevance 5%]

* Re: GNAT can't vectorize Real_Matrix multiplication from Ada.Numerics.Real_Arrays. What a surprise!
  2018-02-18 12:05  6%     ` Bojan Bozovic
@ 2018-02-18 13:31 11%       ` Jeffrey R. Carter
  2018-02-18 19:38  5%         ` Bojan Bozovic
  0 siblings, 1 reply; 61+ results
From: Jeffrey R. Carter @ 2018-02-18 13:31 UTC (permalink / raw)


On 02/18/2018 01:05 PM, Bojan Bozovic wrote:
> Thanks very much for clarification! It's always good to learn something new, I suppose.

The real optimization in your example seems to be that the compiler optimizes 
away the 10E6 loop around the in-line code, but not around the call to "*". 
Removing both loops gives similar times for both multiplications. The call to 
"*" will never be as fast because it copies its result into your variable. 
Replacing Ada.Numerics.Real_Arrays with an instantiation of 
Ada.Numerics.Generic_Real_Arrays gives an additional factor of 2 reduction.

-- 
Jeff Carter
Just as Khan was hindered by two-dimensional thinking in a
three-dimensional situation, so many developers are hindered
by sequential thinking in concurrent situations.
118

^ permalink raw reply	[relevance 11%]

* Re: GNAT can't vectorize Real_Matrix multiplication from Ada.Numerics.Real_Arrays. What a surprise!
  2018-02-18 10:35 11%   ` Jeffrey R. Carter
@ 2018-02-18 12:05  6%     ` Bojan Bozovic
  2018-02-18 13:31 11%       ` Jeffrey R. Carter
  0 siblings, 1 reply; 61+ results
From: Bojan Bozovic @ 2018-02-18 12:05 UTC (permalink / raw)


Thanks very much for clarification! It's always good to learn something new, I suppose.

^ permalink raw reply	[relevance 6%]

* Re: GNAT can't vectorize Real_Matrix multiplication from Ada.Numerics.Real_Arrays. What a surprise!
  2018-02-18  1:51 10% ` Bojan Bozovic
@ 2018-02-18 10:35 11%   ` Jeffrey R. Carter
  2018-02-18 12:05  6%     ` Bojan Bozovic
  0 siblings, 1 reply; 61+ results
From: Jeffrey R. Carter @ 2018-02-18 10:35 UTC (permalink / raw)


On 02/18/2018 02:51 AM, Bojan Bozovic wrote:
> 
> Apart from response that they don't offer support on GPL versions of compiler, I got no response. I hope this will be useful to someone.

Nor should you expect anything to happen, since you have not found an error. An 
error is when the compiler accepts illegal code, rejects legal code, or produces 
object code that gives incorrect results. At best you have found an opportunity 
for better optimization. Even that seems unlikely.

Remember that Ada.Numerics.Real_Arrays."*" is a general-purpose library 
function. As such, it has to do things that your specific implementation of 
matrix multiplication doesn't: It has to check that Left'Length (2) = 
Right'Length (1) and raise an exception if they're not equal. Your code doesn't, 
and any such check should be optimized away because its condition will be 
statically False. The general code has to handle the case where Left'First (2) 
/= Right'First (1). Even when the offset is zero, that's still an extra addition 
in the inner loop.

Also, Ada.Numerics.Real_Arrays is provided precompiled, and is surely compiled 
with different optimization options than your code. (IIRC, -O3 is considered 
experimental, and AdaCore is not going to compile its library code with 
experimental optimization.)

You can find GNAT's implementation of matrix multiplication as 
System.Generic_Array_Operations.Matrix_Matrix_Product. This is extremely 
general, allowing for non-numeric matrix components (complex numbers, for 
example), and different component types for the left, right, and result 
matrices. This may introduce additional barriers to optimization.

Since Ada.Numerics.Real_Arrays is an instantiation of 
Ada.Numerics.Generic_Real_Arrays for Float, and GNAT does macro expansion of 
generics, if you use an explicit instantiation of 
Ada.Numerics.Generic_Real_Arrays in your code, it should be compiled with your 
compiler options and thus remove that variable from your comparison. Doing that 
in your code, and building with

gnatmake -O3 -mavx2 matrix_mul -largs -s

cuts the reported time for "*" by a factor of about 4. Not surprisingly, still 
slower. YMMV

-- 
Jeff Carter
Just as Khan was hindered by two-dimensional thinking in a
three-dimensional situation, so many developers are hindered
by sequential thinking in concurrent situations.
118

^ permalink raw reply	[relevance 11%]

* Re: GNAT can't vectorize Real_Matrix multiplication from Ada.Numerics.Real_Arrays. What a surprise!
  2018-02-17 12:55  7% GNAT can't vectorize Real_Matrix multiplication from Ada.Numerics.Real_Arrays. What a surprise! Bojan Bozovic
  2018-02-17 15:17  6% ` Bojan Bozovic
@ 2018-02-18  1:51 10% ` Bojan Bozovic
  2018-02-18 10:35 11%   ` Jeffrey R. Carter
  1 sibling, 1 reply; 61+ results
From: Bojan Bozovic @ 2018-02-18  1:51 UTC (permalink / raw)


On Saturday, February 17, 2018 at 1:55:49 PM UTC+1, Bojan Bozovic wrote:
> -- code
> 
> with Ada.Calendar;
> with Ada.Text_IO;
> with Ada.Numerics.Real_Arrays;
> use Ada.Calendar;
> use Ada.Text_IO;
> use Ada.Numerics.Real_Arrays;
> 
> procedure Matrix_Mul is
> 
>    package F_IO is new Ada.Text_IO.Fixed_IO (Day_Duration);
>    use F_IO;
> 
>    Start_Time, End_Time : Time;
> 
>    procedure Put (X : Real_Matrix) is
>    begin
>       for I in X'Range (1) loop
>          for J in X'Range (2) loop
>             Put (Float'Image (Float (X (I, J))));
>          end loop;
>          New_Line;
>       end loop;
>    end Put;
> 
>    Matrix_A, Matrix_B, Result : Real_Matrix (1 .. 4, 1 .. 4);
>    Elapsed_Time               : Duration;
>    Sum                        : Float;
> begin
>    Matrix_A :=
>      ((1.0, 1.0, 1.0, 1.0),
>       (2.0, 2.0, 2.0, 2.0),
>       (3.0, 3.0, 3.0, 3.0),
>       (4.0, 4.0, 4.0, 4.0));
>    Matrix_B :=
>      ((16.0, 15.0, 14.0, 13.0),
>       (12.0, 11.0, 10.0, 9.0),
>       (8.0, 7.0, 6.0, 5.0),
>       (4.0, 3.0, 2.0, 1.0));
> 
>    Start_Time := Clock;
>    for Iteration in 1 .. 10_000_000 loop
>       Result := Matrix_A * Matrix_B;
>    end loop;
>    End_Time     := Clock;
>    Elapsed_Time := End_Time - Start_Time;
>    Put (Result);
>    New_Line;
>    Put ("Elapsed Time is ");
>    Put (Elapsed_Time);
>    New_Line;
>    Start_Time := Clock;
>    for Iteration in 1 .. 10_000_000 loop
>       for I in Matrix_A'Range (1) loop
>          for J in Matrix_A'Range (2) loop
>             Sum := 0.0;
>             for K in Matrix_A'Range (2) loop
>                Sum := Sum + Matrix_A (I, K) * Matrix_B (K, J);
>             end loop;
>             Result (I, J) := Sum;
>          end loop;
>       end loop;
>    end loop;
>    End_Time     := Clock;
>    Elapsed_Time := End_Time - Start_Time;
>    Put (Result);
>    New_Line;
>    Put ("Elapsed time is ");
>    Put (Elapsed_Time);
>    New_Line;
> end Matrix_Mul;
> -- end code
> 
> Results: FSF GNAT 7.2.0 x64
> C:\Users\Bojan\Documents>gnatmake -O3 -fopt-info -march=skylake matrix_mul.adb -largs -s
> gcc -c -O3 -fopt-info -march=skylake matrix_mul.adb
> matrix_mul.adb:56:41: note: loop turned into non-loop; it never loops.
> matrix_mul.adb:56:41: note: loop with 4 iterations completely unrolled
> matrix_mul.adb:54:38: note: loop turned into non-loop; it never loops.
> matrix_mul.adb:54:38: note: loop with 4 iterations completely unrolled
> matrix_mul.adb:53:35: note: loop turned into non-loop; it never loops.
> matrix_mul.adb:53:35: note: loop with 4 iterations completely unrolled
> matrix_mul.adb:40:15: note: basic block vectorized
> matrix_mul.adb:42:26: note: basic block vectorized
> matrix_mul.adb:18:31: note: basic block vectorized
> matrix_mul.adb:49:9: note: basic block vectorized
> C:/MSYS64/MINGW64/lib/gcc/x86_64-w64-mingw32/7.2.0/adainclude/a-tifiio.adb:706:10: note: basic block vectorized
> matrix_mul.adb:64:17: note: basic block vectorized
> matrix_mul.adb:18:31: note: basic block vectorized
> matrix_mul.adb:68:9: note: basic block vectorized
> C:/MSYS64/MINGW64/lib/gcc/x86_64-w64-mingw32/7.2.0/adainclude/a-tifiio.adb:706:10: note: basic block vectorized
> gnatbind -x matrix_mul.ali
> gnatlink matrix_mul.ali -O3 -fopt-info -march=skylake -s
> 
> C:\Users\Bojan\Documents>matrix_mul
>  4.00000E+01 3.60000E+01 3.20000E+01 2.80000E+01
>  8.00000E+01 7.20000E+01 6.40000E+01 5.60000E+01
>  1.20000E+02 1.08000E+02 9.60000E+01 8.40000E+01
>  1.60000E+02 1.44000E+02 1.28000E+02 1.12000E+02
> 
> Elapsed Time is      1.338206667
>  4.00000E+01 3.60000E+01 3.20000E+01 2.80000E+01
>  8.00000E+01 7.20000E+01 6.40000E+01 5.60000E+01
>  1.20000E+02 1.08000E+02 9.60000E+01 8.40000E+01
>  1.60000E+02 1.44000E+02 1.28000E+02 1.12000E+02
> 
> Elapsed time is      0.000000445
> 
> C:\Users\Bojan\Documents>set path=C:\GNAT\2017\BIN;%path%
> 
> Results GPL GNAT/2017 from AdaCore.
> 
> C:\Users\Bojan\Documents>gnatmake -O3 -fopt-info -mavx2 matrix_mul.adb -largs -s
> gcc -c -O3 -fopt-info -mavx2 matrix_mul.adb
> matrix_mul.adb:56:41: note: loop turned into non-loop; it never loops.
> matrix_mul.adb:56:41: note: loop with 4 iterations completely unrolled
> matrix_mul.adb:54:38: note: loop turned into non-loop; it never loops.
> matrix_mul.adb:54:38: note: loop with 4 iterations completely unrolled
> matrix_mul.adb:53:35: note: loop turned into non-loop; it never loops.
> matrix_mul.adb:53:35: note: loop with 4 iterations completely unrolled
> matrix_mul.adb:40:15: note: basic block vectorized
> matrix_mul.adb:68:9: note: basic block vectorized
> gnatbind -x matrix_mul.ali
> gnatlink matrix_mul.ali -O3 -fopt-info -mavx2 -s
> 
> C:\Users\Bojan\Documents>matrix_mul
>  4.00000E+01 3.60000E+01 3.20000E+01 2.80000E+01
>  8.00000E+01 7.20000E+01 6.40000E+01 5.60000E+01
>  1.20000E+02 1.08000E+02 9.60000E+01 8.40000E+01
>  1.60000E+02 1.44000E+02 1.28000E+02 1.12000E+02
> 
> Elapsed Time is      2.145337334
>  4.00000E+01 3.60000E+01 3.20000E+01 2.80000E+01
>  8.00000E+01 7.20000E+01 6.40000E+01 5.60000E+01
>  1.20000E+02 1.08000E+02 9.60000E+01 8.40000E+01
>  1.60000E+02 1.44000E+02 1.28000E+02 1.12000E+02
> 
> Elapsed time is      0.000000444
> 
> C:\Users\Bojan\Documents>gcc --version
> gcc (GCC) 6.3.1 20170510 (for GNAT GPL 2017 20170515)
> Copyright (C) 2016 Free Software Foundation, Inc.
> This is free software; see the source for copying conditions.
> See your AdaCore support agreement for details of warranty and support.
> If you do not have a current support agreement, then there is absolutely
> no warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
> PURPOSE.
> 
> Should I submit this as bug to AdaCore? My computer is Intel Core i3-6100U (Skylake AVX2). Please try to reproduce.

Apart from response that they don't offer support on GPL versions of compiler, I got no response. I hope this will be useful to someone.

with Ada.Calendar;
with Ada.Text_IO;
with Ada.Numerics.Real_Arrays;
use Ada.Calendar;
use Ada.Text_IO;
use Ada.Numerics.Real_Arrays;

procedure Matrix_Mul is

   package F_IO is new Ada.Text_IO.Fixed_IO (Day_Duration);
   use F_IO;

   Start_Time, End_Time : Time;
   
   procedure Put (X : Real_Matrix) is
   begin
      for I in X'Range (1) loop
         for J in X'Range (2) loop
            Put (Float'Image (Float (X (I, J))));
         end loop;
         New_Line;
      end loop;
   end Put;


   Matrix_A, Matrix_B, Result : Real_Matrix (1 .. 4, 1 .. 4);
   Elapsed_Time               : Duration;
   Sum                        : Float;
   pragma Volatile (Matrix_A);
   pragma Volatile (Matrix_B);
   pragma Volatile (Result);
   Iterations : constant := 10_000_000;
begin
   Matrix_A :=
     ((1.0, 1.0, 1.0, 1.0),
      (2.0, 2.0, 2.0, 2.0),
      (3.0, 3.0, 3.0, 3.0),
      (4.0, 4.0, 4.0, 4.0));
   Matrix_B :=
     ((16.0, 15.0, 14.0, 13.0),
      (12.0, 11.0, 10.0, 9.0),
      (8.0, 7.0, 6.0, 5.0),
      (4.0, 3.0, 2.0, 1.0));

   Start_Time := Clock;
   for Iteration in 1..Iterations loop
      Result := Matrix_A * Matrix_B;
	end loop;
   End_Time     := Clock;
   Elapsed_Time := End_Time - Start_Time;
   Put (Result);
   New_Line;
   Put ("Elapsed Time is ");
   Put (Elapsed_Time);
   New_Line;
   Start_Time := Clock;
   for Iteration in 1 .. Iterations loop
   
      for I in Matrix_A'Range (1) loop
         for J in Matrix_A'Range (2) loop
            Sum := 0.0;
            for K in Matrix_A'Range (2) loop
               Sum := Sum + Matrix_A (I, K) * Matrix_B (K, J);
            end loop;
            Result (I, J) := Sum;
         end loop;
      end loop;
end loop;
   End_Time     := Clock;
   Elapsed_Time := End_Time - Start_Time;
   Put (Result);
   New_Line;
   Put ("Elapsed time is ");
   Put (Elapsed_Time);
   New_Line;
end Matrix_Mul;

-- end code

C:\Users\Bojan\Documents>gnatmake -O3 -mavx2 matrix_mul -largs -s
gcc -c -O3 -mavx2 matrix_mul.adb
gnatbind -x matrix_mul.ali
gnatlink matrix_mul.ali -O3 -mavx2 -s

C:\Users\Bojan\Documents>matrix_mul
 4.00000E+01 3.60000E+01 3.20000E+01 2.80000E+01
 8.00000E+01 7.20000E+01 6.40000E+01 5.60000E+01
 1.20000E+02 1.08000E+02 9.60000E+01 8.40000E+01
 1.60000E+02 1.44000E+02 1.28000E+02 1.12000E+02

Elapsed Time is      2.134868889
 4.00000E+01 3.60000E+01 3.20000E+01 2.80000E+01
 8.00000E+01 7.20000E+01 6.40000E+01 5.60000E+01
 1.20000E+02 1.08000E+02 9.60000E+01 8.40000E+01
 1.60000E+02 1.44000E+02 1.28000E+02 1.12000E+02

Elapsed time is      0.337315111

This is from GNAT/2017 compiler with these switches above.

^ permalink raw reply	[relevance 10%]

* Re: GNAT can't vectorize Real_Matrix multiplication from Ada.Numerics.Real_Arrays. What a surprise!
  2018-02-17 15:17  6% ` Bojan Bozovic
@ 2018-02-17 15:49  5%   ` Bojan Bozovic
  0 siblings, 0 replies; 61+ results
From: Bojan Bozovic @ 2018-02-17 15:49 UTC (permalink / raw)


On Saturday, February 17, 2018 at 4:17:41 PM UTC+1, Bojan Bozovic wrote:
> On Saturday, February 17, 2018 at 1:55:49 PM UTC+1, Bojan Bozovic wrote:
> > -- code
> > 
> > with Ada.Calendar;
> > with Ada.Text_IO;
> > with Ada.Numerics.Real_Arrays;
> > use Ada.Calendar;
> > use Ada.Text_IO;
> > use Ada.Numerics.Real_Arrays;
> > 
> > procedure Matrix_Mul is
> > 
> >    package F_IO is new Ada.Text_IO.Fixed_IO (Day_Duration);
> >    use F_IO;
> > 
> >    Start_Time, End_Time : Time;
> > 
> >    procedure Put (X : Real_Matrix) is
> >    begin
> >       for I in X'Range (1) loop
> >          for J in X'Range (2) loop
> >             Put (Float'Image (Float (X (I, J))));
> >          end loop;
> >          New_Line;
> >       end loop;
> >    end Put;
> > 
> >    Matrix_A, Matrix_B, Result : Real_Matrix (1 .. 4, 1 .. 4);
> >    Elapsed_Time               : Duration;
> >    Sum                        : Float;
> > begin
> >    Matrix_A :=
> >      ((1.0, 1.0, 1.0, 1.0),
> >       (2.0, 2.0, 2.0, 2.0),
> >       (3.0, 3.0, 3.0, 3.0),
> >       (4.0, 4.0, 4.0, 4.0));
> >    Matrix_B :=
> >      ((16.0, 15.0, 14.0, 13.0),
> >       (12.0, 11.0, 10.0, 9.0),
> >       (8.0, 7.0, 6.0, 5.0),
> >       (4.0, 3.0, 2.0, 1.0));
> > 
> >    Start_Time := Clock;
> >    for Iteration in 1 .. 10_000_000 loop
> >       Result := Matrix_A * Matrix_B;
> >    end loop;
> >    End_Time     := Clock;
> >    Elapsed_Time := End_Time - Start_Time;
> >    Put (Result);
> >    New_Line;
> >    Put ("Elapsed Time is ");
> >    Put (Elapsed_Time);
> >    New_Line;
> >    Start_Time := Clock;
> >    for Iteration in 1 .. 10_000_000 loop
> >       for I in Matrix_A'Range (1) loop
> >          for J in Matrix_A'Range (2) loop
> >             Sum := 0.0;
> >             for K in Matrix_A'Range (2) loop
> >                Sum := Sum + Matrix_A (I, K) * Matrix_B (K, J);
> >             end loop;
> >             Result (I, J) := Sum;
> >          end loop;
> >       end loop;
> >    end loop;
> >    End_Time     := Clock;
> >    Elapsed_Time := End_Time - Start_Time;
> >    Put (Result);
> >    New_Line;
> >    Put ("Elapsed time is ");
> >    Put (Elapsed_Time);
> >    New_Line;
> > end Matrix_Mul;
> > -- end code
> > 
> > Results: FSF GNAT 7.2.0 x64
> > C:\Users\Bojan\Documents>gnatmake -O3 -fopt-info -march=skylake matrix_mul.adb -largs -s
> > gcc -c -O3 -fopt-info -march=skylake matrix_mul.adb
> > matrix_mul.adb:56:41: note: loop turned into non-loop; it never loops.
> > matrix_mul.adb:56:41: note: loop with 4 iterations completely unrolled
> > matrix_mul.adb:54:38: note: loop turned into non-loop; it never loops.
> > matrix_mul.adb:54:38: note: loop with 4 iterations completely unrolled
> > matrix_mul.adb:53:35: note: loop turned into non-loop; it never loops.
> > matrix_mul.adb:53:35: note: loop with 4 iterations completely unrolled
> > matrix_mul.adb:40:15: note: basic block vectorized
> > matrix_mul.adb:42:26: note: basic block vectorized
> > matrix_mul.adb:18:31: note: basic block vectorized
> > matrix_mul.adb:49:9: note: basic block vectorized
> > C:/MSYS64/MINGW64/lib/gcc/x86_64-w64-mingw32/7.2.0/adainclude/a-tifiio.adb:706:10: note: basic block vectorized
> > matrix_mul.adb:64:17: note: basic block vectorized
> > matrix_mul.adb:18:31: note: basic block vectorized
> > matrix_mul.adb:68:9: note: basic block vectorized
> > C:/MSYS64/MINGW64/lib/gcc/x86_64-w64-mingw32/7.2.0/adainclude/a-tifiio.adb:706:10: note: basic block vectorized
> > gnatbind -x matrix_mul.ali
> > gnatlink matrix_mul.ali -O3 -fopt-info -march=skylake -s
> > 
> > C:\Users\Bojan\Documents>matrix_mul
> >  4.00000E+01 3.60000E+01 3.20000E+01 2.80000E+01
> >  8.00000E+01 7.20000E+01 6.40000E+01 5.60000E+01
> >  1.20000E+02 1.08000E+02 9.60000E+01 8.40000E+01
> >  1.60000E+02 1.44000E+02 1.28000E+02 1.12000E+02
> > 
> > Elapsed Time is      1.338206667
> >  4.00000E+01 3.60000E+01 3.20000E+01 2.80000E+01
> >  8.00000E+01 7.20000E+01 6.40000E+01 5.60000E+01
> >  1.20000E+02 1.08000E+02 9.60000E+01 8.40000E+01
> >  1.60000E+02 1.44000E+02 1.28000E+02 1.12000E+02
> > 
> > Elapsed time is      0.000000445
> > 
> > C:\Users\Bojan\Documents>set path=C:\GNAT\2017\BIN;%path%
> > 
> > Results GPL GNAT/2017 from AdaCore.
> > 
> > C:\Users\Bojan\Documents>gnatmake -O3 -fopt-info -mavx2 matrix_mul.adb -largs -s
> > gcc -c -O3 -fopt-info -mavx2 matrix_mul.adb
> > matrix_mul.adb:56:41: note: loop turned into non-loop; it never loops.
> > matrix_mul.adb:56:41: note: loop with 4 iterations completely unrolled
> > matrix_mul.adb:54:38: note: loop turned into non-loop; it never loops.
> > matrix_mul.adb:54:38: note: loop with 4 iterations completely unrolled
> > matrix_mul.adb:53:35: note: loop turned into non-loop; it never loops.
> > matrix_mul.adb:53:35: note: loop with 4 iterations completely unrolled
> > matrix_mul.adb:40:15: note: basic block vectorized
> > matrix_mul.adb:68:9: note: basic block vectorized
> > gnatbind -x matrix_mul.ali
> > gnatlink matrix_mul.ali -O3 -fopt-info -mavx2 -s
> > 
> > C:\Users\Bojan\Documents>matrix_mul
> >  4.00000E+01 3.60000E+01 3.20000E+01 2.80000E+01
> >  8.00000E+01 7.20000E+01 6.40000E+01 5.60000E+01
> >  1.20000E+02 1.08000E+02 9.60000E+01 8.40000E+01
> >  1.60000E+02 1.44000E+02 1.28000E+02 1.12000E+02
> > 
> > Elapsed Time is      2.145337334
> >  4.00000E+01 3.60000E+01 3.20000E+01 2.80000E+01
> >  8.00000E+01 7.20000E+01 6.40000E+01 5.60000E+01
> >  1.20000E+02 1.08000E+02 9.60000E+01 8.40000E+01
> >  1.60000E+02 1.44000E+02 1.28000E+02 1.12000E+02
> > 
> > Elapsed time is      0.000000444
> > 
> > C:\Users\Bojan\Documents>gcc --version
> > gcc (GCC) 6.3.1 20170510 (for GNAT GPL 2017 20170515)
> > Copyright (C) 2016 Free Software Foundation, Inc.
> > This is free software; see the source for copying conditions.
> > See your AdaCore support agreement for details of warranty and support.
> > If you do not have a current support agreement, then there is absolutely
> > no warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
> > PURPOSE.
> > 
> > Should I submit this as bug to AdaCore? My computer is Intel Core i3-6100U (Skylake AVX2). Please try to reproduce.
> 
> Compiler is smart enough to not iterate 10 million times over constant values, but there is still optimization problem.

I don't know how to use pragma Volatile to force  iterations, even though with no 10 million iterations but with single multiplication results are (from AdaCore GNAT/2017 GPL)

C:\Users\Bojan\Documents>matrix_mul
 4.00000E+01 3.60000E+01 3.20000E+01 2.80000E+01
 8.00000E+01 7.20000E+01 6.40000E+01 5.60000E+01
 1.20000E+02 1.08000E+02 9.60000E+01 8.40000E+01
 1.60000E+02 1.44000E+02 1.28000E+02 1.12000E+02

Elapsed Time is      0.000009333
 4.00000E+01 3.60000E+01 3.20000E+01 2.80000E+01
 8.00000E+01 7.20000E+01 6.40000E+01 5.60000E+01
 1.20000E+02 1.08000E+02 9.60000E+01 8.40000E+01
 1.60000E+02 1.44000E+02 1.28000E+02 1.12000E+02

Elapsed time is      0.000000889

I'm submitting this as bug to AdaCore.


^ permalink raw reply	[relevance 5%]

* Re: GNAT can't vectorize Real_Matrix multiplication from Ada.Numerics.Real_Arrays. What a surprise!
  2018-02-17 12:55  7% GNAT can't vectorize Real_Matrix multiplication from Ada.Numerics.Real_Arrays. What a surprise! Bojan Bozovic
@ 2018-02-17 15:17  6% ` Bojan Bozovic
  2018-02-17 15:49  5%   ` Bojan Bozovic
  2018-02-18  1:51 10% ` Bojan Bozovic
  1 sibling, 1 reply; 61+ results
From: Bojan Bozovic @ 2018-02-17 15:17 UTC (permalink / raw)


On Saturday, February 17, 2018 at 1:55:49 PM UTC+1, Bojan Bozovic wrote:
> -- code
> 
> with Ada.Calendar;
> with Ada.Text_IO;
> with Ada.Numerics.Real_Arrays;
> use Ada.Calendar;
> use Ada.Text_IO;
> use Ada.Numerics.Real_Arrays;
> 
> procedure Matrix_Mul is
> 
>    package F_IO is new Ada.Text_IO.Fixed_IO (Day_Duration);
>    use F_IO;
> 
>    Start_Time, End_Time : Time;
> 
>    procedure Put (X : Real_Matrix) is
>    begin
>       for I in X'Range (1) loop
>          for J in X'Range (2) loop
>             Put (Float'Image (Float (X (I, J))));
>          end loop;
>          New_Line;
>       end loop;
>    end Put;
> 
>    Matrix_A, Matrix_B, Result : Real_Matrix (1 .. 4, 1 .. 4);
>    Elapsed_Time               : Duration;
>    Sum                        : Float;
> begin
>    Matrix_A :=
>      ((1.0, 1.0, 1.0, 1.0),
>       (2.0, 2.0, 2.0, 2.0),
>       (3.0, 3.0, 3.0, 3.0),
>       (4.0, 4.0, 4.0, 4.0));
>    Matrix_B :=
>      ((16.0, 15.0, 14.0, 13.0),
>       (12.0, 11.0, 10.0, 9.0),
>       (8.0, 7.0, 6.0, 5.0),
>       (4.0, 3.0, 2.0, 1.0));
> 
>    Start_Time := Clock;
>    for Iteration in 1 .. 10_000_000 loop
>       Result := Matrix_A * Matrix_B;
>    end loop;
>    End_Time     := Clock;
>    Elapsed_Time := End_Time - Start_Time;
>    Put (Result);
>    New_Line;
>    Put ("Elapsed Time is ");
>    Put (Elapsed_Time);
>    New_Line;
>    Start_Time := Clock;
>    for Iteration in 1 .. 10_000_000 loop
>       for I in Matrix_A'Range (1) loop
>          for J in Matrix_A'Range (2) loop
>             Sum := 0.0;
>             for K in Matrix_A'Range (2) loop
>                Sum := Sum + Matrix_A (I, K) * Matrix_B (K, J);
>             end loop;
>             Result (I, J) := Sum;
>          end loop;
>       end loop;
>    end loop;
>    End_Time     := Clock;
>    Elapsed_Time := End_Time - Start_Time;
>    Put (Result);
>    New_Line;
>    Put ("Elapsed time is ");
>    Put (Elapsed_Time);
>    New_Line;
> end Matrix_Mul;
> -- end code
> 
> Results: FSF GNAT 7.2.0 x64
> C:\Users\Bojan\Documents>gnatmake -O3 -fopt-info -march=skylake matrix_mul.adb -largs -s
> gcc -c -O3 -fopt-info -march=skylake matrix_mul.adb
> matrix_mul.adb:56:41: note: loop turned into non-loop; it never loops.
> matrix_mul.adb:56:41: note: loop with 4 iterations completely unrolled
> matrix_mul.adb:54:38: note: loop turned into non-loop; it never loops.
> matrix_mul.adb:54:38: note: loop with 4 iterations completely unrolled
> matrix_mul.adb:53:35: note: loop turned into non-loop; it never loops.
> matrix_mul.adb:53:35: note: loop with 4 iterations completely unrolled
> matrix_mul.adb:40:15: note: basic block vectorized
> matrix_mul.adb:42:26: note: basic block vectorized
> matrix_mul.adb:18:31: note: basic block vectorized
> matrix_mul.adb:49:9: note: basic block vectorized
> C:/MSYS64/MINGW64/lib/gcc/x86_64-w64-mingw32/7.2.0/adainclude/a-tifiio.adb:706:10: note: basic block vectorized
> matrix_mul.adb:64:17: note: basic block vectorized
> matrix_mul.adb:18:31: note: basic block vectorized
> matrix_mul.adb:68:9: note: basic block vectorized
> C:/MSYS64/MINGW64/lib/gcc/x86_64-w64-mingw32/7.2.0/adainclude/a-tifiio.adb:706:10: note: basic block vectorized
> gnatbind -x matrix_mul.ali
> gnatlink matrix_mul.ali -O3 -fopt-info -march=skylake -s
> 
> C:\Users\Bojan\Documents>matrix_mul
>  4.00000E+01 3.60000E+01 3.20000E+01 2.80000E+01
>  8.00000E+01 7.20000E+01 6.40000E+01 5.60000E+01
>  1.20000E+02 1.08000E+02 9.60000E+01 8.40000E+01
>  1.60000E+02 1.44000E+02 1.28000E+02 1.12000E+02
> 
> Elapsed Time is      1.338206667
>  4.00000E+01 3.60000E+01 3.20000E+01 2.80000E+01
>  8.00000E+01 7.20000E+01 6.40000E+01 5.60000E+01
>  1.20000E+02 1.08000E+02 9.60000E+01 8.40000E+01
>  1.60000E+02 1.44000E+02 1.28000E+02 1.12000E+02
> 
> Elapsed time is      0.000000445
> 
> C:\Users\Bojan\Documents>set path=C:\GNAT\2017\BIN;%path%
> 
> Results GPL GNAT/2017 from AdaCore.
> 
> C:\Users\Bojan\Documents>gnatmake -O3 -fopt-info -mavx2 matrix_mul.adb -largs -s
> gcc -c -O3 -fopt-info -mavx2 matrix_mul.adb
> matrix_mul.adb:56:41: note: loop turned into non-loop; it never loops.
> matrix_mul.adb:56:41: note: loop with 4 iterations completely unrolled
> matrix_mul.adb:54:38: note: loop turned into non-loop; it never loops.
> matrix_mul.adb:54:38: note: loop with 4 iterations completely unrolled
> matrix_mul.adb:53:35: note: loop turned into non-loop; it never loops.
> matrix_mul.adb:53:35: note: loop with 4 iterations completely unrolled
> matrix_mul.adb:40:15: note: basic block vectorized
> matrix_mul.adb:68:9: note: basic block vectorized
> gnatbind -x matrix_mul.ali
> gnatlink matrix_mul.ali -O3 -fopt-info -mavx2 -s
> 
> C:\Users\Bojan\Documents>matrix_mul
>  4.00000E+01 3.60000E+01 3.20000E+01 2.80000E+01
>  8.00000E+01 7.20000E+01 6.40000E+01 5.60000E+01
>  1.20000E+02 1.08000E+02 9.60000E+01 8.40000E+01
>  1.60000E+02 1.44000E+02 1.28000E+02 1.12000E+02
> 
> Elapsed Time is      2.145337334
>  4.00000E+01 3.60000E+01 3.20000E+01 2.80000E+01
>  8.00000E+01 7.20000E+01 6.40000E+01 5.60000E+01
>  1.20000E+02 1.08000E+02 9.60000E+01 8.40000E+01
>  1.60000E+02 1.44000E+02 1.28000E+02 1.12000E+02
> 
> Elapsed time is      0.000000444
> 
> C:\Users\Bojan\Documents>gcc --version
> gcc (GCC) 6.3.1 20170510 (for GNAT GPL 2017 20170515)
> Copyright (C) 2016 Free Software Foundation, Inc.
> This is free software; see the source for copying conditions.
> See your AdaCore support agreement for details of warranty and support.
> If you do not have a current support agreement, then there is absolutely
> no warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
> PURPOSE.
> 
> Should I submit this as bug to AdaCore? My computer is Intel Core i3-6100U (Skylake AVX2). Please try to reproduce.

Compiler is smart enough to not iterate 10 million times over constant values, but there is still optimization problem.


^ permalink raw reply	[relevance 6%]

* GNAT can't vectorize Real_Matrix multiplication from Ada.Numerics.Real_Arrays. What a surprise!
@ 2018-02-17 12:55  7% Bojan Bozovic
  2018-02-17 15:17  6% ` Bojan Bozovic
  2018-02-18  1:51 10% ` Bojan Bozovic
  0 siblings, 2 replies; 61+ results
From: Bojan Bozovic @ 2018-02-17 12:55 UTC (permalink / raw)


-- code

with Ada.Calendar;
with Ada.Text_IO;
with Ada.Numerics.Real_Arrays;
use Ada.Calendar;
use Ada.Text_IO;
use Ada.Numerics.Real_Arrays;

procedure Matrix_Mul is

   package F_IO is new Ada.Text_IO.Fixed_IO (Day_Duration);
   use F_IO;

   Start_Time, End_Time : Time;

   procedure Put (X : Real_Matrix) is
   begin
      for I in X'Range (1) loop
         for J in X'Range (2) loop
            Put (Float'Image (Float (X (I, J))));
         end loop;
         New_Line;
      end loop;
   end Put;

   Matrix_A, Matrix_B, Result : Real_Matrix (1 .. 4, 1 .. 4);
   Elapsed_Time               : Duration;
   Sum                        : Float;
begin
   Matrix_A :=
     ((1.0, 1.0, 1.0, 1.0),
      (2.0, 2.0, 2.0, 2.0),
      (3.0, 3.0, 3.0, 3.0),
      (4.0, 4.0, 4.0, 4.0));
   Matrix_B :=
     ((16.0, 15.0, 14.0, 13.0),
      (12.0, 11.0, 10.0, 9.0),
      (8.0, 7.0, 6.0, 5.0),
      (4.0, 3.0, 2.0, 1.0));

   Start_Time := Clock;
   for Iteration in 1 .. 10_000_000 loop
      Result := Matrix_A * Matrix_B;
   end loop;
   End_Time     := Clock;
   Elapsed_Time := End_Time - Start_Time;
   Put (Result);
   New_Line;
   Put ("Elapsed Time is ");
   Put (Elapsed_Time);
   New_Line;
   Start_Time := Clock;
   for Iteration in 1 .. 10_000_000 loop
      for I in Matrix_A'Range (1) loop
         for J in Matrix_A'Range (2) loop
            Sum := 0.0;
            for K in Matrix_A'Range (2) loop
               Sum := Sum + Matrix_A (I, K) * Matrix_B (K, J);
            end loop;
            Result (I, J) := Sum;
         end loop;
      end loop;
   end loop;
   End_Time     := Clock;
   Elapsed_Time := End_Time - Start_Time;
   Put (Result);
   New_Line;
   Put ("Elapsed time is ");
   Put (Elapsed_Time);
   New_Line;
end Matrix_Mul;
-- end code

Results: FSF GNAT 7.2.0 x64
C:\Users\Bojan\Documents>gnatmake -O3 -fopt-info -march=skylake matrix_mul.adb -largs -s
gcc -c -O3 -fopt-info -march=skylake matrix_mul.adb
matrix_mul.adb:56:41: note: loop turned into non-loop; it never loops.
matrix_mul.adb:56:41: note: loop with 4 iterations completely unrolled
matrix_mul.adb:54:38: note: loop turned into non-loop; it never loops.
matrix_mul.adb:54:38: note: loop with 4 iterations completely unrolled
matrix_mul.adb:53:35: note: loop turned into non-loop; it never loops.
matrix_mul.adb:53:35: note: loop with 4 iterations completely unrolled
matrix_mul.adb:40:15: note: basic block vectorized
matrix_mul.adb:42:26: note: basic block vectorized
matrix_mul.adb:18:31: note: basic block vectorized
matrix_mul.adb:49:9: note: basic block vectorized
C:/MSYS64/MINGW64/lib/gcc/x86_64-w64-mingw32/7.2.0/adainclude/a-tifiio.adb:706:10: note: basic block vectorized
matrix_mul.adb:64:17: note: basic block vectorized
matrix_mul.adb:18:31: note: basic block vectorized
matrix_mul.adb:68:9: note: basic block vectorized
C:/MSYS64/MINGW64/lib/gcc/x86_64-w64-mingw32/7.2.0/adainclude/a-tifiio.adb:706:10: note: basic block vectorized
gnatbind -x matrix_mul.ali
gnatlink matrix_mul.ali -O3 -fopt-info -march=skylake -s

C:\Users\Bojan\Documents>matrix_mul
 4.00000E+01 3.60000E+01 3.20000E+01 2.80000E+01
 8.00000E+01 7.20000E+01 6.40000E+01 5.60000E+01
 1.20000E+02 1.08000E+02 9.60000E+01 8.40000E+01
 1.60000E+02 1.44000E+02 1.28000E+02 1.12000E+02

Elapsed Time is      1.338206667
 4.00000E+01 3.60000E+01 3.20000E+01 2.80000E+01
 8.00000E+01 7.20000E+01 6.40000E+01 5.60000E+01
 1.20000E+02 1.08000E+02 9.60000E+01 8.40000E+01
 1.60000E+02 1.44000E+02 1.28000E+02 1.12000E+02

Elapsed time is      0.000000445

C:\Users\Bojan\Documents>set path=C:\GNAT\2017\BIN;%path%

Results GPL GNAT/2017 from AdaCore.

C:\Users\Bojan\Documents>gnatmake -O3 -fopt-info -mavx2 matrix_mul.adb -largs -s
gcc -c -O3 -fopt-info -mavx2 matrix_mul.adb
matrix_mul.adb:56:41: note: loop turned into non-loop; it never loops.
matrix_mul.adb:56:41: note: loop with 4 iterations completely unrolled
matrix_mul.adb:54:38: note: loop turned into non-loop; it never loops.
matrix_mul.adb:54:38: note: loop with 4 iterations completely unrolled
matrix_mul.adb:53:35: note: loop turned into non-loop; it never loops.
matrix_mul.adb:53:35: note: loop with 4 iterations completely unrolled
matrix_mul.adb:40:15: note: basic block vectorized
matrix_mul.adb:68:9: note: basic block vectorized
gnatbind -x matrix_mul.ali
gnatlink matrix_mul.ali -O3 -fopt-info -mavx2 -s

C:\Users\Bojan\Documents>matrix_mul
 4.00000E+01 3.60000E+01 3.20000E+01 2.80000E+01
 8.00000E+01 7.20000E+01 6.40000E+01 5.60000E+01
 1.20000E+02 1.08000E+02 9.60000E+01 8.40000E+01
 1.60000E+02 1.44000E+02 1.28000E+02 1.12000E+02

Elapsed Time is      2.145337334
 4.00000E+01 3.60000E+01 3.20000E+01 2.80000E+01
 8.00000E+01 7.20000E+01 6.40000E+01 5.60000E+01
 1.20000E+02 1.08000E+02 9.60000E+01 8.40000E+01
 1.60000E+02 1.44000E+02 1.28000E+02 1.12000E+02

Elapsed time is      0.000000444

C:\Users\Bojan\Documents>gcc --version
gcc (GCC) 6.3.1 20170510 (for GNAT GPL 2017 20170515)
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
See your AdaCore support agreement for details of warranty and support.
If you do not have a current support agreement, then there is absolutely
no warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.

Should I submit this as bug to AdaCore? My computer is Intel Core i3-6100U (Skylake AVX2). Please try to reproduce.


^ permalink raw reply	[relevance 7%]

* Re: {Pre,Post}conditions and side effects
  2015-04-24  8:59  4%             ` Jacob Sparre Andersen
  2015-04-24 22:26  0%               ` Peter Chapin
@ 2015-04-25  0:31  0%               ` Bob Duff
  1 sibling, 0 replies; 61+ results
From: Bob Duff @ 2015-04-25  0:31 UTC (permalink / raw)


Jacob Sparre Andersen <jacob@jacob-sparre.dk> writes:

> Robert A Duff <bobduff@shell01.TheWorld.com> writes:
>> Peter Chapin <PChapin@vtc.vsc.edu> writes:
>
>>> ... Thus putting anything resembling essential program logic in an
>>> assertion is, of course, just wrong.
>>
>> Yes.
>
> But when are you putting "essential program logic" in an assertion?

I think what Peter meant by "essential program logic" is code that,
if deleted from the program, would cause the program to malfunction.

> 1) subtype Non_Negative_Matrix is Ada.Numerics.Real_Arrays.Real_Matrix
>      with Dynamic_Predicate
>             => (Non_Negative_Matrix'First (1) = 1) and
>                (Non_Negative_Matrix'First (2) = 1) and
>                (for all E of Non_Negative_Matrix => E >= 0.0);
>
> 2) procedure New_Line (File : in File_Type)
>      with Pre => Is_Open (File) and then
>                  Mode (File) in (Out_File | Append_File);

The assertions in (1) and (2) are not "essential program logic"; if you
delete them, the program will still work properly.  That's fine -- you
should write assertions so that deleting them from a correct program
will have no effect.

> 3) function Binary_Search (Source : in List;
>                            Key    : in Keys) return Values
>      with Pre => Sort (Source); --  Sorts Source if it isn't already sorted.

That's illegal.  (I assume Sort is a procedure with an 'in out'
parameter that sorts in place.  Passing Source (an 'in') parameter is
illegal.)  I suppose you could make Source 'in out', but as you say
below that's a very bad idea.

> I consider examples (1) and (2) fine, but example (3) a very bad idea.

Agreed.  (3) is trying to put "essential program logic" in an assertion,
which is a bad idea.

> At the same time, I know that my application may fail silently if the
> assertion in example (1) isn't true.
>
> When it comes to example (2), I expect that the operating system (if
> nothing else) will make sure that my application doesn't fail silently
> if the assertion isn't true.
>
> But I dislike banning "essential program logic" in assertions, as any
> assertion is program logic.  And if it isn't essential, why should it be
> there?

Same reason we put comments in the code.  Comments are not "essential
program logic" in the sense defined above -- if you delete all the
comments, the program will still work.  But we still want comments.
Likewise, one should normally write assertions (like Pre and Predicate)
so the program still works if they are deleted.

Assertions are like comments, except we have a higher confidence
that they are actually true.

> One problem I have with assertion aspects is that I get the same
> exception no matter which mistake I have made.  If I put the check
> inside a subprogram instead of in its profile, I can get more clear
> information about which kinds of mistakes I make.

You can say:

    Pre => X = Y or else raise X_Not_Equal_To_Y;

- Bob

^ permalink raw reply	[relevance 0%]

* Re: {Pre,Post}conditions and side effects
  2015-04-24 22:26  0%               ` Peter Chapin
@ 2015-04-25  0:13  0%                 ` Randy Brukardt
  0 siblings, 0 replies; 61+ results
From: Randy Brukardt @ 2015-04-25  0:13 UTC (permalink / raw)


"Peter Chapin" <PChapin@vtc.vsc.edu> wrote in message 
news:alpine.CYG.2.11.1504241811360.5268@WIL414CHAPIN.vtc.vsc.edu...
...
> In a correct program all assertions should always be true.

Sure, but that applies to lots of other things, too. For instance, in a 
correct program, Constraint_Error or Program_Error should not be raised. But 
it still happens.

>> 1) subtype Non_Negative_Matrix is Ada.Numerics.Real_Arrays.Real_Matrix
>>     with Dynamic_Predicate
>>            => (Non_Negative_Matrix'First (1) = 1) and
>>               (Non_Negative_Matrix'First (2) = 1) and
>>               (for all E of Non_Negative_Matrix => E >= 0.0);
>
> Although the Dynamic_Predicate asserts that the matrix elements are all 
> non-negative, this does not remove the program's obligation to include 
> checks that no negative elements are added to the matrix. The assertion 
> only exists to catch mistakes in those checks. It does not exist to 
> actually *be* those checks. In that respect the assertion is not 
> "essential program logic."

I disagree with this (see below).

>> 2) procedure New_Line (File : in File_Type)
>>     with Pre => Is_Open (File) and then
>>                 Mode (File) in (Out_File | Append_File);
>
> Similarly here the program is still obligated to only pass File objects to 
> New_Line that represent open files. If the program accidentally passes an 
> unopened file to New_Line the assertion will catch the logical error. 
> However, the assertion should not take the place of earlier checks. Again 
> the assertion is not essential program logic.

I definitely disagree here. This example is essentially similar to the one 
given in the upcoming Corrigendum (3.2.4(41-51/4). In a case like this, the 
precondition (or predicates as in the example) *replace* the checks required 
by English text in the RM. There would no internal checks of correctness.

You are of course correct that no caller should call New_Line with a closed 
file, but that's irrelevant because it can happen anyway (there is no static 
way to prevent it). There has to be code somewhere to handle it. So, in such 
a case, a precondition serves two purposes: (1) to signal to the client what 
conditions are expected, and (2) to determine what happens if those 
conditions aren't met. (2) certainly is "essential program logic", at so far 
as one cannot meet the published specification of New_Line without it.

Ada prior to Ada 2012 has a problem in that the reasons an exception can be 
raised conflate the programmer mistakes with conditions that are impossible 
for the programmer to know (consider the difference between whether a file 
object is open vs. whether a file exists on the disk). Preconditions and 
predicates provide a way to separately specify the first kind of situation 
vs. the second kind. (Ultimately, one hopes, compilers will be able to 
eliminate much of the runtime checking associated with preconditions and 
predicates, which is not possible in the pre-Ada 2012 world.)

                                   Randy.



^ permalink raw reply	[relevance 0%]

* Re: {Pre,Post}conditions and side effects
  2015-04-24  8:59  4%             ` Jacob Sparre Andersen
@ 2015-04-24 22:26  0%               ` Peter Chapin
  2015-04-25  0:13  0%                 ` Randy Brukardt
  2015-04-25  0:31  0%               ` Bob Duff
  1 sibling, 1 reply; 61+ results
From: Peter Chapin @ 2015-04-24 22:26 UTC (permalink / raw)


On Fri, 24 Apr 2015, Jacob Sparre Andersen wrote:

> But when are you putting "essential program logic" in an assertion?

I think a servicable rule is this: If the program works as required, with 
all necessary checks still present, with all assertions removed, then we 
can say the assertions contain no essential program logic.

In a correct program all assertions should always be true.

> 1) subtype Non_Negative_Matrix is Ada.Numerics.Real_Arrays.Real_Matrix
>     with Dynamic_Predicate
>            => (Non_Negative_Matrix'First (1) = 1) and
>               (Non_Negative_Matrix'First (2) = 1) and
>               (for all E of Non_Negative_Matrix => E >= 0.0);

Although the Dynamic_Predicate asserts that the matrix elements are all 
non-negative, this does not remove the program's obligation to include 
checks that no negative elements are added to the matrix. The assertion 
only exists to catch mistakes in those checks. It does not exist to 
actually *be* those checks. In that respect the assertion is not 
"essential program logic."

> 2) procedure New_Line (File : in File_Type)
>     with Pre => Is_Open (File) and then
>                 Mode (File) in (Out_File | Append_File);

Similarly here the program is still obligated to only pass File objects to 
New_Line that represent open files. If the program accidentally passes an 
unopened file to New_Line the assertion will catch the logical error. 
However, the assertion should not take the place of earlier checks. Again 
the assertion is not essential program logic.

> 3) function Binary_Search (Source : in List;
>                           Key    : in Keys) return Values
>     with Pre => Sort (Source); --  Sorts Source if it isn't already sorted.

Yes, definitely wrong. On the other hand using something like

     with Pre => Is_Sorted(Source);

could be reasonable.

> I consider examples (1) and (2) fine, but example (3) a very bad idea.

I agree that (1) and (2) are fine, but that doesn't mean the program 
should rely on the assertions for its proper functioning. The assertions 
check correctness; they don't implement it. Even if the assertions are 
removed, the program should still execute properly.

> But I dislike banning "essential program logic" in assertions, as any 
> assertion is program logic.  And if it isn't essential, why should it be 
> there?

Because we often make mistakes and it's nice to have our thinking double 
checked. Also, of course, the assertions make our intentions known to 
tools, such as SPARK, that can automatically verify our code implements 
the conditions we are asserting.

> One problem I have with assertion aspects is that I get the same 
> exception no matter which mistake I have made.  If I put the check 
> inside a subprogram instead of in its profile, I can get more clear 
> information about which kinds of mistakes I make.

Putting the check inside the subprogram is quite a different thing. That 
is part of your implementation of correctness. Since assertions should 
never fail, using the same exception for all of them isn't terrible. That 
said, the upcoming feature that allows different exceptions to be used 
when an assertion fails is nice too.

Peter



^ permalink raw reply	[relevance 0%]

* Re: {Pre,Post}conditions and side effects
  @ 2015-04-24  8:59  4%             ` Jacob Sparre Andersen
  2015-04-24 22:26  0%               ` Peter Chapin
  2015-04-25  0:31  0%               ` Bob Duff
  0 siblings, 2 replies; 61+ results
From: Jacob Sparre Andersen @ 2015-04-24  8:59 UTC (permalink / raw)


Robert A Duff <bobduff@shell01.TheWorld.com> writes:
> Peter Chapin <PChapin@vtc.vsc.edu> writes:

>> ... Thus putting anything resembling essential program logic in an
>> assertion is, of course, just wrong.
>
> Yes.

But when are you putting "essential program logic" in an assertion?

1) subtype Non_Negative_Matrix is Ada.Numerics.Real_Arrays.Real_Matrix
     with Dynamic_Predicate
            => (Non_Negative_Matrix'First (1) = 1) and
               (Non_Negative_Matrix'First (2) = 1) and
               (for all E of Non_Negative_Matrix => E >= 0.0);

2) procedure New_Line (File : in File_Type)
     with Pre => Is_Open (File) and then
                 Mode (File) in (Out_File | Append_File);

3) function Binary_Search (Source : in List;
                           Key    : in Keys) return Values
     with Pre => Sort (Source); --  Sorts Source if it isn't already sorted.

I consider examples (1) and (2) fine, but example (3) a very bad idea.

At the same time, I know that my application may fail silently if the
assertion in example (1) isn't true.

When it comes to example (2), I expect that the operating system (if
nothing else) will make sure that my application doesn't fail silently
if the assertion isn't true.

But I dislike banning "essential program logic" in assertions, as any
assertion is program logic.  And if it isn't essential, why should it be
there?

One problem I have with assertion aspects is that I get the same
exception no matter which mistake I have made.  If I put the check
inside a subprogram instead of in its profile, I can get more clear
information about which kinds of mistakes I make.

Greetings,

Jacob
-- 
"Any politician with a live opposition does not understand
 how to make proper use of the true instruments of politics."

^ permalink raw reply	[relevance 4%]

* Re: X : Real_Vector := Solve(A => A, X => B); -- Why X as argument name?
  2012-12-24 11:50  0%   ` Simon Wright
  2012-12-24 12:58  0%     ` Niklas Holsti
@ 2012-12-24 21:25  0%     ` Gustaf Thorslund
  1 sibling, 0 replies; 61+ results
From: Gustaf Thorslund @ 2012-12-24 21:25 UTC (permalink / raw)


Simon Wright <simon@pushface.org> writes:

> Niklas Holsti <niklas.holsti@tidorum.invalid> writes:
>
>> Or do you mean to ask if it was a mistake in the definition of
>> Ada.Numerics.Real_Arrays.Solve to give the second formal parameter the
>> name "X", given that "X" is a common name in client code?
>
> This is certainly a style issue. The second parameter has been 'X' ever
> since it was introduced in v4 of ai-00296 in June 2003[1]. I would
> probably have chosen 'B', but there may well be mathematical texts that
> would take the approach adopted in the ARM.

Thanks for the link! So then we are three who would have chosen 'B' over
'X'. I'm curious why 'X' was chosen. But whatever the reason was it's
already done.

> It's very common for mathematical code to adopt terse naming, in line
> with the way mathematicians seem to work, and I find it hard to think of
> sensible names for these parameters. But it ought to be possible for
> client code to be more explicit (unless, of course, the algorithm to be
> implemented was specified by one of the above-referenced mathematicians!)

When it comes to an abstract generic level it may be hard to come up
with more explicit names. A queue will have a head and tail (or some
other names). Depending on application it may be good or bad to be
first.

/Gustaf



^ permalink raw reply	[relevance 0%]

* Re: X : Real_Vector := Solve(A => A, X => B); -- Why X as argument name?
  2012-12-24  8:33  4% ` Niklas Holsti
  2012-12-24 11:50  0%   ` Simon Wright
@ 2012-12-24 20:42  0%   ` Gustaf Thorslund
  1 sibling, 0 replies; 61+ results
From: Gustaf Thorslund @ 2012-12-24 20:42 UTC (permalink / raw)


Niklas Holsti <niklas.holsti@tidorum.invalid> writes:

> Or you could ask, why use "X" as the name of a local variable?

Since it's a common name of an unknown in the context of linear
equations.

>
>>    
>> begin
>>    for I in X'Range loop
>>       Put_Line(Float'Image(X(I)));
>>    end loop;
>> end Why_X;
>> 
>> -- Executing the program gives
>> -- $ ./why_x 
>> --  6.00000E+00
>> -- So we found the expected value of x.
>
> Do you see that as a problem? :-)

No :-) But someone reading
  http://www.adaic.org/resources/add_content/standards/05rat/html/Rat-7-6.html#I1361

without a knowing what linear equations are could get a bit confused.

(in the middle of the page there is an equation "Ax = y")

>> -- Was it a misstake to use X as argument name in Solve?
>
> Do you mean, is it an error that your program uses "X" as the name of a
> local variable, when it also calls a function that has a formal
> parameter called "X"?
>
> No, it is not an error and is quite legal. The compiler knows from the
> named-association syntax ("X => ...") that "X" refers to the name of a
> formal parameter.

No, I used X intentionally to show the why it can be confusing.

> Or do you mean to ask if it was a mistake in the definition of
> Ada.Numerics.Real_Arrays.Solve to give the second formal parameter the
> name "X", given that "X" is a common name in client code?

Right!

> That is a matter of coding style and habit. (I would probably have
> chosen the name "B" for the second parameter, since "X" suggests
> "unknowns" to me, while "A" and "B" suggest "knowns".) And most coding
> style guidelines recommend against single-letter names like "X" in
> application programs, so "X" should not really be a common name.

"X" could be a common name in short examples or even a local
variable. Just like "I" and "J" in loops.

> Or do you mean to ask if it is mistake that your program uses the name
> "X" for a local variable, which the reader can confuse with the formal
> parameter "X"?

No.

> If you have no important reason to call your local variable "X", it
> would be slightly clearer to choose a different name, at least for
> readers not yet familiar with Ada.

For readers not familiar with Ada but familiar with linear equations one
might as well write:

  X := Solve (A, B);

From what I see the argument name "X" doesn't really add any value
anyway.

/Gustaf



^ permalink raw reply	[relevance 0%]

* Re: X : Real_Vector := Solve(A => A, X => B); -- Why X as argument name?
  2012-12-23 22:28  6% X : Real_Vector := Solve(A => A, X => B); -- Why X as argument name? Gustaf Thorslund
  2012-12-24  8:33  4% ` Niklas Holsti
@ 2012-12-24 20:10  0% ` jpwoodruff
  1 sibling, 0 replies; 61+ results
From: jpwoodruff @ 2012-12-24 20:10 UTC (permalink / raw)


I would agree that calling the formal parameter "x" is
infelicitous. But it's been that way for a long time, so we live with
it.  The important thing is that the originators made the decision and
moved on.

I'm glad the topic came up.  I like to engage the people who think
this subject is interesting.  I'm going to reopen the topic of Ada
bindings to Lapack, and the subject of parameter names looms in that
discussion.  I'll put something up a couple days after Christmas.  

Ho Ho Ho.  

John



On Sunday, December 23, 2012 3:28:13 PM UTC-7, Gustaf Thorslund wrote:
> -- why_x.adb by confused Gustaf Thorslund
> 
> 
> 
> with Ada.Numerics.Real_Arrays; use Ada.Numerics.Real_Arrays;
<...>
> 
>    -- x is found using 
> 
>    -- function Solve (A : Real_Matrix; X : Real_Vector) return
> 
>    -- Real_Vector;
> 
>    X : Real_Vector := Solve(A => A, X => B); -- Why X as argument name?
> 



^ permalink raw reply	[relevance 0%]

* Re: X : Real_Vector := Solve(A => A, X => B); -- Why X as argument name?
  2012-12-24 11:50  0%   ` Simon Wright
@ 2012-12-24 12:58  0%     ` Niklas Holsti
  2012-12-24 21:25  0%     ` Gustaf Thorslund
  1 sibling, 0 replies; 61+ results
From: Niklas Holsti @ 2012-12-24 12:58 UTC (permalink / raw)


On 12-12-24 13:50 , Simon Wright wrote:
> Niklas Holsti <niklas.holsti@tidorum.invalid> writes:
> 
>> Or do you mean to ask if it was a mistake in the definition of
>> Ada.Numerics.Real_Arrays.Solve to give the second formal parameter the
>> name "X", given that "X" is a common name in client code?
> 
> This is certainly a style issue. The second parameter has been 'X' ever
> since it was introduced in v4 of ai-00296 in June 2003[1]. I would
> probably have chosen 'B', but there may well be mathematical texts that
> would take the approach adopted in the ARM.

There may indeed.

> It's very common for mathematical code to adopt terse naming, in line
> with the way mathematicians seem to work,

Agreed. Writing long names in chalk on a black-board (or with ink on a
white-board) is cumbersome and one quickly runs out of space.

> and I find it hard to think of
> sensible names for these parameters.

One problem is that even the subprogram name "Solve" is not according to
good practice. Firstly, an imperative verb like "Solve", should name a
procedure, not a function. For a function, a noun should be used, for
example "Solution". Secondly, "Solve" and "Solution" are really far too
general; the name should be more specific, for example
"Linear_Inverse_Image".

A more specific subprogram name could in turn suggest sensible names for
the parameters, for example "Map" for the matrix Solve.A, and "Value"
for Solve.X.

The overly general names "Solve" or "Solution" suggest parameter names
like "Problem" or "Equation", which are not so good.

> But it ought to be possible for
> client code to be more explicit (unless, of course, the algorithm to be
> implemented was specified by one of the above-referenced mathematicians!)

I have had the pleasure ;-) of implementing some computations specified
by mathematicians (well, control-theory specialist, really). The
mathematical symbols in the given equations were (as typical)
semi-fractal collections of indices and sub-indices surrounding some
base symbol on all (well, most) corners, in different alphabets (latin,
greek, etc.). The Ada identifiers logically became monsters like
"alpha_sub_i_sub_kappa".

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
      .      @       .



^ permalink raw reply	[relevance 0%]

* Re: X : Real_Vector := Solve(A => A, X => B); -- Why X as argument name?
  2012-12-24  8:33  4% ` Niklas Holsti
@ 2012-12-24 11:50  0%   ` Simon Wright
  2012-12-24 12:58  0%     ` Niklas Holsti
  2012-12-24 21:25  0%     ` Gustaf Thorslund
  2012-12-24 20:42  0%   ` Gustaf Thorslund
  1 sibling, 2 replies; 61+ results
From: Simon Wright @ 2012-12-24 11:50 UTC (permalink / raw)


Niklas Holsti <niklas.holsti@tidorum.invalid> writes:

> Or do you mean to ask if it was a mistake in the definition of
> Ada.Numerics.Real_Arrays.Solve to give the second formal parameter the
> name "X", given that "X" is a common name in client code?

This is certainly a style issue. The second parameter has been 'X' ever
since it was introduced in v4 of ai-00296 in June 2003[1]. I would
probably have chosen 'B', but there may well be mathematical texts that
would take the approach adopted in the ARM.

It's very common for mathematical code to adopt terse naming, in line
with the way mathematicians seem to work, and I find it hard to think of
sensible names for these parameters. But it ought to be possible for
client code to be more explicit (unless, of course, the algorithm to be
implemented was specified by one of the above-referenced mathematicians!)

[1] http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ais/ai-00296.txt?diffbase=1.3&rev=1.4



^ permalink raw reply	[relevance 0%]

* Re: X : Real_Vector := Solve(A => A, X => B); -- Why X as argument name?
  2012-12-23 22:28  6% X : Real_Vector := Solve(A => A, X => B); -- Why X as argument name? Gustaf Thorslund
@ 2012-12-24  8:33  4% ` Niklas Holsti
  2012-12-24 11:50  0%   ` Simon Wright
  2012-12-24 20:42  0%   ` Gustaf Thorslund
  2012-12-24 20:10  0% ` jpwoodruff
  1 sibling, 2 replies; 61+ results
From: Niklas Holsti @ 2012-12-24  8:33 UTC (permalink / raw)


On 12-12-24 00:28 , Gustaf Thorslund wrote:
> -- why_x.adb by confused Gustaf Thorslund
> 
> with Ada.Numerics.Real_Arrays; use Ada.Numerics.Real_Arrays;
> with Ada.Text_IO; use Ada.Text_IO;
> 
> procedure Why_X is
>    -- Let's say we have an equation Ax = b according to the notation
>    from
>    -- http://en.wikipedia.org/wiki/Matrix_(mathematics)#Linear_equations
>    -- where A and b are known while x is unknown.
>    
>    A : Real_Matrix(1..1, 1..1) := (others => (others => 2.0));
>    B : Real_Vector(1..1) := (others => 12.0);
>    
>    -- x is found using 
>    -- function Solve (A : Real_Matrix; X : Real_Vector) return
>    -- Real_Vector;
>    X : Real_Vector := Solve(A => A, X => B); -- Why X as argument name?


Or you could ask, why use "X" as the name of a local variable?

>    
> begin
>    for I in X'Range loop
>       Put_Line(Float'Image(X(I)));
>    end loop;
> end Why_X;
> 
> -- Executing the program gives
> -- $ ./why_x 
> --  6.00000E+00
> -- So we found the expected value of x.

Do you see that as a problem? :-)

> -- Was it a misstake to use X as argument name in Solve?

Do you mean, is it an error that your program uses "X" as the name of a
local variable, when it also calls a function that has a formal
parameter called "X"?

No, it is not an error and is quite legal. The compiler knows from the
named-association syntax ("X => ...") that "X" refers to the name of a
formal parameter.

Or do you mean to ask if it was a mistake in the definition of
Ada.Numerics.Real_Arrays.Solve to give the second formal parameter the
name "X", given that "X" is a common name in client code?

That is a matter of coding style and habit. (I would probably have
chosen the name "B" for the second parameter, since "X" suggests
"unknowns" to me, while "A" and "B" suggest "knowns".) And most coding
style guidelines recommend against single-letter names like "X" in
application programs, so "X" should not really be a common name.

Or do you mean to ask if it is mistake that your program uses the name
"X" for a local variable, which the reader can confuse with the formal
parameter "X"?

If you have no important reason to call your local variable "X", it
would be slightly clearer to choose a different name, at least for
readers not yet familiar with Ada.

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
      .      @       .



^ permalink raw reply	[relevance 4%]

* X : Real_Vector := Solve(A => A, X => B); -- Why X as argument name?
@ 2012-12-23 22:28  6% Gustaf Thorslund
  2012-12-24  8:33  4% ` Niklas Holsti
  2012-12-24 20:10  0% ` jpwoodruff
  0 siblings, 2 replies; 61+ results
From: Gustaf Thorslund @ 2012-12-23 22:28 UTC (permalink / raw)


-- why_x.adb by confused Gustaf Thorslund

with Ada.Numerics.Real_Arrays; use Ada.Numerics.Real_Arrays;
with Ada.Text_IO; use Ada.Text_IO;

procedure Why_X is
   -- Let's say we have an equation Ax = b according to the notation
   from
   -- http://en.wikipedia.org/wiki/Matrix_(mathematics)#Linear_equations
   -- where A and b are known while x is unknown.
   
   A : Real_Matrix(1..1, 1..1) := (others => (others => 2.0));
   B : Real_Vector(1..1) := (others => 12.0);
   
   -- x is found using 
   -- function Solve (A : Real_Matrix; X : Real_Vector) return
   -- Real_Vector;
   X : Real_Vector := Solve(A => A, X => B); -- Why X as argument name?
   
begin
   for I in X'Range loop
      Put_Line(Float'Image(X(I)));
   end loop;
end Why_X;

-- Executing the program gives
-- $ ./why_x 
--  6.00000E+00
-- So we found the expected value of x.
-- Was it a misstake to use X as argument name in Solve?



^ permalink raw reply	[relevance 6%]

* Re: ada lapack
  @ 2012-08-18 15:22  5%                         ` Nasser M. Abbasi
  0 siblings, 0 replies; 61+ results
From: Nasser M. Abbasi @ 2012-08-18 15:22 UTC (permalink / raw)


On 8/18/2012 8:48 AM, Ada novice wrote:
> Thanks. This is rather unfortunate to see that one cannot use the many operators
>and functions in Ada.Numerics.Generic_Complex_Arrays in example file example01.adb
>automatically. Adding two matrices is simple but other functions are not so easy to implement.
>
> YC
>

I already found this "issue" and mentioned it before here in this newsgroup
when I was working on the Ada Lapack package by Wasu Chaopanon.

see

http://coding.derkeiler.com/Archive/Ada/comp.lang.ada/2012-07/msg00290.html

"The Ada lapack binding defines its own Matrix types. However, it
does not define operators (multiply, add, etc.. ) to work on these
types similar to Ada's Real Vectors and Matrices in the
Ada.Numerics.Real_Arrays package"

Yes. Each time a new type is made, one in Ada, you must define
a new set of operators on this type.

--Nasser








^ permalink raw reply	[relevance 5%]

* Re: Lapack Ada binding matrices/vectors issue, how to best to resolve?
  2012-07-12  0:38  7% Lapack Ada binding matrices/vectors issue, how to best to resolve? Nasser M. Abbasi
@ 2012-07-12  0:45  0% ` Nasser M. Abbasi
  0 siblings, 0 replies; 61+ results
From: Nasser M. Abbasi @ 2012-07-12  0:45 UTC (permalink / raw)


On 7/11/2012 7:38 PM, Nasser M. Abbasi wrote:
>
> ---------------------------
> with Interfaces.Fortran; use Interfaces.Fortran;
> with Ada.Numerics.Real_Arrays; use Ada.Numerics.Real_Arrays;
> with labase; use labase;  -- LAPACK binding
>
> procedure foo3 is
>
>     A1 : constant Fortran_Real_Matrix(1..2,1..2):=
>           12.0*((12.0,  6.0),(-12.0, 6.0)); -- ERROR
>
>     A2 : constant Real_Matrix(1..2,1..2) :=
>            12.0*((12.0,  6.0),(-12.0,  6.0)); -- OK
>     begin
>       null;
> end foo3;
> --------------------
>

opps that should be foo3.adb in the command below (I copied the file content
to new file and named it foo3, but pasted the older command on the window which
was foo2.adb)

>> gnatmake -gnat2012 -I/lapada/ada  foo2.adb -largs -lblas
> gcc -c -gnat2012 -I/lapada/ada foo2.adb
> foo2.adb:24:20: expected type "Fortran_Real_Matrix" defined at labase.ads:94
> foo2.adb:24:20: found type "Interfaces.Fortran.Complex"
> gnatmake: "foo2.adb" compilation error
>>
>

here is the command again:

>gnatmake -gnat2012 -I/lapada/ada  foo3.adb -largs -lblas
gcc -c -gnat2012 -I/lapada/ada foo3.adb
foo3.adb:10:13: expected type "Fortran_Real_Matrix" defined at labase.ads:94
foo3.adb:10:13: found type "Complex_Star_16" defined at labase.ads:52
gnatmake: "foo3.adb" compilation error
>

(I just did not want someone to get confused if they saw this).

--Nasser




^ permalink raw reply	[relevance 0%]

* Lapack Ada binding matrices/vectors issue, how to best to resolve?
@ 2012-07-12  0:38  7% Nasser M. Abbasi
  2012-07-12  0:45  0% ` Nasser M. Abbasi
  0 siblings, 1 reply; 61+ results
From: Nasser M. Abbasi @ 2012-07-12  0:38 UTC (permalink / raw)



The Ada lapack binding defines its own Matrix types. However, it
does not define operators (multiply, add, etc.. ) to work on these
types similar to Ada's Real Vectors and Matrices in the
Ada.Numerics.Real_Arrays package

http://www.ada-auth.org/standards/12rm/html/RM-G-3-1.html

What this means, is that one can't even multiply a number by the
matrix if the Matrix is Fortran_Real_Matrix like one can with
Real_Matrix. Here is a simple example

---------------------------
with Interfaces.Fortran; use Interfaces.Fortran;
with Ada.Numerics.Real_Arrays; use Ada.Numerics.Real_Arrays;
with labase; use labase;  -- LAPACK binding

procedure foo3 is
      
   A1 : constant Fortran_Real_Matrix(1..2,1..2):=
         12.0*((12.0,  6.0),(-12.0, 6.0)); -- ERROR
          
   A2 : constant Real_Matrix(1..2,1..2) :=
          12.0*((12.0,  6.0),(-12.0,  6.0)); -- OK
   begin
     null;
end foo3;
--------------------

>gnatmake -gnat2012 -I/lapada/ada  foo2.adb -largs -lblas
gcc -c -gnat2012 -I/lapada/ada foo2.adb
foo2.adb:24:20: expected type "Fortran_Real_Matrix" defined at labase.ads:94
foo2.adb:24:20: found type "Interfaces.Fortran.Complex"
gnatmake: "foo2.adb" compilation error
>

I tried to do conversion of the Fortran_Real_Matrix to
Real_Matrix but the compiler does not like it as it is
aggregate.

So, this means this binding as it stands is too limited to
use as is.

What would be a good way to fix this whole issue? Make a
pacakge similar to Numerics.Generic_Real_Arrays for
the Fortran_Real_Matrix so that all the operators '*','+', etc..
are available now for this Matrix type?

The Ada lapack package with's :

with Ada.Numerics.Generic_Complex_Types;
with Interfaces.Fortran; use  Interfaces.Fortran;

Then it defines many types, such as
----------------------
type Fortran_Integer_Matrix is array (Fortran_Integer range <>,
                                       Fortran_Integer range <>)
          of Fortran_Integer;
pragma Convention (Fortran, Fortran_Integer_Matrix);
etc..
----------------------

But it does NOT define operators to work on these types like
the Ada package Ada.Numerics.Real_Arrays  does:

-------------------------------
function "*" (Left : Real'Base;   Right : Real_Matrix)
       return Real_Matrix;
---------------------------

I was thinking of just copying all these functions as the above to the
Lapack package and edit things and change all the Real_Matrix to
Fortran_Real_Matrix etc..  but this seems like not the right way
to do this.

The main Lapack package is lapada/ada/labase.ads in
the tar file

ftp://ftp.cs.kuleuven.be/pub/Ada-Belgium/mirrors/gnu-ada/OLD/contrib/lapack-ada/

Any suggestion how to resolve this from experts will be great as I am
a newbie in Ada.

--Nasser




^ permalink raw reply	[relevance 7%]

* Re: how to print an array range?
  2012-06-26 13:47  7% how to print an array range? Nasser M. Abbasi
  @ 2012-06-28  6:59  0% ` Shark8
  1 sibling, 0 replies; 61+ results
From: Shark8 @ 2012-06-28  6:59 UTC (permalink / raw)
  Cc: nma

On Tuesday, June 26, 2012 8:47:01 AM UTC-5, Nasser M. Abbasi wrote:
> simple question from newbie. How do I print array range?
> I tried using image' attribute, but can't get the syntax to
> work right.
> 
> ----------------------------
> with Ada.Text_Io; use Ada.Text_Io;
> with Ada.Float_Text_Io; use Ada.Float_Text_Io;
> with Ada.integer_Text_Io; use Ada.integer_Text_Io;
> with Ada.Numerics.Real_Arrays;  use Ada.Numerics.Real_Arrays;
> 
> procedure foo1 is
>      A : constant Real_Matrix :=
>               (( 1.0,  2.0,  3.0),
>                ( 4.0,  5.0,  6.0),
>                ( 7.0,  8.0,  9.0));
> begin
> 
>      put(A'range(1));
>      
> end foo1;
> ----------------------
> 
> I expected to see "1..3". How do you use image' on this
> or other way to display the range?
> 
> thanks,
> --Nasser

Ok, let's say you have Array_Type which is defined as Array (Integer Range <>) of Integer. We can achieve this by the following function:

Procedure Put_Range( A : In Array_Type ) is
  Use Text_IO, Integer_IO;
begin
  Put( A'First );
  Put( ".." );
  Put( A'Last );
end Put_Range;

For a mulch-dimensional array you would do something similar either a) calling the given function as an iteration through the minor-index, or b) expanding the above with the 'Range(Index_Number) attribute. {If I remember the attribute name correctly.}



^ permalink raw reply	[relevance 0%]

* Re: Why this error, value not in range of subtype of "Standard.Integer"?
  2012-06-26 15:49  7% Why this error, value not in range of subtype of "Standard.Integer"? Nasser M. Abbasi
  2012-06-26 17:20  0% ` Adam Beneschan
  2012-06-26 18:00  4% ` Niklas Holsti
@ 2012-06-26 21:39  0% ` Robert A Duff
  2 siblings, 0 replies; 61+ results
From: Robert A Duff @ 2012-06-26 21:39 UTC (permalink / raw)


"Nasser M. Abbasi" <nma@12000.org> writes:

> If I write this, I get an error as show: (notice the B
> matrix declaration, that is where the problem is)
>
> -------------- this does not work ------
> with Ada.Numerics.Real_Arrays;  use Ada.Numerics.Real_Arrays;
>
> procedure foo2 is
>     A : constant Real_Matrix :=
>              (( 1.0,  2.0,  3.0),
>               ( 4.0,  5.0,  6.0),
>               ( 7.0,  8.0,  9.0));
>     B : Real_Matrix(1 .. 3,1 .. 3);  -- this is the problem

Others answered your question, but:  You might find it convenient
to declare a subtype:

    subtype My_Real_Matrix is Real_Matrix(1..3, 1..3);
    A: constant My_Real_Matrix := ((1.0, ....
    B: My_Real_Matrix;

Also look into the "for ... of" syntax of Ada 2012.

- Bob



^ permalink raw reply	[relevance 0%]

* Re: Why this error, value not in range of subtype of "Standard.Integer"?
  2012-06-26 15:49  7% Why this error, value not in range of subtype of "Standard.Integer"? Nasser M. Abbasi
@ 2012-06-26 17:20  0% ` Adam Beneschan
  2012-06-26 18:00  4% ` Niklas Holsti
  2012-06-26 21:39  0% ` Robert A Duff
  2 siblings, 0 replies; 61+ results
From: Adam Beneschan @ 2012-06-26 17:20 UTC (permalink / raw)


On Tuesday, June 26, 2012 8:49:18 AM UTC-7, Nasser M. Abbasi wrote:
> experts;
> 
> If I write this, I get an error as show: (notice the B
> matrix declaration, that is where the problem is)
> 
> -------------- this does not work ------
> with Ada.Numerics.Real_Arrays;  use Ada.Numerics.Real_Arrays;
> 
> procedure foo2 is
>      A : constant Real_Matrix :=
>               (( 1.0,  2.0,  3.0),
>                ( 4.0,  5.0,  6.0),
>                ( 7.0,  8.0,  9.0));
>      B : Real_Matrix(1 .. 3,1 .. 3);  -- this is the problem
> begin
> 
>      FOR I in A'range(1) LOOP
>            FOR J in A'range(2) LOOP
>                B(I,J) := 1.0;
>            END LOOP;
>      END LOOP;
>      
> end foo2;
> -------------------------------
> 
> >gnatmake foo2.adb
> gcc-4.6 -c foo2.adb
> foo2.adb:13:17: warning: value not in range of subtype of "Standard.Integer" defined at line 8
> foo2.adb:13:17: warning: "Constraint_Error" will be raised at run time
> foo2.adb:13:19: warning: value not in range of subtype of "Standard.Integer" defined at line 8
> foo2.adb:13:19: warning: "Constraint_Error" will be raised at run time
> gnatbind -x foo2.ali
> gnatlink foo2.ali
> 
> But if I change the declaration of B from
>       B : Real_Matrix(1 .. 3,1 .. 3);
> to
>       B : Real_Matrix(A'RANGE(1), A'RANGE(2));
> 
> then Ada is happy now.
> 
> Isn't A'RANGE(1) the same as 1 .. 3 and A'RANGE(2) the same as 1 .. 3?
> or is this one of those typing issues?

A'Range(1) is the same as A'First(1) .. A'Last(1), which is in this case -2147483648 .. -2147483646, not 1 .. 3.  I've said more about this in my response on another thread.

                             -- Adam



^ permalink raw reply	[relevance 0%]

* Re: Why this error, value not in range of subtype of "Standard.Integer"?
  2012-06-26 15:49  7% Why this error, value not in range of subtype of "Standard.Integer"? Nasser M. Abbasi
  2012-06-26 17:20  0% ` Adam Beneschan
@ 2012-06-26 18:00  4% ` Niklas Holsti
  2012-06-26 21:39  0% ` Robert A Duff
  2 siblings, 0 replies; 61+ results
From: Niklas Holsti @ 2012-06-26 18:00 UTC (permalink / raw)


On 12-06-26 18:49 , Nasser M. Abbasi wrote:
> experts;
>
> If I write this, I get an error as show: (notice the B
> matrix declaration, that is where the problem is)

No, the problem is in the declaration of the A matrix. Or really in the 
difference in their declarations.

> -------------- this does not work ------
> with Ada.Numerics.Real_Arrays; use Ada.Numerics.Real_Arrays;
>
> procedure foo2 is
> A : constant Real_Matrix :=
> (( 1.0, 2.0, 3.0),
> ( 4.0, 5.0, 6.0),
> ( 7.0, 8.0, 9.0));

The Real_Matrix type is defined in Ada.Numerics.Real_Arrays with Integer 
as the index type:

type Real_Matrix is array (Integer range <>, Integer range <>)
                                                    of Real'Base;

This means that the matrix A, which is constrained by its initial value, 
has the lower index bounds Integer'First, which in the case of 32-bit 
integers is -2147483648, and the upper index bound is Integer'First + 2, 
which is -2147483646. Far out of the range of the indices of B, 1..3.

Change the declaration of A to specify the index ranges:

    A : constant Real_Matrix (1 .. 3, 1 .. 3) :=

> But if I change the declaration of B from
> B : Real_Matrix(1 .. 3,1 .. 3);
> to
> B : Real_Matrix(A'RANGE(1), A'RANGE(2));
>
> then Ada is happy now.

Yep. Now B also has the index range Integer'First .. Integer'First + 2.

> Isn't A'RANGE(1) the same as 1 .. 3 and A'RANGE(2) the same as 1 .. 3?

That would be the case, if Real_Matrix were defined with Positive as the 
index range. But not with Integer.

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .



^ permalink raw reply	[relevance 4%]

* Why this error, value not in range of subtype of "Standard.Integer"?
@ 2012-06-26 15:49  7% Nasser M. Abbasi
  2012-06-26 17:20  0% ` Adam Beneschan
                   ` (2 more replies)
  0 siblings, 3 replies; 61+ results
From: Nasser M. Abbasi @ 2012-06-26 15:49 UTC (permalink / raw)


experts;

If I write this, I get an error as show: (notice the B
matrix declaration, that is where the problem is)

-------------- this does not work ------
with Ada.Numerics.Real_Arrays;  use Ada.Numerics.Real_Arrays;

procedure foo2 is
     A : constant Real_Matrix :=
              (( 1.0,  2.0,  3.0),
               ( 4.0,  5.0,  6.0),
               ( 7.0,  8.0,  9.0));
     B : Real_Matrix(1 .. 3,1 .. 3);  -- this is the problem
begin

     FOR I in A'range(1) LOOP
           FOR J in A'range(2) LOOP
               B(I,J) := 1.0;
           END LOOP;
     END LOOP;
     
end foo2;
-------------------------------

>gnatmake foo2.adb
gcc-4.6 -c foo2.adb
foo2.adb:13:17: warning: value not in range of subtype of "Standard.Integer" defined at line 8
foo2.adb:13:17: warning: "Constraint_Error" will be raised at run time
foo2.adb:13:19: warning: value not in range of subtype of "Standard.Integer" defined at line 8
foo2.adb:13:19: warning: "Constraint_Error" will be raised at run time
gnatbind -x foo2.ali
gnatlink foo2.ali

But if I change the declaration of B from
      B : Real_Matrix(1 .. 3,1 .. 3);
to
      B : Real_Matrix(A'RANGE(1), A'RANGE(2));

then Ada is happy now.

Isn't A'RANGE(1) the same as 1 .. 3 and A'RANGE(2) the same as 1 .. 3?
or is this one of those typing issues?

---------------------------------------------
with Ada.Numerics.Real_Arrays;  use Ada.Numerics.Real_Arrays;

procedure foo1 is
     A : constant Real_Matrix :=
              (( 1.0,  2.0,  3.0),
               ( 4.0,  5.0,  6.0),
               ( 7.0,  8.0,  9.0));
     B : Real_Matrix(A'RANGE(1), A'RANGE(2));
begin
     FOR I in A'range(1) LOOP
           FOR J in A'range(2) LOOP
               B(I,J) := 1.0;
           END LOOP;
     END LOOP;
         
end foo1;
------------------------------

(one thing I like about Ada, is that once the program compiles clean,
then it runs fine !)

thanks
--Nasser



^ permalink raw reply	[relevance 7%]

* Re: how to print an array range?
  2012-06-26 14:08  7%   ` Nasser M. Abbasi
@ 2012-06-26 14:24  7%     ` Nasser M. Abbasi
  0 siblings, 0 replies; 61+ results
From: Nasser M. Abbasi @ 2012-06-26 14:24 UTC (permalink / raw)


On 6/26/2012 9:08 AM, Nasser M. Abbasi wrote:
...
>       put(A'First(1)); new_line;
>       put(A'Last(1));
>
> end foo1;
> ----------------------------
>
>> gnatmake foo1.adb
> gcc-4.6 -c foo1.adb
> gnatbind -x foo1.ali
> gnatlink foo1.ali
>> ./foo1
> -2147483648
> -2147483646

I think I know what these numbers are. Look like Integer'first.

But I wanted to see the range of
the first dimension of the Matrix A below. (1..3, 1..3)

----------------------------------
with Ada.Text_Io; use Ada.Text_Io;
with Ada.Float_Text_Io; use Ada.Float_Text_Io;
with Ada.integer_Text_Io; use Ada.integer_Text_Io;
with Ada.Numerics.Real_Arrays;  use Ada.Numerics.Real_Arrays;

procedure foo1 is
      A : constant Real_Matrix :=
               (( 1.0,  2.0,  3.0),
                ( 4.0,  5.0,  6.0),
                ( 7.0,  8.0,  9.0));
begin

      put(A'First(1)); new_line;
      put(A'Last(1));
          
end foo1;
-------------------------------

I think I Will go hunt for a book on Ada, and will
look at the packages Dmitry just posted.

thanks,

--Nasser



^ permalink raw reply	[relevance 7%]

* Re: how to print an array range?
  @ 2012-06-26 14:08  7%   ` Nasser M. Abbasi
  2012-06-26 14:24  7%     ` Nasser M. Abbasi
  0 siblings, 1 reply; 61+ results
From: Nasser M. Abbasi @ 2012-06-26 14:08 UTC (permalink / raw)


On 6/26/2012 8:54 AM, Georg Bauhaus wrote:
> On 26.06.12 15:47, Nasser M. Abbasi wrote:
>>
>> simple question from newbie. How do I print array range?
>
> A range is not a value of some type.
>
> For type T, print T'First and T'Last; for array A(..., ...),
> print A'First(n) and A'Last(n), n > 0 being the nth index type.
>

Ok fair enough.
btw, would you know by any chance why I get these values?

----------------------------------
with Ada.Text_Io; use Ada.Text_Io;
with Ada.Float_Text_Io; use Ada.Float_Text_Io;
with Ada.integer_Text_Io; use Ada.integer_Text_Io;
with Ada.Numerics.Real_Arrays;  use Ada.Numerics.Real_Arrays;

procedure foo1 is
     A : constant Real_Matrix :=
              (( 1.0,  2.0,  3.0),
               ( 4.0,  5.0,  6.0),
               ( 7.0,  8.0,  9.0));
begin

     put(A'First(1)); new_line;
     put(A'Last(1));
         
end foo1;
----------------------------

>gnatmake foo1.adb
gcc-4.6 -c foo1.adb
gnatbind -x foo1.ali
gnatlink foo1.ali
>./foo1
-2147483648
-2147483646
>

I know I am doing something silly here.

(I feel I have so much catching to do with Ada)

--Nasser



^ permalink raw reply	[relevance 7%]

* how to print an array range?
@ 2012-06-26 13:47  7% Nasser M. Abbasi
    2012-06-28  6:59  0% ` Shark8
  0 siblings, 2 replies; 61+ results
From: Nasser M. Abbasi @ 2012-06-26 13:47 UTC (permalink / raw)



simple question from newbie. How do I print array range?
I tried using image' attribute, but can't get the syntax to
work right.

----------------------------
with Ada.Text_Io; use Ada.Text_Io;
with Ada.Float_Text_Io; use Ada.Float_Text_Io;
with Ada.integer_Text_Io; use Ada.integer_Text_Io;
with Ada.Numerics.Real_Arrays;  use Ada.Numerics.Real_Arrays;

procedure foo1 is
     A : constant Real_Matrix :=
              (( 1.0,  2.0,  3.0),
               ( 4.0,  5.0,  6.0),
               ( 7.0,  8.0,  9.0));
begin

     put(A'range(1));
     
end foo1;
----------------------

I expected to see "1..3". How do you use image' on this
or other way to display the range?

thanks,
--Nasser



^ permalink raw reply	[relevance 7%]

* Any easy/build-in construct to extract submatrices from larger matrix?
@ 2012-06-24  8:05  5% Nasser M. Abbasi
  0 siblings, 0 replies; 61+ results
From: Nasser M. Abbasi @ 2012-06-24  8:05 UTC (permalink / raw)



Given square matrix, say 3 by 3 real matrix, and we
want to extract a submatrix from it, a 2 by 2 submatrix,
which is found by removing column and row given by
index I and J.

For example, given

  A : constant Real_Matrix :=
              (( 1.0,  2.0,  3.0),
               ( 4.0,  5.0,  6.0),
               ( 7.0,  8.0,  9.0));

and I=1, J=1, then the submatrix to extract is

                  5 6
                  8 9

because we removed row I=1, and column J=1, and what
is left is what is needed.

Ofcourse I can code it the hard way, using lots of if's,
and loops, and build the submatrix by hand, one row/column at
a time. But I wanted to see if there is a build-in
easy way, like slicing off a row and column off a matrix
on the fly.

Here is a skeleton code if someone wants to give this a try

---------------------------------------------
with Ada.Text_Io; use Ada.Text_Io;
with Ada.Float_Text_Io; use Ada.Float_Text_Io;
with Ada.Numerics.Real_Arrays;  use Ada.Numerics.Real_Arrays;

procedure foo is
     A : constant Real_Matrix :=
              (( 1.0,  2.0,  3.0),
               ( 4.0,  5.0,  6.0),
               ( 7.0,  8.0,  9.0));
     B : real_matrix(1 .. 2, 1 .. 2);

begin

     FOR I in A'range(1) LOOP
       FOR J in A'range(2) LOOP
           --B := -- ??? smart way to do this?
           put(A(I,J));
       END LOOP;
       new_line;
     END LOOP;

end foo;
--------------------------------

fyi, modern Fortran has a nice facility to do this, called
pack(). It works like this: make up a MASK matrix of same size
as A. For those elements we want removed, put in a logical
.false at that location.

Hence, to extract column 1 say from A, build up a MASK matrix
with .false. in each element of the first column, then call
PACK() with this mask and A. Then PACK() return all elements
of A that has corresponding .true. in the MASK.

So, the above in Fortran works like this:

--------------------------------------------------
program t46
implicit none

integer, parameter :: n=3
integer :: i,j
real (kind=kind(0.0d0)) :: A(n,n),B(n-1,n-1)
logical :: mask(n,n)
  
A(1,:) = [1, 2, 3];
A(2,:) = [4, 5, 6];
A(3,:) = [7, 8, 9];

DO j=1,n
    DO i=1,n
       
       mask = .true.
       mask(:,j) = .false.
       mask(i,:) = .false.
       
       !-- extract submatrix (looking for Ada equivalent)
       B = reshape(pack(A, mask),[n-1,n-1])
       
       write(*,'(2F6.1)') B
       print *,'------------'
       
    END DO
END DO
end program t46
------------------------------

>gfortran -fcheck=all -Wall t46.f90
>./a.out
    5.0   8.0
    6.0   9.0
  ------------
    2.0   8.0
    3.0   9.0
  ------------
    2.0   5.0
    3.0   6.0
  ------------
    4.0   7.0
    6.0   9.0
  ------------
    1.0   7.0
    3.0   9.0
  ------------
    1.0   4.0
    3.0   6.0
  ------------
    4.0   7.0
    5.0   8.0
  ------------
    1.0   7.0
    2.0   8.0
  ------------
    1.0   4.0
    2.0   5.0
  ------------
>


I have googled on-line looking for something build-in, but
so far, no luck. But will continue searching...

thanks,
--Nasser



^ permalink raw reply	[relevance 5%]

* Re: questions on using the array component iterator for 2012
  2012-06-23 12:02  5% questions on using the array component iterator for 2012 Nasser M. Abbasi
@ 2012-06-23 12:04  0% ` Nasser M. Abbasi
  0 siblings, 0 replies; 61+ results
From: Nasser M. Abbasi @ 2012-06-23 12:04 UTC (permalink / raw)


On 6/23/2012 7:02 AM, Nasser M. Abbasi wrote:

> ---------------------------------------------
> with Ada.Numerics.Real_Arrays;  use Ada.Numerics.Real_Arrays;
> procedure foo is
>      A : constant Real_Matrix :=
>            ( ( 1.0,  2.0, 3.0 ) ,
>              ( 3.0,  5.0, 6.0 ) ,
>              ( 7.0,  8.0, 9.0 ) );
> begin
>      FOR e of A  LOOP
>          e := e + 1 ;
>      END
> end Matrix_Product;
> ---------------------------------------------
>

opps, need to remove the 'constant' word above, so that A can be updated
ofocurse.

--Nasser



^ permalink raw reply	[relevance 0%]

* questions on using the array component iterator for 2012
@ 2012-06-23 12:02  5% Nasser M. Abbasi
  2012-06-23 12:04  0% ` Nasser M. Abbasi
  0 siblings, 1 reply; 61+ results
From: Nasser M. Abbasi @ 2012-06-23 12:02 UTC (permalink / raw)


reference

http://www.ada-auth.org/standards/12rm/html/RM-5-5-2.html

The  array component iterator seems nice, but I was not sure
if it can be used access elements in the matrix that are
indexed off the current iterator.

For example, assume I write

---------------------------------------------
with Ada.Numerics.Real_Arrays;  use Ada.Numerics.Real_Arrays;
procedure foo is
    A : constant Real_Matrix :=
          ( ( 1.0,  2.0, 3.0 ) ,
            ( 3.0,  5.0, 6.0 ) ,
            ( 7.0,  8.0, 9.0 ) );
begin
    FOR e of A  LOOP
        e := e + 1 ;
    END
end Matrix_Product;
---------------------------------------------

So the above adds '1' to each element in the matrix.
(order of iterations is defined in the RM, say I used
FORTRAN order).

But suppose I want to implement say a Jacobi relaxation
iteration to solve a 2D Laplace pde on that grid, which
is defined to update each element in the grid using

A(i) := (1/4) (  A(i-1,j)+A(i+1,j)+A(i,j-1)+A(i,j+1)

where here 'i' is row index, and 'j' is column index.

http://en.wikipedia.org/wiki/Relaxation_%28iterative_method%29

(iteration has to start from the second row and second column,
to avoid falling off the edge of the grid ofcourse, but this
is not important now)

i.e the above just replaces the current element in the matrix by
the average of the 4 adjacent elements in the little grid around
the current element.

My question is:

using 'e', this new iterator, can one somehow implement the above,
by somehow referencing these 4 adjacent elements in the grid?
(above, left, right, below)?

My point is that, if the iterator can be used only to access
the current element, then this might not be too useful.

For example, in the above example toy example, I do not
even need an iterator, I can use direct operation in Fortran or
Matlab say and just type

           A = 1.0 + A

(I do not know if one can do this in Ada btw?) May be
one needs to just define a "+" function for this. (I am not
too experienced in Ada, will try it).

Thanks
--Nasser



^ permalink raw reply	[relevance 5%]

* Re: Basic question on Ada multi-dimensional arrays, are they true (contiguous) arrays? aliasing rules?
    2011-12-21 21:11  5% ` Adrian-Ken Rueegsegger
@ 2011-12-21 21:13  5% ` Adrian-Ken Rueegsegger
  1 sibling, 0 replies; 61+ results
From: Adrian-Ken Rueegsegger @ 2011-12-21 21:13 UTC (permalink / raw)


On 12/21/2011 02:08 AM, Nasser M. Abbasi wrote:
> Sorry for such a basic question on Ada, it has been a while since
> I used Ada (but it remains my most favorite computer language).

[snip]

> Are there are benchmarks comparing Ada for Fortran in this specific area?

This is just barely related but maybe it is still of interest to you: as
part of writing the CUDA/Ada binding [1] I did some benchmarking of
matrix operations (addition and multiplication) using the
Ada.Numerics.Real_Arrays package. I compared the native Ada
implementation ("*"-operator), doing the multiplication on the GPU using
the CUDA/Ada binding and a native CUDA C implementation.

We are in the middle of finishing up the article documenting CUDA/Ada
which will contain a section analyzing the performance measurements. The
main focus is on the potential performance penalty of CUDA/Ada vs native
CUDA C though so as mentionend in the beginning this is probably
tangential to your question...

Cheers,
Adrian
--
[1] - http://www.codelabs.ch/cuda-ada/



^ permalink raw reply	[relevance 5%]

* Re: Basic question on Ada multi-dimensional arrays, are they true (contiguous) arrays? aliasing rules?
  @ 2011-12-21 21:11  5% ` Adrian-Ken Rueegsegger
  2011-12-21 21:13  5% ` Adrian-Ken Rueegsegger
  1 sibling, 0 replies; 61+ results
From: Adrian-Ken Rueegsegger @ 2011-12-21 21:11 UTC (permalink / raw)


On 12/21/2011 02:08 AM, Nasser M. Abbasi wrote:
> Sorry for such a basic question on Ada, it has been a while since
> I used Ada (but it remains my most favorite computer language).

[snip]

> Are there are benchmarks comparing Ada for Fortran in this specific area?

This is just barely related but maybe it is still of interest to you: as
part of writing the CUDA/Ada binding [1] I did some benchmarking of
matrix operations (addition and multiplication) using the
Ada.Numerics.Real_Arrays package. I compared the native Ada
implementation ("*"-operator), doing the multiplication on the GPU using
the CUDA/Ada binding and a native CUDA C implementation.

We are in the middle of finishing up the article documenting CUDA/Ada
which will contain a section analyzing the performance measurements. The
main focus is on the potential performance penalty of CUDA/Ada vs native
CUDA C though so as mentionend in the beginning this is probably
tangential to your question...

Cheers,
Adrian
--
[1] - http://www.codelabs.ch/cuda-ada/



^ permalink raw reply	[relevance 5%]

* Re: anyone seen this link error trying to link Ada program with blas and lapack? "cannot find -lgnalasup"
  @ 2010-10-16  6:25  4% ` Nasser M. Abbasi
  0 siblings, 0 replies; 61+ results
From: Nasser M. Abbasi @ 2010-10-16  6:25 UTC (permalink / raw)


On 10/15/2010 10:46 PM, Nasser M. Abbasi wrote:
>
>
> Hello;
>
> I've send this email to the cygwin mailing list.
>
> I thought I check here also.
>
> I am trying to build an Ada file which has to be linked to blas and
> lapack as it uses the new Ada 2005 Solve() of linear system function.
>
> The link problem is on cygwin. I think it is a gcc installation issue
> may be.
>
> "It seems there is a library missing in the system. Did a search on
> this, but not able to find anything.
>
> $ uname -a
> CYGWIN_NT-6.1-WOW64 me-PC 1.7.7(0.230/5/3) 2010-08-31 09:58 i686 Cygwin
>
> $ gcc --version
> gcc (GCC) 4.3.4 20090804 (release) 1
>
> $ gnatmake main.adb -largs -L/usr/lib  -lgnala -llapack -lblas
> gnatbind -x main.ali
> gnatlink main.ali -L/usr/lib -lgnala -llapack -lblas
> /usr/lib/gcc/i686-pc-cygwin/4.3.4/../../../../i686-pc-cygwin/bin/ld:
> cannot find -lgnalasup
> collect2: ld returned 1 exit status
> gnatlink: error when calling /usr/bin/gcc.exe
> gnatmake: *** link failed.
>
> When I copy the source file (the Ada file) to a linux system, with
> ubuntu 10.10 (linux 2.6.35-22) running gcc 4.4.5, the same command above
> works with no problem. no link error.
> "
>
> The blas and lapack libraries should come with the system normally, but
> sometime they do not.  On cygwin, they are there. On Ubuntu I had to
> install them afterwords (easy with the package manager).
>
> The Ada source file is just one file. If someone wants to try the above
> gnatmake command on my file, here it is:
>
> http://12000.org/tmp/AAA/main.adb
>
> Need to use the above command to build it, which is:
>
> gnatmake main.adb -largs -L/usr/lib  -lgnala -llapack -lblas
>
> It does nothing now, just wanted first to see if it builds oK.
>
> thanks
> --Nasser


I found one reference on this library, here it is

http://objectmix.com/ada/382814-gnatmake-ada-numerics-real_arrays-not-predefined-library-unit.html

"Anyway, I've started investigating the "libgnalasup" issue. This
library is referenced by i-forbla.adb, but doesn't seem to be
distributed. Replacing it with "liblapack" and "libblas" may be
enough."

But the suggestion given does not work for my on cygwin (gcc 4.3.3). I 
get the same error. Using  -lgnalasup or  -lgnala or not using or using 
gnatmake -static, nothing works.

I think now after reading the above, this is some gnat version being a 
bit old on cygwin (gcc 4.3).  The problem is that this is the latest 
version I have of gcc on cygwin.

I now downloaded from libre site gnat 2010 GPL, on windows, and 
installed it. Then did the same command above (had to add -gnat05, 
becuase it now complained).

But I do not get the above error, but I do not have blas and lapack on 
windows. I need to figure now where to get them for windows and where to 
put them to make gnatmake happy (I think that will be

      C:\GNAT\2010\LIB

(wonder why blas and lapack do not come with GNAT GPL distribution since 
there are needed to link against for building the new numeric stuff?

 >gnatmake main.adb -gnat05 -largs -L/usr/lib  -lgnala -llapack -lblas

gnatbind -x main.ali
gnatlink main.ali -L/usr/lib -lgnala -llapack -lblas
c:/gnat/2010/bin/../libexec/gcc/i686-pc-mingw32/4.3.6/ld.exe: cannot 
find -llapack
collect2: ld returned 1 exit status
gnatlink: error when calling C:\GNAT\2010\bin\gcc.exe
gnatmake: *** link failed.


--Nasser



^ permalink raw reply	[relevance 4%]

* Re: gnatmake: "ada.numerics.real_arrays" is not a predefined library unit
  2008-04-21 21:05  5%           ` Ludovic Brenta
@ 2008-04-22 20:13  6%             ` Simon Wright
  0 siblings, 0 replies; 61+ results
From: Simon Wright @ 2008-04-22 20:13 UTC (permalink / raw)


Ludovic Brenta <ludovic@ludovic-brenta.org> writes:

> For example, libgnala.a is currently installed in
> /usr/lib/gcc/x86_64-linux-gnu/4.3/rts-native/adalib/ without any
> symlink to it from /usr/lib, and so linking with it may require ugly
> linker options (ugly because they depend on the OS and version of
> GCC).

FWIW, this

$ gnatmake hello \
  -largs -lgnala -L/Developer/SDKs/MacOSX10.4u.sdk/usr/lib -lblas -llapack 

_nearly_ works with an unedited i-forbla.adb GNAT-GPL-2007 on Mac OS X Tiger;

opt/gnat-gpl-2007-dynamic/lib/gcc/powerpc-apple-darwin8.11.0/4.1.3/adalib//libgnala.a(a-nlcoar.o) reference to undefined _zdot_

So the ugly linker options involved finding libblas and liblapack only.



^ permalink raw reply	[relevance 6%]

* Re: gnatmake: "ada.numerics.real_arrays" is not a predefined library unit
  2008-04-22 10:46  6%   ` Samuel Tardieu
@ 2008-04-22 12:04  5%     ` Ludovic Brenta
  0 siblings, 0 replies; 61+ results
From: Ludovic Brenta @ 2008-04-22 12:04 UTC (permalink / raw)


Samuel Tardieu wrote:
> Yes, I changed the GCC sources this morning to reference LAPACK and
> BLAS directly by default instead of gnalasup which is a repackaging of
> those libraries done by AdaCore.

This patch will make it into the next upload of gnat-4.3. However,
since I uploaded a new gnat-4.3 just yesterday evening, I'll wait a
couple of weeks before the next upload, to see if new bugs are
introduced.

(Note: yesterday's upload, 4.3.0-5, brings in several bug fixes that
Sam backported from GCC 4.4, as well as support for 64-bit PowerPC.
Debian is the only distribution that has these bug fixes and I didn't
want to deprive our users of them any longer. So, happy hacking :))

--
Ludovic Brenta.



^ permalink raw reply	[relevance 5%]

* Re: gnatmake: "ada.numerics.real_arrays" is not a predefined library unit
  2008-04-21 21:34  5% ` Jerry
@ 2008-04-22 10:46  6%   ` Samuel Tardieu
  2008-04-22 12:04  5%     ` Ludovic Brenta
  0 siblings, 1 reply; 61+ results
From: Samuel Tardieu @ 2008-04-22 10:46 UTC (permalink / raw)


>>>>> "Jerry" == Jerry  <lanceboyle@qwest.net> writes:

Jerry> The upshot is that the file i-forbla.adb is edited to comment
Jerry> out one line, so that after the edit we see this:

Jerry> -- pragma Linker_Options ("-lgnalasup")

Yes, I changed the GCC sources this morning to reference LAPACK and
BLAS directly by default instead of gnalasup which is a repackaging of
those libraries done by AdaCore.

  Sam
-- 
Samuel Tardieu -- sam@rfc1149.net -- http://www.rfc1149.net/



^ permalink raw reply	[relevance 6%]

* Re: gnatmake: "ada.numerics.real_arrays" is not a predefined library unit
  2008-04-21 11:34 14% gnatmake: "ada.numerics.real_arrays" is not a predefined library unit Reinert Korsnes
  2008-04-21 12:28 11% ` Georg Bauhaus
@ 2008-04-21 21:34  5% ` Jerry
  2008-04-22 10:46  6%   ` Samuel Tardieu
  1 sibling, 1 reply; 61+ results
From: Jerry @ 2008-04-21 21:34 UTC (permalink / raw)


On Apr 21, 4:34 am, Reinert Korsnes <a...@b.no> wrote:
> Hello,
>
> My linux system (opensuse 10.3 updated) does not
> find "ada.numerics.real_arrays.  Should it ?
>
> Details:
> --------
> I tried to compile a program starting like this:
>
> with Text_IO;
> use  Text_IO;
> with   Ada.Numerics,Ada.Numerics.Real_Arrays;
> with   Ada.Numerics.Generic_Elementary_Functions;
> procedure test2 is
>
> ...
>
> I used the command:
>
> gnatmake -gnat05 test2.adb
>
> Then I get the error message:
>
> test2.adb:3:21: "ada.numerics.real_arrays" is not a predefined library unit
> gnatmake: "test2.adb" compilation error
>
> Is there any hope for me to use "Ada.Numerics.Real.Arrays" ?
>
> reinert

I don't want to confuse the discussion here, but the OS X ada list
(www.macada.org) has been discussing this lately, (as well as
December, 2007 if you're inclined to dig through archives).

The upshot is that the file i-forbla.adb is edited to comment out one
line, so that after the edit we see this:

--  pragma Linker_Options ("-lgnalasup")

All I did then was to compile a "hello" program using -a that with-ed
Ada.Numerics.Long_Real_Arrays and Ada.Numerics.Long_Complex_Arrays,
then copied the new .o and .ali to the proper Ada library directory. I
can supply more details if needed. Also, I don't pretend to understand
why this works.

Incidentally, BLAS and LAPACK, both Fortran and C versions, come pre-
installed on OS X so linking to them is pretty trivial.

Jerry

P.S. Sorry if this post appears twice. My last two posts did, and I'm
blaming it on my browser.



^ permalink raw reply	[relevance 5%]

* Re: gnatmake: "ada.numerics.real_arrays" is not a predefined library unit
  2008-04-21 20:35  4%         ` Samuel Tardieu
@ 2008-04-21 21:05  5%           ` Ludovic Brenta
  2008-04-22 20:13  6%             ` Simon Wright
  0 siblings, 1 reply; 61+ results
From: Ludovic Brenta @ 2008-04-21 21:05 UTC (permalink / raw)


Samuel Tardieu <sam@rfc1149.net> writes:
>>>>>> "Ludovic" == Ludovic Brenta <ludovic@ludovic-brenta.org> writes:
>
> Ludovic> Definitely; this is an area where all distributions would
> Ludovic> benefit.  However, Debian is a bit peculiar since it patches
> Ludovic> the library building process (in gcc/ada/Makefile.in) heavily
> Ludovic> so as to build both the zero-cost and setjump/longjump
> Ludovic> versions of the library.  So, if I produce a patch, someone
> Ludovic> will have to adjust it for upstream GCC.
>
> In fact, I've had a look and I'm not sure it is interesting to make a
> shared version of libgnala at all. It contains mostly generics.

That's a thought.  In that case, it would be nice to investigate how
easy it is for the programmer to link with libgnala.a and lapack.  For
example, libgnala.a is currently installed in
/usr/lib/gcc/x86_64-linux-gnu/4.3/rts-native/adalib/ without any
symlink to it from /usr/lib, and so linking with it may require ugly
linker options (ugly because they depend on the OS and version of
GCC).

>>> Concerning the distribution, why separate libgnala.so from libgnat?
>>> You don't need a dependency on lapack/blas, only a "suggests" or
>>> "recommends" if people want to build applications requiring annex g
>>> support. As far as compiled applications are concerned, the
>>> lapack/blas dependency will be recored as part of a regular Debian
>>> dependency.
>
> Ludovic> "Suggests" or "Recommends" is not good enough because it
> Ludovic> would foil the automatic dependency management Debian is
> Ludovic> renowned for.  The proper solution is to place libgnala.so in
> Ludovic> a separate package (suggested or recommended by gnat-4.3) but
> Ludovic> that Depends on (i.e. requires) lapack to be installed.
>
> What is the difference between:
>
>   - gnat bundles libgnala with gnat, and recommends lapack
>   - gnat recommends libgnala, which depends on lapack (your recommendation)
>
> ?
>
> In both configurations, someone wanting to use GNAT with Annex G will
> have to install a package on which GNAT does not depend, be it
> libgnala or lapack.

Yes indeed.

> Ludovic> This way, if someone builds a package where they use Annex G,
> Ludovic> their package will automatically depend on libgnala.so and,
> Ludovic> indirectly, on lapack.  With your proposal, this would not
> Ludovic> happen as lapack would be only recommended.
>
> With my proposal, someone building a system using Annex G would get a
> "depends" on lapack through the shared library. With yours, they would
> get a "depends" on libgnala.so which has in turn a "depends" on
> lapack.
>
> I fail to see the difference, except maybe a matter of taste :)

Now I see what you mean, i.e. the lapack shared library will cause the
new package to depend on the lapack package.  I agree that it doesn't
make much of a difference in the end.  However, it is still necessary
that whatever package contains a (now hypothetical) libgnala.so depend
on lapack.  Good taste, as you put it, requires that shared library
dependencies be captured in the package system.

> Anyway, I've started investigating the "libgnalasup" issue. This
> library is referenced by i-forbla.adb, but doesn't seem to be
> distributed. Replacing it with "liblapack" and "libblas" may be
> enough.

Cool!

-- 
Ludovic Brenta.



^ permalink raw reply	[relevance 5%]

* Re: gnatmake: "ada.numerics.real_arrays" is not a predefined library unit
  2008-04-21 19:35  5%       ` Ludovic Brenta
@ 2008-04-21 20:35  4%         ` Samuel Tardieu
  2008-04-21 21:05  5%           ` Ludovic Brenta
  0 siblings, 1 reply; 61+ results
From: Samuel Tardieu @ 2008-04-21 20:35 UTC (permalink / raw)


>>>>> "Ludovic" == Ludovic Brenta <ludovic@ludovic-brenta.org> writes:

Ludovic> Definitely; this is an area where all distributions would
Ludovic> benefit.  However, Debian is a bit peculiar since it patches
Ludovic> the library building process (in gcc/ada/Makefile.in) heavily
Ludovic> so as to build both the zero-cost and setjump/longjump
Ludovic> versions of the library.  So, if I produce a patch, someone
Ludovic> will have to adjust it for upstream GCC.

In fact, I've had a look and I'm not sure it is interesting to make a
shared version of libgnala at all. It contains mostly generics.

>> Concerning the distribution, why separate libgnala.so from libgnat?
>> You don't need a dependency on lapack/blas, only a "suggests" or
>> "recommends" if people want to build applications requiring annex g
>> support. As far as compiled applications are concerned, the
>> lapack/blas dependency will be recored as part of a regular Debian
>> dependency.

Ludovic> "Suggests" or "Recommends" is not good enough because it
Ludovic> would foil the automatic dependency management Debian is
Ludovic> renowned for.  The proper solution is to place libgnala.so in
Ludovic> a separate package (suggested or recommended by gnat-4.3) but
Ludovic> that Depends on (i.e. requires) lapack to be installed.

What is the difference between:

  - gnat bundles libgnala with gnat, and recommends lapack
  - gnat recommends libgnala, which depends on lapack (your recommendation)

?

In both configurations, someone wanting to use GNAT with Annex G will
have to install a package on which GNAT does not depend, be it
libgnala or lapack.

Ludovic> This way, if someone builds a package where they use Annex G,
Ludovic> their package will automatically depend on libgnala.so and,
Ludovic> indirectly, on lapack.  With your proposal, this would not
Ludovic> happen as lapack would be only recommended.

With my proposal, someone building a system using Annex G would get a
"depends" on lapack through the shared library. With yours, they would
get a "depends" on libgnala.so which has in turn a "depends" on
lapack.

I fail to see the difference, except maybe a matter of taste :)

Anyway, I've started investigating the "libgnalasup" issue. This
library is referenced by i-forbla.adb, but doesn't seem to be
distributed. Replacing it with "liblapack" and "libblas" may be
enough.

  Sam
-- 
Samuel Tardieu -- sam@rfc1149.net -- http://www.rfc1149.net/



^ permalink raw reply	[relevance 4%]

* Re: gnatmake: "ada.numerics.real_arrays" is not a predefined library unit
  2008-04-21 17:01  5%     ` Samuel Tardieu
@ 2008-04-21 19:35  5%       ` Ludovic Brenta
  2008-04-21 20:35  4%         ` Samuel Tardieu
  0 siblings, 1 reply; 61+ results
From: Ludovic Brenta @ 2008-04-21 19:35 UTC (permalink / raw)


Samuel Tardieu writes:
>>>>>> "Ludovic" == Ludovic Brenta <ludovic@ludovic-brenta.org> writes:
>
> Ludovic> It's been in the back of my mind for a few months that I
> Ludovic> should build a shared libgnala.so, package it separately from
> Ludovic> libgnat-4.3.so, and arrange for it to depend on
> Ludovic> lapack. Patches to that effect are, of course, welcome and
> Ludovic> will be gratefully accepted.
>
> Maybe we can work out the shared/static issue in GCC sources. Patches
> welcome too there :)

Definitely; this is an area where all distributions would benefit.
However, Debian is a bit peculiar since it patches the library
building process (in gcc/ada/Makefile.in) heavily so as to build both
the zero-cost and setjump/longjump versions of the library.  So, if I
produce a patch, someone will have to adjust it for upstream GCC.

> Concerning the distribution, why separate libgnala.so from libgnat?
> You don't need a dependency on lapack/blas, only a "suggests" or
> "recommends" if people want to build applications requiring annex g
> support. As far as compiled applications are concerned, the
> lapack/blas dependency will be recored as part of a regular Debian
> dependency.

"Suggests" or "Recommends" is not good enough because it would foil
the automatic dependency management Debian is renowned for.  The
proper solution is to place libgnala.so in a separate package
(suggested or recommended by gnat-4.3) but that Depends on
(i.e. requires) lapack to be installed.  This way, if someone builds a
package where they use Annex G, their package will automatically
depend on libgnala.so and, indirectly, on lapack.  With your proposal,
this would not happen as lapack would be only recommended.

-- 
Ludovic Brenta.



^ permalink raw reply	[relevance 5%]

* Re: gnatmake: "ada.numerics.real_arrays" is not a predefined library unit
  2008-04-21 13:46  5%   ` Ludovic Brenta
@ 2008-04-21 17:01  5%     ` Samuel Tardieu
  2008-04-21 19:35  5%       ` Ludovic Brenta
  0 siblings, 1 reply; 61+ results
From: Samuel Tardieu @ 2008-04-21 17:01 UTC (permalink / raw)


>>>>> "Ludovic" == Ludovic Brenta <ludovic@ludovic-brenta.org> writes:

Ludovic> It's been in the back of my mind for a few months that I
Ludovic> should build a shared libgnala.so, package it separately from
Ludovic> libgnat-4.3.so, and arrange for it to depend on
Ludovic> lapack. Patches to that effect are, of course, welcome and
Ludovic> will be gratefully accepted.

Maybe we can work out the shared/static issue in GCC sources. Patches
welcome too there :)

Concerning the distribution, why separate libgnala.so from libgnat?
You don't need a dependency on lapack/blas, only a "suggests" or
"recommends" if people want to build applications requiring annex g
support. As far as compiled applications are concerned, the
lapack/blas dependency will be recored as part of a regular Debian
dependency.

  Sam
-- 
Samuel Tardieu -- sam@rfc1149.net -- http://www.rfc1149.net/



^ permalink raw reply	[relevance 5%]

* Re: gnatmake: "ada.numerics.real_arrays" is not a predefined library unit
  2008-04-21 12:28 11% ` Georg Bauhaus
@ 2008-04-21 13:46  5%   ` Ludovic Brenta
  2008-04-21 17:01  5%     ` Samuel Tardieu
  0 siblings, 1 reply; 61+ results
From: Ludovic Brenta @ 2008-04-21 13:46 UTC (permalink / raw)


Georg Bauhaus wrote:
> Also, I'd consider getting Debian (or Ubuntu);

Thanks; I really appreciate this but in this particular area, Debian
is probably no better than any other distribution. You see, the GNAT
implementation of Annex G is, essentially, a binding to LAPACK. The
relevant units (Ada.Numerics.*) are in a static library called
libgnala.a (GNAT Linear Algebra) which is separate from libgnat.a.
Moreover, the upstream Makefile does not build a shared version of
libgnala.a.

So, if someone wants to use Annex G you must:
- build with "gnatmake -static"
- link with libgnala.a
- link with LAPACK

It's been in the back of my mind for a few months that I should build
a shared libgnala.so, package it separately from libgnat-4.3.so, and
arrange for it to depend on lapack. Patches to that effect are, of
course, welcome and will be gratefully accepted.

To the OP: this libgnala.a only appeared in GCC 4.3 released in
January 2008. If SuSE ships anything older than that, you must upgrade
your compiler if you want to take advantage of Annex G.

--
Ludovic Brenta.



^ permalink raw reply	[relevance 5%]

* Re: gnatmake: "ada.numerics.real_arrays" is not a predefined library unit
  2008-04-21 11:34 14% gnatmake: "ada.numerics.real_arrays" is not a predefined library unit Reinert Korsnes
@ 2008-04-21 12:28 11% ` Georg Bauhaus
  2008-04-21 13:46  5%   ` Ludovic Brenta
  2008-04-21 21:34  5% ` Jerry
  1 sibling, 1 reply; 61+ results
From: Georg Bauhaus @ 2008-04-21 12:28 UTC (permalink / raw)


Reinert Korsnes schrieb:
> Hello,
> 
> My linux system (opensuse 10.3 updated) does not
> find "ada.numerics.real_arrays.  Should it ?
> 
> test2.adb:3:21: "ada.numerics.real_arrays" is not a predefined library unit
> gnatmake: "test2.adb" compilation error
> 
> Is there any hope for me to use "Ada.Numerics.Real.Arrays" ?

Looks like SuSE is still shipping an older compiler.
However, there does seem to be a GNAT GPL 2007 RPM.

Also, I'd consider getting Debian (or Ubuntu); runs nicely
on a virtual machine in case you need SuSE to be you main
OS for some reason.


For SuSE, another starting point is:
http://gnuada.sourceforge.net/pmwiki.php/Install/SuSE

$ gnatkr Ada.Numerics.Real_Arrays.ads
a-nurear.ads
$ locate a-nurear.ads
/usr/local/ada-4.3/lib/gcc/i686-apple-darwin8/4.3.0/adainclude/a-nurear.ads



^ permalink raw reply	[relevance 11%]

* gnatmake: "ada.numerics.real_arrays" is not a predefined library unit
@ 2008-04-21 11:34 14% Reinert Korsnes
  2008-04-21 12:28 11% ` Georg Bauhaus
  2008-04-21 21:34  5% ` Jerry
  0 siblings, 2 replies; 61+ results
From: Reinert Korsnes @ 2008-04-21 11:34 UTC (permalink / raw)


Hello,

My linux system (opensuse 10.3 updated) does not
find "ada.numerics.real_arrays.  Should it ?

Details:
--------
I tried to compile a program starting like this:

with Text_IO;
use  Text_IO;
with   Ada.Numerics,Ada.Numerics.Real_Arrays;
with   Ada.Numerics.Generic_Elementary_Functions;
procedure test2 is

...


I used the command:

gnatmake -gnat05 test2.adb

Then I get the error message:

test2.adb:3:21: "ada.numerics.real_arrays" is not a predefined library unit
gnatmake: "test2.adb" compilation error

Is there any hope for me to use "Ada.Numerics.Real.Arrays" ?

reinert






^ permalink raw reply	[relevance 14%]

* Re: C Interface example
  @ 2007-02-03 19:17  5%     ` Georg Bauhaus
  0 siblings, 0 replies; 61+ results
From: Georg Bauhaus @ 2007-02-03 19:17 UTC (permalink / raw)


On Sat, 2007-02-03 at 10:09 -0800, artifact.one@googlemail.com wrote:
> On Feb 3, 5:48 pm, Gautier <gaut...@fakeaddress.nil> wrote:
> > Looking at your code the most simple and portable way will be not to interface
> > at all with C!
> >
> > package Vectors is
> >
> >    type Vector is array(Natural range <>) of Float;
> >
> >    procedure Add(va: in out Vector; vb: in Vector);
> >
> > end Vectors;

In fact, Ada 2007 will provide this in the standard library,

with Ada.Numerics.Real_Arrays;

   va, vb, result: Real_Array(1 .. n);

   result := va + vb;

Not sure whether there is a big performance penalty
when not modifying va in place.


> Yes this was quite a contrived example because my real version of
> vec_add()
> actually calls Altivec, SSE, SSE2 or pure C code depending on detected
> hardware,
> which stretches on to about 300 lines.

Any reason to dismiss the BLAS libraries optimized for
the respective processors?





^ permalink raw reply	[relevance 5%]

Results 1-61 of 61 | reverse | options above
-- pct% links below jump to the message on this page, permalinks otherwise --
2007-02-03 15:20     C Interface example artifact.one
2007-02-03 17:48     ` Gautier
2007-02-03 18:09       ` artifact.one
2007-02-03 19:17  5%     ` Georg Bauhaus
2008-04-21 11:34 14% gnatmake: "ada.numerics.real_arrays" is not a predefined library unit Reinert Korsnes
2008-04-21 12:28 11% ` Georg Bauhaus
2008-04-21 13:46  5%   ` Ludovic Brenta
2008-04-21 17:01  5%     ` Samuel Tardieu
2008-04-21 19:35  5%       ` Ludovic Brenta
2008-04-21 20:35  4%         ` Samuel Tardieu
2008-04-21 21:05  5%           ` Ludovic Brenta
2008-04-22 20:13  6%             ` Simon Wright
2008-04-21 21:34  5% ` Jerry
2008-04-22 10:46  6%   ` Samuel Tardieu
2008-04-22 12:04  5%     ` Ludovic Brenta
2010-10-16  5:46     anyone seen this link error trying to link Ada program with blas and lapack? "cannot find -lgnalasup" Nasser M. Abbasi
2010-10-16  6:25  4% ` Nasser M. Abbasi
2011-12-21  1:08     Basic question on Ada multi-dimensional arrays, are they true (contiguous) arrays? aliasing rules? Nasser M. Abbasi
2011-12-21 21:11  5% ` Adrian-Ken Rueegsegger
2011-12-21 21:13  5% ` Adrian-Ken Rueegsegger
2012-06-23 12:02  5% questions on using the array component iterator for 2012 Nasser M. Abbasi
2012-06-23 12:04  0% ` Nasser M. Abbasi
2012-06-24  8:05  5% Any easy/build-in construct to extract submatrices from larger matrix? Nasser M. Abbasi
2012-06-26 13:47  7% how to print an array range? Nasser M. Abbasi
2012-06-26 13:54     ` Georg Bauhaus
2012-06-26 14:08  7%   ` Nasser M. Abbasi
2012-06-26 14:24  7%     ` Nasser M. Abbasi
2012-06-28  6:59  0% ` Shark8
2012-06-26 15:49  7% Why this error, value not in range of subtype of "Standard.Integer"? Nasser M. Abbasi
2012-06-26 17:20  0% ` Adam Beneschan
2012-06-26 18:00  4% ` Niklas Holsti
2012-06-26 21:39  0% ` Robert A Duff
2012-07-12  0:38  7% Lapack Ada binding matrices/vectors issue, how to best to resolve? Nasser M. Abbasi
2012-07-12  0:45  0% ` Nasser M. Abbasi
2012-08-15  6:16     ada lapack Leo Brewin
2012-08-17  6:25     ` Ada novice
2012-08-17  7:11       ` Leo Brewin
2012-08-17  7:42         ` Ada novice
2012-08-17  9:43           ` Niklas Holsti
2012-08-17 10:27             ` Ada novice
2012-08-17 11:08               ` Niklas Holsti
2012-08-17 11:33                 ` Ada novice
2012-08-17 13:45                   ` Leo Brewin
2012-08-17 14:11                     ` Marc C
2012-08-18 11:57                       ` Ada novice
2012-08-18 13:13                         ` Niklas Holsti
2012-08-18 13:48                           ` Ada novice
2012-08-18 15:22  5%                         ` Nasser M. Abbasi
2012-12-23 22:28  6% X : Real_Vector := Solve(A => A, X => B); -- Why X as argument name? Gustaf Thorslund
2012-12-24  8:33  4% ` Niklas Holsti
2012-12-24 11:50  0%   ` Simon Wright
2012-12-24 12:58  0%     ` Niklas Holsti
2012-12-24 21:25  0%     ` Gustaf Thorslund
2012-12-24 20:42  0%   ` Gustaf Thorslund
2012-12-24 20:10  0% ` jpwoodruff
2014-12-22 16:22     {Pre,Post}conditions and side effects Jean François Martinez
2014-12-22 17:18     ` Brad Moore
2014-12-23  8:22       ` Jean François Martinez
2014-12-23 17:05         ` Robert A Duff
2014-12-23 21:09           ` Jean François Martinez
2014-12-23 23:02             ` Peter Chapin
2014-12-24  1:03               ` Robert A Duff
2015-04-24  8:59  4%             ` Jacob Sparre Andersen
2015-04-24 22:26  0%               ` Peter Chapin
2015-04-25  0:13  0%                 ` Randy Brukardt
2015-04-25  0:31  0%               ` Bob Duff
2018-02-17 12:55  7% GNAT can't vectorize Real_Matrix multiplication from Ada.Numerics.Real_Arrays. What a surprise! Bojan Bozovic
2018-02-17 15:17  6% ` Bojan Bozovic
2018-02-17 15:49  5%   ` Bojan Bozovic
2018-02-18  1:51 10% ` Bojan Bozovic
2018-02-18 10:35 11%   ` Jeffrey R. Carter
2018-02-18 12:05  6%     ` Bojan Bozovic
2018-02-18 13:31 11%       ` Jeffrey R. Carter
2018-02-18 19:38  5%         ` Bojan Bozovic
2018-02-18 21:48  6%           ` Nasser M. Abbasi
2018-02-18 22:50  5%             ` Bojan Bozovic
2018-02-19 21:08  5%             ` Robert Eachus
2018-02-20  2:31  5%               ` Bojan Bozovic
2018-02-26  6:58  5%                 ` Robert Eachus
2018-11-21  9:56     overloading operators hnptz
2018-11-21 13:50     ` AdaMagica
2018-11-21 16:39       ` hnptz
2018-11-21 17:37  5%     ` Simon Wright
2018-11-22  8:18  0%       ` briot.emmanuel
2018-11-22 11:39  0%         ` Simon Wright
2018-11-26 17:47  0%         ` Anh Vo
2018-11-26 18:03  0%           ` Simon Wright
2018-11-26 18:24  0%             ` Dmitry A. Kazakov
2019-01-24  3:59  9% basic question on Ada programming Nasser M. Abbasi
2019-01-24  7:58  7% ` Niklas Holsti

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox