extern all: [call]
data DOUBLE

def init():
    self.DOUBLE = create('jacobian_double.se')

def call(axn, axd, ayn, ayd, bxn, bxd, byn, byd):
    if !axn and !ayn:
        o = [bxn, bxd, byn, byd]
    if !bxn and !byn:
        o = [axn, axd, ayn, ayd]
    if o:
        return(o, 4)
    with P = -4294968273:
        if addmod(mulmod(axn, bxd, P), P - mulmod(axd, bxn, P), P) == 0:
            if addmod(mulmod(ayn, byd, P), P - mulmod(ayd, byn, P), P) == 0:
                return(self.DOUBLE.call(axn, axd, ayn, ayd, outsz=4), 4)
            else:
                return([0, 1, 0, 1], 4)
        with mn = mulmod(addmod(mulmod(byn, ayd, P), P - mulmod(ayn, byd, P), P), mulmod(bxd, axd, P), P):
            with md = mulmod(mulmod(byd, ayd, P), addmod(mulmod(bxn, axd, P), P - mulmod(axn, bxd, P), P), P):
                with msqn = mulmod(mn, mn, P):
                    with msqd = mulmod(md, md, P):
                        with msqman = addmod(mulmod(msqn, axd, P), P - mulmod(msqd, axn, P), P):
                            with msqmad = mulmod(msqd, axd, P):
                                with xn = addmod(mulmod(msqman, bxd, P), P - mulmod(msqmad, bxn, P), P):
                                    with xd = mulmod(msqmad, bxd, P):
                                        with mamxn = mulmod(mn, addmod(mulmod(axn, xd, P), P - mulmod(xn, axd, P), P), P):
                                            with mamxd = mulmod(md, mulmod(axd, xd, P), P):
                                                with yn = addmod(mulmod(mamxn, ayd, P), P - mulmod(mamxd, ayn, P), P):
                                                    with yd = mulmod(mamxd, ayd, P):
                                                        return([xn, xd, yn, yd], 4)
