+ Conversion of number from string

This commit is contained in:
Vovanium 2023-12-18 02:49:39 +03:00
parent 7f62b51b5b
commit 9b5348d431
17 changed files with 685 additions and 0 deletions

View file

@ -0,0 +1,46 @@
function VSSL.Conversions.Generic_Mantissa_To_Number (
S : String;
Radix : Radix_Type;
Exponent : Exponent_Type := 0)
return Number_Type
is
Digit_N : Exponent_Type := 0;
Fraction : Boolean := False;
Negative : Boolean := False;
D : Integer;
R : Number_Type := To_Number (0);
Rdx : Number_Type := To_Number (Radix);
procedure Next_Digit (Digit : Integer) is
begin
if Digit >= Radix then
raise Constraint_Error with "Illegal digit";
end if;
R := R * Rdx + To_Number (Digit);
Digit_N := Digit_N + 1;
end Next_Digit;
begin
for J in S'Range loop
case S (J) is
when '0' .. '9' =>
D := Character'Pos (S (J)) - Character'Pos ('0');
Next_Digit (D);
when 'A' .. 'Z' =>
D := Character'Pos (S (J)) - Character'Pos ('A') + 10;
Next_Digit (D);
when 'a' .. 'z' =>
D := Character'Pos (S (J)) - Character'Pos ('a') + 10;
Next_Digit (D);
when '-' =>
Negative := True;
when '.' | ',' =>
Fraction := True;
Digit_N := 0;
when others =>
null;
end case;
end loop;
if Negative then
R := -R;
end if;
return Multiply_by_Power (R, Rdx, Exponent - (if Fraction then Digit_N else 0));
end VSSL.Conversions.Generic_Mantissa_To_Number;

View file

@ -0,0 +1,30 @@
--
-- Convert string to numeric type
--
generic
type Number_Type (<>) is private; -- arbitrary numeric type
type Exponent_Type is range <>;
with function To_Number (
A : Integer)
return Number_Type is <>;
with function "-" (
A : Number_Type)
return Number_Type is <>;
with function "+" (
A,
B : Number_Type)
return Number_Type is <>;
with function "*" (
A,
B : Number_Type)
return Number_Type is <>;
with function Multiply_by_Power (
A,
R : Number_Type;
N : Exponent_Type)
return Number_Type is <>;
function VSSL.Conversions.Generic_Mantissa_to_Number (
S : String;
Radix : Radix_Type;
Exponent : Exponent_Type := 0)
return Number_Type;

View file

@ -0,0 +1,227 @@
with Ada.Characters.Latin_1;
use Ada.Characters.Latin_1;
function VSSL.Conversions.Generic_String_to_Number (
S : String)
return Number_Type
is
function Is_Ignored (C : Character) return Boolean is (C in NUL .. ' ' | '_');
function To_Upper (C : Character) return Character is
(if C in 'a' .. 'z' then
Character'Val (Character'Pos (C) - (Character'Pos ('a') - Character'Pos ('A')))
else
C);
function Equal_No_Case (A, B : String) return Boolean is
(A'Length = B'Length and then (for all J in A'Range =>
To_Upper (A (J)) = To_Upper (B (J - A'First + B'First))));
function Have_Affix (S, Prefix, Postfix : String) return Boolean is
(S'Length > Prefix'Length + Postfix'Length and then
Equal_No_Case (S (S'First .. S'First + Prefix'Length - 1), Prefix) and then
Equal_No_Case (S (S'Last - Postfix'Length + 1 .. S'Last), Postfix));
procedure Remove_Affix (F, L : in out Natural; Prefix, Postfix : in String) is
begin
F := F + Prefix'Length;
L := L - Postfix'Length;
end Remove_Affix;
function Have_BOZ (S : String) return Boolean is
(S'Length >= 4 and then S (S'First) in 'B' | 'b' | 'O' | 'o' | 'Z' | 'z' and then
S (S'First + 1) = S (S'Last) and then S (S'Last) in ''' | '"'); --"
procedure Mantissa (
S : in String;
R : in Radix_Type;
N : out Number_Type;
E : out Exponent_Type)
is
Rdx : Number_Type := To_Number (R);
Frac : Boolean := False;
procedure Next_Digit (D : Integer) is
begin
if D >= R then
raise Constraint_Error with "Illegal digit";
end if;
N := N * Rdx + To_Number (D);
E := E - 1;
end Next_Digit;
begin
N := To_Number (0);
for J in S'Range loop
if not Is_Ignored (S (J)) then
case S (J) is
when '0' .. '9' =>
Next_Digit (Character'Pos (S (J)) - Character'Pos ('0'));
when 'A' .. 'Z' =>
Next_Digit (Character'Pos (S (J)) - Character'Pos ('A') + 10);
when 'a' .. 'z' =>
Next_Digit (Character'Pos (S (J)) - Character'Pos ('a') + 10);
when '.' | ',' =>
Frac := True;
E := 0;
when others =>
raise Constraint_Error with "Invalid character " &
Character'Image (S (J)) & " in number";
end case;
end if;
end loop;
if not Frac then
E := 0;
end if;
end Mantissa;
procedure Skip_Spaces (S : in String; J : in out Natural; L : in Natural) is
begin
while J <= L and then Is_Ignored (S (J)) loop
J := J + 1;
end loop;
if J > L then
raise Constraint_Error with "No number";
end if;
end Skip_Spaces;
procedure Sign (S : in String; F : in out Natural; L : in Natural; Neg : out Boolean) is
begin
Neg := False;
if S (F) = '+' then
F := F + 1;
elsif S (F) = '-' then
F := F + 1;
Neg := True;
end if;
end Sign;
Radix : Radix_Type := 10;
MF : Natural := S'First;
ML : Natural := S'Last;
EF, EL,
RF, RL : Natural := 0;
Neg, -- Flag for negative
Exp, -- Flag for exponential form
Bin, -- Flag for binary exponent (when radix is not binary)
Based, -- Flag for number with explicit radix
NE : Boolean := False; -- Flag for negative exponent
EP,
EE : Exponent_Type := 0;
N : Number_Type := To_Number (0);
begin
while ML >= MF and then Is_Ignored (S (ML)) loop -- skip
ML := ML - 1;
end loop;
Skip_Spaces (S, MF, ML);
Sign (S, MF, ML, Neg);
Skip_Spaces (S, MF, ML);
if Have_Affix (S (MF .. ML), "0X", "") then
Radix := 16; -- C-style 0x..
Remove_Affix (MF, ML, "0X", "");
Bin_Exp_Find : for J in MF + 1 .. ML - 1 loop
Exp := S (J) in 'P' | 'p';
if Exp then
EL := ML;
EF := J + 1;
ML := J - 1;
Bin := True;
exit Bin_Exp_Find;
end if;
end loop Bin_Exp_Find;
elsif Have_Affix (S (MF .. ML), "0B", "") then
Radix := 2; -- C-style 0b...
Remove_Affix (MF, ML, "0B", "");
elsif Have_Affix (S (MF .. ML), "B'", "'") or else Have_Affix (S (MF .. ML), "B""", """") then
Radix := 2;
Remove_Affix (MF, ML, "B'", "'");
elsif Have_Affix (S (MF .. ML), "O'", "'") or else Have_Affix (S (MF .. ML), "O""", """") then
Radix := 8;
Remove_Affix (MF, ML, "O'", "'");
elsif Have_Affix (S (MF .. ML), "Z'", "'") or else Have_Affix (S (MF .. ML), "Z""", """") then
Radix := 16;
Remove_Affix (MF, ML, "Z'", "'");
else
Radix_Find : for J in MF + 1 .. ML loop
if S (J) in '#' | ':' then -- Ada-style based
if not Based then -- first occurence of '#'
RF := MF;
RL := J - 1;
MF := J + 1;
Based := True;
else -- second occurence of '#'
if J < ML - 1 and then S (J + 1) in 'E' | 'e' then
EL := ML;
EF := J + 2;
ML := J - 1;
Exp := True;
exit Radix_Find;
elsif J = ML then
ML := J - 1;
end if;
end if;
elsif not Based and S (J) in 'R' | 'r' then -- Algol-style
RF := MF;
RL := J - 1;
MF := J + 1;
Based := True;
exit Radix_Find;
end if;
end loop Radix_Find;
if Based then
Radix := Decimal_to_Number (S (RF .. RL));
-- raise constraint error when not in range
elsif not Based then
Dec_Exp_Find : for J in MF + 1 .. ML - 1 loop
Exp := S (J) in 'D' | 'd' | 'E' | 'e';
if Exp then
EL := ML;
EF := J + 1;
ML := J - 1;
exit Dec_Exp_Find;
end if;
end loop Dec_Exp_Find;
end if;
if not Exp then
if Have_Affix (S (MF .. ML), "", "B") then
Radix := 2;
Remove_Affix (MF, ML, "", "B");
elsif Have_Affix (S (MF .. ML), "", "H") then
Radix := 16;
Remove_Affix (MF, ML, "", "B");
end if;
end if;
end if;
<<Common_Format>>
Mantissa (S (MF .. ML), Radix, N, EP);
if Exp then
Sign (S, EF, EL, NE);
EE := Decimal_to_Number (S (EF .. EL));
if EE < 0 then
raise Constraint_Error with "Exponent value is out of range";
end if;
if NE then
EE := -EE;
end if;
end if;
if Bin then
N := Multiply_by_Power (N, To_Number (Radix), EP);
N := Multiply_by_Power (N, To_Number (2), EE);
else
N := Multiply_by_Power (N, To_Number (Radix), EP + EE);
end if;
if Neg then
N := -N;
end if;
return N;
end VSSL.Conversions.Generic_String_to_Number;

View file

@ -0,0 +1,94 @@
generic
type Number_Type (<>) is private;
with function "-" (
A : Number_Type)
return Number_Type is <>;
with function "+" (
A,
B : Number_Type)
return Number_Type is <>;
with function "*" (
A,
B : Number_Type)
return Number_Type is <>;
type Exponent_Type is range <>; -- A type to store exponent values
with function To_Number (
A : Integer)
return Number_Type is <>; -- A function to convert a digit to a given type
with function Decimal_to_Number (
S : String)
return Exponent_Type is <>; -- A function to convert decimal digits to number
with function Multiply_by_Power (
A,
R : Number_Type;
N : Exponent_Type)
return Number_Type is <>;
function VSSL.Conversions.Generic_String_to_Number (
S : String)
return Number_Type;
-- Converts a textual representation of a number to an arbitrary type.
--
-- Supported formats:
--
-- * With integer and/or fractional part with or without decimal separator
-- (required if fractional part exists). Decimal separator can be dot or comma.
-- "1" => 1.0
-- "1." => 1.0
-- "1.0" => 1.0
-- "0.4" => 0.4
-- ".4" => 0.4
-- "2,3" => 2.3
-- * With or without a sign
-- "1" => 1.0
-- "+1" => 1.0
-- "-1" => -1.0
-- * Digits can be separated with undercsores (_) or spaces ( ).
-- C0 Control characters (like NUL, TAB) are also ignored in most positions.
-- "31 968" => 31.968
-- "3.14159_26" => 3.1415926
-- * In scientific exponentional format. Common letters E or e and
-- also Fortran-ish D or d can be used to introduce exponent.
-- "12E7" => 120000000.0
-- "+1.24d-03" => 0.00123
-- * In Ada-style based format. Base range is enhanced to 2..36.
-- Both hash (#) and colon (:) are supported (colon was a valid replacement
-- for hash in Ada-83).
-- If there's no exponent, the second hash can be omitted.
-- "16#7FFD.8#" => 32765.5
-- "8#3.77#E+2" => 255.0
-- * With C-style prefixes for hexadecimal (0x) and binary (0b).
-- "0x7FFD.8" => 32765.5
-- "0b1101" => 13.0
-- * With C-stype binary exponent also
-- "0x1.8p1" => 3.0
-- * In Fortran-style BOZ-format.
-- "B'1101'" => 13.0
-- "O'377'" => 255.0
-- "Z'7FFD'" => 32765.0
-- * In Algol-style 'r' based format.
-- "16r7FFD.8" => 32765.5
-- * Postfix H and B for hexadecimal and binary numbers.
-- "1101B" => 13.0
-- "7FFD.8H" => 32765.5
-- * Upper and lowercase letters allowed.
-- "16#7fFd.8#" => 32765.5
--
-- NOT supported formats:
--
-- * Any kind of non-finite values, like NANs, Infinities.
-- * Imaginary, complex, dual, imprecise etc. multi-component numbers.
-- * Periodic fractions.
-- * C-style octals.
-- * Sexagesimal numbers like in HMS time or DMS angles.
-- * Roman numerals.
-- * Anything out of the ASCII character set.
--
-- It tries to analyse the whole string. If data is in wrong format
-- then exception may be raised or wrong result produced.
-- The behaviour if the result is out of range is on the implementation
-- of underlying arithmetic subprograms.
--
-- Implementation of numeric type is required to be able a hold a value of Base**Number_of_Digits - 1.
-- (More precisely, the largest number that resemble all the digits without decimal separator)
-- This generally fits well in floating point or integers but does not fit in fixed point.

View file

@ -0,0 +1,8 @@
with VSSL.Conversions.Generic_Mantissa_to_Number;
function VSSL.Conversions.Mantissa_to_Integer
is new VSSL.Conversions.Generic_Mantissa_To_Number (
Number_Type => Integer,
Exponent_Type => Integer,
To_Number => "+",
Multiply_by_Power => Multiply_by_Power);

View file

@ -0,0 +1,24 @@
with Ada.Characters.Latin_1;
use Ada.Characters.Latin_1;
package body VSSL.Conversions is
function Decimal_to_Number (S : String) return Integer is
N : Integer := 0;
D : Integer;
begin
for C of S loop
if C in '0' .. '9' then
D := Character'Pos (C) - Character'Pos ('0');
if N > (Integer'Last - D) / 10 then
return Integer'First; -- carefully treat overflow
end if; -- to have meaningfull exception
N := N * 10 + D;
elsif C not in NUL .. ' ' | '|' then
raise Constraint_Error with "Illegal character " & Character'Image (C);
end if;
end loop;
return N;
end Decimal_to_Number;
end VSSL.Conversions;

View file

@ -0,0 +1,17 @@
package VSSL.Conversions with Pure is
subtype Radix_Type is Integer range 2 .. 36;
function Multiply_by_Power (
A : Integer;
R : Integer; N : Integer)
return Integer is (if N >= 0 then A * R**N else A / R**(-N));
-- used by conversion subprograms
function Decimal_to_Number (
S : String)
return Integer;
-- Convert decimal number (without a sign) to an integer
-- It is used by conversion subprograms
end VSSL.Conversions;

View file

@ -0,0 +1,6 @@
with VSSL.Conversions.Generic_String_to_Number;
use VSSL.Conversions;
function VSSL.Floating_Point.String_to_Float is new VSSL.Conversions.Generic_String_to_Number (
Number_Type => Float,
Exponent_Type => Integer);

View file

@ -0,0 +1,6 @@
with VSSL.Conversions.Generic_String_to_Number;
use VSSL.Conversions;
function VSSL.Floating_Point.String_to_Long_Float is new VSSL.Conversions.Generic_String_to_Number (
Number_Type => Long_Float,
Exponent_Type => Integer);

View file

@ -1,4 +1,21 @@
pragma SPARK_Mode;
package VSSL.Floating_Point with Pure is
function Multiply_by_Power (A, R : Float; N : Integer) return Float
is (A * R**N);
-- used in conversion subprograms
function To_Number (N : Integer) return Float
is (Float (N));
-- used in conversion subprograms
function Multiply_by_Power (A, R : Long_Float; N : Integer) return Long_Float
is (A * R**N);
-- used in conversion subprograms
function To_Number (N : Integer) return Long_Float
is (Long_Float (N));
-- used in conversion subprograms
end VSSL.Floating_Point;

View file

@ -0,0 +1,55 @@
with AUnit.Simple_Test_Cases;
with AUnit.Assertions;
use AUnit.Assertions;
with VSSL.Conversions.Mantissa_to_Integer;
package body VSSL.Conversions.Test is
type Mantissa_to_Integer_Test is new AUnit.Simple_Test_Cases.Test_Case with null record;
function Name (T : Mantissa_to_Integer_Test) return AUnit.Message_String;
procedure Run_Test (T : in out Mantissa_to_Integer_Test);
function Name (T : Mantissa_to_Integer_Test) return AUnit.Message_String is
pragma Unreferenced (T);
begin
return AUnit.Format ("VSSL.Conversions.Mantissa_to_Integer test");
end Name;
procedure Run_Test (T : in out Mantissa_to_Integer_Test) is
procedure A (
A : String;
R : Radix_Type;
E : Integer;
B : Integer)
is
begin
Assert (Mantissa_to_Integer (A, R, E) = B,
"Mantissa_to_Integer (""" & A & """, "
& Radix_Type'Image (R) & ", "
& Integer'Image (E) & ") = " & Integer'Image (B));
end;
begin
A ("0", 10, 0, 0);
A ("1", 10, 0, 1);
A ("12", 10, 0, 12);
A ("-1", 10, 0, -1);
A ("1", 10, 3, 1000);
A ("1.2", 10, 3, 1200);
A ("10", 10, -1, 1);
A ("CAFE", 16, 0, 16#CAFE#);
end Run_Test;
function Suite return Access_Test_Suite is
R : Access_Test_Suite := new Test_Suite;
begin
R.Add_Test (new Mantissa_to_Integer_Test);
--R.Add_Test (Functions_Test.Suite);
return R;
end;
end VSSL.Conversions.Test;

View file

@ -0,0 +1,8 @@
with AUnit.Test_Suites;
use AUnit.Test_Suites;
package VSSL.Conversions.Test is
function Suite return Access_Test_Suite;
end VSSL.Conversions.Test;

View file

@ -0,0 +1,131 @@
with VSSL.Floating_Point.String_to_Float;
with VSSL.Floating_Point.String_to_Long_Float;
with VSSL.Floating_Point.Generic_Approximate_Relative;
with VSSL.Test_Cases;
use VSSL.Test_Cases;
with VSSL.Test_Cases.Traits;
use VSSL.Test_Cases.Traits;
with VSSL.Test_Cases.Unary_Functions;
use VSSL.Test_Cases.Unary_Functions;
package body VSSL.Floating_Point.Conversion_Test is
generic
type Real_Type is digits <>;
Real_Name : in String;
with function String_to_Real (S : String) return Real_Type;
Epsilon : Real_Type := Real_Type'Model_Epsilon;
package Generic_String_to_Float_Test is
function Suite return Access_Test_Suite;
end Generic_String_to_Float_Test;
package body Generic_String_to_Float_Test is
Prefix : constant String := "VSSL.Floating_Point.";
package Approx is new Generic_Approximate_Relative (Real_Type, Epsilon);
package Real_Traits is new Type_Traits (Real_Type, Real_Name, Real_Type'Image, Approx."=");
package String_to_Real_Case is new Unary_Function_Case (
String_Traits,
Real_Traits,
String_to_Real,
"String_to_" & Real_Name,
Prefix);
type String_to_Real_Test is new String_to_Real_Case.Test with null record;
overriding procedure Run_Test (T : in out String_to_Real_Test);
procedure Run_Test (T : in out String_to_Real_Test) is
begin
T.Assert ("0", 0.0);
T.Assert (" 0 ", 0.0);
T.Assert ("1", 1.0);
T.Assert ("2", 2.0);
T.Assert ("34", 34.0);
T.Assert (" 3_5 ", 35.0);
T.Assert ("01 2", 12.0);
T.Assert ("1.5", 1.5);
T.Assert ("1.01", 1.01);
T.Assert ("0.01", 0.01);
T.Assert ("15.24", 15.24);
T.Assert ("3.456789012", 3.456789012);
T.Assert (".5", 0.5);
T.Assert ("-0", 0.0);
T.Assert ("-1", -1.0);
T.Assert ("-7", -7.0);
T.Assert ("1E3", 1.0E+3);
T.Assert ("1_E3", 1.0E+3);
T.Assert ("5E+3", 5.0E+3);
T.Assert ("5E-3", 5.0E-3);
T.Assert ("1.9E+2", 1.9E+2);
T.Assert ("1.9E-2", 1.9E-2);
T.Assert ("4E31", 4.0E+31);
T.Assert ("4E-31", 4.0E-31);
T.Assert ("5.2D16", 5.2E+16);
T.Assert ("5.2D+16", 5.2E+16);
T.Assert ("5.2D-16", 5.2E-16);
T.Assert ("16#F#", 16#F.0#);
T.Assert ("16#F", 16#F.0#);
T.Assert ("16#Ed#", 16#ED.0#);
T.Assert ("16#cd#", 16#CD.0#);
T.Assert ("16:cd:", 16#CD.0#);
T.Assert ("-16#cd#", -16#CD.0#);
T.Assert ("2#1#E0", 2#1.0#E+00);
T.Assert ("2#1#E1", 2#1.0#E+01);
T.Assert ("8#1#E1", 8#1.0#E+01);
T.Assert ("8#1.1#E1", 8#1.1#E+01);
T.Assert ("8#3.77#E2", 8#3.77#E+02);
T.Assert ("8#3.77#e2", 8#3.77#E+02);
T.Assert ("8:3.77:e2", 8#3.77#E+02);
T.Assert ("16r7FFD.8", 16#7FFD.8#);
T.Assert ("8r377", 8#377.0#);
T.Assert ("B'1011_0101'", 2#1011_0101.0#);
T.Assert ("O'376'", 8#376.0#);
T.Assert ("Z'CAFE'", 16#CAFE.0#);
T.Assert ("Z""DEAD""", 16#DEAD.0#);
T.Assert ("0b1011_0101", 2#1011_0101.0#);
T.Assert ("0B1111_0101", 2#1111_0101.0#);
T.Assert ("0xBABE", 16#BABE.0#);
T.Assert ("0xc0de", 16#C0DE.0#);
T.Assert ("0XFACE8D", 16#FACE8D.0#);
T.Assert ("0XFACE.8D", 16#FACE.8D#);
T.Assert ("0x1p0", 2#0001.0#E0);
T.Assert ("-0x1EFp0", -2#0001_1110_1111.0#E0);
T.Assert ("0xF.p-1", 2#1111.0#E-1);
T.Assert ("0X0.123P-4", 2#0000.0001_0010_0011#E-4);
T.Assert ("0x1.8p1", 3.0);
T.Assert ("1001_1011B", 2#1001_1011.0#);
T.Assert ("0101_1010b", 2#0101_1010.0#);
T.Assert ("C0ACH", 16#C0AC.0#);
end Run_Test;
function Suite return Access_Test_Suite is
R : Access_Test_Suite := new Test_Suite;
begin
R.Add_Test (new String_to_Real_Test);
return R;
end Suite;
end Generic_String_to_Float_Test;
package String_to_Float_Test is new Generic_String_to_Float_Test (
Float, "Float", String_To_Float);
package String_to_Long_Float_Test is new Generic_String_to_Float_Test (
Long_Float, "Long_Float", String_To_Long_Float);
function Suite return Access_Test_Suite is
R : Access_Test_Suite := new Test_Suite;
begin
R.Add_Test (String_to_Float_Test.Suite);
R.Add_Test (String_to_Long_Float_Test.Suite);
return R;
end Suite;
end VSSL.Floating_Point.Conversion_Test;

View file

@ -0,0 +1,8 @@
with AUnit.Test_Suites;
use AUnit.Test_Suites;
package VSSL.Floating_Point.Conversion_Test is
function Suite return Access_Test_Suite;
end VSSL.Floating_Point.Conversion_Test;

View file

@ -1,5 +1,6 @@
with VSSL.Floating_Point.Approximate_Absolute_Test;
with VSSL.Floating_Point.Approximate_Test;
with VSSL.Floating_Point.Conversion_Test;
with VSSL.Floating_Point.Quaternions;
with VSSL.Floating_Point.Generic_Quaternions.Test;
@ -13,6 +14,7 @@ package body VSSL.Floating_Point.Test is
begin
R.Add_Test (Approximate_Absolute_Test.Suite);
R.Add_Test (Approximate_Test.Suite);
R.Add_Test (Conversion_Test.Suite);
R.Add_Test (Quaternions_Test.Suite);
return R;
end;

View file

@ -1,5 +1,6 @@
with VSSL.Champernowne_Constant.Test;
with VSSL.Combinatorial.Test;
with VSSL.Conversions.Test;
with VSSL.Fixed_Point.Test;
with VSSL.Floating_Point.Test;
with VSSL.Integers.Test;
@ -13,6 +14,7 @@ package body VSSL.Test is
R.Add_Test (VSSL.Extensible_Arithmetic.Test.Suite);
R.Add_Test (VSSL.Champernowne_Constant.Test.Suite);
R.Add_Test (VSSL.Combinatorial.Test.Suite);
R.Add_Test (VSSL.Conversions.Test.Suite);
R.Add_Test (VSSL.Fixed_Point.Test.Suite);
R.Add_Test (VSSL.Floating_Point.Test.Suite);
R.Add_Test (VSSL.Integers.Test.Suite);

View file

@ -4,4 +4,8 @@ package VSSL.Test_Cases.Traits is
package Integer_Traits is new Type_Traits (Integer, "Integer", Integer'Image, "=");
function String_Image (S : String) return String is ("""" & S & """");
package String_Traits is new Type_Traits (String, "String", String_Image, "=");
end VSSL.Test_Cases.Traits;