Skip to content

GMP, MPFR, Flint & ARB 32-bit libraries build guide for Windows.

Notifications You must be signed in to change notification settings

ahrvoje/arb4win

Repository files navigation

GMP, MPFR, FLINT (& ARB) for Windows

Introduction

GMP, MPFR, FLINT and ARB are well known numerical libraries for large integer and arbitrary precision floating point arithmetic. A special emphasis is given to ball arithmetic library ARB by Frederik Johansson.

Arb was merged with Flint 3.0.0 and is not updated as a separate library since.

The repository doesn't contribute to the functionality. It's just a guide for building 32-bit & 64-bit static and shared libraries for Windows.

System and environment

Cygwin isn't used as it does not handle symbolic links used by some configure and make scripts as expected, and is generaly not intended to be used as a Windows build environment. MSYS2 solves the issues by implementing customized ln command which simply creates hard-copies and is designed as a build environment.

Workflow

  1. Install MSYS2, update it, and install base-devel, i686 & x86_64 mingw, yasm, m4, make, autotools
  2. Extract GMP, MPFR & FLINT src into MSYS2 /opt/src folder.
  3. Check and adapt GMP, MPFR & FLINT source variables in build_ARB.sh, e.g. GMP=$SOURCE/gmp-6.3.0.
  4. Finally, after starting MSYS2 mingw32.exe shell for 32-bit or mingw64.exe shell for 64-bit build, execute the following command and the build process will start:
$ ./build_ARB.sh

build_ARB.sh automatically executes the entire workflow with timing & log files written to MSYS2 /var/log folder.

Deliverables

Once built, i686 or x86_64 folder will be created in MSYS2 /opt folder based on the compiler bitness ($arch).

/opt/$arch/bin contains shared libraries (libgmp-10.dll, libgmpxx-4.dll, libmpfr-6.dll, libflint.dll). /opt/$arch/include contains header files needed to build against the libraries. /opt/$arch/lib contains static libraries for compiler and target defined in build_ARB.sh. /opt/$arch/shared contains some documentation automatically generated during the build process.

Demo

In this demo we evaluate one simple pandigital approximation of natural constant e correct to 46 decimal places. ARB also calculates accumulated numerical error so every result is printed as ball containing the result with absolute certainty. Internal computational precision is set to p=1000, way more than needed. Both static and dynamic lib versions are presented.

equation

Static

#include <stdlib.h>

#include "arb.h"
#include "flint.h"

int main()
{
    long p = 1000;
    long d = 53;
    arb_t a, b, x, t;

    printf("Computed with %d-bit Flint %s\n", sizeof(void*) * 8, FLINT_VERSION);
	
    arb_init(a);
    arb_init(b);
    arb_init(x);
    arb_init(t);

    // a = 1 + 2 ^ -76
    arb_set_str(a, "2", p);
    arb_set_str(t, "-76", p);
    arb_pow(a, a, t, p);
    arb_set_str(t, "1", p);
    arb_add(a, t, a, p);
    printf("a   = "); arb_printd(a, d); printf("\n");

    // b = 4 ^ 38 + 0.5
    arb_set_str(b, "0.5", p);
    arb_ui_pow_ui(t, 4, 38, p);
    arb_add(b, t, b, p);
    printf("b   = "); arb_printd(b, d); printf("\n");

    // x = a ^ b
    arb_pow(x, a, b, p);
    printf("x   = "); arb_printd(x, d); printf("\n");
    arb_const_e(t, p);
    printf("e   = "); arb_printd(t, d); printf("\n");
    arb_sub(t, x, t, p);
    printf("x-e = "); arb_printd(t, d); printf("\n");

    arb_clear(a);
    arb_clear(b);
    arb_clear(x);
    arb_clear(t);

    return EXIT_SUCCESS;
}

32-bit demo is compiled using build_arb_demo_32.sh or via the following command line in MSYS2 mingw32 environment.

>>> gcc -Ibuild/i686/include -Ibuild/i686/include/flint arb_demo.c -obuild/i686/bin/static_demo.exe -Lbuild/i686/lib -lflint -lmpfr -lgmp
>>> build/i686/bin/static_demo.exe
Computed with 32-bit Flint 3.2.0-dev
a   = 1.0000000000000000000000132348898008484427979425390731 +/- 0
b   = 75557863725914323419136.500000000000000000000000000000 +/- 0
x   = 2.7182818284590452353602874713526624977572470937396380 +/- 1.1407e-300
e   = 2.7182818284590452353602874713526624977572470936999596 +/- 3.7331e-301
x-e = 3.9678376581476207465438603498757884997818078351607135e-47 +/- 1.5140e-300

Shared (dynamic) for Windows

#include <windows.h>

#include "arb.h"
#include "flint.h"

int main()
{
    HINSTANCE hFlint = LoadLibrary(TEXT("libflint.dll"));

    if (! hFlint) {
        printf("Error loading libflint.dll\n");
        printf("Error code: %ld\n", GetLastError());
        printf("https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes\n");

        return EXIT_FAILURE;
    }

    printf("Computed with %d-bit Flint %s\n", sizeof(void*) * 8, FLINT_VERSION);

    typedef void(__cdecl *arb_add_t)      (arb_t, arb_t, arb_t, long);
    typedef void(__cdecl *arb_clear_t)    (arb_t);
    typedef void(__cdecl *arb_const_e_t)  (arb_t, long);
    typedef void(__cdecl *arb_init_t)     (arb_t);
    typedef void(__cdecl *arb_pow_t)      (arb_t, arb_t, arb_t, long);
    typedef void(__cdecl *arb_printd_t)   (arb_t, long);
    typedef void(__cdecl *arb_set_str_t)  (arb_t, const char*, long);
    typedef void(__cdecl *arb_sub_t)      (arb_t, arb_t, arb_t, long);
    typedef void(__cdecl *arb_ui_pow_ui_t)(arb_t, long, long, long);

    arb_add_t       arb_add_d       = (arb_add_t)      GetProcAddress(hFlint, "arb_add");
    arb_clear_t     arb_clear_d     = (arb_clear_t)    GetProcAddress(hFlint, "arb_clear");
    arb_const_e_t   arb_const_e_d   = (arb_const_e_t)  GetProcAddress(hFlint, "arb_const_e");
    arb_init_t      arb_init_d      = (arb_init_t)     GetProcAddress(hFlint, "arb_init");
    arb_pow_t       arb_pow_d       = (arb_pow_t)      GetProcAddress(hFlint, "arb_pow");
    arb_printd_t    arb_printd_d    = (arb_printd_t)   GetProcAddress(hFlint, "arb_printd");
    arb_set_str_t   arb_set_str_d   = (arb_set_str_t)  GetProcAddress(hFlint, "arb_set_str");
    arb_sub_t       arb_sub_d       = (arb_sub_t)      GetProcAddress(hFlint, "arb_sub");
    arb_ui_pow_ui_t arb_ui_pow_ui_d = (arb_ui_pow_ui_t)GetProcAddress(hFlint, "arb_ui_pow_ui");

    long p = 1000;
    long d = 53;
    arb_t a, b, x, t;

    arb_init_d(a);
    arb_init_d(b);
    arb_init_d(x);
    arb_init_d(t);

    // a = 1 + 2 ^ -76
    arb_set_str_d(a, "2", p);
    arb_set_str_d(t, "-76", p);
    arb_pow_d(a, a, t, p);
    arb_set_str_d(t, "1", p);
    arb_add_d(a, t, a, p);
    printf("a   = "); arb_printd_d(a, d); printf("\n");

    // b = 4 ^ 38 + 0.5
    arb_set_str_d(b, "0.5", p);
    arb_ui_pow_ui_d(t, 4, 38, p);
    arb_add_d(b, t, b, p);
    printf("b   = "); arb_printd_d(b, d); printf("\n");

    // x = a ^ b
    arb_pow_d(x, a, b, p);
    printf("x   = "); arb_printd_d(x, d); printf("\n");
    arb_const_e_d(t, p);
    printf("e   = "); arb_printd_d(t, d); printf("\n");
    arb_sub_d(t, x, t, p);
    printf("x-e = "); arb_printd_d(t, d); printf("\n");

    arb_clear_d(a);
    arb_clear_d(b);
    arb_clear_d(x);
    arb_clear_d(t);

    FreeLibrary(hFlint);

    return EXIT_SUCCESS;
}

32-bit DLL demo is compiled using build_arb_dll_demo_32.sh or via the following command line in MSYS2 mingw32 environment.

>>> gcc -Ibuild/i686/include -Ibuild/i686/include/flint arb_dll_demo.c -obuild/i686/bin/shared_demo.exe
>>> build/i686/bin/shared_demo.exe
Computed with 32-bit Flint 3.2.0-dev
a   = 1.0000000000000000000000132348898008484427979425390731 +/- 0
b   = 75557863725914323419136.500000000000000000000000000000 +/- 0
x   = 2.7182818284590452353602874713526624977572470937396380 +/- 1.1407e-300
e   = 2.7182818284590452353602874713526624977572470936999596 +/- 3.7331e-301
x-e = 3.9678376581476207465438603498757884997818078351607135e-47 +/- 1.5140e-300

About

GMP, MPFR, Flint & ARB 32-bit libraries build guide for Windows.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages