❌ About FreshRSS

Normal view

There are new articles available, click to refresh the page.
Before yesterdayNews from the Ada programming language world

Coding Ada: Timing code and passing functions to functions

By: spqr
19 March 2019 at 14:03

If you have to time a function in a language like Ada, one option is to create a timer function that takes the function to be timed as a parameter. Here is an Ada program that times the Ackermann function. There is nothing special about the ackermann() function, except that it is recursive. The interesting part of the code involves creating a type, functype, to hold the function “pointer”, or access point. The type uses the phrase “access function” followed by the parameter list for the function in question, and the type of the return value. This denotes an Access type, which is the equivalent of a pointer in other languages. Rather than using the term “points to”, Ada prefers to refer to this type of entity as “granting access” to an object. An access to subprogram allows the caller to call a subprogram without knowing its name nor its declaration location.

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Calendar; use Ada.Calendar;

procedure passingfunc is

   type functype is access function (x,y: integer) return integer;

   function ackermann(m,n: in integer) return integer is
   begin
      if m = 0 then
         return n+1;
      elsif n = 0 then
         return ackermann(m-1,1);
      else
         return ackermann(m-1,ackermann(m,n-1));
      end if;
   end ackermann;

   procedure timeit(Func : functype; m,n : in integer) is 
      result : integer;
      startTime, endTime : time;
      milliS : Duration;
   begin
      startTime := Clock;
      result := Func(m,n);
      endTime := Clock;
      milliS := (endTime - startTime) * 1000;
      put_line("Result: " & Integer'Image(result));
      put_line("Runtime = " & Duration'Image(milliS) & " milliseconds.");
   end timeit;

begin
   timeit(ackermann'Access, 4, 1);
end passingfunc;

The function timeit() can then be implemented. It declares Func as one of the parameters, implying that a function (pointer) can be passed to it. The remaining two parameters are the two parameters to be passed onto ackermann(). Note that the call to Func() is quite normal as well – no magic needed. The guts of the timing algorithm are described in another post, so the interested reader is referred there. When the function timeit() is called in the main program, the ackermann() function is passed using ackermann’Access.

Here’s the program running… with some trivial output:

Result: 65533
Runtime = 17441.122000000 milliseconds.

Those of you who have ever implemented a non-recursive version of Ackermann will note the runtime of 17-odd seconds, which is much faster than the 60-80 seconds of the version using a stack.

spqr

Coding Ada: Timing code and passing functions to functions

By: spqr
19 March 2019 at 14:03

If you have to time a function in a language like Ada, one option is to create a timer function that takes the function to be timed as a parameter. Here is an Ada program that times the Ackermann function. There is nothing special about the ackermann() function, except that it is recursive. The interesting part of the code involves creating a type, functype, to hold the function “pointer”, or access point. The type uses the phrase “access function” followed by the parameter list for the function in question, and the type of the return value. This denotes an Access type, which is the equivalent of a pointer in other languages. Rather than using the term “points to”, Ada prefers to refer to this type of entity as “granting access” to an object. An access to subprogram allows the caller to call a subprogram without knowing its name nor its declaration location.

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Calendar; use Ada.Calendar;

procedure passingfunc is

   type functype is access function (x,y: integer) return integer;

   function ackermann(m,n: in integer) return integer is
   begin
      if m = 0 then
         return n+1;
      elsif n = 0 then
         return ackermann(m-1,1);
      else
         return ackermann(m-1,ackermann(m,n-1));
      end if;
   end ackermann;

   procedure timeit(Func : functype; m,n : in integer) is 
      result : integer;
      startTime, endTime : time;
      milliS : Duration;
   begin
      startTime := Clock;
      result := Func(m,n);
      endTime := Clock;
      milliS := (endTime - startTime) * 1000;
      put_line("Result: " & Integer'Image(result));
      put_line("Runtime = " & Duration'Image(milliS) & " milliseconds.");
   end timeit;

begin
   timeit(ackermann'Access, 4, 1);
end passingfunc;

The function timeit() can then be implemented. It declares Func as one of the parameters, implying that a function (pointer) can be passed to it. The remaining two parameters are the two parameters to be passed onto ackermann(). Note that the call to Func() is quite normal as well – no magic needed. The guts of the timing algorithm are described in another post, so the interested reader is referred there. When the function timeit() is called in the main program, the ackermann() function is passed using ackermann’Access.

Here’s the program running… with some trivial output:

Result: 65533
Runtime = 17441.122000000 milliseconds.

Those of you who have ever implemented a non-recursive version of Ackermann will note the runtime of 17-odd seconds, which is much faster than the 60-80 seconds of the version using a stack.

spqr

❌
❌