Commit f17f5647 by Arnaud Charlet Committed by Pierre-Marie de Rodat

[Ada] AI12-0208 Support for Ada.Numerics.Big_Numbers.Big_Integers and Big_Reals

2019-12-16  Arnaud Charlet  <charlet@adacore.com>

gcc/ada/

	* impunit.adb: Add a-nbnbin, a-nbnbre, a-nubinu to Ada 2020
	units.
	* Makefile.rtl: Enable new file.
	* libgnat/a-nbnbin.adb, libgnat/a-nbnbin.ads,
	libgnat/a-nbnbre.adb, libgnat/a-nbnbre.ads,
	libgnat/a-nubinu.ads: New files. Provide default standalone
	implementation of Ada.Numerics.Big_Numbers.Big_* based on
	System.Generic_Bignum.
	* libgnat/a-nbnbin__gmp.adb: Alternate implementation of
	Ada.Numerics.Big_Numbers.Big_Integers based on GMP. Not enabled
	for now.
	* libgnat/s-bignum.ads, libgnat/s-bignum.adb: Now a simple
	wrapper on top of s-genbig.ads.
	* libgnat/s-genbig.ads, libgnat/s-genbig.adb: New files, making
	s-bignum generic for reuse in Ada.Numerics.Big_Numbers.

From-SVN: r279418
parent a4ada47e
2019-12-16 Arnaud Charlet <charlet@adacore.com>
* impunit.adb: Add a-nbnbin, a-nbnbre, a-nubinu to Ada 2020
units.
* Makefile.rtl: Enable new file.
* libgnat/a-nbnbin.adb, libgnat/a-nbnbin.ads,
libgnat/a-nbnbre.adb, libgnat/a-nbnbre.ads,
libgnat/a-nubinu.ads: New files. Provide default standalone
implementation of Ada.Numerics.Big_Numbers.Big_* based on
System.Generic_Bignum.
* libgnat/a-nbnbin__gmp.adb: Alternate implementation of
Ada.Numerics.Big_Numbers.Big_Integers based on GMP. Not enabled
for now.
* libgnat/s-bignum.ads, libgnat/s-bignum.adb: Now a simple
wrapper on top of s-genbig.ads.
* libgnat/s-genbig.ads, libgnat/s-genbig.adb: New files, making
s-bignum generic for reuse in Ada.Numerics.Big_Numbers.
2019-12-16 Bob Duff <duff@adacore.com> 2019-12-16 Bob Duff <duff@adacore.com>
* doc/gnat_ugn/building_executable_programs_with_gnat.rst: * doc/gnat_ugn/building_executable_programs_with_gnat.rst:
......
...@@ -205,6 +205,8 @@ GNATRTL_NONTASKING_OBJS= \ ...@@ -205,6 +205,8 @@ GNATRTL_NONTASKING_OBJS= \
a-lliwti$(objext) \ a-lliwti$(objext) \
a-llizti$(objext) \ a-llizti$(objext) \
a-locale$(objext) \ a-locale$(objext) \
a-nbnbin$(objext) \
a-nbnbre$(objext) \
a-ncelfu$(objext) \ a-ncelfu$(objext) \
a-ngcefu$(objext) \ a-ngcefu$(objext) \
a-ngcoar$(objext) \ a-ngcoar$(objext) \
...@@ -224,6 +226,7 @@ GNATRTL_NONTASKING_OBJS= \ ...@@ -224,6 +226,7 @@ GNATRTL_NONTASKING_OBJS= \
a-nscefu$(objext) \ a-nscefu$(objext) \
a-nscoty$(objext) \ a-nscoty$(objext) \
a-nselfu$(objext) \ a-nselfu$(objext) \
a-nubinu$(objext) \
a-nucoar$(objext) \ a-nucoar$(objext) \
a-nucoty$(objext) \ a-nucoty$(objext) \
a-nudira$(objext) \ a-nudira$(objext) \
...@@ -570,6 +573,7 @@ GNATRTL_NONTASKING_OBJS= \ ...@@ -570,6 +573,7 @@ GNATRTL_NONTASKING_OBJS= \
s-flocon$(objext) \ s-flocon$(objext) \
s-fore$(objext) \ s-fore$(objext) \
s-gearop$(objext) \ s-gearop$(objext) \
s-genbig$(objext) \
s-geveop$(objext) \ s-geveop$(objext) \
s-gloloc$(objext) \ s-gloloc$(objext) \
s-htable$(objext) \ s-htable$(objext) \
......
...@@ -620,11 +620,10 @@ package body Impunit is ...@@ -620,11 +620,10 @@ package body Impunit is
-- The following units should be used only in Ada 202X mode -- The following units should be used only in Ada 202X mode
Non_Imp_File_Names_2X : constant File_List := ( Non_Imp_File_Names_2X : constant File_List := (
0 => ("a-stteou", T) -- Ada.Strings.Text_Output ("a-stteou", T), -- Ada.Strings.Text_Output
-- ???We use named notation, because there is only one of these so far. ("a-nubinu", T), -- Ada.Numerics.Big_Numbers
-- When we add more, we should switch to positional notation, and erase ("a-nbnbin", T), -- Ada.Numerics.Big_Numbers.Big_Integers
-- the "0 =>". ("a-nbnbre", T)); -- Ada.Numerics.Big_Numbers.Big_Reals
);
----------------------- -----------------------
-- Alternative Units -- -- Alternative Units --
......
------------------------------------------------------------------------------
-- --
-- GNAT RUN-TIME COMPONENTS --
-- --
-- ADA.NUMERICS.BIG_NUMBERS.BIG_INTEGERS --
-- --
-- S p e c --
-- --
-- This specification is derived from the Ada Reference Manual for use with --
-- GNAT. In accordance with the copyright of that document, you can freely --
-- copy and modify this specification, provided that if you redistribute a --
-- modified version, any changes that you have made are clearly indicated. --
-- --
------------------------------------------------------------------------------
with Ada.Finalization;
with Ada.Streams;
private with System;
-- Note that some Ada 2020 aspects are commented out since they are not
-- supported yet.
package Ada.Numerics.Big_Numbers.Big_Integers
with Preelaborate
-- Nonblocking
is
type Optional_Big_Integer is private
with Default_Initial_Condition => not Is_Valid (Optional_Big_Integer);
-- Integer_Literal => From_String,
-- Put_Image => Put_Image;
function Is_Valid (Arg : Optional_Big_Integer) return Boolean;
subtype Big_Integer is Optional_Big_Integer
with Dynamic_Predicate => Is_Valid (Big_Integer),
Predicate_Failure => (raise Constraint_Error);
function Invalid_Big_Integer return Optional_Big_Integer
with Post => not Is_Valid (Invalid_Big_Integer'Result);
function "=" (L, R : Big_Integer) return Boolean;
function "<" (L, R : Big_Integer) return Boolean;
function "<=" (L, R : Big_Integer) return Boolean;
function ">" (L, R : Big_Integer) return Boolean;
function ">=" (L, R : Big_Integer) return Boolean;
function To_Big_Integer (Arg : Integer) return Big_Integer;
subtype Optional_Big_Positive is Optional_Big_Integer
with Dynamic_Predicate =>
(not Is_Valid (Optional_Big_Positive))
or else (Optional_Big_Positive > To_Big_Integer (0)),
Predicate_Failure => (raise Constraint_Error);
subtype Optional_Big_Natural is Optional_Big_Integer
with Dynamic_Predicate =>
(not Is_Valid (Optional_Big_Natural))
or else (Optional_Big_Natural >= To_Big_Integer (0)),
Predicate_Failure => (raise Constraint_Error);
subtype Big_Positive is Big_Integer
with Dynamic_Predicate => Big_Positive > To_Big_Integer (0),
Predicate_Failure => (raise Constraint_Error);
subtype Big_Natural is Big_Integer
with Dynamic_Predicate => Big_Natural >= To_Big_Integer (0),
Predicate_Failure => (raise Constraint_Error);
function In_Range (Arg, Low, High : Big_Integer) return Boolean is
((Low <= Arg) and (Arg <= High));
function To_Integer (Arg : Big_Integer) return Integer
with Pre => In_Range (Arg,
Low => To_Big_Integer (Integer'First),
High => To_Big_Integer (Integer'Last))
or else (raise Constraint_Error);
generic
type Int is range <>;
package Signed_Conversions is
function To_Big_Integer (Arg : Int) return Big_Integer;
function From_Big_Integer (Arg : Big_Integer) return Int
with Pre => In_Range (Arg,
Low => To_Big_Integer (Int'First),
High => To_Big_Integer (Int'Last))
or else (raise Constraint_Error);
end Signed_Conversions;
generic
type Int is mod <>;
package Unsigned_Conversions is
function To_Big_Integer (Arg : Int) return Big_Integer;
function From_Big_Integer (Arg : Big_Integer) return Int
with Pre => In_Range (Arg,
Low => To_Big_Integer (Int'First),
High => To_Big_Integer (Int'Last))
or else (raise Constraint_Error);
end Unsigned_Conversions;
function To_String (Arg : Big_Integer;
Width : Field := 0;
Base : Number_Base := 10) return String
with Post => To_String'Result'First = 1;
function From_String (Arg : String) return Big_Integer;
procedure Put_Image
(Stream : not null access Ada.Streams.Root_Stream_Type'Class;
Arg : Big_Integer);
function "+" (L : Big_Integer) return Big_Integer;
function "-" (L : Big_Integer) return Big_Integer;
function "abs" (L : Big_Integer) return Big_Integer;
function "+" (L, R : Big_Integer) return Big_Integer;
function "-" (L, R : Big_Integer) return Big_Integer;
function "*" (L, R : Big_Integer) return Big_Integer;
function "/" (L, R : Big_Integer) return Big_Integer;
function "mod" (L, R : Big_Integer) return Big_Integer;
function "rem" (L, R : Big_Integer) return Big_Integer;
function "**" (L : Big_Integer; R : Natural) return Big_Integer;
function Min (L, R : Big_Integer) return Big_Integer;
function Max (L, R : Big_Integer) return Big_Integer;
function Greatest_Common_Divisor
(L, R : Big_Integer) return Big_Positive
with Pre => (L /= To_Big_Integer (0) and R /= To_Big_Integer (0))
or else (raise Constraint_Error);
private
type Controlled_Bignum is new Ada.Finalization.Controlled with record
C : System.Address := System.Null_Address;
end record;
procedure Adjust (This : in out Controlled_Bignum);
procedure Finalize (This : in out Controlled_Bignum);
type Optional_Big_Integer is record
Value : Controlled_Bignum;
end record;
end Ada.Numerics.Big_Numbers.Big_Integers;
------------------------------------------------------------------------------
-- --
-- GNAT RUN-TIME COMPONENTS --
-- --
-- ADA.NUMERICS.BIG_NUMBERS.BIG_REALS --
-- --
-- S p e c --
-- --
-- This specification is derived from the Ada Reference Manual for use with --
-- GNAT. In accordance with the copyright of that document, you can freely --
-- copy and modify this specification, provided that if you redistribute a --
-- modified version, any changes that you have made are clearly indicated. --
-- --
------------------------------------------------------------------------------
with Ada.Numerics.Big_Numbers.Big_Integers;
with Ada.Streams;
-- Note that some Ada 2020 aspects are commented out since they are not
-- supported yet.
package Ada.Numerics.Big_Numbers.Big_Reals
with Preelaborate
-- Nonblocking, Global => in out synchronized Big_Reals
is
type Optional_Big_Real is private with
Default_Initial_Condition => not Is_Valid (Optional_Big_Real);
-- Real_Literal => From_String,
-- Put_Image => Put_Image;
function Is_Valid (Arg : Optional_Big_Real) return Boolean;
function No_Big_Real return Optional_Big_Real
with Post => not Is_Valid (No_Big_Real'Result);
subtype Big_Real is Optional_Big_Real
with Dynamic_Predicate => Is_Valid (Big_Real),
Predicate_Failure => (raise Constraint_Error);
function "/" (Num, Den : Big_Integers.Big_Integer) return Big_Real;
-- with Pre => (if Big_Integers."=" (Den, Big_Integers.To_Big_Integer (0))
-- then raise Constraint_Error);
function Numerator (Arg : Big_Real) return Big_Integers.Big_Integer;
function Denominator (Arg : Big_Real) return Big_Integers.Big_Positive
with Post =>
(Arg = To_Real (0)) or else
(Big_Integers."="
(Big_Integers.Greatest_Common_Divisor
(Numerator (Arg), Denominator'Result),
Big_Integers.To_Big_Integer (1)));
function To_Big_Real
(Arg : Big_Integers.Big_Integer)
return Big_Real is (Arg / Big_Integers.To_Big_Integer (1));
function To_Real (Arg : Integer) return Big_Real is
(Big_Integers.To_Big_Integer (Arg) / Big_Integers.To_Big_Integer (1));
function "=" (L, R : Big_Real) return Boolean;
function "<" (L, R : Big_Real) return Boolean;
function "<=" (L, R : Big_Real) return Boolean;
function ">" (L, R : Big_Real) return Boolean;
function ">=" (L, R : Big_Real) return Boolean;
function In_Range (Arg, Low, High : Big_Real) return Boolean is
(Low <= Arg and then Arg <= High);
generic
type Num is digits <>;
package Float_Conversions is
function To_Big_Real (Arg : Num) return Big_Real;
function From_Big_Real (Arg : Big_Real) return Num
with Pre => In_Range (Arg,
Low => To_Big_Real (Num'First),
High => To_Big_Real (Num'Last))
or else (raise Constraint_Error);
end Float_Conversions;
generic
type Num is delta <>;
package Fixed_Conversions is
function To_Big_Real (Arg : Num) return Big_Real;
function From_Big_Real (Arg : Big_Real) return Num
with Pre => In_Range (Arg,
Low => To_Big_Real (Num'First),
High => To_Big_Real (Num'Last))
or else (raise Constraint_Error);
end Fixed_Conversions;
function To_String (Arg : Big_Real;
Fore : Field := 2;
Aft : Field := 3;
Exp : Field := 0) return String
with Post => To_String'Result'First = 1;
function From_String (Arg : String) return Big_Real;
function To_Quotient_String (Arg : Big_Real) return String is
(Big_Integers.To_String (Numerator (Arg)) & " / "
& Big_Integers.To_String (Denominator (Arg)));
function From_Quotient_String (Arg : String) return Big_Real;
procedure Put_Image
(Stream : not null access Ada.Streams.Root_Stream_Type'Class;
Arg : Big_Real);
function "+" (L : Big_Real) return Big_Real;
function "-" (L : Big_Real) return Big_Real;
function "abs" (L : Big_Real) return Big_Real;
function "+" (L, R : Big_Real) return Big_Real;
function "-" (L, R : Big_Real) return Big_Real;
function "*" (L, R : Big_Real) return Big_Real;
function "/" (L, R : Big_Real) return Big_Real;
function "**" (L : Big_Real; R : Integer) return Big_Real;
function Min (L, R : Big_Real) return Big_Real;
function Max (L, R : Big_Real) return Big_Real;
private
type Optional_Big_Real is record
Num, Den : Big_Integers.Optional_Big_Integer;
end record;
end Ada.Numerics.Big_Numbers.Big_Reals;
------------------------------------------------------------------------------
-- --
-- GNAT RUN-TIME COMPONENTS --
-- --
-- A D A . N U M E R I C S --
-- --
-- S p e c --
-- --
-- This specification is derived from the Ada Reference Manual for use with --
-- GNAT. In accordance with the copyright of that document, you can freely --
-- copy and modify this specification, provided that if you redistribute a --
-- modified version, any changes that you have made are clearly indicated. --
-- --
------------------------------------------------------------------------------
-- Note that some Ada 2020 aspects are commented out since they are not
-- supported yet.
package Ada.Numerics.Big_Numbers
-- with Pure, Nonblocking, Global => null
with Pure
is
subtype Field is Integer range 0 .. 255;
subtype Number_Base is Integer range 2 .. 16;
end Ada.Numerics.Big_Numbers;
...@@ -33,51 +33,13 @@ ...@@ -33,51 +33,13 @@
-- use in computing intermediate values in expressions for the case where -- use in computing intermediate values in expressions for the case where
-- pragma Overflow_Check (Eliminated) is in effect. -- pragma Overflow_Check (Eliminated) is in effect.
with Interfaces; -- Note that we cannot use a straight instantiation of System.Generic_Bignums
-- because the rtsfind mechanism is not ready to handle instantiations.
package System.Bignums is package System.Bignums is
pragma Preelaborate;
pragma Assert (Long_Long_Integer'Size = 64); type Bignum is private;
-- This package assumes that Long_Long_Integer size is 64 bit (i.e. that it
-- has a range of -2**63 to 2**63-1). The front end ensures that the mode
-- ELIMINATED is not allowed for overflow checking if this is not the case.
subtype Length is Natural range 0 .. 2 ** 23 - 1;
-- Represent number of words in Digit_Vector
Base : constant := 2 ** 32;
-- Digit vectors use this base
subtype SD is Interfaces.Unsigned_32;
-- Single length digit
type Digit_Vector is array (Length range <>) of SD;
-- Represent digits of a number (most significant digit first)
type Bignum_Data (Len : Length) is record
Neg : Boolean;
-- Set if value is negative, never set for zero
D : Digit_Vector (1 .. Len);
-- Digits of number, most significant first, represented in base
-- 2**Base. No leading zeroes are stored, and the value of zero is
-- represented using an empty vector for D.
end record;
for Bignum_Data use record
Len at 0 range 0 .. 23;
Neg at 3 range 0 .. 7;
end record;
type Bignum is access all Bignum_Data;
-- This is the type that is used externally. Possibly this could be a
-- private type, but we leave the structure exposed for now. For one
-- thing it helps with debugging. Note that this package never shares
-- an allocated Bignum value, so for example for X + 0, a copy of X is
-- returned, not X itself.
-- Note: none of the subprograms in this package modify the Bignum_Data
-- records referenced by Bignum arguments of mode IN.
function Big_Add (X, Y : Bignum) return Bignum; -- "+" function Big_Add (X, Y : Bignum) return Bignum; -- "+"
function Big_Sub (X, Y : Bignum) return Bignum; -- "-" function Big_Sub (X, Y : Bignum) return Bignum; -- "-"
...@@ -113,4 +75,27 @@ package System.Bignums is ...@@ -113,4 +75,27 @@ package System.Bignums is
-- Convert Bignum to Long_Long_Integer. Constraint_Error raised with -- Convert Bignum to Long_Long_Integer. Constraint_Error raised with
-- appropriate message if value is out of range of Long_Long_Integer. -- appropriate message if value is out of range of Long_Long_Integer.
private
type Bignum is new System.Address;
pragma Inline (Big_Add);
pragma Inline (Big_Sub);
pragma Inline (Big_Mul);
pragma Inline (Big_Div);
pragma Inline (Big_Exp);
pragma Inline (Big_Mod);
pragma Inline (Big_Rem);
pragma Inline (Big_Neg);
pragma Inline (Big_Abs);
pragma Inline (Big_EQ);
pragma Inline (Big_NE);
pragma Inline (Big_GE);
pragma Inline (Big_LE);
pragma Inline (Big_GT);
pragma Inline (Big_LT);
pragma Inline (Bignum_In_LLI_Range);
pragma Inline (To_Bignum);
pragma Inline (From_Bignum);
end System.Bignums; end System.Bignums;
------------------------------------------------------------------------------
-- --
-- GNAT COMPILER COMPONENTS --
-- --
-- S Y S T E M . G E N E R I C _ B I G N U M S --
-- --
-- S p e c --
-- --
-- Copyright (C) 2012-2019, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
-- ware Foundation; either version 3, or (at your option) any later ver- --
-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE. --
-- --
-- As a special exception under Section 7 of GPL version 3, you are granted --
-- additional permissions described in the GCC Runtime Library Exception, --
-- version 3.1, as published by the Free Software Foundation. --
-- --
-- You should have received a copy of the GNU General Public License and --
-- a copy of the GCC Runtime Library Exception along with this program; --
-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
-- <http://www.gnu.org/licenses/>. --
-- --
-- GNAT was originally developed by the GNAT team at New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc. --
-- --
------------------------------------------------------------------------------
-- This package provides arbitrary precision signed integer arithmetic
-- and can be used either built into the compiler via System.Bignums or to
-- implement a default version of Ada.Numerics.Big_Numbers.Big_Integers.
-- If Use_Secondary_Stack is True then all Bignum values are allocated on the
-- secondary stack. If False, the heap is used and the caller is responsible
-- for memory management.
with Ada.Unchecked_Conversion;
with Interfaces;
generic
Use_Secondary_Stack : Boolean;
package System.Generic_Bignums is
pragma Preelaborate;
pragma Assert (Long_Long_Integer'Size = 64);
-- This package assumes that Long_Long_Integer size is 64 bit (i.e. that it
-- has a range of -2**63 to 2**63-1). The front end ensures that the mode
-- ELIMINATED is not allowed for overflow checking if this is not the case.
subtype Length is Natural range 0 .. 2 ** 23 - 1;
-- Represent number of words in Digit_Vector
Base : constant := 2 ** 32;
-- Digit vectors use this base
subtype SD is Interfaces.Unsigned_32;
-- Single length digit
type Digit_Vector is array (Length range <>) of SD;
-- Represent digits of a number (most significant digit first)
type Bignum_Data (Len : Length) is record
Neg : Boolean;
-- Set if value is negative, never set for zero
D : Digit_Vector (1 .. Len);
-- Digits of number, most significant first, represented in base
-- 2**Base. No leading zeroes are stored, and the value of zero is
-- represented using an empty vector for D.
end record;
for Bignum_Data use record
Len at 0 range 0 .. 23;
Neg at 3 range 0 .. 7;
end record;
type Bignum is access all Bignum_Data;
-- This is the type that is used externally. Possibly this could be a
-- private type, but we leave the structure exposed for now. For one
-- thing it helps with debugging. Note that this package never shares
-- an allocated Bignum value, so for example for X + 0, a copy of X is
-- returned, not X itself.
function To_Bignum is new Ada.Unchecked_Conversion (System.Address, Bignum);
function To_Address is new
Ada.Unchecked_Conversion (Bignum, System.Address);
-- Note: none of the subprograms in this package modify the Bignum_Data
-- records referenced by Bignum arguments of mode IN.
function Big_Add (X, Y : Bignum) return Bignum; -- "+"
function Big_Sub (X, Y : Bignum) return Bignum; -- "-"
function Big_Mul (X, Y : Bignum) return Bignum; -- "*"
function Big_Div (X, Y : Bignum) return Bignum; -- "/"
function Big_Exp (X, Y : Bignum) return Bignum; -- "**"
function Big_Mod (X, Y : Bignum) return Bignum; -- "mod"
function Big_Rem (X, Y : Bignum) return Bignum; -- "rem"
function Big_Neg (X : Bignum) return Bignum; -- "-"
function Big_Abs (X : Bignum) return Bignum; -- "abs"
-- Perform indicated arithmetic operation on bignum values. No exception
-- raised except for Div/Mod/Rem by 0 which raises Constraint_Error with
-- an appropriate message.
function Big_EQ (X, Y : Bignum) return Boolean; -- "="
function Big_NE (X, Y : Bignum) return Boolean; -- "/="
function Big_GE (X, Y : Bignum) return Boolean; -- ">="
function Big_LE (X, Y : Bignum) return Boolean; -- "<="
function Big_GT (X, Y : Bignum) return Boolean; -- ">"
function Big_LT (X, Y : Bignum) return Boolean; -- "<"
-- Perform indicated comparison on bignums, returning result as Boolean.
-- No exception raised for any input arguments.
function Bignum_In_LLI_Range (X : Bignum) return Boolean;
-- Returns True if the Bignum value is in the range of Long_Long_Integer,
-- so that a call to From_Bignum is guaranteed not to raise an exception.
function To_Bignum (X : Long_Long_Integer) return Bignum;
-- Convert Long_Long_Integer to Bignum. No exception can be raised for any
-- input argument.
function To_Bignum (X : Interfaces.Unsigned_64) return Bignum;
-- Convert Unsigned_64 to Bignum. No exception can be raised for any
-- input argument.
function From_Bignum (X : Bignum) return Long_Long_Integer;
-- Convert Bignum to Long_Long_Integer. Constraint_Error raised with
-- appropriate message if value is out of range of Long_Long_Integer.
function Is_Zero (X : Bignum) return Boolean;
-- Return True if X = 0
end System.Generic_Bignums;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment