﻿/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
*/

/* Elliptic Curve Point class */

public sealed class ECP
{
	private FP x;
	private FP y;
	private FP z;
	private bool INF;

/* Constructor - set to O */
	public ECP()
	{
		INF = true;
		x = new FP(0);
		y = new FP(1);
		z = new FP(1);
	}
/* test for O point-at-infinity */
	public bool is_infinity()
	{
		if (ROM.CURVETYPE == ROM.EDWARDS)
		{
			x.reduce();
			y.reduce();
			z.reduce();
			return (x.iszilch() && y.Equals(z));
		}
		else
		{
			return INF;
		}
	}
/* Conditional swap of P and Q dependant on d */
	private void cswap(ECP Q, int d)
	{
		x.cswap(Q.x,d);
		if (ROM.CURVETYPE != ROM.MONTGOMERY)
		{
			y.cswap(Q.y,d);
		}
		z.cswap(Q.z,d);
		if (ROM.CURVETYPE != ROM.EDWARDS)
		{
			bool bd;
			if (d == 0)
			{
				bd = false;
			}
			else
			{
				bd = true;
			}
			bd = bd & (INF ^ Q.INF);
			INF ^= bd;
			Q.INF ^= bd;
		}
	}

/* Conditional move of Q to P dependant on d */
	private void cmove(ECP Q, int d)
	{
		x.cmove(Q.x,d);
		if (ROM.CURVETYPE != ROM.MONTGOMERY)
		{
			y.cmove(Q.y,d);
		}
		z.cmove(Q.z,d);
		if (ROM.CURVETYPE != ROM.EDWARDS)
		{
			bool bd;
			if (d == 0)
			{
				bd = false;
			}
			else
			{
				bd = true;
			}
			INF ^= (INF ^ Q.INF) & bd;
		}
	}

/* return 1 if b==c, no branching */
	private static int teq(int b, int c)
	{
		int x = b ^ c;
		x -= 1; // if x=0, x now -1
		return ((x >> 31) & 1);
	}

/* Constant time select from pre-computed table */
	private void select(ECP[] W, int b)
	{
		ECP MP = new ECP();
		int m = b >> 31;
		int babs = (b ^ m) - m;

		babs = (babs - 1) / 2;

		cmove(W[0],teq(babs,0)); // conditional move
		cmove(W[1],teq(babs,1));
		cmove(W[2],teq(babs,2));
		cmove(W[3],teq(babs,3));
		cmove(W[4],teq(babs,4));
		cmove(W[5],teq(babs,5));
		cmove(W[6],teq(babs,6));
		cmove(W[7],teq(babs,7));

		MP.copy(this);
		MP.neg();
		cmove(MP,(int)(m & 1));
	}


/* Test P == Q */
	public bool Equals(ECP Q)
	{
		if (is_infinity() && Q.is_infinity())
		{
			return true;
		}
		if (is_infinity() || Q.is_infinity())
		{
			return false;
		}
		if (ROM.CURVETYPE == ROM.WEIERSTRASS)
		{
			FP zs2 = new FP(z);
			zs2.sqr();
			FP zo2 = new FP(Q.z);
			zo2.sqr();
			FP zs3 = new FP(zs2);
			zs3.mul(z);
			FP zo3 = new FP(zo2);
			zo3.mul(Q.z);
			zs2.mul(Q.x);
			zo2.mul(x);
			if (!zs2.Equals(zo2))
			{
				return false;
			}
			zs3.mul(Q.y);
			zo3.mul(y);
			if (!zs3.Equals(zo3))
			{
				return false;
			}
		}
		else
		{
			FP a = new FP(0);
			FP b = new FP(0);
			a.copy(x);
			a.mul(Q.z);
			a.reduce();
			b.copy(Q.x);
			b.mul(z);
			b.reduce();
			if (!a.Equals(b))
			{
				return false;
			}
			if (ROM.CURVETYPE == ROM.EDWARDS)
			{
				a.copy(y);
				a.mul(Q.z);
				a.reduce();
				b.copy(Q.y);
				b.mul(z);
				b.reduce();
				if (!a.Equals(b))
				{
					return false;
				}
			}
		}
		return true;
	}

/* this=P */
	public void copy(ECP P)
	{
		x.copy(P.x);
		if (ROM.CURVETYPE != ROM.MONTGOMERY)
		{
			y.copy(P.y);
		}
		z.copy(P.z);
		INF = P.INF;
	}
/* this=-this */
	public void neg()
	{
		if (is_infinity())
		{
			return;
		}
		if (ROM.CURVETYPE == ROM.WEIERSTRASS)
		{
			y.neg();
			y.reduce();
		}
		if (ROM.CURVETYPE == ROM.EDWARDS)
		{
			x.neg();
			x.reduce();
		}
		return;
	}
/* set this=O */
	public void inf()
	{
		INF = true;
		x.zero();
		y.one();
		z.one();
	//	y=new FP(1);
	//	z=new FP(1);
	}

/* Calculate RHS of curve equation */
	public static FP RHS(FP x)
	{
		x.norm();
		FP r = new FP(x);
		r.sqr();

		if (ROM.CURVETYPE == ROM.WEIERSTRASS)
		{ // x^3+Ax+B
			FP b = new FP(new BIG(ROM.CURVE_B));
			r.mul(x);
			if (ROM.CURVE_A == -3)
			{
				FP cx = new FP(x);
				cx.imul(3);
				cx.neg();
				cx.norm();
				r.add(cx);
			}
			r.add(b);
		}
		if (ROM.CURVETYPE == ROM.EDWARDS)
		{ // (Ax^2-1)/(Bx^2-1)
			FP b = new FP(new BIG(ROM.CURVE_B));

			FP one = new FP(1);
			b.mul(r);
			b.sub(one);
			if (ROM.CURVE_A == -1)
			{
				r.neg();
			}
			r.sub(one);

			b.inverse();

			r.mul(b);
		}
		if (ROM.CURVETYPE == ROM.MONTGOMERY)
		{ // x^3+Ax^2+x
			FP x3 = new FP(0);
			x3.copy(r);
			x3.mul(x);
			r.imul(ROM.CURVE_A);
			r.add(x3);
			r.add(x);
		}
		r.reduce();
		return r;
	}

/* set (x,y) from two BIGs */
	public ECP(BIG ix, BIG iy)
	{
		x = new FP(ix);
		y = new FP(iy);
		z = new FP(1);
		FP rhs = RHS(x);

		if (ROM.CURVETYPE == ROM.MONTGOMERY)
		{
			if (rhs.jacobi() == 1)
			{
				INF = false;
			}
			else
			{
				inf();
			}
		}
		else
		{
			FP y2 = new FP(y);
			y2.sqr();
			if (y2.Equals(rhs))
			{
				INF = false;
			}
			else
			{
				inf();
			}
		}
	}
/* set (x,y) from BIG and a bit */
	public ECP(BIG ix, int s)
	{
		x = new FP(ix);
		FP rhs = RHS(x);
		y = new FP(0);
		z = new FP(1);
		if (rhs.jacobi() == 1)
		{
			FP ny = rhs.sqrt();
			if (ny.redc().parity() != s)
			{
				ny.neg();
			}
			y.copy(ny);
			INF = false;
		}
		else
		{
			inf();
		}
	}

/* set from x - calculate y from curve equation */
	public ECP(BIG ix)
	{
		x = new FP(ix);
		FP rhs = RHS(x);
		y = new FP(0);
		z = new FP(1);
		if (rhs.jacobi() == 1)
		{
			if (ROM.CURVETYPE != ROM.MONTGOMERY)
			{
				y.copy(rhs.sqrt());
			}
			INF = false;
		}
		else
		{
			INF = true;
		}
	}

/* set to affine - from (x,y,z) to (x,y) */
	public void affine()
	{
		if (is_infinity())
		{
			return;
		}
		FP one = new FP(1);
		if (z.Equals(one))
		{
			return;
		}
		z.inverse();
		if (ROM.CURVETYPE == ROM.WEIERSTRASS)
		{
			FP z2 = new FP(z);
			z2.sqr();
			x.mul(z2);
			x.reduce();
			y.mul(z2);
			y.mul(z);
			y.reduce();
		}
		if (ROM.CURVETYPE == ROM.EDWARDS)
		{
			x.mul(z);
			x.reduce();
			y.mul(z);
			y.reduce();
		}
		if (ROM.CURVETYPE == ROM.MONTGOMERY)
		{
			x.mul(z);
			x.reduce();
		}
		z.copy(one);
	}
/* extract x as a BIG */
	public BIG X
	{
		get
		{
			affine();
			return x.redc();
		}
	}
/* extract y as a BIG */
	public BIG Y
	{
		get
		{
			affine();
			return y.redc();
		}
	}

/* get sign of Y */
	public int S
	{
		get
		{
			affine();
			BIG y = Y;
			return y.parity();
		}
	}
/* extract x as an FP */
	public FP getx()
	{
		return x;
	}
/* extract y as an FP */
	public FP gety()
	{
		return y;
	}
/* extract z as an FP */
	public FP getz()
	{
		return z;
	}
/* convert to byte array */
	public void toBytes(sbyte[] b)
	{
		sbyte[] t = new sbyte[ROM.MODBYTES];
		if (ROM.CURVETYPE != ROM.MONTGOMERY)
		{
			b[0] = 0x04;
		}
		else
		{
			b[0] = 0x02;
		}

		affine();
		x.redc().toBytes(t);
		for (int i = 0;i < ROM.MODBYTES;i++)
		{
			b[i + 1] = t[i];
		}
		if (ROM.CURVETYPE != ROM.MONTGOMERY)
		{
			y.redc().toBytes(t);
			for (int i = 0;i < ROM.MODBYTES;i++)
			{
				b[i + ROM.MODBYTES + 1] = t[i];
			}
		}
	}
/* convert from byte array to point */
	public static ECP fromBytes(sbyte[] b)
	{
		sbyte[] t = new sbyte[ROM.MODBYTES];
		BIG p = new BIG(ROM.Modulus);

		for (int i = 0;i < ROM.MODBYTES;i++)
		{
			t[i] = b[i + 1];
		}
		BIG px = BIG.fromBytes(t);
		if (BIG.comp(px,p) >= 0)
		{
			return new ECP();
		}

		if (b[0] == 0x04)
		{
			for (int i = 0;i < ROM.MODBYTES;i++)
			{
				t[i] = b[i + ROM.MODBYTES + 1];
			}
			BIG py = BIG.fromBytes(t);
			if (BIG.comp(py,p) >= 0)
			{
				return new ECP();
			}
			return new ECP(px,py);
		}
		else
		{
			return new ECP(px);
		}
	}
/* convert to hex string */
	public override string ToString()
	{
		if (is_infinity())
		{
			return "infinity";
		}
		affine();
		if (ROM.CURVETYPE == ROM.MONTGOMERY)
		{
			return "(" + x.redc().ToString() + ")";
		}
		else
		{
			return "(" + x.redc().ToString() + "," + y.redc().ToString() + ")";
		}
	}
/* this*=2 */
	public void dbl()
	{
		if (ROM.CURVETYPE == ROM.WEIERSTRASS)
		{
			if (INF)
			{
				return;
			}
			if (y.iszilch())
			{
				inf();
				return;
			}

			FP w1 = new FP(x);
			FP w6 = new FP(z);
			FP w2 = new FP(0);
			FP w3 = new FP(x);
			FP w8 = new FP(x);

			if (ROM.CURVE_A == -3)
			{
				w6.sqr();
				w1.copy(w6);
				w1.neg();
				w3.add(w1);
				w8.add(w6);
				w3.mul(w8);
				w8.copy(w3);
				w8.imul(3);
			}
			else
			{
				w1.sqr();
				w8.copy(w1);
				w8.imul(3);
			}

			w2.copy(y);
			w2.sqr();
			w3.copy(x);
			w3.mul(w2);
			w3.imul(4);
			w1.copy(w3);
			w1.neg();
	//		w1.norm();

			x.copy(w8);
			x.sqr();
			x.add(w1);
			x.add(w1);
	//		x.reduce();
			x.norm();

			z.mul(y);
			z.add(z);

			w2.add(w2);
			w2.sqr();
			w2.add(w2);
			w3.sub(x);
			y.copy(w8);
			y.mul(w3);
	//		w2.norm();
			y.sub(w2);
	//		y.reduce();
	//		z.reduce();
			y.norm();
			z.norm();
		}
		if (ROM.CURVETYPE == ROM.EDWARDS)
		{
			FP C = new FP(x);
			FP D = new FP(y);
			FP H = new FP(z);
			FP J = new FP(0);

			x.mul(y);
			x.add(x);
			C.sqr();
			D.sqr();
			if (ROM.CURVE_A == -1)
			{
				C.neg();
			}
			y.copy(C);
			y.add(D);
	//		y.norm();
			H.sqr();
			H.add(H);
			z.copy(y);
			J.copy(y);
			J.sub(H);
			x.mul(J);
			C.sub(D);
			y.mul(C);
			z.mul(J);

			x.norm();
			y.norm();
			z.norm();
		}
		if (ROM.CURVETYPE == ROM.MONTGOMERY)
		{
			FP A = new FP(x);
			FP B = new FP(x);
			FP AA = new FP(0);
			FP BB = new FP(0);
			FP C = new FP(0);

			if (INF)
			{
				return;
			}

			A.add(z);
			AA.copy(A);
			AA.sqr();
			B.sub(z);
			BB.copy(B);
			BB.sqr();
			C.copy(AA);
			C.sub(BB);
	//		C.norm();

			x.copy(AA);
			x.mul(BB);

			A.copy(C);
			A.imul((ROM.CURVE_A + 2) / 4);

			BB.add(A);
			z.copy(BB);
			z.mul(C);
	//		x.reduce();
	//		z.reduce();
			x.norm();
			z.norm();
		}
		return;
	}

/* this+=Q */
	public void add(ECP Q)
	{
		if (ROM.CURVETYPE == ROM.WEIERSTRASS)
		{
			if (INF)
			{
				copy(Q);
				return;
			}
			if (Q.INF)
			{
				return;
			}

			bool aff = false;

			FP one = new FP(1);
			if (Q.z.Equals(one))
			{
				aff = true;
			}

			FP A, C;
			FP B = new FP(z);
			FP D = new FP(z);
			if (!aff)
			{
				A = new FP(Q.z);
				C = new FP(Q.z);

				A.sqr();
				B.sqr();
				C.mul(A);
				D.mul(B);

				A.mul(x);
				C.mul(y);
			}
			else
			{
				A = new FP(x);
				C = new FP(y);

				B.sqr();
				D.mul(B);
			}

			B.mul(Q.x);
			B.sub(A);
			D.mul(Q.y);
			D.sub(C);

			if (B.iszilch())
			{
				if (D.iszilch())
				{
					dbl();
					return;
				}
				else
				{
					INF = true;
					return;
				}
			}

			if (!aff)
			{
				z.mul(Q.z);
			}
			z.mul(B);

			FP e = new FP(B);
			e.sqr();
			B.mul(e);
			A.mul(e);

			e.copy(A);
			e.add(A);
			e.add(B);
			x.copy(D);
			x.sqr();
			x.sub(e);

			A.sub(x);
			y.copy(A);
			y.mul(D);
			C.mul(B);
			y.sub(C);

		//	x.reduce();
		//	y.reduce();
		//	z.reduce();
			x.norm();
			y.norm();
			z.norm();
		}
		if (ROM.CURVETYPE == ROM.EDWARDS)
		{
			FP b = new FP(new BIG(ROM.CURVE_B));
			FP A = new FP(z);
			FP B = new FP(0);
			FP C = new FP(x);
			FP D = new FP(y);
			FP E = new FP(0);
			FP F = new FP(0);
			FP G = new FP(0);
		//	FP H=new FP(0);
		//	FP I=new FP(0);

			A.mul(Q.z);
			B.copy(A);
			B.sqr();
			C.mul(Q.x);
			D.mul(Q.y);

			E.copy(C);
			E.mul(D);
			E.mul(b);
			F.copy(B);
			F.sub(E);
			G.copy(B);
			G.add(E);
			C.add(D);

			if (ROM.CURVE_A == 1)
			{
				E.copy(D);
				D.sub(C);
			}

			B.copy(x);
			B.add(y);
			D.copy(Q.x);
			D.add(Q.y);
			B.mul(D);
			B.sub(C);
			B.mul(F);
			x.copy(A);
			x.mul(B);

			if (ROM.CURVE_A == 1)
			{
				C.copy(E);
				C.mul(G);
			}
			if (ROM.CURVE_A == -1)
			{
				C.mul(G);
			}
			y.copy(A);
			y.mul(C);
			z.copy(F);
			z.mul(G);
		//	x.reduce(); y.reduce(); z.reduce();
			x.norm();
			y.norm();
			z.norm();
		}
		return;
	}

/* Differential Add for Montgomery curves. this+=Q where W is this-Q and is affine. */
	public void dadd(ECP Q, ECP W)
	{
			FP A = new FP(x);
			FP B = new FP(x);
			FP C = new FP(Q.x);
			FP D = new FP(Q.x);
			FP DA = new FP(0);
			FP CB = new FP(0);

			A.add(z);
			B.sub(z);

			C.add(Q.z);
			D.sub(Q.z);

			DA.copy(D);
			DA.mul(A);
			CB.copy(C);
			CB.mul(B);

			A.copy(DA);
			A.add(CB);
			A.sqr();
			B.copy(DA);
			B.sub(CB);
			B.sqr();

			x.copy(A);
			z.copy(W.x);
			z.mul(B);

			if (z.iszilch())
			{
				inf();
			}
			else
			{
				INF = false;
			}

	//		x.reduce();
			x.norm();
	}
/* this-=Q */
	public void sub(ECP Q)
	{
		Q.neg();
		add(Q);
		Q.neg();
	}

	public static void multiaffine(int m, ECP[] P)
	{
		int i;
		FP t1 = new FP(0);
		FP t2 = new FP(0);

		FP[] work = new FP[m];

		for (i = 0;i < m;i++)
		{
			work[i] = new FP(0);
		}

		work[0].one();
		work[1].copy(P[0].z);

		for (i = 2;i < m;i++)
		{
			work[i].copy(work[i - 1]);
			work[i].mul(P[i - 1].z);
		}

		t1.copy(work[m - 1]);
		t1.mul(P[m - 1].z);
		t1.inverse();
		t2.copy(P[m - 1].z);
		work[m - 1].mul(t1);

		for (i = m - 2;;i--)
		{
			if (i == 0)
			{
				work[0].copy(t1);
				work[0].mul(t2);
				break;
			}
			work[i].mul(t2);
			work[i].mul(t1);
			t2.mul(P[i].z);
		}
/* now work[] contains inverses of all Z coordinates */

		for (i = 0;i < m;i++)
		{
			P[i].z.one();
			t1.copy(work[i]);
			t1.sqr();
			P[i].x.mul(t1);
			t1.mul(work[i]);
			P[i].y.mul(t1);
		}
	}

/* constant time multiply by small integer of length bts - use ladder */
	public ECP pinmul(int e, int bts)
	{
		if (ROM.CURVETYPE == ROM.MONTGOMERY)
		{
			return this.mul(new BIG(e));
		}
		else
		{
			int nb, i, b;
			ECP P = new ECP();
			ECP R0 = new ECP();
			ECP R1 = new ECP();
			R1.copy(this);

			for (i = bts - 1;i >= 0;i--)
			{
				b = (e >> i) & 1;
				P.copy(R1);
				P.add(R0);
				R0.cswap(R1,b);
				R1.copy(P);
				R0.dbl();
				R0.cswap(R1,b);
			}
			P.copy(R0);
			P.affine();
			return P;
		}
	}

/* return e.this */

	public ECP mul(BIG e)
	{
		if (e.iszilch() || is_infinity())
		{
			return new ECP();
		}
		ECP P = new ECP();
		if (ROM.CURVETYPE == ROM.MONTGOMERY)
		{
/* use Ladder */
			int nb, i, b;
			ECP D = new ECP();
			ECP R0 = new ECP();
			R0.copy(this);
			ECP R1 = new ECP();
			R1.copy(this);
			R1.dbl();
			D.copy(this);
			D.affine();
			nb = e.nbits();
			for (i = nb - 2;i >= 0;i--)
			{
				b = e.bit(i);
				P.copy(R1);
				P.dadd(R0,D);
				R0.cswap(R1,b);
				R1.copy(P);
				R0.dbl();
				R0.cswap(R1,b);
			}
			P.copy(R0);
		}
		else
		{
// fixed size windows
			int i, b, nb, m, s, ns;
			BIG mt = new BIG();
			BIG t = new BIG();
			ECP Q = new ECP();
			ECP C = new ECP();
			ECP[] W = new ECP[8];
			sbyte[] w = new sbyte[1 + (ROM.NLEN * ROM.BASEBITS + 3) / 4];

			affine();

// precompute table
			Q.copy(this);
			Q.dbl();
			W[0] = new ECP();
			W[0].copy(this);

			for (i = 1;i < 8;i++)
			{
				W[i] = new ECP();
				W[i].copy(W[i - 1]);
				W[i].add(Q);
			}

// convert the table to affine
			if (ROM.CURVETYPE == ROM.WEIERSTRASS)
			{
				multiaffine(8,W);
			}

// make exponent odd - add 2P if even, P if odd
			t.copy(e);
			s = t.parity();
			t.inc(1);
			t.norm();
			ns = t.parity();
			mt.copy(t);
			mt.inc(1);
			mt.norm();
			t.cmove(mt,s);
			Q.cmove(this,ns);
			C.copy(Q);

			nb = 1 + (t.nbits() + 3) / 4;

// convert exponent to signed 4-bit window
			for (i = 0;i < nb;i++)
			{
				w[i] = (sbyte)(t.lastbits(5) - 16);
				t.dec(w[i]);
				t.norm();
				t.fshr(4);
			}
			w[nb] = (sbyte)t.lastbits(5);

			P.copy(W[(w[nb] - 1) / 2]);
			for (i = nb - 1;i >= 0;i--)
			{
				Q.select(W,w[i]);
				P.dbl();
				P.dbl();
				P.dbl();
				P.dbl();
				P.add(Q);
			}
			P.sub(C); // apply correction
		}
		P.affine();
		return P;
	}
/* Return e.this+f.Q */

	public ECP mul2(BIG e, ECP Q, BIG f)
	{
		BIG te = new BIG();
		BIG tf = new BIG();
		BIG mt = new BIG();
		ECP S = new ECP();
		ECP T = new ECP();
		ECP C = new ECP();
		ECP[] W = new ECP[8];
		sbyte[] w = new sbyte[1 + (ROM.NLEN * ROM.BASEBITS + 1) / 2];
		int i, s, ns, nb;
		sbyte a, b;

		affine();
		Q.affine();

		te.copy(e);
		tf.copy(f);

// precompute table
		W[1] = new ECP();
		W[1].copy(this);
		W[1].sub(Q);
		W[2] = new ECP();
		W[2].copy(this);
		W[2].add(Q);
		S.copy(Q);
		S.dbl();
		W[0] = new ECP();
		W[0].copy(W[1]);
		W[0].sub(S);
		W[3] = new ECP();
		W[3].copy(W[2]);
		W[3].add(S);
		T.copy(this);
		T.dbl();
		W[5] = new ECP();
		W[5].copy(W[1]);
		W[5].add(T);
		W[6] = new ECP();
		W[6].copy(W[2]);
		W[6].add(T);
		W[4] = new ECP();
		W[4].copy(W[5]);
		W[4].sub(S);
		W[7] = new ECP();
		W[7].copy(W[6]);
		W[7].add(S);

// convert the table to affine
		if (ROM.CURVETYPE == ROM.WEIERSTRASS)
		{
			multiaffine(8,W);
		}

// if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction

		s = te.parity();
		te.inc(1);
		te.norm();
		ns = te.parity();
		mt.copy(te);
		mt.inc(1);
		mt.norm();
		te.cmove(mt,s);
		T.cmove(this,ns);
		C.copy(T);

		s = tf.parity();
		tf.inc(1);
		tf.norm();
		ns = tf.parity();
		mt.copy(tf);
		mt.inc(1);
		mt.norm();
		tf.cmove(mt,s);
		S.cmove(Q,ns);
		C.add(S);

		mt.copy(te);
		mt.add(tf);
		mt.norm();
		nb = 1 + (mt.nbits() + 1) / 2;

// convert exponent to signed 2-bit window
		for (i = 0;i < nb;i++)
		{
			a = (sbyte)(te.lastbits(3) - 4);
			te.dec(a);
			te.norm();
			te.fshr(2);
			b = (sbyte)(tf.lastbits(3) - 4);
			tf.dec(b);
			tf.norm();
			tf.fshr(2);
			w[i] = (sbyte)(4 * a + b);
		}
		w[nb] = (sbyte)(4 * te.lastbits(3) + tf.lastbits(3));
		S.copy(W[(w[nb] - 1) / 2]);

		for (i = nb - 1;i >= 0;i--)
		{
			T.select(W,w[i]);
			S.dbl();
			S.dbl();
			S.add(T);
		}
		S.sub(C); // apply correction
		S.affine();
		return S;
	}

/*
	public static void main(String[] args) {

		BIG Gx=new BIG(ROM.CURVE_Gx);
		BIG Gy;
		ECP P;
		if (ROM.CURVETYPE!=ROM.MONTGOMERY) Gy=new BIG(ROM.CURVE_Gy);
		BIG r=new BIG(ROM.CURVE_Order);

		//r.dec(7);

		System.out.println("Gx= "+Gx.toString());
		if (ROM.CURVETYPE!=ROM.MONTGOMERY) System.out.println("Gy= "+Gy.toString());

		if (ROM.CURVETYPE!=ROM.MONTGOMERY) P=new ECP(Gx,Gy);
		else  P=new ECP(Gx);

		System.out.println("P= "+P.toString());

		ECP R=P.mul(r);
		//for (int i=0;i<10000;i++)
		//	R=P.mul(r);

		System.out.println("R= "+R.toString());
    } */
}

