# Path: pyem/geom/geom_numba.py
# @numba.jit(nopython=True, cache=False, nogil=True)
# def cross3_sca(u, v):
#     w = np.zeros_like(u)
#     w[0] = u[1] * v[2] - u[2] * v[1]
#     w[1] = u[2] * v[0] - u[0] * v[2]
#     w[2] = u[0] * v[1] - u[1] * v[0]
#     return w


import numba
import numpy as np
from .geom_numba import cross3_sca
# def dqpower(q, t):
#     theta, d, l, m = dq2sc(q)
#     theta_half = 0.5 * theta
#     d_half = 0.5 * d
#     da_real = t * np.cos(theta_half)
#     da_dual = t * -d_half * np.sin(theta_half)


@numba.jit(nopython=True, cache=False, parallel=True)
def pdistdq(q, d):
    relq = np.zeros((4,), dtype=np.complex128)
    for i in numba.prange(d.shape[0]):
        # relq = geom.dqtimes(geom.dqconj(q[i, None]), q)
        for j in range(i + 1, d.shape[1]):
            relq[:] = dqtimes_sca(dqconj_sca(q[i]), q[j])
            theta, dax, l, m = dq2sc(relq)
            p0 = cross3_sca(l, m)
            r2 = np.sum(p0 ** 2)
            v = np.sqrt(dax ** 2 + theta ** 2 * r2)
            d[i, j] = d[j, i] = v
    return d


@numba.jit(nopython=True, cache=False, parallel=True)
def cdistdq(q1, q2, d):
    relq = np.zeros((4,), dtype=np.complex128)
    for i in numba.prange(d.shape[0]):
        for j in range(d.shape[1]):
            relq = dqtimes_sca(dqconj_sca(q1[i]), q2[j])
            theta, dax, l, m = dq2sc(relq)

# Path: pyem/geom/geom_numba.py
# @numba.jit(nopython=True, cache=False, nogil=True)
# def cross3_sca(u, v):
#     w = np.zeros_like(u)
#     w[0] = u[1] * v[2] - u[2] * v[1]
#     w[1] = u[2] * v[0] - u[0] * v[2]
#     w[2] = u[0] * v[1] - u[1] * v[0]
#     return w


# Path: pyem/geom/quat_numba.py
import numba
import numpy as np
from .geom_numba import cross3_sca

# def dqpower(q, t):
#     theta, d, l, m = dq2sc(q)
#     theta_half = 0.5 * theta
#     d_half = 0.5 * d
#     da_real = t * np.cos(theta_half)
#     da_dual = t * -d_half * np.sin(theta_half)


@numba.jit(nopython=True, cache=False, parallel=True)
def pdistdq(q, d):
    relq = np.zeros((4,), dtype=np.complex128)
    for i in numba.prange(d.shape[0]):
        # relq = geom.dqtimes(geom.dqconj(q[i, None]), q)
        for j in range(i + 1, d.shape[1]):
            relq[:] = dqtimes_sca(dqconj_sca(q[i]), q[j])
            theta, dax, l, m = dq2sc(relq)
            p0 = cross3_sca(l, m)
            r2 = np.sum(p0 ** 2)
            v = np.sqrt(dax ** 2 + theta ** 2 * r2)
            d[i, j] = d[j, i] = v
    return d


@numba.jit(nopython=True, cache=False, parallel=True)
def cdistdq(q1, q2, d):
    relq = np.zeros((4,), dtype=np.complex128)
    for i in numba.prange(d.shape[0]):
        for j in range(d.shape[1]):
            relq = dqtimes_sca(dqconj_sca(q1[i]), q2[j])
            theta, dax, l, m = dq2sc(relq)

            p0 = cross3_sca(l, m)