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. > 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