-- $Date: 2004/01/11 02:35:31 $
-- $Revision: 1.7 $
-- $Author: jcrocholl $

with Ada.Text_IO; use Ada.Text_IO;

package body Digits_Strings is

   -- Convert a string to a number.
   function To_Number
     (Value : in String-- The string to convert.
     return Number       -- The floating point number.
   is
      Index     : Positive := Value'First;
      Result    : Number := 0.0;
      Negative  : Boolean := Value(Index) = '-';
      Dot_Found : Boolean := False;
      Factor    : Number := 1.0;
      I         : Integer;
   begin
      if Negative then Index := Index + 1; end if;
      loop
         exit when Index > Value'Last;
         if Value(Index) = '.' then
            Dot_Found := True;
            Index := Index + 1;
         end if;
         exit when not (Value(Index) in '0' .. '9');
         I := Character'Pos(Value(Index)) - Character'Pos('0');
         if not Dot_Found then
            Result := Result * 10.0 + Number(I);
         else
            Factor := Factor / 10.0;
            Result := Result + Factor * Number(I);
         end if;
         Index := Index + 1;
      end loop;
      if Negative then Result := -Result; end if;
      return Result;
   end To_Number;

   -- Convert a number to a string.
   function To_String_Internal
     (Value     : in Number;            -- The number to convert.
      Done      : in Number;            -- The part that was already done.
      Divisor   : in Number;            -- The scaling divisor for the rest.
      Tolerance : in Number := 0.00005) -- Cut-off precision.
     return String                      -- The decimal string representation.
   is
      Rest  : Number := Value - Done;
      I     : Integer := Integer(Number'Floor(Rest / Divisor));
      C     : Character := Character'Val(Character'Pos('0') + I);
      Done2 : Number := Done + Number(I) * Divisor;
   begin
      -- pragma Debug(Put_Line(Number'Image(Value) & Number'Image(Done) &
      -- Number'Image(Divisor) & Number'Image(Rest) & Integer'Image(I) &
      -- Number'Image(Done2)));
      if Rest < Tolerance and Divisor < 0.5 then
         return "";
      elsif Divisor > 0.5 then
         return C &
           To_String_Internal(Value, Done2, Divisor / 10.0, Tolerance);
      elsif Divisor > 0.05 then
         return "." & C &
           To_String_Internal(Value, Done2, Divisor / 10.0, Tolerance);
      else
         return C &
           To_String_Internal(Value, Done2, Divisor / 10.0, Tolerance);
      end if;
   end To_String_Internal;

   -- Convert a number to a string.
   function To_String
     (Value     : in Number-- The number to convert.
      Tolerance : in Number-- Cut-off precision.
     return String           -- The decimal string representation.
   is
      Divisor : Number := 1.0;
   begin
      if Value < 0.0 then
         return "-" & To_String(-Value);
      elsif Value < Tolerance then
         return "0";
      else
         while Divisor <= Value loop
            Divisor := Divisor * 10.0;
         end loop;
         return To_String_Internal(Value, 0.0, Divisor / 10.0, Tolerance);
      end if;
   end To_String;

   -- Convert a number to a string.
   function To_String
     (Value : in Number-- The number to convert.
     return String is    -- The decimal string representation.
   begin
      return To_String(Value, 0.00001);
   end To_String;

end Digits_Strings;