cam16_inverse = function cam16_inverse({Q, M, J, C, s, h}) {
if (!(exists(h) && (exists(J) + exists(Q) == 1) &&
(exists(M) + exists(C) + exists(s) == 1))) {
throw new Error('Need exactly need exactly one of each of ' +
'{J, Q}, {M, C, s}, {h} as model inputs'); }
if ((J == 0) || (Q == 0)) return [0, 0, 0];
const
h_rad = radians(h),
cos_h = Math.cos(h_rad),
sin_h = Math.sin(h_rad),
J_root = sqrt(J)*0.1 || 0.25 * c * Q / ((A_w + 4) * F_L_4),
alpha = (s == null) ? (C || (M / F_L_4) || 0) / J_root
: 0.0004*s*s*(A_w + 4) / c,
t = pow(alpha * pow(1.64 - pow(0.29, n), -0.73), 10 / 9),
e_t = 0.25 * (Math.cos(h_rad + 2) + 3.8),
A = A_w * pow(J_root, 2 / c / z),
p_1 = 5e4 / 13 * N_c * N_cb * e_t,
p_2 = A / N_bb,
r = 23 * (p_2 + 0.305) * t / (23*p_1 + t * (11*cos_h + 108*sin_h)),
a = r * cos_h,
b = r * sin_h,
denom = 1 / 1403,
RGB_c = [(460*p_2 + 451*a + 288*b) * denom,
(460*p_2 - 891*a - 261*b) * denom,
(460*p_2 - 220*a - 6300*b) * denom].map(unadapt),
XYZ = M16_inv(elem_mul(RGB_c, D_RGB_inv));
return XYZ;
}