packages feed

mcl 1.0.0 → 1.0.1

raw patch · 4 files changed

+368/−3 lines, 4 files

Files

+ 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