Search code examples
c++mathlinear-algebracomputer-algebra-systemsfinite-field

Exact Large Finite Field Linear Algebra Library (e.g. GF(2^128) / GF(2^256) )


General

I'm looking for a library that is able to do exact calculations on large finite fields such as GF(2128)/𝔽2128 and GF(2256)/𝔽2256. I listed the features that I need and the features that would be cool below. Obviously, the library should be as fast as possible :-). Ah, since I'm no C++ master (and probably most of the libraries are C++), sample code of say generate a random element/a constant and multiply it to it's multiplicative inverse

Must-Have Features

  • Addition of field elements
  • Multiplication of field element
  • Find the multiplicative inverse of a field element

Nice to Have Features

  • Vector/Matrix support
  • Random Element support

Libraries I already looked at that will probably not work

  • FFLAS/FFPACK, seems not to work with such large finite fields
  • Givaro, seems not to work on such large finite fields

Libraries I already looked at that could work (but I was unable to use)

  • NTL, I was not able to invert an element, but it should really work since SAGE seems to use this library when defining GF(2^256) and there an element can be inverted using x^(-1)
  • PARI/GP, I was not able to find everything I need in the documentation, but the SAGE documentation kind of says that it should work

Other notes

  • I'm writing a Haskell program and will interface that library later, so easier Haskell interfacing is better :-)

Solution

  • The NTL library seems to work, using this (sorry I'm quite unable to program in C++) code

    #include <NTL/GF2E.h>
    #include <NTL/GF2EX.h>
    #include <NTL/GF2X.h>
    #include <NTL/GF2XFactoring.h>
    
    NTL_CLIENT
    
    int main()
    {
        GF2X P = BuildIrred_GF2X(256);
        GF2E::init(P);
    
        GF2E zero = GF2E::zero();
        GF2E one;
        GF2E r = random_GF2E();
        GF2E r2 = random_GF2E();
        conv(one, 1L);
        cout << "Cardinality: " << GF2E::cardinality() << endl;
        cout << "ZERO: " << zero << " --> " << IsZero(zero) << endl;
        cout << "ONE:  " << one  << " --> " << IsOne(one)   << endl;
        cout << "1/r:  " << 1/r  << ", r * (1/r): " << (r * (1/r)) << endl;
        cout << "1/r2:  " << 1/r2  << ", r2 * (1/r2): " << (r2 * (1/r2)) << endl;
    }
    

    it seems to work, proof (output of this program):

    Cardinality: 115792089237316195423570985008687907853269984665640564039457584007913129639936
    ZERO: [] --> 1
    ONE:  [1] --> 1
    1/r:  [0 1 0 1 1 0 1 1 1 0 1 1 1 0 0 1 1 0 1 1 1 0 1 1 0 0 0 0 0 1 0 1 0 1 1 0 1 1 0 0 0 0 0 0 1 1 1 0 1 1 1 0 1 0 1 0 0 0 1 1 1 0 1 1 1 1 0 1 0 1 0 1 1 0 1 1 1 0 0 0 1 0 0 1 0 1 1 1 0 1 1 0 1 1 0 0 0 0 0 1 1 0 1 0 1 0 0 0 0 0 1 0 0 1 1 0 0 1 0 0 1 0 1 1 1 1 0 0 1 1 0 1 0 1 1 1 1 1 1 0 1 1 0 0 0 0 0 1 1 0 1 0 0 1 1 1 0 1 1 1 1 1 0 1 0 1 0 0 0 1 1 0 0 1 1 0 0 1 0 1 1 1 0 1 1 1 1 1 0 1 1 0 1 1 1 1 0 1 0 0 0 0 1 1 1 0 1 1 1 0 1 1 1 1 1 1 1 1 0 1 0 1 0 0 1 1 0 1 1 0 1 1 1 1 1 0 0 1 1 0 1 0 1 0 0 0 0 1 1 0 0 1 1 1 0 1], r * (1/r): [1]
    1/r2:  [1 0 1 1 0 0 0 0 1 0 1 0 0 0 1 0 0 0 1 1 0 0 1 0 1 0 0 0 1 1 1 0 0 0 1 1 1 1 1 0 1 0 1 1 0 0 1 1 1 0 1 0 1 0 0 1 0 0 0 0 1 1 1 0 0 0 1 1 1 1 1 0 0 1 0 0 0 1 1 0 1 0 1 1 1 0 0 1 0 1 0 1 0 0 1 0 0 0 1 0 0 1 1 1 1 1 0 0 0 0 1 1 1 0 1 0 1 0 1 0 0 0 1 0 1 0 1 1 0 0 0 1 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 1 1 1 0 1 1 0 0 0 0 1 1 0 1 1 1 0 1 0 0 0 0 0 1 1 0 1 1 1 0 0 0 0 1 1 0 1 0 0 0 0 1 0 0 0 0 1 1 1 1 1 0 1 0 1 1 0 1 0 1 0 1 1 1 1 0 0 1 1 0 1 1 1 1 1 0 1 1 1 0 1 0 0 0 0 1 0 1 1 0 0 0 1 1 0 0 1 1 0 1 0 0 1 0 1 0 0 1 1], r2 * (1/r2): [1]
    

    Even inverting seems to work (scroll as right as possible in the output sample above) :-)