packages feed

mcl-1.0.1: cbits/include/hs_mcl_impl.hpp

#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