mcl 1.0.0 → 1.0.1
raw patch · 4 files changed
+368/−3 lines, 4 files
Files
- cbits/include/hs_mcl_impl.hpp +259/−0
- cbits/include/hs_mcl_misc.hpp +102/−0
- cbits/mcl_fp254bnb.cpp +1/−1
- mcl.cabal +6/−2
+ cbits/include/hs_mcl_impl.hpp view
@@ -0,0 +1,259 @@+#ifndef HAVE_HS_MCL_IMPL+#define HAVE_HS_MCL_IMPL++#include "HsFFI.h"+#include "hs_mcl_misc.hpp"++namespace hs_mcl {+namespace field_impl {++template <typename FpT>+inline void hash_to(const char *s, const size_t s_length, FpT *result)+{+ mem_util::init(result);+ result->setMsg(s, s_length);+}++template <typename FpT>+inline void add(const FpT *a, const FpT *b, FpT *result)+{+ mem_util::init(result);+ FpT::add(*result, *a, *b);+}++template <typename FpT>+inline void subtract(const FpT *a, const FpT *b, FpT *result)+{+ mem_util::init(result);+ FpT::sub(*result, *a, *b);+}++template <typename FpT>+inline void multiply(const FpT *a, const FpT *b, FpT *result)+{+ mem_util::init(result);+ FpT::mul(*result, *a, *b);+}++template <typename FpT, typename FrT>+inline void pow_native(const int const_time, const FpT *a,+ const FrT *p, FpT *result)+{+ mem_util::init(result);+ if (const_time)+ FpT::powCT(*result, *a, *p);+ else+ FpT::pow(*result, *a, *p);+}++template <typename FpT>+inline void negate(const FpT *a, FpT *result)+{+ mem_util::init(result);+ FpT::neg(*result, *a);+}++template <typename FpT>+inline void invert(const FpT *a, FpT *result)+{+ mem_util::init(result);+ FpT::inv(*result, *a);+}++template <typename FpT>+inline int eq(const FpT *a, const FpT *b)+{+ return *a == *b;+}++template <typename FpT>+inline int is_zero(const FpT *a)+{+ return a->isZero();+}++template <typename FpT>+inline int sqrt(const FpT *a, FpT *result)+{+ mem_util::init(result);+ return FpT::squareRoot(*result, *a);+}++template <typename FpT>+inline void to_gmp_integer(const FpT *a, mp_limb_t *result,+ const size_t result_length_bytes)+{+ mcl::fp::Block bl;+ a->getBlock(bl);++ static_assert(sizeof(bl.v_[0]) == sizeof(mp_limb_t),+ "mcl::fp::Unit and mp_limb_t have different size");++ // Check that we have the exact amount of bytes needed.+ assert(result_length_bytes == sizeof(bl.v_[0]) * bl.n);++ std::copy(bl.v_, bl.v_ + bl.n, result);+}++template <typename FpT>+inline void from_gmp_integer(const mp_limb_t *scalar,+ const mp_size_t scalar_limbs,+ FpT *result)+{+ mem_util::init(result);+ // Throws if passed value bigger than modulus, we divide modulo in Haskell.+ result->setArray(scalar, scalar_limbs);+}++template <typename FpT>+inline void from_hsint(const HsInt scalar, FpT *result)+{+ mem_util::copy(result, scalar);+}++template <typename FpT, typename... Args>+inline void from_base(FpT *result, Args&&... args)+{+ mem_util::init(result);+ result->set(std::forward<Args>(args)...);+}++}++namespace group_impl {++template <typename GrT>+inline void zero(GrT *result)+{+ mem_util::init(result);+ result->clear();+}++template <typename FpT, typename GrT>+inline int construct(const FpT *x, const FpT *y, GrT *result)+{+ mem_util::init(result);+ result->set(*x, *y, false);+ return result->isValid();+}++template <typename MapT, typename FpT, typename GrT>+inline void map_to(MapT map, const FpT *ca, GrT *result)+{+ FpT a = *ca;+ mem_util::init(result);+ while (true)+ {+ try+ {+ map(*result, a);+ break;+ }+ catch (cybozu::Exception &)+ {+ *a.getFp0() += FpT::BaseFp::one();+ }+ }+}++template <typename GrT>+inline void add(const GrT *p, const GrT *q, GrT *result)+{+ mem_util::init(result);+ GrT::add(*result, *p, *q);+}++template <typename GrT>+inline void invert(const GrT *p, GrT *result)+{+ mem_util::init(result);+ GrT::neg(*result, *p);+}++template <typename FrT, typename GrT>+inline void scalar_mul_native(const int const_time,+ const FrT *scalar,+ const GrT *p,+ GrT *result)+{+ mem_util::init(result);+ if (const_time)+ GrT::mulCT(*result, *p, *scalar);+ else+ GrT::mul(*result, *p, *scalar);+}++template <typename GrT>+inline void scalar_mul(const int const_time,+ const mp_limb_t *scalar,+ const mp_size_t scalar_limbs,+ const int is_negative,+ const GrT *p,+ GrT *result)+{+ mem_util::init(result);+ GrT::mulArray(*result, *p, limb_unit_compat(scalar).units,+ scalar_limbs, is_negative, const_time);+}++template <typename FrT, typename GrT>+inline void scalar_mul_small(const int const_time,+ const HsInt scalar,+ const GrT *p,+ GrT *result)+{+ mem_util::init(result);+ if (const_time)+ GrT::mulCT(*result, *p, FrT{scalar});+ else+ GrT::mul(*result, *p, FrT{scalar});+}++template <typename GrT>+inline int eq(const GrT *p, const GrT *q)+{+ return *p == *q;+}++template <typename GrT>+inline int is_zero(const GrT *p)+{+ return p->isZero();+}++template <typename GrT, typename FpT>+inline void affine_coords(const GrT *p, FpT *result_x, FpT *result_y)+{+ assert(!p->isZero());++ if (p->isNormalized())+ {+ mem_util::copy(result_x, p->x);+ mem_util::copy(result_y, p->y);+ }+ else+ {+ GrT r{*p};+ r.normalize();+ mem_util::copy(result_x, r.x);+ mem_util::copy(result_y, r.y);+ }+}++template <typename GrT, typename FpT>+inline int y_from_x(const int y_lsb, const FpT *x, FpT *result)+{+ int success = 1;+ mem_util::init(result);+ try {+ GrT::getYfromX(*result, *x, y_lsb);+ } catch (cybozu::Exception &) {+ success = 0;+ }+ return success;+}++}+}++#endif // HAVE_HS_MCL_IMPL
+ cbits/include/hs_mcl_misc.hpp view
@@ -0,0 +1,102 @@+#ifndef HAVE_HS_MCL_MISC+#define HAVE_HS_MCL_MISC++#include <mcl/fp.hpp>++namespace hs_mcl {++// On x86_32 mp_limb_t is a typedef for unsigned long int, whereas mcl::fp::Unit+// is typedef for unsigned int. These, even though of the same size, are+// distinct types, hence compiler complains when we pass a pointer to the former+// when a pointer to the latter is expected. Below is used to safely bridge that+// gap.+union limb_unit_compat+{+ limb_unit_compat(const mp_limb_t *limbs_)+ : limbs(limbs_)+ { }++ const mp_limb_t *limbs;+ const mcl::fp::Unit *units;++ static_assert(sizeof(*limbs) == sizeof(*units),+ "mp_limb_t and mcl::fp::Unit have different size");+};++// In order to avoid using foreign pointers to manage memory for MCL numeric+// classes inside Haskell we take advantage of the fact that all of them are+// trivially destructible. As there is no need to run the destructor, we can+// allocate memory for them inside Haskell and construct them at C++ level+// within that memory block using placement new operator.+//+// This class statically guarantees that objects we construct and copy are+// trivially destructible classes. If at any point in time some of them cease to+// be so (which is highly doubtful, but nevertheless), it can be easily adjusted+// to use ordinary operator new (unfortunately then we can't escape ForeignPtr+// management in Haskell).+struct mem_util+{+ template <typename TargetT>+ inline static void init(TargetT *target)+ {+ static_assert(std::is_class<TargetT>::value,+ "Target is not a class");++ mem_util_impl<TargetT, TargetT,+ std::is_trivially_destructible<TargetT>::value+ >::init(target);+ }++ template <typename TargetT, typename SourceT>+ inline static void copy(TargetT *target, SourceT &&source)+ {+ static_assert(std::is_class<TargetT>::value,+ "Target is not a class");++ mem_util_impl<TargetT, SourceT,+ std::is_trivially_destructible<TargetT>::value+ >::copy(target,+ std::forward<SourceT>(source));+ }++private:+ template <typename TargetT, typename SourceT,+ bool is_trivially_destructible>+ struct mem_util_impl+ {+ static_assert(is_trivially_destructible,+ "Target is not trivially destructible");+ };++ template <typename TargetT, typename SourceT>+ struct mem_util_impl<TargetT, SourceT, true>+ {+ inline static void init(TargetT *target)+ {+ new (target) TargetT{};+ }++ inline static void copy(TargetT *target, SourceT &&source)+ {+ new (target) TargetT{std::forward<SourceT>(source)};+ }+ };++};++////////////////////////////////////////////////////////////++inline void mpz_class_to_gmp_integer(const mpz_class &z, mp_limb_t *result,+ const size_t result_length_bytes)+{+ mpz_srcptr mp = z.get_mpz_t();+ size_t n = mpz_size(mp);++ assert(n * sizeof(mp->_mp_d[0]) == result_length_bytes);++ std::copy(mp->_mp_d, mp->_mp_d + n, result);+}++}++#endif // HAVE_HS_MCL_MISC
cbits/mcl_fp254bnb.cpp view
@@ -1,5 +1,5 @@ #include <mcl/bn256.hpp>-#include "impl.hpp"+#include "hs_mcl_impl.hpp" using namespace hs_mcl; using namespace mcl::bn256;
mcl.cabal view
@@ -1,7 +1,7 @@ name: mcl-version: 1.0.0+version: 1.0.1 synopsis: Bindings to mcl, a generic and fast pairing-based cryptography library-description: Base library: https://github.com/herumi/mcl+description: Base library: <https://github.com/herumi/mcl> license: BSD3 license-file: LICENSE author: Andrzej Rybczak@@ -55,6 +55,10 @@ default-language: Haskell2010 cc-options: -std=c++11 -Wall -Wextra++ include-dirs: cbits/include+ install-includes: cbits/include/hs_mcl_impl.hpp+ cbits/include/hs_mcl_misc.hpp c-sources: cbits/mcl_fp254bnb.cpp