Coder Social home page Coder Social logo

gmp-d's Introduction

gmp-d

D-language high-level wrapper for GNU MP (GMP) library that aims to be mostly compatible with std.bigint.BigInt and @safe pure nothrow @nogc except when converting to string.

Basics

  • Integers (GMP's mpz_t) are wrapped in gmp.z.MpZ
  • Rationals (GMP's mpq_t) are wrapped in gmp.q.MpQ

along with most of their common operations implemented either as member functions, free functions or both.

Sample Usage

MpZ

import gmp.z;

@safe pure nothrow @nogc:

unittest
{
    alias Z = MpZ;
    assert(Z.mersennePrime(15) == 2^^15 - 1);
    const a = 42.Z;
    const b = a.dup; // explicit copying required
}

MpQ

import gmp.q;

@safe pure nothrow @nogc:

unittest
{
    alias Q = MpQ;

    Q x = Q(-4, 6);

    assert(x.numerator == -4);
    assert(x.denominator == 6);

    x.canonicalize();

    assert(x.numerator == -2);
    assert(x.denominator == 3);

    assert(inverse(x) == Q(-3, 2));

    assert(Q(1, 2) + Q(1, 3) == Q(5, 6));
}

Value passing

Value semantics with explicit copying and move

For MpZ, copy construction is disabled by default to prevent inadvertent copying. Instead use f(move(z)) or f(z.move) (from std.algorithm.mutation) to pass by move or f(z.dup) to pass by explicit copy (via MpZ's member function .dup).

Value semantics with copy-on-write a la Phobos’ std.bigint.BigInt

Use Z (CopyableMpZ), for a drop-in-replacement for Phobos’ std.bigint.BigInt. For reference see https://dlang.org/phobos/std_bigint.html#.BigInt.

Mappings to GNU MP C library

Implementation is optimized through

  • mapping of GMP's C macros into D inline functions that operate directly on the internal C-representations __mpz_struct and __mpq_struct,

  • passing of MpZ-typed parameters as auto ref const in combination with conditional compilation for r-value MpZ passed parameters via __traits(isRef). This enables clever reuse of mpz_t instances when passed to __gmpz-functions. For instance, x + 42.Z can be lowered to

__gmpz_add(rhs._ptr, this._ptr, rhs._ptr);
return move(rhs);

in

opBinary!"+"()(auto ref const MpZ rhs)

Compilation Performance

Compilation is fast; DMD compiles gmp-d in about 0.1 seconds on a modern machine.

Run-time Performance

Wrapper is as light-weight as possible; Some D-functions directly access the internal C-datastructure exposed by the structs and macros in the C-headers of GNU GMP.

Limitations

Note that D's __traits(isRef) currently cannot be used to distinguish l-value from r-value passing of this. This severly limits the possibilities of using C++-style expression templates to realize lazy evaluation in operator overloading. If this limitation were to be fixed (probably via some introspection mechanism other than the trait isRef or non-struct-member operator overloading), this library could implement lowering of expressions such

Z result = base^^exp % modulo

to the builtin

__gmpz_powm(result._ptr, base._ptr, expr._ptr, modulo._ptr)

See the unittests for MpzAddExpr, MpzMulExpr, etc for details on how this currently can be implemented and verified (in ccc-version) with free functions such add and sub.

Future

There are more mpz_t- and mpq_t-functions that should be wrapped but these are good start.

gmp-d's People

Contributors

basiliscos avatar luhrel avatar nordlow avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

gmp-d's Issues

Problem with disabled default construction in use with std.container

So I have the problem that I want to use RedBlackTree!MpZ or simply Array!MpZ with gmd-d.
I cannot instantiate Array!MpZ since gmp.z.MpZ is not copyable.

import gmp.z,std.container,std.stdio;
void main() {
    const a = 73.MpZ, b = 3.MpZ;
    writeln((a+b).toString); //to see if everything works fine
    Array!MpZ d = make!(Array!MpZ)(); d.insert(23.MpZ); //saidly does not work.
}

After enabling your enum useCopy = true; // disable copy construction for now on line 132 in z.d I can instantiate this array, however I directly get a malloc error as soon as I try to insert something:
moredtesting(88429,0x7ffff19fd3c0) malloc: *** error for object 0x7fc895403a30: pointer being freed was not allocated
(Also it seems MpQ doesn't even have the option of enabling useCopy)

Additionally another error seems to come up when instantiating a RedBlackTree:
RedBlackTree!MpZ rb = new RedBlackTree!MpZ(); rb.insert(3.MpZ);, since it requires an enabled default construction.
Again I can circumvent this by commenting //@disable this(); on line 76 in z.d.

I have the feeling that I'm not supposed to do these changes (I directly get malloc errors and am fairly new to D), so what do you recommend as a work around in order to use MpZ together with std.container?
Since it has to do with malloc I thought this might be due to the recent changes done there.

Speed Test gmp-d vs Bigint vs gmp vs rust-gmp ...

So far, this is all talk. We need numbers to show people why they should use gmp-d over the other options. Can we beat rust-gmp? How much overhead is added on top of optimal gmp C code? How fast is gmp-d against the major competitor, Bigint?

Compiling unittests on OSX

When compiling on OSX, the unittests are importing libs that don't exist:

dub build --build=unittest
Fetching gmp-d 0.0.3 (getting selected version)...
Performing "unittest" build using dmd for x86_64.
libgmp 1.0.0: target for configuration "library" is up to date.
gmp-d 0.0.3: building configuration "library"...
numfmtted ~master: building configuration "application"...
../../.dub/packages/gmp-d-0.0.3/gmp-d/src/gmp/q.d(646,12): Error: module dbgio is in file 'dbgio.d' which cannot be read

When removing that specific unittest - there's other errors:

dub build --build=unittest
Performing "unittest" build using dmd for x86_64.
libgmp 1.0.0: target for configuration "library" is up to date.
gmp-d 0.0.3: building configuration "library"...
numfmtted ~master: building configuration "application"...
Linking...
Undefined symbols for architecture x86_64:
  "free", referenced from:
      _D3gmp1z3MpZ6__ctorMFNaNbNcNiNexAyakZS3gmp1z3MpZ in libgmp-d.a(z_16_117.o)
      _D3gmp1z3MpZ10fromStringMFNaNbNcNiNjNexAyakZS3gmp1z3MpZ in libgmp-d.a(z_16_117.o)
     (maybe you meant: _D2rt4util9container5treap33__T5TreapTS2gc11gcinterface4RootZ5Treap8freeNodeFNbNiPS2rt4util9container5treap33__T5TreapTS2gc11gcinterface4RootZ5Treap4NodeZv, _D2gc4impl12conservative2gc15LargeObjectPool9freePagesMFNbmmZv , _D2gc4impl12conservative2gc14ConservativeGC163__T9runLockedS63_D2gc4impl12conservative2gc14ConservativeGC10freeNoSyncMFNbPvZvS37_D2gc4impl12conservative2gc8freeTimelS37_D2gc4impl12conservative2gc8numFreeslTPvZ9runLockedMFNbKPvZv , _D2gc4impl12conservative2gc14ConservativeGC4freeMFNbPvZv , _D2rt5minfo11ModuleGroup4freeMFZv , _D2rt7dwarfeh15ExceptionHeader4freeFPS2rt7dwarfeh15ExceptionHeaderZv , _D2gc4impl12conservative2gc14ConservativeGC10freeNoSyncMFNbPvZv , _D2gc4impl12conservative2gc3Gcx8log_freeMFNbPvZv , _D2rt4util9container5treap34__T5TreapTS2gc11gcinterface5RangeZ5Treap8freeNodeFNbNiPS2rt4util9container5treap34__T5TreapTS2gc11gcinterface5RangeZ5Treap4NodeZv , _D2gc4impl6manual2gc8ManualGC4freeMFNbPvZv , _D4core6memory2GC4freeFNaNbPvZv , _gc_free , _D2gc4impl12conservative2gc8freeTimel , _D2gc4impl12conservative2gc4Pool12freePageBitsMFNbmKxG4mZv )
  "malloc", referenced from:
      _D3gmp1z3MpZ19_allocStringzCopyOfMFNaNbNiNexAyaZPa in libgmp-d.a(z_16_117.o)
     (maybe you meant: _D2gc4impl12conservative2gc14ConservativeGC207__T9runLockedS83_D2gc4impl12conservative2gc14ConservativeGC13reallocNoSyncMFNbPvmKkKmxC8TypeInfoZPvS40_D2gc4impl12conservative2gc10mallocTimelS40_D2gc4impl12conservative2gc10numMallocslTPvTmTkTmTxC8TypeInfoZ9runLockedMFNbKPvKmKkKmKxC8TypeInfoZPv, _D2gc4impl12conservative2gc14ConservativeGC200__T9runLockedS79_D2gc4impl12conservative2gc14ConservativeGC12mallocNoSyncMFNbmkKmxC8TypeInfoZPvS40_D2gc4impl12conservative2gc10mallocTimelS40_D2gc4impl12conservative2gc10numMallocslTmTkTmTxC8TypeInfoZ9runLockedMFNbKmKkKmKxC8TypeInfoZPv , _D2gc4impl12conservative2gc14ConservativeGC6mallocMFNbmkxC8TypeInfoZPv , _D2gc4impl12conservative2gc10mallocTimel , _gc_malloc , _D4core6memory2GC6mallocFNaNbmkxC8TypeInfoZPv , _D2rt4util9container6common7xmallocFNbNimZPv , _D2gc4impl12conservative2gc3Gcx10log_mallocMFNbPvmZv , _D2gc4impl6manual2gc8ManualGC6mallocMFNbmkxC8TypeInfoZPv , _D2gc4impl12conservative2gc14ConservativeGC12mallocNoSyncMFNbmkKmxC8TypeInfoZPv )
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Error: linker exited with status 1
dmd failed with exit code 1.

Has this lib been tested on OSX at all?

When compiling in not-unittest mode, it all just works.

importC gain?

Could this project get gain from importC?
To have automatically all methods from GMP?

Compile errors

Hi, I have problem using this library on Ubuntu 16.04:

Fetching libgmp 1.0.0 (getting selected version)...
Fetching gmp-d 0.0.1 (getting selected version)...
Performing "debug" build using ldc2 for x86_64.
libgmp 1.0.0: building configuration "library"...
gmp-d 0.0.1: building configuration "library"...
../../.dub/packages/gmp-d-0.0.1/gmp-d/src/gmp.d(192,43): Error: no property '_ccc' for type 'MpZ'
../../.dub/packages/gmp-d-0.0.1/gmp-d/src/gmp.d(189,9): Error: function gmp.MpZ.dup no return exp; or assert(0); at end of function
memberFun:non-ref this
../../.dub/packages/gmp-d-0.0.1/gmp-d/src/gmp.d(1144,63): Error: undefined identifier '_ccc'
ldc2 failed with exit code 1.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.