Sign in Join
Wiki copytemporary

gmp: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
1-FPC 2.4.0 includes an initial version of a Free Pascal interface for the GNU Multiple Precision Arithmetic Library in packages/gmp.
1+An editor has declared this article to be a stub, meaning that it needs more information. Can you help out and [[/wiki.freepascal.org/index.php?title=gmp&action=edit|add some]]? If you have some useful information, you can [[Help:Editing|help]] the Free Pascal Wiki by clicking on the edit box on the left and expanding this page.
22
3-To use the bindings in your projects (and be able to build them) you have to:
3+FPC 2.4.0 includes an initial version of a Free Pascal interface for the GNU Multiple Precision Arithmetic Library in packages/gmp.
44
5-- Include gmp in the uses clause of a program/unit source from which you will use the GMP types/functions.
6-- Have the gmp library installed on your system
7- - Most, if not all, *nix systems have GMP (libgmp) installed by default but it is still necessary to have the dev package (libgmpX-dev) installed also (needed in the link stage). This package is not included by default everywhere (e.g. Ubuntu).
8- - On Windows, you can get the [mingw-dynamic package](http://cs.nyu.edu/exact/core/gmp/) and rename it to gmp.dll.
9- - On Mac OS X, gmp can be installed as documented on gmplib.org or using the package managers MacPorts or Fink.
10-- Have the necessary knowledge of the [GMP documentation](http://gmplib.org/#DOC).
5+To use the bindings in your projects (and be able to build them) you have to:
116
12-Some gmp unit tests and usage examples for both the standard and extensions bindings can be found at the INSTALLATION_PREFIX/share/doc/fpc-x.y.z/gmp/examples folder.
7+ * Include gmp in the uses clause of a program/unit source from which you will use the GMP types/functions.
8+ * Have the gmp library installed on your system
9+ * Most, if not all, *nix systems have GMP (libgmp) installed by default but it is still necessary to have the dev package (libgmpX-dev) installed also (needed in the link stage). This package is not included by default everywhere (e.g. Ubuntu).
10+ * On Windows, you can get the [mingw-dynamic package](<http://cs.nyu.edu/exact/core/gmp/>) and rename it to gmp.dll.
11+ * On Mac OS X, gmp can be installed as documented on gmplib.org or using the package managers MacPorts or Fink.
12+ * Have the necessary knowledge of the [GMP documentation](<http://gmplib.org/#DOC>).
1313
14+Some gmp unit tests and usage examples for both the standard and extensions bindings can be found at the INSTALLATION_PREFIX/share/doc/fpc-x.y.z/gmp/examples folder.
15+
1416# Standard bindings & types
1517
16-The standard bindings cover almost all of the GMP types and functions as they appear in the GMP documentation. The few exceptions are listed near the top of the gmp unit.
18+The standard bindings cover almost all of the GMP types and functions as they appear in the GMP documentation. The few exceptions are listed near the top of the gmp unit.
1719
1820## Naming conventions
1921
20-The interfaced names of the FPC functions, types and parameters are identical to those in the GMP documentation with the minor deviations of the added underscore suffix to some of the (possibly) conflicting identifiers, e.g. the original documentation C function "void mpz_init (mpz_t integer)" is declared here as:
21-
22-``` pascal
22+The interfaced names of the FPC functions, types and parameters are identical to those in the GMP documentation with the minor deviations of the added underscore suffix to some of the (possibly) conflicting identifiers, e.g. the original documentation C function "void mpz_init (mpz_t integer)" is declared here as:
23+```
2324{ Initialise integer, and set its value to 0 }
24-procedure mpz_init(out integer_: mpz_t); cdecl; external LIB name '__gmpz_init';
25+ procedure mpz_init(out integer_: mpz_t); cdecl; external LIB name '__gmpz_init';
2526```
2627
2728## Memory issues
2829
29-With the standard bindings you have direct access to the full power of the GMP without any overhead. On the same time, to avoid heap corruption and/or memory leaks, the programmer is the only one responsible for the proper initialisation of GMP variables (mpz_t, mpf_t, ... types) before passing them to functions that expect them being already in such state. The same applies to finalisation of (properly invoking *_clear on) those variables.
30-
31-Take for granted to run into heap problems and/or program crashes by doing e.g.:
30+With the standard bindings you have direct access to the full power of the GMP without any overhead. On the same time, to avoid heap corruption and/or memory leaks, the programmer is the only one responsible for the proper initialisation of GMP variables (mpz_t, mpf_t, ... types) before passing them to functions that expect them being already in such state. The same applies to finalisation of (properly invoking *_clear on) those variables.
3231
33-- Passing an uninitiated GMP variable to any GMP functions other than *_init.
34-- Initialising an already initialised GMP variable without previously clearing it.
35-- Clearing an already cleared one. This can easily happen e.g. on a copy of a GMP variable, created by a simple assignment. GMP variables are true value types (declared as record types in gmp) and invoking a *_clear on any of the (assigned) copies creates dangling pointers in all of the other copies.
32+Take for granted to run into heap problems and/or program crashes by doing e.g.:
3633
37-The last issue generalises to the invocation of any function that modifies the address/size of memory owned by a GMP variable. The net result is thus to avoid existence of any memory image copy (as is the case for assignment of record variables) of any GMP variable. Instead of an assignment to another variable (equals shallow copying), which will be rightfully accepted by the compiler without any warning, use GMP functions like in the following example:
34+ * Passing an uninitiated GMP variable to any GMP functions other than *_init.
35+ * Initialising an already initialised GMP variable without previously clearing it.
36+ * Clearing an already cleared one. This can easily happen e.g. on a copy of a GMP variable, created by a simple assignment. GMP variables are true value types (declared as record types in gmp) and invoking a *_clear on any of the (assigned) copies creates dangling pointers in all of the other copies.
3837
39-``` pascal
38+The last issue generalises to the invocation of any function that modifies the address/size of memory owned by a GMP variable. The net result is thus to avoid existence of any memory image copy (as is the case for assignment of record variables) of any GMP variable. Instead of an assignment to another variable (equals shallow copying), which will be rightfully accepted by the compiler without any warning, use GMP functions like in the following example:
39+```
4040procedure DoSomething;
41-var A, B: mpz_t; // multi precision (big) integers
42-begin
43- mpz_init_set_si(A, 123); // This allocates mem owned by A and initialises it to the given value
44- B := A; // Wrong: B renders invalid as soon as the mem adr/size owned by A is altered in any way
45- mpz_init_set(B, A); // Now the numeric value of B is equal to that of A. Only this is the safe way of doing it.
46- try
47- // Number crunching goes here
48- finally
49- mpz_clear(A); // Release the mem owned by A and B
50- mpz_clear(B);
51- end;
52-end;
41+ var A, B: mpz_t; // multi precision (big) integers
42+ begin
43+ mpz_init_set_si(A, 123); // This allocates mem owned by A and initialises it to the given value
44+ B := A; // Wrong: B renders invalid as soon as the mem adr/size owned by A is altered in any way
45+ mpz_init_set(B, A); // Now the numeric value of B is equal to that of A. Only this is the safe way of doing it.
46+ try
47+ // Number crunching goes here
48+ finally
49+ mpz_clear(A); // Release the mem owned by A and B
50+ mpz_clear(B);
51+ end;
52+ end;
5353```
5454
55-As the interns of all GMP variables have a private pointer to a memory block allocated for that variable instance (effectively owned by the instance), the correct handling of them has the same methodology as the proper usage of New/Dispose or GetMem/FreeMem pairs, not limited to but including also the necessity of using try/finally constructs where an exception can occur between a *_init and the corresponding *_clear of any GMP variable as shown in the snippet above.
55+As the interns of all GMP variables have a private pointer to a memory block allocated for that variable instance (effectively owned by the instance), the correct handling of them has the same methodology as the proper usage of New/Dispose or GetMem/FreeMem pairs, not limited to but including also the necessity of using try/finally constructs where an exception can occur between a *_init and the corresponding *_clear of any GMP variable as shown in the snippet above.
5656
5757## String formatting & I/O functions
5858
59-All these functions (mp_asprintf, mp_printf, mp_snprintf, mp_sprintf, mp_scanf, mp_sscanf) have two versions with different invocation syntax:
60-
61-``` pascal
59+All these functions (mp_asprintf, mp_printf, mp_snprintf, mp_sprintf, mp_scanf, mp_sscanf) have two versions with different invocation syntax:
60+```
6261// Declarations in gmp.pas
63-{ V1: Print to the standard output stdout. Return the number of characters written, or −1 if an error occurred. }
64-function mp_printf(fmt: pchar): longint; cdecl; varargs; external LIB name '__gmp_printf';
65-{ V2: Print to the standard output stdout. Return the number of characters written, or −1 if an error occurred. }
66-function mp_printf(fmt: pchar; args: array of const): longint; cdecl; external LIB name '__gmp_printf';
67-
68-// Can be used as
69-var
70- f: mpf_t;
71- n, bits, digits: integer;
72-begin
73- mp_printf('Sqrt(%d) to %d digits (%d bits) = %.*Fg'#10, n, digits, bits, digits, @f); // V1: from printf_example.pas
74- mp_printf('Sqrt(%d) to %d digits (%d bits) = %.*Fg'#10, [n, digits, bits, digits, @f]); // V2: this produces the same behaviour as the above line
75-end;
62+ { V1: Print to the standard output stdout. Return the number of characters written, or −1 if an error occurred. }
63+ function mp_printf(fmt: pchar): longint; cdecl; varargs; external LIB name '__gmp_printf';
64+ { V2: Print to the standard output stdout. Return the number of characters written, or −1 if an error occurred. }
65+ function mp_printf(fmt: pchar; args: array of const): longint; cdecl; external LIB name '__gmp_printf';
66+
67+ // Can be used as
68+ var
69+ f: mpf_t;
70+ n, bits, digits: integer;
71+ begin
72+ mp_printf('Sqrt(%d) to %d digits (%d bits) = %.*Fg'#10, n, digits, bits, digits, @f); // V1: from printf_example.pas
73+ mp_printf('Sqrt(%d) to %d digits (%d bits) = %.*Fg'#10, [n, digits, bits, digits, @f]); // V2: this produces the same behaviour as the above line
74+ end;
7675```
7776
78-- It is obligatory to pass pointers to GMP variables to these functions, so if a GMP variable is declared as in the snippet above, you must use the @ operator. The compiler has no way to check this, so one has to be careful here.
79-- The allocated memory for the C string (PChar) returned by mp_asprintf is owned by the invoker and is not handled automatically as an Object Pascal string.
80-- At least on Linux the mp_printf requires a LF character to actually show (flush) the stdout.
77+ * It is obligatory to pass **pointers** to GMP variables to these functions, so if a GMP variable is declared as in the snippet above, you must use the @ operator. The compiler has no way to check this, so one has to be careful here.
78+ * The allocated memory for the C string (PChar) returned by mp_asprintf is owned by the invoker and is not handled automatically as an Object Pascal string.
79+ * At least on Linux the mp_printf requires a LF character to actually show (flush) the stdout.
8180
82-For further details about the formatting functions and format strings please consult the GMP manual.
81+For further details about the formatting functions and format strings please consult the GMP manual.
8382
8483### Extensions layer
8584
86-When using the [[gmp|extensions layer]] the above functions can be used, however a pointer to the underlying variable must be obtained using the **ptr** member function. Alternatively the types can be converted to AnsiString.
87-
88-``` pascal
85+When using the [[gmp|extensions layer]] the above functions can be used, however a pointer to the underlying variable must be obtained using the **ptr** member function. Alternatively the types can be converted to AnsiString.
86+```
8987var
90- SomeNumber: MPInteger;
91-begin
92- { These two produce the same output }
93- mp_printf('The value of ''SomeNumber'' is: %Zd'#10, SomeNumber.ptr);
94- WriteLn('The value of ''SomeNumber'' is: ', AnsiString(SomeNumber));
95-end;
88+ SomeNumber: MPInteger;
89+ begin
90+ { These two produce the same output }
91+ mp_printf('The value of ''SomeNumber'' is: %Zd'#10, SomeNumber.ptr);
92+ WriteLn('The value of ''SomeNumber'' is: ', AnsiString(SomeNumber));
93+ end;
9694```
9795
9896# Extensions bindings & types
9997
100-The possible issues with memory management as discussed in the standard bindings section, are addressed by an extensions layer providing automated memory management for the GMP variables in the style of the Object Pascal String type. The similar approach includes also a comparable overhead both in runtime and size of the generated code as it is with (memory automated) string variables - reference counting, copy on write and protected finalisation blocks. But all of this is now handled by the compiler itself (and partially in the gmp unit) without requesting any additional effort from the programmer.
98+The possible issues with memory management as discussed in the standard bindings section, are addressed by an extensions layer providing automated memory management for the GMP variables in the style of the Object Pascal String type. The similar approach includes also a comparable overhead both in runtime and size of the generated code as it is with (memory automated) string variables - reference counting, copy on write and protected finalisation blocks. But all of this is now handled by the compiler itself (and partially in the gmp unit) without requesting any additional effort from the programmer.
10199
102100## Naming conventions
103101
104-The standard types and their extensions counterparts:
102+The standard types and their extensions counterparts:
105103
106-| std | ext |
107-|-------------|-------------|
108-| mpz_t | MPInteger |
109-| mpq_t | MPRational |
110-| mpf_t | MPFloat |
104+| std | ext |
105+|---|---|
106+| mpz_t | MPInteger |
107+| mpq_t | MPRational |
108+| mpf_t | MPFloat |
111109| randstate_t | MPRandState |
112-| | |
113110
114-Extensions counterparts of the standard bindings functions are named sans the "mp" or "mp_" prefix, e.g.:
111+Extensions counterparts of the standard bindings functions are named sans the "mp" or "mp_" prefix, e.g.:
115112
116-| std | ext |
117-|---------------------|------------------|
118-| mpz_add | z_add |
119-| mpq_cmp | q_cmp |
120-| mpf_sub | f_sub |
113+| std | ext |
114+|---|---|
115+| mpz_add | z_add |
116+| mpq_cmp | q_cmp |
117+| mpf_sub | f_sub |
121118| mp_randinit_default | randinit_default |
122-| | |
123119
124-Most of the extensions functions, except for the extensions parameter/result types, are fully equal to the standard ones. There are some minor deviations, e.g. few of the standard bindings functions returning a zero/non-zero indicator value have the usual and expected Boolean type instead in the extensions version.
125-
126-``` pascal
127- { std: Return non-zero if n is exactly divisible by d }
128- function mpz_divisible_p(var n, d: mpz_t): longint; cdecl; external LIB name '__gmpz_divisible_p';
129- { ext: Return true if n is exactly divisible by d }
130- function z_divisible_p(var n, d: MPInteger): boolean;
120+Most of the extensions functions, except for the extensions parameter/result types, are fully equal to the standard ones. There are some minor deviations, e.g. few of the standard bindings functions returning a zero/non-zero indicator value have the usual and expected Boolean type instead in the extensions version.
131121```
132-
133-Some of the standard bindings numeric procedures are here available as an overloaded function to allow for - among other things - a choice of style, e.g.:
122+{ std: Return non-zero if n is exactly divisible by d }
123+ function mpz_divisible_p(var n, d: mpz_t): longint; cdecl; external LIB name '__gmpz_divisible_p';
124+ { ext: Return true if n is exactly divisible by d }
125+ function z_divisible_p(var n, d: MPInteger): boolean;
126+```
134127
135-``` pascal
136- mpz_add(A, B, C); // three ops std procedure
137- z_add(D, E, F); // dtto in ext layer
138- D := z_add(E, F); // the functional, two ops overloaded alternative of the above line
128+Some of the standard bindings numeric procedures are here available as an overloaded function to allow for - among other things - a choice of style, e.g.:
139129```
130+mpz_add(A, B, C); // three ops std procedure
131+ z_add(D, E, F); // dtto in ext layer
132+ D := z_add(E, F); // the functional, two ops overloaded alternative of the above line
133+```
140134
141135## Memory issues
142136
143137### Good news
144138
145-In common (presumably most) situations you can now just forget the underlying memory handling. The equivalent of the DoSomething snippet (without the assignment operator, which is to be discussed in a later section) using the extensions layer becomes:
146-
147-``` pascal
139+In common (presumably most) situations you can now just forget the underlying memory handling. The equivalent of the DoSomething snippet (without the assignment operator, which is to be discussed in a later section) using the extensions layer becomes:
140+```
148141procedure DoSomethingExt;
149-var A, B: MPInteger; // multi precision (big) integers
150-begin
151- z_init_set_si(A, 123); // This allocates mem owned by A and initialises it to the given value
152- z_init_set(B, A); // Now the numeric value of B is equal to that of A.
153- // Number crunching goes here
154-end;
142+ var A, B: MPInteger; // multi precision (big) integers
143+ begin
144+ z_init_set_si(A, 123); // This allocates mem owned by A and initialises it to the given value
145+ z_init_set(B, A); // Now the numeric value of B is equal to that of A.
146+ // Number crunching goes here
147+ end;
155148```
156149
157-Still you get exactly the same functionality as in the former case. That includes proper release of any memory owned by A and B even in the case of an exception generated in the "number crunching" section.
150+Still you get exactly the same functionality as in the former case. That includes proper release of any memory owned by A and B even in the case of an exception generated in the "number crunching" section.
158151
159152### Bad news
160153
161-The similarity with the string type includes the fact, that with the power of the Free Pascal language, it is anyway still possible to break the automatic memory management when certain conditions are met. Don't expect this to happen in math abstraction implementation code, but it can and without taking caution will occur on extensions numeric types I/O and also by improperly mixing the standard and extensions bindings, which is on the other side perfectly possible when done correctly.
154+The similarity with the string type includes the fact, that with the power of the Free Pascal language, it is anyway still possible to break the automatic memory management when certain conditions are met. Don't expect this to happen in math abstraction implementation code, but it can and without taking caution will occur on extensions numeric types I/O and also by improperly mixing the standard and extensions bindings, which is on the other side perfectly possible when done correctly.
162155
163-Things not to do or which are to be done in a specific way include e.g.: TODO
156+Things not to do or which are to be done in a specific way include e.g.: TODO
164157
165-# Operators
158+# Usage example
166159
167-TODO
160+For example, you use GMP on Windows 11, Lazarus 64 bits.
168161
162+ * Download the file gmp.pas from Free Pascal repository: <https://gitlab.com/freepascal.org/fpc/source/-/tree/main/packages/gmp/src>
163+ * Put the file in your project folder.
164+ * Download GMP library for Windows. For example from here: <https://github.com/gx/gmp/releases/tag/6.1.2-2> (only 6.1.2 version need MSVC 2019 redistribuable library).
165+ * From gmp-6.1.2-2-msvc2019-x64-Release.zip file extract libgmp-13.dll and rename it gmp.dll. Put it in your project folder or in the Windows System32 folder.
166+
167+Example to use GMP in Lazarus:
168+```
169+implementation
170+ uses math, gmp;
171+
172+ {$R *.lfm}
173+
174+ procedure TForm1.Button1Click(Sender: TObject);
175+ const
176+ N = 2;
177+ NBITS = 100;
178+ var
179+ f: mpfloat;
180+ bits, digits: integer;
181+ begin
182+ f_set_default_prec(NBITS);
183+ bits := f_get_default_prec;
184+ digits := floor(bits * LOG_10_2);
185+ f := f_sqrt_ui(N);
186+ Memo1.Append(format('Sqrt(%d) to %d digits (%d bits) = %s', [N, digits, bits, AnsiString(f)]));
187+ f := f ** 2;
188+ Memo1.Append(format('Squared back = %s', [AnsiString(f)]));
189+ f -= N;
190+ Memo1.Append(format('Minus %d = %s', [N, AnsiString(f)]));
191+ end;
192+```
193+
169194---
170-*From the Free Pascal wiki, page "gmp", as it stood on 2023-08-26 after a change by Alextpp, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
171-Category: Packages
172-Category: SciTech
195+*From the Free Pascal wiki, page "gmp", as the Internet Archive kept it on 2025-01-23, last changed on 2024-09-11. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history