// ~100 Cyc ex public static ULong DivRem(ULong lowDividend, ULong highDividend, ULong lowDivisor, ULong highDivisor, out ULong lowRemainder, out ULong highRemainder, out ULong highResult) { unchecked { if (0u != highDivisor) { if (0 <= (Long)highDivisor) { ULong lowProduct; ULong highProduct; ULong lowResult; ULong t; { var cc = 0; // CountLeadingZeros // ? using CountLeadingZeros is better or not? t = highDivisor; for (; 0 <= (Long)t; t <<= 1) { ++cc; } lowResult = MathEx.BigDivInternal( lowDividend >> (ULong_Misc.BitSizeAsIntUnchecked - cc) | (highDividend << cc), highDividend >> (ULong_Misc.BitSizeAsIntUnchecked - cc), (lowDivisor >> (ULong_Misc.BitSizeAsIntUnchecked - cc)) | t); } t = lowResult * highDivisor; lowProduct = MathEx.BigMul(lowResult, lowDivisor, out highProduct); highProduct += t; if (t > highProduct || highProduct > highDividend) { goto L_0001; } if (highDividend > highProduct || lowProduct <= lowDividend) { goto L_0002; } L_0001: --lowResult; highProduct = ((lowDivisor > lowProduct) ? (highProduct - highDivisor - 1u) : (highProduct - highDivisor)); lowProduct -= lowDivisor; L_0002: highResult = 0u; highRemainder = ((lowProduct > lowDividend) ? (highDividend - highProduct - 1u) : (highDividend - highProduct)); lowRemainder = lowDividend - lowProduct; return(lowResult); } else { highResult = 0u; if (highDivisor <= highDividend && (highDivisor != highDividend || lowDivisor <= lowDividend)) { lowRemainder = MathEx.SubtractUnchecked(lowDividend, highDividend, lowDivisor, highDivisor, out highRemainder); return(1u); } else { highRemainder = highDividend; lowRemainder = lowDividend; return(0u); } } } else { ULong t; highResult = Math.DivRem(highDividend, lowDivisor, out t); highRemainder = 0u; return(MathEx.BigDivRemInternal(lowDividend, t, lowDivisor, out lowRemainder)); } } }