/*
*******************************************************************************
\file ec.h
\brief Elliptic curves
\project bee2 [cryptographic library]
\created 2012.04.19
\version 2025.09.29
\copyright The Bee2 authors
\license Licensed under the Apache License, Version 2.0 (see LICENSE.txt).
*******************************************************************************
*/

/*!
*******************************************************************************
\file ec.h
\brief Эллиптические кривые
*******************************************************************************
*/

#ifndef __BEE2_EC_H
#define __BEE2_EC_H

#include "bee2/math/qr.h"

#ifdef __cplusplus
extern "C" {
#endif


/*!
*******************************************************************************
\file ec.h

Определяются вычисления на эллиптических кривых над конечными полями. 
Поле представляется как кольцо вычетов с помощью структуры 
типа qr_o (см. заголовочный файл qr.h). Описание кривой соответствует 
соглашениям ANSI X 9.62 (ECDSA) и последующих стандартов.

Эллиптическая кривая описывается структурой типа ec_o. Пусть ec -- указатель
на такую структуру. Тогда ec->f указывает на описание базового поля,
ec->A и ec->B --- коэффициенты из базового поля, которые определяют 
уравнение эллиптической кривой.

В описание ec->f базового поля включается функции арифметики в этом поле.
Описание должно быть настроено вызывающей программой 
(см. описание qrCreate() в qr.h). 

Используется внутреннее (для ec->f) представление элементов базового поля.
Импорт элементов базового поля из строк октетов выполняется 
с помощью функции ec->f->from(), экспорт -- с помощью функции ec->f->to().
Можно также использовать макросы qrFrom, qrTo (см. заголовочный файл qr.h).

Точка эллиптической кривой задается ec->d координатами из базового поля. 
Каждая координата представляется ec->f->n машинными словами. Координаты 
записываются друг за другом и в целом образуют массив pt из ec->d * ec->f->n 
машинных слов. Первые три координаты именованные: X, Y, Z. Макросы 
ecX, ecY, ecZ поддерживают извлечение именованных координат из буфера pt.

Точки с двумя координатами называются аффинными, а точки 
pt = (X : Y : Z :...) с тремя и более координатами -- проективными.
Бесконечно удаленную точку O нельзя представить аффинной, но можно проективной:
точке O соответствует точка pt, у которой Z == 0. Макросы ecSetO, ecIsO
выполняют присваивание pt = O и проверку pt == O.

Для организации вычислений требуется, чтобы среди точек эллиптической 
кривой имелась бесконечно удаленная. Поэтому должны обязательно использоваться 
проективные координаты (проективные точки). Размерность ec->d >= 3.

Проективную точку можно построить по аффинной точке (x, y) с помощью функции 
интерфейса ec_froma_i. Как правило, построение состоит в присваиваниях
\code
	X <- x, Y <- y, Z <- ec->f->unity,.... 
\endcode	
Обратно, проективную точку можно преобразовать в аффинную с помощью 
функции интерфейса ec_toa_i (при преобразовании бесконечно удаленной точки 
функция возвращает соответствующий признак).

Описание ec может быть использовано для организации вычислений в аффинных 
координатах, несмотря на заданные этим описанием проективные.

\remark Если используется ec->d == 3, то Z-координата точки pt всегда 
равняется единице для pt != O и нулю для pt == O, то вычисления на кривой 
фактически ведутся в аффинных координатах.

В структуре типа ec_o предусмотрены поля для описания циклической группы 
точек эллиптической кривой. Эта группа задается образующим ec->base. 
Образующий представляется аффинной точкой, т.е. задается 
2 * ec->f->n машинными словами. Порядок циклической группы 
ec->order задается 2 * ec->f->n + 1 машинным словом. Кофактор -- 
отношение числа всех ec->f-рациональных точек к ec->order --
задается одним машинным словом ec->cofactor.

Если работа с группой точек не предусматривается, то поля base, order 
и cofactor могут не задаваться.

По адресу ec->params могут размещаться дополнительные данные, например, 
определенные кратные базовой точки, с помощью которых можно ускорить 
криптографические вычисления на эллиптической кривой. 

Описание ec эллиптической кривой включает указатели на функции арифметики 
в группе точек этой кривой. Функцию интерфейса ec_tpl_i
можно не поддерживать. Указатель на неподдерживаемую функцию 
должен быть нулевым.

Описание кольца организовано как объект, и можно применять функции, 
описанные в заголовочном файле obj.h.

Эллиптическая кривая должна создаваться специальной функцией ecCreate(), 
которая является аналогом конструктора. В эту функцию должен передаваться 
указатель ec на структуру типа ec_o. По этому указателю будет размещаться 
описание (состояние) кривой. По адресу ec может быть зарезервировано больше 
памяти, чем sizeof(ec_o). Дело в том, что коэффициенты A, B, порядок order, 
базовая точка base могут размещаться в поле descr открытого размера. 
Функция ecCreate() должна сопровождаться функцией ecCreate_keep(), 
которая поддерживает расчет длины состояния (в октетах).

Функция ecCreate_keep() должна оценивать длину состояния сверху. 
Оценка может быть неточной. Точная длина состояния фиксируется при 
непосредственном выполнении ecCreate() и сохраняется в поле keep описания
кривой.

В функцию ecCreate() должен передаваться указатель на память для стека. 
Функция ecCreate() должна сопровождаться функцией ecCreate_deep(), которая 
выполняет расчет глубины стека. При расчете глубины следует предполагать, 
что в ecCreate() явно или неявно вызываются все функции интерфейсов кривой. 
Получив результат работы ecCreate_deep(), внешние программы могут определить, 
сколько вспомогательной памяти потребуется при всевозможных способах 
работы с функциями арифметики на кривой.

Оценка глубины стека, определяемая функцией ecCreate_deep(), может быть 
неточной. Точная глубина фиксируется при непосредственном выполнении ecCreate()
и сохраняется в поле deep описания кривой.

В функцию ecCreate() могут не передаваться параметры base, order и cofactor, 
определяющие строение группы точек, хотя буферы для base и order могут 
подготавливаться в ecCreate(). Параметры могут устанавливаться позднее 
с помощью функции ecGroupCreate(). 

\pre Все указатели действительны. 

\pre Буферы точек кривой не пересекаются с буферами, поддерживающими описание 
эллиптической кривой.
*******************************************************************************
*/

struct ec_o;

/*!	\brief Импорт из аффинной точки

	По аффинной точке [2 * ec->f->n]a эллиптической кривой ec строится 
	точка [ec->d * ec->f->n]b.
	\pre Описание ec работоспособно.
	\pre Буферы a и b либо не пересекаются, либо указатели a и b совпадают.
	\pre Координаты a лежат в базовом поле.
	\expect Описание ec корректно.
	\expect Точка a лежит на кривой.
	\return TRUE, если преобразование успешно выполнено, и FALSE в противном 
	случае.
*/
typedef bool_t (*ec_froma_i)(
	word b[],				/*!< [out] выходная точка */
	const word a[],			/*!< [in] аффинная точка */
	const struct ec_o* ec,	/*!< [in] описание эллиптической кривой */
	void* stack				/*!< [in] вспомогательная память */
);

/*!	\brief Экспорт в аффинную точку

	По точке [ec->d * ec->f->n]a эллиптической кривой ec строится 
	аффинная точка [2 * ec->f->n]b.
	\pre Описание ec работоспособно.
	\pre Буферы a и b либо не пересекаются, либо указатели a и b совпадают.
	\pre Координаты a лежат в базовом поле.
	\expect Описание ec корректно.
	\expect Точка a лежит на кривой.
	\return TRUE, если аффинная точка построена, и FALSE, если точке a 
	соответствует бесконечно удаленная точка.
*/
typedef bool_t (*ec_toa_i)(
	word b[],				/*!< [out] аффинная точка */
	const word a[],			/*!< [in] входная точка */
	const struct ec_o* ec,	/*!< [in] описание эллиптической кривой */
	void* stack				/*!< [in] вспомогательная память */
);

/*!	\brief Обратная точка

	На эллиптической кривой ec определяется точка [ec->d * ec->f->n]b,
	обратная к точке [ec->d * ec->f->n]a:
	\code
		b <- -a.
	\endcode
	\pre Описание ec работоспособно.
	\pre Буфер b либо не пересекается, либо совпадает с буфером a.
	\pre Координаты a лежат в базовом поле.
	\expect Описание ec корректно.
	\expect Точка a лежит на кривой.
*/
typedef void (*ec_neg_i)(
	word b[],				/*!< [out] обратная точка */
	const word a[],			/*!< [in] обращаемая точка */
	const struct ec_o* ec,	/*!< [in] описание эллиптической кривой */
	void* stack				/*!< [in] вспомогательная память */
);

/*!	\brief Сложение точек

	На эллиптической кривой ec определяется сумма [ec->d * ec->f->n]c точек 
	[ec->d * ec->f->n]a и [ec->d * ec->f->n]b:
	\code
		c <- a + b.
	\endcode
	\pre Описание ec работоспособно.
	\pre Буфер с либо не пересекается с каждым из буферов a и b, либо 
	совпадает с некоторым из них.
	\pre Координаты a и b лежат в базовом поле.
	\expect Описание ec корректно.
	\expect Точки a и b лежат на кривой.
*/
typedef void (*ec_add_i)(
	word c[],				/*!< [out] сумма */
	const word a[],			/*!< [in] первое слагаемое */
	const word b[],			/*!< [in] второе слагаемое */
	const struct ec_o* ec,	/*!< [in] описание эллиптической кривой */
	void* stack				/*!< [in] вспомогательная память */
);

/*!	\brief Сложение с аффинной точкой

	На эллиптической кривой ec определяется сумма [ec->d * ec->f->n]c 
	проективной точки [ec->d * ec->f->n]a и аффинной точки [2 * ec->f->n]b:
	\code
		c <- a + b.
	\endcode
	\pre Описание ec работоспособно.
	\pre Буфер с либо не пересекается с каждым из буферов a и b, либо 
	указатель c совпадает с некоторым из указателей a или b.
	\pre Координаты a и b лежат в базовом поле.
	\expect Описание ec корректно.
	\expect Точки a и b лежат на кривой.
*/
typedef void (*ec_adda_i)(
	word c[],				/*!< [out] сумма */
	const word a[],			/*!< [in] первое слагаемое */
	const word b[],			/*!< [in] второе слагаемое */
	const struct ec_o* ec,	/*!< [in] описание эллиптической кривой */
	void* stack				/*!< [in] вспомогательная память */
);

/*!	\brief Вычитание точек

	На эллиптической кривой ec определяется разность [ec->d * ec->f->n]c точек 
	[ec->d * ec->f->n]a и [ec->d * ec->f->n]b:
	\code
		c <- a - b.
	\endcode
	\pre Описание ec работоспособно.
	\pre Буфер с либо не пересекается с каждым из буферов a и b, либо 
	совпадает с некоторым из них.
	\pre Координаты a и b лежат в базовом поле.
	\expect Описание ec корректно.
	\expect Точки a и b лежат на кривой.
*/
typedef void (*ec_sub_i)(
	word c[],				/*!< [out] разность */
	const word a[],			/*!< [in] уменьшаемое */
	const word b[],			/*!< [in] вычитаемое */
	const struct ec_o* ec,	/*!< [in] описание эллиптической кривой */
	void* stack				/*!< [in] вспомогательная память */
);

/*!	\brief Вычитание аффинной точки

	На эллиптической кривой ec определяется разность [ec->d * ec->f->n]c 
	проективной точки [ec->d * ec->f->n]a и аффинной точки [2 * ec->f->n]b:
	\code
		c <- a - b.
	\endcode
	\pre Описание ec работоспособно.
	\pre Буфер с либо не пересекается с каждым из буферов a и b, либо 
	указатель c совпадает с некоторым из указателей a или b.
	\pre Координаты a и b лежат в базовом поле.
	\expect Описание ec корректно.
	\expect Точки a и b лежат на кривой.
*/
typedef void (*ec_suba_i)(
	word c[],				/*!< [out] разность */
	const word a[],			/*!< [in] уменьшаемое */
	const word b[],			/*!< [in] вычитаемое */
	const struct ec_o* ec,	/*!< [in] описание эллиптической кривой */
	void* stack				/*!< [in] вспомогательная память */
);

/*!	\brief Удвоение точки

	На эллиптической кривой ec определяется точка [ec->d * ec->f->n]b, 
	полученная удвоением точки [ec->d * ec->f->n]a:
	\code
		b <- 2 a.
	\endcode
	\pre Описание ec работоспособно.
	\pre Буфер b либо не пересекается, либо совпадает с буфером a.
	\pre Координаты a лежат в базовом поле.
	\expect Описание ec корректно.
	\expect Точка a лежит на кривой.
*/
typedef void (*ec_dbl_i)(
	word b[],				/*!< [out] удвоенная точка */
	const word a[],			/*!< [in] первоначальная точка */
	const struct ec_o* ec,	/*!< [in] описание эллиптической кривой */
	void* stack				/*!< [in] вспомогательная память */
);

/*!	\brief Удвоение аффинной точки

	На эллиптической кривой ec определяется проективная 
	точка [ec->d * ec->f->n]b, полученная удвоением аффинной 
	точки [2 * ec->f->n]a:
	\code
		b <- 2 a.
	\endcode
	\pre Описание ec работоспособно.
	\pre Буферы a и b либо не пересекаются, либо указатели a и b совпадают.
	\pre Координаты a лежат в базовом поле.
	\expect Описание ec корректно.
	\expect Точка a лежит на кривой.
*/
typedef void (*ec_dbla_i)(
	word b[],				/*!< [out] удвоенная точка */
	const word a[],			/*!< [in] первоначальная точка */
	const struct ec_o* ec,	/*!< [in] описание эллиптической кривой */
	void* stack				/*!< [in] вспомогательная память */
);

/*!	\brief Утроение точки

	На эллиптической кривой ec определяется точка [ec->d * ec->f->n]b, 
	полученная утроением точки [ec->d * ec->f->n]a:
	\code
		b <- 3 a.
	\endcode
	\pre Описание ec работоспособно.
	\pre Буфер b либо не пересекается, либо совпадает с буфером a.
	\pre Координаты a лежат в базовом поле.
	\expect Описание ec корректно.
	\expect Точка a лежит на кривой.
*/
typedef void (*ec_tpl_i)(
	word b[],				/*!< [out] утроенная точка */
	const word a[],			/*!< [in] первоначальная точка */
	const struct ec_o* ec,	/*!< [in] описание эллиптической кривой */
	void* stack				/*!< [in] вспомогательная память */
);

/*!	\brief Описание эллиптической кривой

	Описывается эллиптическая кривая, правила представления ее элементов, 
	группа точек и функции, реализующие операции в группе.
	\remark В таблицу указателей описания кривой как объекта входят поля 
	f, A, B, base, order, params. Поле f является указателем на объект.
*/
typedef struct ec_o
{
	obj_hdr_t hdr;			/*!< заголовок */
// ptr_table {
	const qr_o* f;			/*!< базовое поле */
	word* A;				/*!< коэффициент A */
	word* B;				/*!< коэффициент B */
	word* base;				/*!< базовая точка */
	word* order;			/*!< порядок группы точек */
	void* params;			/*!< дополнительные параметры */
// }
	size_t d;				/*!< размерность */
	word cofactor;			/*!< кофактор группы точек */
	ec_froma_i froma;		/*!< функция импорта из аффинной точки */
	ec_toa_i toa;			/*!< функция экспорта в аффинную точку */
	ec_neg_i neg;			/*!< функция обращения */
	ec_add_i add;			/*!< функция сложения */
	ec_adda_i adda;			/*!< функция сложения с аффинной точкой */
	ec_sub_i sub;			/*!< функция вычитания */
	ec_suba_i suba;			/*!< функция вычитания аффинной точки */
	ec_dbl_i dbl;			/*!< функция удвоения */
	ec_dbla_i dbla;			/*!< функция удвоения аффинной точки */
	ec_tpl_i tpl;			/*!< функция утроения */
	size_t deep;			/*!< максимальная глубина стека функций */
	mem_align_t descr[];	/*!< память для размещения данных */
} ec_o;

/*
*******************************************************************************
Псевдонимы
*******************************************************************************
*/

#define ecX(pt)\
	(pt)

#define ecY(pt, n)\
	((pt) + (n))

#define ecZ(pt, n)\
	((pt) + (n) + (n))

#define ecFromA(b, a, ec, stack)\
	(ec)->froma(b, a, ec, stack)

#define ecToA(b, a, ec, stack)\
	(ec)->toa(b, a, ec, stack)

#define ecFrom(b, a, ec, stack)\
	(qrFrom(ecX(b), a, (ec)->f, stack) &&\
		qrFrom(ecY(b, (ec)->f->n), (a) + (ec)->f->no, (ec)->f, stack) &&\
			ecFromA(b, b, ec, stack))

#define ecTo(b, a, ec, stack)\
	(ecToA(b, a, ec, stack) ?\
		qrTo((b), ecX(b), (ec)->f, stack),\
			qrTo((b) + (ec)->f->no, ecY(b, (ec)->f->n), (ec)->f, stack),\
		TRUE : FALSE)

#define ecNeg(b, a, ec, stack)\
	(ec)->neg(b, a, ec, stack)

#define ecAdd(c, a, b, ec, stack)\
	(ec)->add(c, a, b, ec, stack)

#define ecAddA(c, a, b, ec, stack)\
	(ec)->adda(c, a, b, ec, stack)

#define ecSub(c, a, b, ec, stack)\
	(ec)->sub(c, a, b, ec, stack)

#define ecSubA(c, a, b, ec, stack)\
	(ec)->suba(c, a, b, ec, stack)

#define ecDbl(b, a, ec, stack)\
	(ec)->dbl(b, a, ec, stack)

#define ecDblA(b, a, ec, stack)\
	(ec)->dbla(b, a, ec, stack)

#define ecSetO(a, ec)\
	wwSetZero(ecZ(a, (ec)->f->n), (ec)->f->n)

#define ecIsO(a, ec)\
	wwIsZero(ecZ(a, (ec)->f->n), (ec)->f->n)

/*
*******************************************************************************
Управление описанием кривой
*******************************************************************************
*/

/*!	\brief Описание эллиптической кривой работоспособно?

	Проверяется работоспособность описания ec эллиптической кривой. 
	Проверяются следующие условия:
	-	объект ec работоспособен;
	-	objKeep(ec) >= sizeof(ec_o);
	-	objPCount(ec) == 6 && objOCount(ec) == 1;
	-	ec->d >= 3;
	-	qrIsOperable(ec->f) == TRUE;
	-	буферы [ec->n]ec->A, [ec->n]ec->B корректны;
	-	указатели ec->froma, r->toa, ..., r->dbla корректны;
	-	ec->deep >= ec->f->deep.
	.
	\return Признак корректности.
	\remark Поля ec->base, ec->order и ec->cofactor, описывающие группу точек,
	не контролируются.
*/
bool_t ecIsOperable(
	const ec_o* ec			/*!< [in] описание кривой */
);

/*!	\brief Описание отдельной эллиптической кривой работоспособно?

	Проверяется работоспособность описания ec эллиптической кривой без учета
	ссылочного описания базового поля. Проверяются следующие условия:
	-	объект ec работоспособен;
	-	objKeep(ec) >= sizeof(ec_o);
	-	objPCount(ec) == 6 && objOCount(ec) == 1;
	-	ec->d >= 3;
	-	буферы [ec->n]ec->A, [ec->n]ec->B корректны;
	-	указатели ec->froma, r->toa, ..., r->dbla корректны.
	.
	\return Признак корректности.
	\remark Поля ec->base, ec->order и ec->cofactor, описывающие группу точек,
	не контролируются.
*/
bool_t ecIsOperable2(
	const ec_o* ec			/*!< [in] описание кривой */
);

/*!	\brief Создание группы точек эллиптической кривой

	В описание ec эллиптической кривой добавляется описание группы, 
	порожденной точкой ([ec->f->no]xbase, [ec->f->no]ybase).
	Группа имеет порядок [order_len]order и ее кофактор равняется cofactor.
	\pre Описание ec работоспособно.
	\pre Буферы [2 * ec->f->n]ec->base, [ec->f->n + 1]ec->order корректны.
	\expect{FALSE} Число [octet_len]octet укладывается в ec->f->n + 1
	машинных слов.
	\expect{FALSE} cofactor != 0 && cofactor укладывается в машинное слово.
	\expect Описание ec корректно.
	\return TRUE, если описание группы успешно задано, и FALSE в 
	противном случае.
	\remark Любой из указателей xbase, ybase может быть нулевым. При нулевом 
	указателе соответствующая координата базовой точки устанавливается равной 
	нулю.
	\deep{stack} ecGroupCreate_deep(f_deep).
*/
bool_t ecGroupCreate(
	ec_o* ec,				/*!< [in,out] описание кривой */
	const octet xbase[],	/*!< [in] x-координата базовой точки */
	const octet ybase[],	/*!< [in] y-координата базовой точки */
	const octet order[],	/*!< [in] порядок группы точек */
	size_t order_len,		/*!< [in] длина order */
	u32 cofactor,			/*!< [in] кофактор группы точек */
	void* stack				/*!< [in] вспомогательная память */
);

size_t ecGroupCreate_deep(size_t f_deep);

/*!	\brief Группа точек эллиптической кривой работоспособна?

	Проверяется работоспособность описания группы точек эллиптической 
	кривой ec. Проверяются следующие условия:
	- буферы [ec->n + 1]ec->order, [2 * ec->n]ec->base корректны;
	- ec->order != 0;
	- cofactor != 0.
	.
	\pre Описание ec работоспособно.
	\return Признак корректности.
*/
bool_t ecGroupIsOperable(
	const ec_o* ec			/*!< [in] описание кривой */
);

/*
*******************************************************************************
Макрооперации с аффинными точками
*******************************************************************************
*/

/*!	\brief Кратная точка

	Определяется аффинная точка [2 * ec->f->n]b эллиптической кривой ec, 
	которая является [m]d-кратной аффинной точки [2 * ec->f->n]a:
	\code
		b <- d a.
	\endcode
	\pre Описание ec работоспособно.
	\pre Координаты a лежат в базовом поле.
	\expect Описание ec корректно.
	\expect Точка a лежит на ec.
	\return TRUE, если кратная точка является аффинной, и FALSE в противном
	случае (b == O).
	\deep{stack} ecpMulA_deep(ec->f->n, ec->d, ec->f->deep, m).
*/
bool_t ecMulA(
	word b[],			/*!< [out] кратная точка */
	const word a[],		/*!<[in] базовая точка */
	const ec_o* ec,		/*!< [in] описание кривой */
	const word d[],		/*!< [in] кратность */
	size_t m,			/*!< [in] длина d в машинных словах */
	void* stack			/*!< [in] вспомогательная память */
);

size_t ecMulA_deep(size_t n, size_t ec_d, size_t ec_deep, size_t m);

/*!	\brief Имеет порядок?

	Проверяется, что аффинная точка [2 * ec->f->n]a имеет порядок [m]q 
	в группе точек кривой ec.
	\pre Описание ec работоспособно.
	\pre Координаты a лежат в базовом поле.
	\pre q > 0.
	\expect Описание ec корректно.
	\expect Точка a лежит на ec.
	\expect Число q -- простое. Если q -- составное, то точка порядка q1 | q
	может быть ошибочно признана точкой порядка q.
	\return Признак успеха проверки.
	\deep{stack} ecpHasOrderA_deep(ec->f->n, ec->d, ec->f->deep, m).
*/
bool_t ecHasOrderA(
	const word a[],		/*!< [in] точка */
	const ec_o* ec,		/*!< [in] описание кривой */
	const word q[],		/*!< [in] порядок */
	size_t m,			/*!< [in] длина q в машинных словах */
	void* stack			/*!< [in] вспомогательная память */
);

size_t ecHasOrderA_deep(size_t n, size_t ec_d, size_t ec_deep, size_t m);

/*!	\brief Сумма кратных точек

	Определяется точка [2n]b эллиптической кривой ec, которая является
	суммой [m[i]]d[i]-кратных точек [2n]a[i], i = 1, 2,.., k:
	\code
		b <- d[1] a[1] + d[2] a[2] + ... + d[k] a[k].
	\endcode
	Тройки a[i], d[i], m[i] передаются как дополнительные параметры
	типов const word[], const word[], size_t соответственно.
	\pre Описание ec работоспособно.
	\pre k > 0.
	\pre Координаты точек a[1], a[2],..., a[k] лежат в базовом поле.
	\expect Описание ec корректно.
	\expect Точки a[1], a[2],..., a[k] лежат на ec.
	\return TRUE, если полученная точка является аффинной, и FALSE
	в противном случае (b == O).
	\deep{stack} ecAddMulA_deep(ec->f->n, ec->d, ec->deep, m[1], ..., m[k]).
*/
bool_t ecAddMulA(
	word b[],			/*!< [out] кратная точка */
	const ec_o* ec,		/*!< [in] описание кривой */
	void* stack,		/*!< [in] вспомогательная память */
	size_t k,			/*!< [in] число троек (a[i], d[i], m[i]) */
	...					/*!< [in] тройки (a[i], d[i], m[i]) */
);

size_t ecAddMulA_deep(size_t n, size_t ec_d, size_t ec_deep, size_t k,...);

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif /* __BEE2_EC_H */
