// Binary operators // Arithmetic operators /// <devdoc> /// <para>[To be supplied.]</para> /// </devdoc> public static SqlDecimal operator +(SqlDecimal x, SqlDecimal y) { if (x.IsNull || y.IsNull) return Null; ulong dwlAccum; //accumulated sum bool fMySignPos; //sign of x was positive at start bool fOpSignPos; // sign of y positive at start bool fResSignPos = true; //sign of result should be positive int MyScale; //scale of x int OpScale; //scale of y int ResScale; //scale of result int ResPrec; //precision of result int ResInteger; //number of digits for the integer part of result int culOp1; //# of UI4s in x int culOp2; //# of UI4s in y int iulData; //which UI4 we are operating on in x, y byte bLen; // length for the result x.AssertValid(); y.AssertValid(); fMySignPos = x.IsPositive; fOpSignPos = y.IsPositive; //result scale = max(s1,s2) //result precision = max(s1,s2) + max(p1-s1,p2-s2) MyScale = x.m_bScale; OpScale = y.m_bScale; // Calculate the integer part of the result. ResInteger = Math.Max((int)x.m_bPrec - MyScale, (int)y.m_bPrec - OpScale); Debug.Assert(ResInteger <= MaxPrecision); // Calculate the scale of the result. ResScale = Math.Max(MyScale, OpScale); Debug.Assert(ResScale <= MaxScale); // Calculate the precision of the result. // Add 1 for final carry. ResPrec = ResInteger + ResScale + 1; ResPrec = Math.Min(MaxPrecision, ResPrec); // If precision adjusted, scale is reduced to keep the integer part untruncated. // But discard the extra carry, only keep the integer part as ResInteger, not ResInteger + 1. Debug.Assert(ResPrec - ResInteger >= 0); if (ResPrec - ResInteger < ResScale) ResScale = ResPrec - ResInteger; // Adjust both operands to be the same scale as ResScale. if (MyScale != ResScale) x.AdjustScale(ResScale - MyScale, true); if (OpScale != ResScale) y.AdjustScale(ResScale - OpScale, true); // When sign of first operand is negative // negate all operands including result. if (!fMySignPos) { fMySignPos = !fMySignPos; fOpSignPos = !fOpSignPos; fResSignPos = !fResSignPos; } // Initialize operand lengths and pointer. culOp1 = x.m_bLen; culOp2 = y.m_bLen; uint[] rglData1 = new uint[4] { x.m_data1, x.m_data2, x.m_data3, x.m_data4 }; uint[] rglData2 = new uint[4] { y.m_data1, y.m_data2, y.m_data3, y.m_data4 }; if (fOpSignPos) { dwlAccum = 0; // CONSIDER: Call AddUlong when possible // Loop through UI4s adding operands and putting result in *this // of the operands and put result in *this for (iulData = 0; iulData < culOp1 || iulData < culOp2; iulData++) { // None of these DWORDLONG additions can overflow, as dwlAccum comes in < x_lInt32Base if (iulData < culOp1) dwlAccum += rglData1[iulData]; if (iulData < culOp2) dwlAccum += rglData2[iulData]; rglData1[iulData] = (uint)dwlAccum; // equiv to mod x_lInt32Base dwlAccum >>= 32; // equiv to div x_lInt32Base } //If carry if (dwlAccum != 0) { Debug.Assert(dwlAccum < s_ulInt32Base); //Either overflowed if (iulData == s_cNumeMax) throw new OverflowException(SQLResource.ArithOverflowMessage); // Or extended length rglData1[iulData] = (uint)dwlAccum; iulData++; } // Set result length bLen = (byte)iulData; } else { int iulLastNonZero = 0; // The last nonzero UI // When second operand is negative, switch operands // if operand2 is greater than operand1 if (x.LAbsCmp(y) < 0) { fResSignPos = !fResSignPos; uint[] rguiTemp = rglData2; rglData2 = rglData1; rglData1 = rguiTemp; culOp1 = culOp2; culOp2 = x.m_bLen; } dwlAccum = s_ulInt32Base; for (iulData = 0; iulData < culOp1 || iulData < culOp2; iulData++) { if (iulData < culOp1) dwlAccum += rglData1[iulData]; if (iulData < culOp2) dwlAccum -= rglData2[iulData]; rglData1[iulData] = (uint)dwlAccum; // equiv to mod BaseUI4 if (rglData1[iulData] != 0) iulLastNonZero = iulData; dwlAccum >>= 32; // equiv to /= BaseUI4 dwlAccum += s_ulInt32BaseForMod; // equiv to BaseUI4 - 1 } // Set length based on highest non-zero ULONG bLen = (byte)(iulLastNonZero + 1); } SqlDecimal ret = new SqlDecimal(rglData1, bLen, (byte)ResPrec, (byte)ResScale, fResSignPos); if (ret.FGt10_38() || ret.CalculatePrecision() > s_NUMERIC_MAX_PRECISION) throw new OverflowException(SQLResource.ArithOverflowMessage); if (ret.FZero()) ret.SetPositive(); ret.AssertValid(); return ret; }
public static SqlDecimal operator +(SqlDecimal x, SqlDecimal y) { int num; ulong num2; byte num11; if (x.IsNull || y.IsNull) { return Null; } bool fPositive = true; bool isPositive = x.IsPositive; bool flag2 = y.IsPositive; int bScale = x.m_bScale; int num7 = y.m_bScale; int num9 = Math.Max((int) (x.m_bPrec - bScale), (int) (y.m_bPrec - num7)); int num3 = Math.Max(bScale, num7); int num6 = (num9 + num3) + 1; num6 = Math.Min(MaxPrecision, num6); if ((num6 - num9) < num3) { num3 = num6 - num9; } if (bScale != num3) { x.AdjustScale(num3 - bScale, true); } if (num7 != num3) { y.AdjustScale(num3 - num7, true); } if (!isPositive) { isPositive = !isPositive; flag2 = !flag2; fPositive = !fPositive; } int bLen = x.m_bLen; int num4 = y.m_bLen; uint[] rglData = new uint[] { x.m_data1, x.m_data2, x.m_data3, x.m_data4 }; uint[] numArray4 = new uint[] { y.m_data1, y.m_data2, y.m_data3, y.m_data4 }; if (flag2) { num2 = 0L; num = 0; while ((num < bLen) || (num < num4)) { if (num < bLen) { num2 += rglData[num]; } if (num < num4) { num2 += numArray4[num]; } rglData[num] = (uint) num2; num2 = num2 >> 0x20; num++; } if (num2 != 0L) { if (num == x_cNumeMax) { throw new OverflowException(SQLResource.ArithOverflowMessage); } rglData[num] = (uint) num2; num++; } num11 = (byte) num; } else { int num10 = 0; if (x.LAbsCmp(y) < 0) { fPositive = !fPositive; uint[] numArray5 = numArray4; numArray4 = rglData; rglData = numArray5; bLen = num4; num4 = x.m_bLen; } num2 = x_ulInt32Base; for (num = 0; (num < bLen) || (num < num4); num++) { if (num < bLen) { num2 += rglData[num]; } if (num < num4) { num2 -= numArray4[num]; } rglData[num] = (uint) num2; if (rglData[num] != 0) { num10 = num; } num2 = num2 >> 0x20; num2 += x_ulInt32BaseForMod; } num11 = (byte) (num10 + 1); } SqlDecimal num12 = new SqlDecimal(rglData, num11, (byte) num6, (byte) num3, fPositive); if (num12.FGt10_38() || (num12.CalculatePrecision() > NUMERIC_MAX_PRECISION)) { throw new OverflowException(SQLResource.ArithOverflowMessage); } if (num12.FZero()) { num12.SetPositive(); } return num12; }