rawify / Complex.js

Complex.js is a com numbers library written in JavaScript
https://raw.org/article/complex-numbers-in-javascript/
MIT License
236 stars 34 forks source link

Internally using a -1-based "polar" form #34

Open PFPF opened 3 years ago

PFPF commented 3 years ago

I had some thoughts about using a near-polar form (-1-based instead of e) to represent complex numbers; I think this will make the semantics of complex infinity etc much more natural, plus enabling infinities and zeros at every angle, to be consistent with js. Please see a more detailed description here. Just curious what you think about this, as I thought the power table there is pretty reasonable. (I understand that this could be a breaking change; thx for your work on the library anyway :)

PFPF commented 3 years ago

Although a majority of the operations would be simpler, admittedly addition and trigonometry could be harder. If this is an issue, an alternative strategy is to use the appropriate form as needed. That is, z's fullest representation looks like {re: ..., im: ..., r: ..., s: ...}, but objects with only re & im (or r & s) are also well-formed, and we can have

function fromRect(re, im) { return { re, im }; }
function fromRS(r, s) { return { r, s }; }
function calcRect(z) {
  z.re = z.r * Math.cos(z.s * Math.PI);
  z.im = z.r * Math.sin(z.s * Math.PI);
}
function calcRS(z) { 
  z.r = ...;
  z.s = ...;
}
// functions that are much faster in RS form
function abs(z) {
  if(!('r' in z && 's' in z)) calcRS(z);
  return {r: z.r, s: z.s && 0};
}
// operations that are much faster in rectangular form (this is an over-simplified version; in reality we should consider Inf/NaN
function add(z1, z2) {
  if(!('re' in z1 && 'im' in z1)) calcRect(z1);   if(!('re' in z2 && 'im' in z2)) calcRect(z2);
  return {re: z1.re + z2.re, im: z1.im + z2.im}; // we don't calculate r and s *now*, because the next operation might also be a plus
}

abs(sqrt(fromRS(3,9))); // fast
add(add(add(fromRect(2,4), fromRect(3,1)), fromRect(1,2)), sin(fromRect(0,0))); // also fast
let a = fromRS(42,0.5); // a = 42i
add(add(add(add(a, a), a), a), a); // fast, because after the first call of calcRect, a is already in the fullest form