/*
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.
*/
//
//  fp2.swift
//  
//
//  Created by Michael Scott on 07/07/2015.
//  Copyright (c) 2015 Michael Scott. All rights reserved.
//

/* Finite Field arithmetic  Fp^2 functions */

/* FP2 elements are of the form a+ib, where i is sqrt(-1) */


final class FP2
{
    private var a:FP
    private var b:FP

    /* Constructors */
    init(_ c: Int32)
    {
        a=FP(c)
        b=FP(0)
    }

    init(_ x:FP2)
    {
        a=FP(x.a)
        b=FP(x.b)
    }

    init(_ c:FP,_ d:FP)
    {
        a=FP(c)
        b=FP(d)
    }

    init(_ c:BIG,_ d:BIG)
    {
        a=FP(c)
        b=FP(d)
    }

    init(_ c:FP)
    {
        a=FP(c)
        b=FP(0)
    }

    init(_ c:BIG)
    {
        a=FP(c)
        b=FP(0)
    }

    /* test this=0 ? */
    func iszilch() -> Bool
    {
        reduce()
        return (a.iszilch() && b.iszilch())
    }

    func cmove(g:FP2,_ d:Int32)
    {
        a.cmove(g.a,d)
        b.cmove(g.b,d)
    }

    /* test this=1 ? */
    func isunity() -> Bool
    {
        let one=FP(1)
        return (a.equals(one) && b.iszilch())
    }

    /* test this=x */
    func equals(x:FP2) -> Bool
    {
        return (a.equals(x.a) && b.equals(x.b));
    }


    /* reduce components mod Modulus */
    func reduce()
    {
        a.reduce()
        b.reduce()
    }

    /* normalise components of w */
    func norm()
    {
        a.norm()
        b.norm()
    }

    /* extract a */
    func getA() -> BIG
    {
        return a.redc()
    }

    /* extract b */
    func getB() -> BIG
    {
        return b.redc()
    }

    /* copy self=x */
    func copy(x:FP2)
    {
        a.copy(x.a)
        b.copy(x.b)
    }

    /* set self=0 */
    func zero()
    {
        a.zero()
        b.zero()
    }

    /* set self=1 */
    func one()
    {
        a.one()
        b.zero()
    }

    /* negate self mod Modulus */
    func neg()
    {
        norm();
        let m=FP(a)
        let t=FP(0)

        m.add(b)
        m.neg()
        m.norm()
        t.copy(m); t.add(b)
        b.copy(m)
        b.add(a)
        a.copy(t)
    }

    /* set to a-ib */
    func conj()
    {
        b.neg()
    }

    /* self+=a */
    func add(x:FP2)
    {
        a.add(x.a)
        b.add(x.b)
    }

    /* self-=a */
    func sub(x:FP2)
    {
        let m=FP2(x)
        m.neg()
        add(m)
    }

    /* self*=s, where s is an FP */
    func pmul(s:FP)
    {
        a.mul(s)
        b.mul(s)
    }

    /* self*=i, where i is an int */
    func imul(c:Int32)
    {
        a.imul(c);
        b.imul(c);
    }

    /* self*=self */
    func sqr()
    {
        norm();

        let w1=FP(a)
        let w3=FP(a)
        let mb=FP(b)
        w3.mul(b)
        w1.add(b)
        mb.neg()
        a.add(mb)
        a.mul(w1)
        b.copy(w3); b.add(w3)
        norm()
    }
    /* self*=y */
    func mul(y:FP2)
    {
        norm();  /* This is needed here as {a,b} is not normed before additions */

        let w1=FP(a)
        let w2=FP(b)
        let w5=FP(a)
        let mw=FP(0)

        w1.mul(y.a)  // w1=a*y.a  - this norms w1 and y.a, NOT a
        w2.mul(y.b)  // w2=b*y.b  - this norms w2 and y.b, NOT b
        w5.add(b)    // w5=a+b
        b.copy(y.a); b.add(y.b) // b=y.a+y.b

        b.mul(w5)
        mw.copy(w1); mw.add(w2); mw.neg()

        b.add(mw); mw.add(w1)
        a.copy(w1);	a.add(mw)

        norm()

    }

    /* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
    /* returns true if this is QR */
    func sqrt() -> Bool
    {
        if iszilch() {return true}
        var w1=FP(b)
        var w2=FP(a)
        w1.sqr(); w2.sqr(); w1.add(w2)
        if w1.jacobi() != 1 { zero(); return false; }
        w1=w1.sqrt()
        w2.copy(a); w2.add(w1); w2.div2()
        if w2.jacobi() != 1
        {
            w2.copy(a); w2.sub(w1); w2.div2()
            if w2.jacobi() != 1 { zero(); return false }
        }
        w2=w2.sqrt()
        a.copy(w2)
        w2.add(w2)
        w2.inverse()
        b.mul(w2)
        return true
    }
    /* output to hex string */
    func toString() -> String
    {
        return ("["+a.toString()+","+b.toString()+"]")
    }

    func toRawString() -> String
    {
        return ("["+a.toRawString()+","+b.toRawString()+"]")
    }

    /* self=1/self */
    func inverse()
    {
        norm();
        let w1=FP(a)
        let w2=FP(b)

        w1.sqr()
        w2.sqr()
        w1.add(w2)
        w1.inverse()
        a.mul(w1)
        w1.neg()
        b.mul(w1)
    }

    /* self/=2 */
    func div2()
    {
        a.div2();
        b.div2();
    }

    /* self*=sqrt(-1) */
    func times_i()
    {
        let z=FP(a)
        a.copy(b); a.neg()
        b.copy(z)
    }

    /* w*=(1+sqrt(-1)) */
    /* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */
    func mul_ip()
    {
        norm();
        let t=FP2(self)
        let z=FP(a)
        a.copy(b)
        a.neg()
        b.copy(z)
        add(t)
        norm()
    }
    /* w/=(1+sqrt(-1)) */
    func div_ip()
    {
        let t=FP2(0)
        norm()
        t.a.copy(a); t.a.add(b)
        t.b.copy(b); t.b.sub(a)
        copy(t)
        div2()
    }

}
