comp.lang.ada
 help / color / mirror / Atom feed
From: hreba <f_hreba@yahoo.com.br>
Subject: Re: Interfaces.C questions
Date: Sun, 19 Mar 2017 13:17:35 +0100
Date: 2017-03-19T13:17:35+01:00	[thread overview]
Message-ID: <ej7b6vF1rdnU1@mid.individual.net> (raw)
In-Reply-To: <403f77a2-992e-45b1-8f5d-a97143783130@googlegroups.com>

On 03/19/2017 12:24 AM, Leo Brewin wrote:
> Hi Frank,
>
> I'd be really interested to see a minimal working example once you've got it running.
> I'd like to be able to use GSL in my own codes.
>
> Cheers,
> Leo
>

Ok, below follows my first working example, numerical quadrature. Any 
critics is welcome. Some remarks:

'void * params' in C can be a pointer to just anything, a number, an 
array, a record. The best solution probably would be  a generic package 
where the actual type is passed as parameter (see type Element in 
Interfaces.C.Pointers). The quadrature algorithm I chose makes no use of 
these parameters, so in my example I translate the type to 'access all 
Integer' and pass null as value.

As I am beginning to build a numerics library, I will now

  - make the package generic, with 2 type parameters, one for the reals
    (digits <>) and one for the parameters (private),
  - write wrappers so that the client needs no Interfaces.C, and that he
    can pass a function of
    'type Real_Function is access function (x: Real) return Real;'
    to the quadrature procedure instead of a record.

So here comes my example. The interface package is (no body):

-----------------------------------------------------------------------
with Interfaces.C;

package GSL is

    package C renames Interfaces.C;

    type Void_Ptr is access all Integer;
    type GSL_Function_Ptr is access
      function (x: C.double; params: Void_Ptr) return C.double;
    type GSL_Function is record
       func:	GSL_Function_Ptr;
       params:	Void_Ptr;
    end record;


    function Integration_QNG
      (f: access GSL_Function;
       a, b, epsabs, epsrel: C.double;
       result, abserr: out C.double;
       neval: out C.size_t)
      return C.int;

private

    pragma Import (C, Integration_QNG, "gsl_integration_qng");
    pragma Convention (C, Void_Ptr);
    pragma Convention (C, GSL_Function_Ptr);
    pragma Convention (C, GSL_Function);

end GSL;
-----------------------------------------------------------------------------

The main subprogram (client) is

-----------------------------------------------------------------------------
with Ada.Text_IO;	use Ada.Text_IO;
with GSL;
with Integ_Aux;

procedure Test_Integration
is
    use type GSL.C.double;
    a:		GSL.C.double;
    abserr:	GSL.C.double;
    neval:	GSL.C.size_t;
    res:		GSL.C.int;
    gslf:	aliased GSL.GSL_Function;

begin
    gslf.func:= Integ_Aux.Circle'Access;
    gslf.params:= null;
    res:= GSL.Integration_QNG
      (gslf'Access, 0.0, 1.0, 0.001, 0.001, a, abserr, neval);
    Put_Line("4*int_0^1 sqrt(1-x^2) dx = " & GSL.C.double'Image(4.0*a));
    Put_Line(GSL.C.size_t'Image(neval) & " function evaluations, " &
	      GSL.C.double'Image(abserr) & " abs. error");
end Test_Integration;
------------------------------------------------------------------------------
Because an access is passed to the function to be integrated it has to 
be in a separated package:
------------------------------------------------------------------------------
with GSL;

package Integ_Aux is
       function Circle (x: GSL.C.double; pars: GSL.Void_Ptr) return 
GSL.C.double;

private
    pragma Convention (C, Circle);
end Integ_Aux;
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
with Ada.Numerics.Generic_Elementary_Functions;
with GSL;

package body Integ_Aux is

    package Functions is new
      Ada.Numerics.Generic_Elementary_Functions (GSL.C.double);

    function Circle (x: GSL.C.double; pars: GSL.Void_Ptr) return 
GSL.C.double is
    use type GSL.C.double;
    begin return Functions.Sqrt(abs(1.0-x*x));
    end Circle;

end Integ_Aux;
--------------------------------------------------------------------------------
The project files of the interface package are
--------------------------------------------------------------------------------
-- External library "Gnu Scientific Library"

with "gslcblas";

Project GSL is

    type OS_Type is ("linux", "linux-gnu", "windows", "unknown");
    act_os: OS_Type:= external ("OSTYPE");
    -- act_os: OS_Type:= external ("OS_TYPE");

    For externally_built use "true";
    For library_dir use "/usr/lib";
    case act_os is
       when "linux"|"linux-gnu" => for library_dir use "/usr/lib";
       when "windows" => for library_dir use "/Lib/GSL";
       when "unknown" => for Source_Dirs use ("/");	-- just anything
    end case;
    For library_name use "gsl";
    For source_dirs use (); -- no sources.
    -- For library_kind use "static";
    -- if it is a static lib .a

    for library_kind use "dynamic";
    -- if it is an so.

end GSL;
-------------------------------------------------------------------------
-------------------------------------------------------------------------
-- External library "Gnu Scientific Library"


Project GSLCBLAS is

    type OS_Type is ("linux", "linux-gnu", "windows", "unknown");
    act_os: OS_Type:= external ("OSTYPE");
    -- act_os: OS_Type:= external ("OS_TYPE");

    For externally_built use "true";
    case act_os is
       when "linux"|"linux-gnu" => for library_dir use "/usr/lib";
       when "windows" => for library_dir use "/Lib/GSL";
       when "unknown" => for Source_Dirs use ("/");	-- just anything
    end case;
    For library_name use "gslcblas";
    For source_dirs use (); -- no sources.
    -- For library_kind use "static";
    -- if it is a static lib .a

    for library_kind use "dynamic";
    -- if it is an so.

end GSLCBLAS;
-----------------------------------------------------------------------------
I tried to make these projects platform independent (Linux and Windows 
so far); only tested on Linux so far. The environment variable OSTYPE 
must exist. If you don't want to do this, just type
for library_dir use "/usr/lib";
instead of the 'case' construct (on Linux).
Finally the project file for the main program:
-----------------------------------------------------------------------------
with "../../gsl.gpr";

project Test_Integration is

    for Source_Dirs use (".", "../../src"); -- test and interface sources
    for Object_Dir use "../obj";
    for Exec_Dir use ".";
    for Main use ("test_integration.adb");

    package Compiler is
       for Default_Switches ("ada") use ("-g", "-gnatf", "-gnat2012");
    end Compiler;

    package Linker is
       for Default_Switches ("ada") use ("-g");
    end Linker;

    package Builder is
       for Default_Switches ("ada") use ("-g");
    end Builder;

end Test_Integration;
------------------------------------------------------------------------------
The result is an approximation of the unit circle area, pi.

-- 
Frank Hrebabetzky		+49 / 6355 / 989 5070


  reply	other threads:[~2017-03-19 12:17 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-17 21:12 Interfaces.C questions hreba
2017-03-17 21:57 ` Niklas Holsti
2017-03-17 22:14 ` Jeffrey R. Carter
2017-03-17 22:24 ` Dmitry A. Kazakov
2017-03-21 21:08   ` Michael B.
2017-03-21 21:28     ` Dmitry A. Kazakov
2017-03-21 21:31     ` Simon Wright
2017-03-22 20:35       ` Randy Brukardt
2017-03-18 15:46 ` hreba
2017-03-18 16:26   ` Jeffrey R. Carter
2017-03-18 16:27   ` Jeffrey R. Carter
2017-03-19  7:03   ` Keith Thompson
2017-03-18 23:24 ` Leo Brewin
2017-03-19 12:17   ` hreba [this message]
2017-03-20  9:44     ` Leo Brewin
2017-03-19  7:00 ` Keith Thompson
2017-03-19 12:05 ` Per Sandberg
2017-03-19 18:39 ` hreba
2017-03-19 19:22   ` Simon Wright
2017-03-19 19:49     ` hreba
2017-03-19 23:53       ` Simon Wright
2017-03-20 11:12         ` hreba
2017-03-20 14:04         ` hreba
2017-03-22 11:21           ` hreba
replies disabled

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