tags:

views:

183

answers:

2

Using Ada (GNAT): I need to determine the power of ten for a given value. The most obvious approach is to use a logarithm; but that fails to compile.

with Ada.Numerics.Generic_Elementary_Functions;
procedure F(Value : in Float) is
      The_Log : Integer := 0;
begin
      The_Log := Integer(Log(Value, 10));
      G(Value, The_Log);
end;

error:

  • utilities.adb:495:26: "Log" is not visible
    • utilities.adb:495:26: non-visible declaration at a-ngelfu.ads:24, instance at line 482
    • utilities.adb:495:26: non-visible declaration at a-ngelfu.ads:23, instance at line 482

So then I attempt to refer to the package, but that also fails:

with Ada.Numerics.Generic_Elementary_Functions;
procedure F(Value : in Float) is
      The_Log : Integer := 0;
      package Float_Functions is new Ada.Numerics.Generic_Elementary_Functions (Float);
begin
      The_Log := Integer(Float_Functions.Log(Value, 10));
      G(Value, The_Log);
end;

error:

  • utilities.adb:495:41: no candidate interpretations match the actuals:
  • utilities.adb:495:41: too many arguments in call to "Log"
  • utilities.adb:495:53: expected type "Standard.Float"
  • utilities.adb:495:53: found type universal integer ==> in call to "Log" at a-ngelfu.ads:24, instance at line 482
+5  A: 

I don't know if you fixed it already or not, but here is the answer.

First of all, as I see you're passing Float when instantiating the generic version you may use the non generic one instead.

If you decide to use the generic version you have to do it the second way you did, you have to instantiate the package before you use its functions.

Looking at a-ngelfu.ads you may see the actual prototype of the function you need (there is another function for the natural logarithm with just 1 parameter):

function Log(X, Base : Float_Type'Base) return Float_Type'Base;

You can see there that the base needs to be in a float type too. The correct code for the generic version would be:

with Ada.Numerics.Generic_Elementary_Functions;

procedure F(Value : in Float) is
    -- Instantiate the package:
    package Float_Functions is new Ada.Numerics.Generic_Elementary_Functions (Float);
    -- The logarithm:
    The_Log : Integer := 0;
begin
    The_Log := Integer(Float_Functions.Log(Value, 10.0));
    G(Value, The_Log);
end;

The non-generic one would be exactly the same:

with Ada.Numerics.Elementary_Functions;

procedure F(Value : in Float) is
    -- The logarithm:
    The_Log : Integer := 0;
begin
    The_Log := Integer(Ada.Numerics.Elementary_Functions.Log(Value, 10.0));
    G(Value, The_Log);
end;
Xandy
+3  A: 

Xandy is right. His solution worked.

However being Ada there were two exceptions to guard against...

  • Value < 0.0
  • Value = 0.0

Without guards this function as it is causes exceptions to be generated. And remember The_Log as returned can be < 0, 0, and > 0.

with Ada.Numerics.Elementary_Functions; 

procedure F(Value : in Float) is 
    -- The logarithm: 
    The_Log : Integer := 0; 
begin 
    if Value /= 0.0 then
        The_Log := Integer(
             Ada.Numerics.Elementary_Functions.Log(abs Value, 10.0)); 
    end if;
    G(Value, The_Log); 
end; 
mat_geek
+1, you're right. I only fixed the compiler errors, didn't realized of that.
Xandy