chromatic_adaptation = (method, source, dest) => {
let WS = tristimulus(source);
let WD = tristimulus(dest);
let m = method.matrix;
let m_inv = method.inverse || invert(m);
let LMS_Src = [
m[0] * WS.X + m[1] * WS.Y + m[2] * WS.Z,
m[3] * WS.X + m[4] * WS.Y + m[5] * WS.Z,
m[6] * WS.X + m[7] * WS.Y + m[8] * WS.Z
];
let LMS_Dest = [
m[0] * WD.X + m[1] * WD.Y + m[2] * WD.Z,
m[3] * WD.X + m[4] * WD.Y + m[5] * WD.Z,
m[6] * WD.X + m[7] * WD.Y + m[8] * WD.Z
];
let ratio = [
LMS_Dest[0] / LMS_Src[0], 0, 0,
0, LMS_Dest[1] / LMS_Src[1], 0,
0, 0, LMS_Dest[2] / LMS_Src[2]
];
return [...multiply(m_inv, multiply(ratio, m))];
}