System.Xml.Xsl.XPathConvert.BigNumber.Mul C# (CSharp) Method

Mul() private method

private Mul ( BigNumber &numOp ) : void
numOp BigNumber
return void
            private void Mul(ref BigNumber numOp) {
                Debug.Assert(0 != (this.u2 & 0x80000000));
                Debug.Assert(0 != (numOp.u2 & 0x80000000));

                //uint *rgu = stackalloc uint[6];
                uint rgu0 = 0, rgu1 = 0, rgu2 = 0, rgu3 = 0, rgu4 = 0, rgu5 = 0;
                uint uLo, uHi, uT;
                uint wCarry;

                if (0 != (uT = this.u0)) {
                    uLo = MulU(uT, numOp.u0, out uHi);
                    rgu0 = uLo;
                    rgu1 = uHi;

                    uLo = MulU(uT, numOp.u1, out uHi);
                    Debug.Assert(uHi < 0xFFFFFFFF);
                    wCarry = AddU(ref rgu1, uLo);
                    AddU(ref rgu2, uHi + wCarry);

                    uLo = MulU(uT, numOp.u2, out uHi);
                    Debug.Assert(uHi < 0xFFFFFFFF);
                    wCarry = AddU(ref rgu2, uLo);
                    AddU(ref rgu3, uHi + wCarry);
                }

                if (0 != (uT = this.u1)) {
                    uLo = MulU(uT, numOp.u0, out uHi);
                    Debug.Assert(uHi < 0xFFFFFFFF);
                    wCarry = AddU(ref rgu1, uLo);
                    wCarry = AddU(ref rgu2, uHi + wCarry);
                    if (0 != wCarry && 0 != AddU(ref rgu3, 1)) {
                        AddU(ref rgu4, 1);
                    }
                    uLo = MulU(uT, numOp.u1, out uHi);
                    Debug.Assert(uHi < 0xFFFFFFFF);
                    wCarry = AddU(ref rgu2, uLo);
                    wCarry = AddU(ref rgu3, uHi + wCarry);
                    if (0 != wCarry) {
                        AddU(ref rgu4, 1);
                    }
                    uLo = MulU(uT, numOp.u2, out uHi);
                    Debug.Assert(uHi < 0xFFFFFFFF);
                    wCarry = AddU(ref rgu3, uLo);
                    AddU(ref rgu4, uHi + wCarry);
                }

                uT = this.u2;
                Debug.Assert(0 != uT);
                uLo = MulU(uT, numOp.u0, out uHi);
                Debug.Assert(uHi < 0xFFFFFFFF);
                wCarry = AddU(ref rgu2, uLo);
                wCarry = AddU(ref rgu3, uHi + wCarry);
                if (0 != wCarry && 0 != AddU(ref rgu4, 1)) {
                    AddU(ref rgu5, 1);
                }
                uLo = MulU(uT, numOp.u1, out uHi);
                Debug.Assert(uHi < 0xFFFFFFFF);
                wCarry = AddU(ref rgu3, uLo);
                wCarry = AddU(ref rgu4, uHi + wCarry);
                if (0 != wCarry) {
                    AddU(ref rgu5, 1);
                }
                uLo = MulU(uT, numOp.u2, out uHi);
                Debug.Assert(uHi < 0xFFFFFFFF);
                wCarry = AddU(ref rgu4, uLo);
                AddU(ref rgu5, uHi + wCarry);

                // Compute the new exponent
                this.exp += numOp.exp;

                // Accumulate the error. Adding doesn't necessarily give an accurate
                // bound if both of the errors are bigger than 2.
                Debug.Assert(this.error <= 2 || numOp.error <= 2);
                this.error += numOp.error;

                // Handle rounding and normalize.
                if (0 == (rgu5 & 0x80000000)) {
                    if (0 != (rgu2 & 0x40000000) &&
                            (0 != (rgu2 & 0xBFFFFFFF) || 0 != rgu1 || 0 != rgu0)) {
                        // Round up by 1
                        if (0 != AddU(ref rgu2, 0x40000000)
                            && 0 != AddU(ref rgu3, 1)
                            && 0 != AddU(ref rgu4, 1)
                        ) {
                            AddU(ref rgu5, 1);
                            if (0 != (rgu5 & 0x80000000)) {
                                goto LNormalized;
                            }
                        }
                    }

                    // have to shift by one
                    Debug.Assert(0 != (rgu5 & 0x40000000));
                    this.u2 = (rgu5 << 1) | (rgu4 >> 31);
                    this.u1 = (rgu4 << 1) | (rgu3 >> 31);
                    this.u0 = (rgu3 << 1) | (rgu2 >> 31);
                    this.exp--;
                    this.error <<= 1;

                    // Add one for the error.
                    if (0 != (rgu2 & 0x7FFFFFFF) || 0 != rgu1 || 0 != rgu0) {
                        this.error++;
                    }
                    return;
                } else {
                    if (0 != (rgu2 & 0x80000000) &&
                        (0 != (rgu3 & 1) || 0 != (rgu2 & 0x7FFFFFFF) ||
                            0 != rgu1 || 0 != rgu0)) {
                        // Round up by 1
                        if (0 != AddU(ref rgu3, 1) && 0 != AddU(ref rgu4, 1) && 0 != AddU(ref rgu5, 1)) {
                            Debug.Assert(0 == rgu3);
                            Debug.Assert(0 == rgu4);
                            Debug.Assert(0 == rgu5);
                            rgu5 = 0x80000000;
                            this.exp++;
                        }
                    }
                }

            LNormalized:
                this.u2 = rgu5;
                this.u1 = rgu4;
                this.u0 = rgu3;

                // Add one for the error.
                if (0 != rgu2 || 0 != rgu1 || 0 != rgu0) {
                    this.error++;
                }
            }