2014-06-03 18:26 GMT-04:00 Rik Cabanier <caban...@gmail.com>: > > > > On Tue, Jun 3, 2014 at 2:40 PM, Benoit Jacob <jacob.benoi...@gmail.com> > wrote: > >> >> >> >> 2014-06-03 17:34 GMT-04:00 Benoit Jacob <jacob.benoi...@gmail.com>: >> >> >>> >>> >>> 2014-06-03 16:20 GMT-04:00 Rik Cabanier <caban...@gmail.com>: >>> >>> >>>> >>>> >>>> On Tue, Jun 3, 2014 at 6:06 AM, Benoit Jacob <jacob.benoi...@gmail.com> >>>> wrote: >>>> >>>>> >>>>> >>>>> >>>>> 2014-06-03 3:34 GMT-04:00 Dirk Schulze <dschu...@adobe.com>: >>>>> >>>>> >>>>>> On Jun 2, 2014, at 12:11 AM, Benoit Jacob <jacob.benoi...@gmail.com> >>>>>> wrote: >>>>>> >>>>>> > Objection #6: >>>>>> > >>>>>> > The determinant() method, being in this API the only easy way to get >>>>>> > something that looks roughly like a measure of invertibility, will >>>>>> probably >>>>>> > be (mis-)used as a measure of invertibility. So I'm quite confident >>>>>> that it >>>>>> > has a strong mis-use case. Does it have a strong good use case? >>>>>> Does it >>>>>> > outweigh that? Note that if the intent is precisely to offer some >>>>>> kind of >>>>>> > measure of invertibility, then that is yet another thing that would >>>>>> be best >>>>>> > done with a singular values decomposition (along with solving, and >>>>>> with >>>>>> > computing a polar decomposition, useful for interpolating >>>>>> matrices), by >>>>>> > returning the ratio between the lowest and the highest singular >>>>>> value. >>>>>> >>>>>> Looking at use cases, then determinant() is indeed often used for: >>>>>> >>>>>> * Checking if a matrix is invertible. >>>>>> * Part of actually inverting the matrix. >>>>>> * Part of some decomposing algorithms as the one in CSS Transforms. >>>>>> >>>>>> I should note that the determinant is the most common way to check >>>>>> for invertibility of a matrix and part of actually inverting the matrix. >>>>>> Even Cairo Graphics, Skia and Gecko’s representation of matrix3x3 do use >>>>>> the determinant for these operations. >>>>>> >>>>> >>>>> I didn't say that determinant had no good use case. I said that it had >>>>> more bad use cases than it had good ones. If its only use case if checking >>>>> whether the cofactors formula will succeed in computing the inverse, then >>>>> make that part of the inversion API so you don't compute the determinant >>>>> twice. >>>>> >>>>> Here is a good use case of determinant, except it's bad because it >>>>> computes the determinant twice: >>>>> >>>>> if (matrix.determinant() != 0) { // once >>>>> result = matrix.inverse(); // twice >>>>> } >>>>> >>>>> If that's the only thing we use the determinant for, then we're better >>>>> served by an API like this, allowing to query success status: >>>>> >>>>> var matrixInversionResult = matrix.inverse(); // once >>>>> if (matrixInversionResult.invertible()) { >>>>> result = matrixInversionResult.inverse(); >>>>> } >>>>> >>>> >>>> This seems to be the main use case for Determinant(). Any objections if >>>> we add isInvertible to DOMMatrixReadOnly? >>>> >>> >>> Can you give an example of how this API would be used and how it would >>> *not* force the implementation to compute the determinant twice if people >>> call isInvertible() and then inverse() ? >>> >> >> Actually, inverse() is already spec'd to throw if the inversion fails. In >> that case (assuming we keep it that way) there is no need at all for any >> isInvertible kind of method. Note that in floating-point arithmetic there >> is no absolute notion of invertibility; there just are different matrix >> inversion algorithms each failing on different matrices, so "invertibility" >> only makes sense with respect to one inversion algorithm, so it is actually >> better to keep the current exception-throwing API than to introduce a >> separate isInvertible getter. >> > > That would require try/catch around all the "invert()" calls. This is ugly > but more importantly, it will significantly slow down javascript execution. > I'd prefer that we don't throw at all but we have to because SVGMatrix did. >
So, if we have to have inverse() throw, do you agree that this removes the need for any isInvertible() kind of method? For the reason I explained above (invertibility is relative to a particular inversion algorithm) I would rather have inversion and invertibility-checking be provided by a single function. If we do have the option of not throwing, then that could be a single function returning both the inverse and a boolean. Benoit > > > >> Typical bad uses of the determinant as "measures of invertibility" >>>>> typically occur in conjunction with people thinking they do the right >>>>> thing >>>>> with "fuzzy compares", like this typical bad pattern: >>>>> >>>>> if (matrix.determinant() < 1e-6) { >>>>> return error; >>>>> } >>>>> result = matrix.inverse(); >>>>> >>>>> Multiple things are wrong here: >>>>> >>>>> 1. First, as mentioned above, the determinant is being computed twice >>>>> here. >>>>> >>>>> 2. Second, floating-point scale invariance is broken: floating point >>>>> computations should generally work for all values across the whole >>>>> exponent >>>>> range, which for doubles goes from 1e-300 to 1e+300 roughly. Take the >>>>> matrix that's 0.01*identity, and suppose we're dealing with 4x4 matrices. >>>>> The determinant of that matrix is 1e-8, so that matrix is incorrectly >>>>> treated as non-invertible here. >>>>> >>>>> 3. Third, if the primary use for the determinant is invertibility and >>>>> inversion is implemented by cofactors (as it would be for 4x4 matrices) >>>>> then in that case only an exact comparison of the determinant to 0 is >>>>> relevant. That's a case where no fuzzy comparison is meaningful. If one >>>>> wanted to guard against cancellation-induced imprecision, one would have >>>>> to >>>>> look at cofactors themselves, not just at the determinant. >>>>> >>>>> In full generality, the determinant is just the volume of the unit >>>>> cube under the matrix transformation. It is exactly zero if and only if >>>>> the >>>>> matrix is singular. That doesn't by itself give any interpretation of >>>>> other >>>>> nonzero values of the determinant, not even "very small" ones. >>>>> >>>>> For special classes of matrices, things are different. Some classes of >>>>> matrices have a specific determinant, for example rotations have >>>>> determinant one, which can be used to do useful things. So in a >>>>> sufficiently advanced or specialized matrix API, the determinant is useful >>>>> to expose. DOMMatrix is special in that it is not advanced and not >>>>> specialized. >>>>> >>>>> Benoit >>>>> >>>>> >>>>>> Greetings, >>>>>> Dirk >>>>> >>>>> >>>>> >>>> >>> >> > _______________________________________________ dev-platform mailing list dev-platform@lists.mozilla.org https://lists.mozilla.org/listinfo/dev-platform