/*
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.
*/

/* Small Finite Field arithmetic */
/* AMCL mod p functions */

public final class FP {
	private final BIG x;
	private static BIG p=new BIG(ROM.Modulus);

/* Constructors */
	public FP(int a)
	{
		x=new BIG(a);
		nres();
	}

	public FP()
	{
		x=new BIG(0);
	}

	public FP(BIG a)
	{
		x=new BIG(a);
		nres();
	}

	public FP(FP a)
	{
		x=new BIG(a.x);
	}

/* convert to string */
	public String toString()
	{
		String s=redc().toString();
		return s;
	}

	public String toRawString()
	{
		String s=x.toRawString();
		return s;
	}

/* convert to Montgomery n-residue form */
	public void nres()
	{
		if (ROM.MODTYPE!=ROM.PSEUDO_MERSENNE)
		{
			DBIG d=new DBIG(x);
			d.shl(ROM.NLEN*ROM.BASEBITS);
			x.copy(d.mod(p));
		}
	}

/* convert back to regular form */
	public BIG redc()
	{
		if (ROM.MODTYPE!=ROM.PSEUDO_MERSENNE)
		{
			DBIG d=new DBIG(x);
			return BIG.mod(d);
		}
		else
		{
			BIG r=new BIG(x);
			return r;
		}
	}

/* test this=0? */
	public boolean iszilch() {
		reduce();
		return x.iszilch();
	}

/* copy from FP b */
	public void copy(FP b)
	{
		x.copy(b.x);
	}

/* set this=0 */
	public void zero()
	{
		x.zero();
	}

/* set this=1 */
	public void one()
	{
		x.one(); nres();
	}

/* normalise this */
	public void norm()
	{
		x.norm();
	}

/* swap FPs depending on d */
	public void cswap(FP b,int d)
	{
		x.cswap(b.x,d);
	}

/* copy FPs depending on d */
	public void cmove(FP b,int d)
	{
		x.cmove(b.x,d);
	}

/* this*=b mod Modulus */
	public void mul(FP b)
	{
		int ea=BIG.EXCESS(x);
		int eb=BIG.EXCESS(b.x);

		if ((ea+1)*(eb+1)+1>=ROM.FEXCESS) reduce();

		DBIG d=BIG.mul(x,b.x);
		x.copy(BIG.mod(d));
	}

/* this*=c mod Modulus, where c is a small int */
	public void imul(int c)
	{
		norm();
		boolean s=false;
		if (c<0)
		{
			c=-c;
			s=true;
		}
		int afx=(BIG.EXCESS(x)+1)*(c+1)+1;
		if (c<ROM.NEXCESS && afx<ROM.FEXCESS)
		{
			x.imul(c);
		}
		else
		{
			if (afx<ROM.FEXCESS) x.pmul(c);
			else
			{
				DBIG d=x.pxmul(c);
				x.copy(d.mod(p));
			}
		}
		if (s) neg();
		norm();
	}

/* this*=this mod Modulus */
	public void sqr()
	{
		DBIG d;
		int ea=BIG.EXCESS(x);
		if ((ea+1)*(ea+1)+1>=ROM.FEXCESS)
			reduce();

		d=BIG.sqr(x);
		x.copy(BIG.mod(d));
	}

/* this+=b */
	public void add(FP b) {
		x.add(b.x);
		if (BIG.EXCESS(x)+2>=ROM.FEXCESS) reduce();
	}

/* this = -this mod Modulus */
	public void neg()
	{
		int sb,ov;
		BIG m=new BIG(p);

		norm();

		ov=BIG.EXCESS(x);
		sb=1; while(ov!=0) {sb++;ov>>=1;}

		m.fshl(sb);
		x.rsub(m);

		if (BIG.EXCESS(x)>=ROM.FEXCESS) reduce();
	}

/* this-=b */
	public void sub(FP b)
	{
		FP n=new FP(b);
		n.neg();
		this.add(n);
	}

/* this/=2 mod Modulus */
	public void div2()
	{
		x.norm();
		if (x.parity()==0)
			x.fshr(1);
		else
		{
			x.add(p);
			x.norm();
			x.fshr(1);
		}
	}

/* this=1/this mod Modulus */
	public void inverse()
	{
		BIG r=redc();
		r.invmodp(p);
		x.copy(r);
		nres();
	}

/* return TRUE if this==a */
	public boolean equals(FP a)
	{
		a.reduce();
		reduce();
		if (BIG.comp(a.x,x)==0) return true;
		return false;
	}

/* reduce this mod Modulus */
	public void reduce()
	{
		x.mod(p);
	}

/* return this^e mod Modulus */
	public FP pow(BIG e)
	{
		int bt;
		FP r=new FP(1);
		e.norm();
		x.norm();
		FP m=new FP(this);
		while (true)
		{
			bt=e.parity();
			e.fshr(1);
			if (bt==1) r.mul(m);
			if (e.iszilch()) break;
			m.sqr();
		}
		r.x.mod(p);
		return r;
	}

/* return sqrt(this) mod Modulus */
	public FP sqrt()
	{
		reduce();
		BIG b=new BIG(p);
		if (ROM.MOD8==5)
		{
			b.dec(5); b.norm(); b.shr(3);
			FP i=new FP(this); i.x.shl(1);
			FP v=i.pow(b);
			i.mul(v); i.mul(v);
			i.x.dec(1);
			FP r=new FP(this);
			r.mul(v); r.mul(i);
			r.reduce();
			return r;
		}
		else
		{
			b.inc(1); b.norm(); b.shr(2);
			return pow(b);
		}
	}

/* return jacobi symbol (this/Modulus) */
	public int jacobi()
	{
		BIG w=redc();
		return w.jacobi(p);
	}
/*
	public static void main(String[] args) {
		BIG m=new BIG(ROM.Modulus);
		BIG x=new BIG(3);
		BIG e=new BIG(m);
		e.dec(1);

		System.out.println("m= "+m.nbits());


		BIG r=x.powmod(e,m);

		System.out.println("m= "+m.toString());
		System.out.println("r= "+r.toString());

		BIG.cswap(m,r,0);

		System.out.println("m= "+m.toString());
		System.out.println("r= "+r.toString());

//		FP y=new FP(3);
//		FP s=y.pow(e);
//		System.out.println("s= "+s.toString());

	} */
}
