1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
GMPAda makes the GNU MultiPrecision library usable with the Ada
language.
Extensive documentation about the GMP original C library can be found
at http://gmplib.org/manual.
The latest source is available on
http://mtn-host.prjek.net/projects/libgmpada.
--------------------- Usage --------------------------
The demo subdirectory contains a test program. It is first intended as
a test for the library, almost without user-readable output. Though,
reading the source file "demo.adb" and the project "demo.gpr" will
give you an idea of how this library works. If the library is well
installed, "gnatmake -Pdemo.gpr" or "gprbuild demo.gpr" should compile it.
The upstream source provides a project file as a demonstration for those
who need to recompile the binding. The most obvious motivation to do so is
the need of performance: inlining optimizations will be efficient for short
wrappers like the ones in this library.
-------------------- Status ---------------------
Big_Integer and Big_Float operations are available and coherent.
Big_Rationals operations are usable. A Mpfr binding has started but is
still far from complete.
--------------- What is GMPAda? ---------------
The GNU_Multiple_Precision package provides the type Big_Integer
allowing integer computations without other space limitation than your
computer's memory.
Initialization, assignement and finalization are provided by a
controlled type. Equivalent of operations and attributes that you
might expect when used to Ada.Standard.Integer and Ada.Standard.Float
are provided.
One day, there would be Big_Rationals and Big_Complexes childs, but
for the moment the former learns philosophy while the later is in
therapy.
The child packages named Random_Numbers, Text_IO, Wide_Text_IO,
Wide_Wide_Text_IO provide the services documented in the Ada Reference
Manual for Ada child packages with the same names (actually, there
are some subtle differences, see Random_Numbers and Generic_Text_IO
specifications).
The Text_IO packages are generic instantiations. This allows each
user to set its own Default_Width and Default_Base by making its own
instantiation, as with Ada.Text_IO subpackages, if it is ever
necessary. There are (better) technical reasons too, see the
Implementation below.
----------- Important performance note -----------------
You should see these Ada types as limited if you seek performance.
Each assignement allocates then frees space for temporary objects,
eating much execution time.
Quickly said: if you mind performance, write
Set (A, B); instead of A := B;
Add (A, A, C); instead of A := A + C;
Then, why allow assignment, and equivalent of Ada.Standard attributes
and primitive operations? For users who need readable code and do not
care for execution speed. I originally needed long integers and a
readable language like Ada for educational purpose.
-------------- Data exchange with C streams ---------------
The Ada Stream attributes of Big_Integer respect the raw format used
by the library for the C mpz_t type.
Other types than Big_Integer provide correct Stream attributes, but
without C raw IO equivalents. In case you write your own procedures:
- for Big_Rational, this library writes the numerator then the
denominator (as Big_Integers=mpz_t)
- for Big_Float, it writes the precision (as an
unsigned_long=unsigned long int), then exponent-precision (as a
long=signed long int), then the item multiplyed by
2**(precision-exponent) (as a Big_Integer=mpz_t).
You may separate Numerator and Denominator, Fraction and Exponent
following your specific needs.
--------- Implementation -----------------
The GMP hierarchy is for internal purpose. The GNU_Multiple_Precision
hierarchy exports controlled types.
The C program "generate_constants" generates the Ada GMP.Constants
package, which contains Ada static constants for C macros and type
sizes, adapted to the current implementation. It displays an error
message if a gmp.h upgrade has modified the internal structure of
mpz_t, which is needed at this time for raw Input/Ouput compatible
with C.
The C library "gmp_macros" expands gmp C preprocessor macros into C
functions, so that they can be imported to Ada and linked. Rewriting
them is an easy temptation, but the former solution is portable and
GMP-version independant. It avoids depending on the internal
structure of mp[tqf]_t C types. There is no significative efficiency
counterpart since the imported procedures can be explicitely inlined
if profiling shows it is necessary (and if the compiler does not do it
during optimization).
The Ada package "GMP.Binding" imports the C types and functions from
gmp.h. It is only intended as a step to build a controlled
abstraction. I cannot see who would benefit from a thin binding like
that anyway. The visible part should only contain informations
gathered in the normative part of the documentation. With GNAT, an
array is passed by reference. This is compatible with a C one-element
array like mpz_t. I hope this won't chage for a while, since "access"
mode instead of "in, out, in out" modes would be much less
readable. Types like mpz_t should be limited, but this would make
another dereference mandatory in the controlled abstraction (a
significative performance hit), or make it limited too (many users
would miss slow but readable "+" overloading), and I think both prices
are too high.
The private part and the body may vary with the gmp version. Namely,
they depend on mpz_t internal structure (for raw input) and GMP raw IO
format (for raw input and output). I cannot see how to rewrite the
Read procedure using only the gmp.h procedures without a huge
performance hit. That would remove the dependance on the mpz_t
internal structure. The binding would be simplier and depend less on
the gmp version (raw IO changes are rare, since C users do not like
them either). Help appreciated.
Types visible by Ada users are controlled, so that initialization and
finalization are handled automatically. Text Input-Output is rewritten
from scratch, with generic packages avoiding code repetition for wide
versions. It allows giving the IO format described by the ARM. Only
change with ARM, each expected out mode parameter is made an "in out"
mode parameter to avoid unuseful Finalization-Initialization.
All types are declared in the same parent package, so that conversions
of private extensions are possible. It avoids that the conversion
programs depend on two tagged type and try to dispatch twice, too...
Suggestions welcome.
------------ Credits ------------
Thanks to Michael Roe and Gisle Saelensmind for providing their work
on the net. This work is inspired by theirs, to say the least.
Thanks to Jerome Delcourt for assembling documentation and links
concerning big numbers in Ada.
Thanks to Ludovic Brenta for providing a readable example of project
file in its debian packaging of gtkada.
Thanks to Vincent Diemunsch for helping to merge his similar work and
correcting bugs.
|