001/** 002 * The MIT License (MIT) 003 * 004 * Copyright (c) 2015-2016 decimal4j (tools4j), Marco Terzer 005 * 006 * Permission is hereby granted, free of charge, to any person obtaining a copy 007 * of this software and associated documentation files (the "Software"), to deal 008 * in the Software without restriction, including without limitation the rights 009 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 010 * copies of the Software, and to permit persons to whom the Software is 011 * furnished to do so, subject to the following conditions: 012 * 013 * The above copyright notice and this permission notice shall be included in all 014 * copies or substantial portions of the Software. 015 * 016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 017 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 018 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 019 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 020 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 021 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 022 * SOFTWARE. 023 */ 024package org.decimal4j.arithmetic; 025 026import org.decimal4j.api.DecimalArithmetic; 027import org.decimal4j.scale.ScaleMetrics; 028import org.decimal4j.scale.Scales; 029import org.decimal4j.truncate.DecimalRounding; 030import org.decimal4j.truncate.TruncatedPart; 031 032/** 033 * Provides static methods to calculate division results. 034 */ 035final class Div { 036 037 private static final long LONG_MASK = 0xffffffffL; 038 039 /** 040 * Calculates unchecked division by a long value with rounding. 041 * 042 * @param rounding 043 * the decimal rounding to apply if rounding is necessary 044 * @param uDecimalDividend 045 * the unscaled decimal dividend 046 * @param lDivisor 047 * the long divisor 048 * @return the division result with rounding and no overflow checks 049 */ 050 public static final long divideByLong(DecimalRounding rounding, long uDecimalDividend, long lDivisor) { 051 final long quotient = uDecimalDividend / lDivisor; 052 final long remainder = uDecimalDividend - quotient * lDivisor; 053 return quotient + Rounding.calculateRoundingIncrementForDivision(rounding, quotient, remainder, lDivisor); 054 } 055 056 /** 057 * Calculates checked division by a long value with rounding. 058 * 059 * @param arith 060 * the arithmetic used to format numbers when throwing exceptions 061 * @param rounding 062 * the decimal rounding to apply if rounding is necessary 063 * @param uDecimalDividend 064 * the unscaled decimal dividend 065 * @param lDivisor 066 * the long divisor 067 * @return the division result with rounding and overflow checks 068 */ 069 public static final long divideByLongChecked(DecimalArithmetic arith, DecimalRounding rounding, long uDecimalDividend, long lDivisor) { 070 if (lDivisor == 0) { 071 throw new ArithmeticException("Division by zero: " + arith.toString(uDecimalDividend) + " / " + lDivisor); 072 } 073 try { 074 final long quotient = Checked.divideByLong(arith, uDecimalDividend, lDivisor); 075 final long remainder = uDecimalDividend - quotient * lDivisor; 076 final long inc = Rounding.calculateRoundingIncrementForDivision(rounding, quotient, remainder, lDivisor); 077 return Checked.add(arith, quotient, inc); 078 } catch (ArithmeticException e) { 079 Exceptions.rethrowIfRoundingNecessary(e); 080 throw Exceptions.newArithmeticExceptionWithCause("Overflow: " + arith.toString(uDecimalDividend) + " / " 081 + lDivisor, e); 082 } 083 } 084 085 /** 086 * Calculates {@code (uDecimalDividend * scaleFactor) / uDecimalDivisor} 087 * without rounding and overflow checks. 088 * 089 * @param arith 090 * the arithmetic with scale metrics and overflow mode 091 * @param uDecimalDividend 092 * the unscaled decimal dividend 093 * @param uDecimalDivisor 094 * the unscaled decimal divisor 095 * @return the division result without rounding and without overflow checks. 096 */ 097 public static final long divide(DecimalArithmetic arith, long uDecimalDividend, long uDecimalDivisor) { 098 // special cases first 099 final SpecialDivisionResult special = SpecialDivisionResult.getFor(arith, uDecimalDividend, uDecimalDivisor); 100 if (special != null) { 101 return special.divide(arith, uDecimalDividend, uDecimalDivisor); 102 } 103 // div by power of 10 104 final ScaleMetrics scaleMetrics = arith.getScaleMetrics(); 105 final ScaleMetrics pow10 = Scales.findByScaleFactor(Math.abs(uDecimalDivisor)); 106 if (pow10 != null) { 107 return Pow10.divideByPowerOf10(uDecimalDividend, scaleMetrics, uDecimalDivisor > 0, pow10); 108 } 109 return divide(uDecimalDividend, scaleMetrics, uDecimalDivisor); 110 } 111 112 /** 113 * Calculates unchecked division by an unscaled value with the given scale 114 * without rounding and overflow checks. 115 * 116 * @param uDecimalDividend 117 * the unscaled decimal dividend 118 * @param unscaledDivisor 119 * the long divisor 120 * @param scale 121 * the scale of the divisor 122 * @return the division result without rounding and without overflow checks 123 */ 124 public static final long divideByUnscaled(long uDecimalDividend, long unscaledDivisor, int scale) { 125 if (scale > Scales.MAX_SCALE) { 126 throw new IllegalArgumentException("Illegal scale, must be <=" + Scales.MAX_SCALE + " but was " + scale); 127 } 128 if (unscaledDivisor == 0 | scale == 0) { 129 return uDecimalDividend / unscaledDivisor; 130 } else if (scale < 0) { 131 if (Checked.isDivideOverflow(uDecimalDividend, unscaledDivisor)) { 132 return -Pow10.multiplyByPowerOf10(uDecimalDividend, scale); 133 } 134 return Pow10.multiplyByPowerOf10(uDecimalDividend / unscaledDivisor, scale); 135 } 136 final ScaleMetrics divisorMetrics = Scales.getScaleMetrics(scale); 137 return divide(uDecimalDividend, divisorMetrics, unscaledDivisor); 138 } 139 140 /** 141 * Calculates {@code (uDecimalDividend * scaleFactor) / uDecimalDivisor} 142 * without rounding and overflow checks. 143 * 144 * @param uDecimalDividend 145 * the unscaled decimal dividend 146 * @param divisorMetrics 147 * the metrics associated with the divisor 148 * @param uDecimalDivisor 149 * the unscaled decimal divisor 150 * @return the division result without rounding and without overflow checks. 151 */ 152 private static final long divide(long uDecimalDividend, ScaleMetrics divisorMetrics, long uDecimalDivisor) { 153 // WE WANT: uDecimalDividend * 10^scale / unscaledDivisor 154 if (divisorMetrics.isValidIntegerValue(uDecimalDividend)) { 155 // just do it, multiplication result fits in long 156 return divisorMetrics.multiplyByScaleFactor(uDecimalDividend) / uDecimalDivisor; 157 } 158 if (divisorMetrics.isValidIntegerValue(uDecimalDivisor)) { 159 // perform component wise division (reminder fits in long after scaling) 160 final long integralPart = uDecimalDividend / uDecimalDivisor; 161 final long remainder = uDecimalDividend - integralPart * uDecimalDivisor; 162 final long fractionalPart = divisorMetrics.multiplyByScaleFactor(remainder) / uDecimalDivisor; 163 return divisorMetrics.multiplyByScaleFactor(integralPart) + fractionalPart; 164 } 165 return scaleTo128divBy64(divisorMetrics, DecimalRounding.DOWN, uDecimalDividend, uDecimalDivisor); 166 } 167 168 /** 169 * Calculates {@code (uDecimalDividend * scaleFactor) / uDecimalDivisor} 170 * with rounding and without overflow checks. 171 * 172 * @param arith 173 * the arithmetic with scale metrics and overflow mode 174 * @param rounding 175 * the decimal rounding to apply if rounding is necessary 176 * @param uDecimalDividend 177 * the unscaled decimal dividend 178 * @param uDecimalDivisor 179 * the unscaled decimal divisor 180 * @return the division result with rounding and without overflow checks 181 */ 182 public static final long divide(DecimalArithmetic arith, DecimalRounding rounding, long uDecimalDividend, long uDecimalDivisor) { 183 // special cases first 184 final SpecialDivisionResult special = SpecialDivisionResult.getFor(arith, uDecimalDividend, uDecimalDivisor); 185 if (special != null) { 186 return special.divide(arith, uDecimalDividend, uDecimalDivisor); 187 } 188 // div by power of 10 189 final ScaleMetrics scaleMetrics = arith.getScaleMetrics(); 190 final ScaleMetrics pow10 = Scales.findByScaleFactor(Math.abs(uDecimalDivisor)); 191 if (pow10 != null) { 192 return Pow10.divideByPowerOf10(rounding, uDecimalDividend, scaleMetrics, uDecimalDivisor > 0, pow10); 193 } 194 return divide(rounding, uDecimalDividend, scaleMetrics, uDecimalDivisor); 195 } 196 197 /** 198 * Calculates unchecked division by an unscaled value with the given scale 199 * without rounding. 200 * 201 * @param rounding 202 * the rounding to apply 203 * @param uDecimalDividend 204 * the unscaled decimal dividend 205 * @param unscaledDivisor 206 * the long divisor 207 * @param scale 208 * the scale of the divisor 209 * @return the division result without rounding and without overflow checks 210 */ 211 public static final long divideByUnscaled(DecimalRounding rounding, long uDecimalDividend, long unscaledDivisor, int scale) { 212 if (scale > Scales.MAX_SCALE) { 213 throw new IllegalArgumentException("Illegal scale, must be <=" + Scales.MAX_SCALE + " but was " + scale); 214 } 215 if (unscaledDivisor == 0 | scale == 0) { 216 return divideByLong(rounding, uDecimalDividend, unscaledDivisor); 217 } else if (scale < 0) { 218 if (Checked.isDivideOverflow(uDecimalDividend, unscaledDivisor)) { 219 return -Pow10.multiplyByPowerOf10(RoundingInverse.SIGN_REVERSION.invert(rounding), uDecimalDividend, scale); 220 } 221 //NOTE: rounding twice could be a problem here, e.g. consider HALF_UP with 10.51 and 10.49 222 final long quot; 223 switch (rounding) { 224 case HALF_UP: 225 quot = uDecimalDividend / unscaledDivisor;//DOWN 226 break; 227 case HALF_DOWN: 228 quot = divideByLong(DecimalRounding.UP, uDecimalDividend, unscaledDivisor); 229 break; 230 case HALF_EVEN: { 231 //try HALF_UP first 232 final long quotD = uDecimalDividend / unscaledDivisor;//DOWN 233 final long powHU = Pow10.multiplyByPowerOf10(DecimalRounding.HALF_UP, quotD, scale); 234 if (0 == (powHU & 0x1)) { 235 //even, we're done 236 return powHU; 237 } 238 //odd, HALF_DOWN may be even in which case it should win 239 final long quotU = divideByLong(DecimalRounding.UP, uDecimalDividend, unscaledDivisor); 240 final long powHD = Pow10.multiplyByPowerOf10(DecimalRounding.HALF_DOWN, quotU, scale); 241 return powHD;//either even or the same as powHU 242 } 243 default: 244 quot = divideByLong(rounding, uDecimalDividend, unscaledDivisor); 245 break; 246 } 247 return Pow10.multiplyByPowerOf10(rounding, quot, scale); 248 } 249 final ScaleMetrics divisorMetrics = Scales.getScaleMetrics(scale); 250 return divide(rounding, uDecimalDividend, divisorMetrics, unscaledDivisor); 251 } 252 253 /** 254 * Calculates {@code (uDecimalDividend * scaleFactor) / uDecimalDivisor} 255 * with rounding and without overflow checks. 256 * 257 * @param rounding 258 * the decimal rounding to apply if rounding is necessary 259 * @param uDecimalDividend 260 * the unscaled decimal dividend 261 * @param divisorMetrics 262 * the metrics associated with the divisor 263 * @param uDecimalDivisor 264 * the unscaled decimal divisor 265 * @return the division result with rounding and without overflow checks 266 */ 267 private static final long divide(DecimalRounding rounding, long uDecimalDividend, ScaleMetrics divisorMetrics, long uDecimalDivisor) { 268 if (divisorMetrics.isValidIntegerValue(uDecimalDividend)) { 269 // just do it, multiplication result fits in long 270 final long scaledDividend = divisorMetrics.multiplyByScaleFactor(uDecimalDividend); 271 final long quot = scaledDividend / uDecimalDivisor; 272 final long rem = scaledDividend - quot * uDecimalDivisor; 273 return quot + Rounding.calculateRoundingIncrementForDivision(rounding, quot, rem, uDecimalDivisor); 274 } 275 if (divisorMetrics.isValidIntegerValue(uDecimalDivisor)) { 276 // perform component wise division (reminder fits in long after 277 // scaling) 278 final long integralPart = uDecimalDividend / uDecimalDivisor; 279 final long remainder = uDecimalDividend - integralPart * uDecimalDivisor; 280 final long scaledReminder = divisorMetrics.multiplyByScaleFactor(remainder); 281 final long fractionalPart = scaledReminder / uDecimalDivisor; 282 final long subFractionalPart = scaledReminder - fractionalPart * uDecimalDivisor; 283 final long truncated = divisorMetrics.multiplyByScaleFactor(integralPart) + fractionalPart; 284 return truncated + Rounding.calculateRoundingIncrementForDivision(rounding, truncated, subFractionalPart, uDecimalDivisor); 285 } 286 return Div.scaleTo128divBy64(divisorMetrics, rounding, uDecimalDividend, uDecimalDivisor); 287 } 288 289 /** 290 * Calculates {@code (uDecimalDividend * scaleFactor) / uDecimalDivisor} 291 * without rounding and with overflow checks. 292 * 293 * @param arith 294 * the arithmetic with scale metrics and overflow mode 295 * @param uDecimalDividend 296 * the unscaled decimal dividend 297 * @param uDecimalDivisor 298 * the unscaled decimal divisor 299 * @return the division result without rounding and with overflow checks 300 */ 301 public static final long divideChecked(DecimalArithmetic arith, long uDecimalDividend, long uDecimalDivisor) { 302 // special cases first 303 final SpecialDivisionResult special = SpecialDivisionResult.getFor(arith, uDecimalDividend, uDecimalDivisor); 304 if (special != null) { 305 return special.divide(arith, uDecimalDividend, uDecimalDivisor); 306 } 307 // div by power of 10 308 final ScaleMetrics scaleMetrics = arith.getScaleMetrics(); 309 final ScaleMetrics pow10 = Scales.findByScaleFactor(Math.abs(uDecimalDivisor)); 310 if (pow10 != null) { 311 return Pow10.divideByPowerOf10Checked(arith, uDecimalDividend, scaleMetrics, uDecimalDivisor > 0, pow10); 312 } 313 return divideChecked(scaleMetrics, uDecimalDividend, scaleMetrics, uDecimalDivisor); 314 } 315 316 /** 317 * Calculates unchecked division by an unscaled value with the given scale 318 * without rounding and with overflow checks. 319 * 320 * @param arith 321 * the arithmetic associated with the dividend 322 * @param uDecimalDividend 323 * the unscaled decimal dividend 324 * @param unscaledDivisor 325 * the long divisor 326 * @param scale 327 * the scale of the divisor 328 * @return the division result without rounding and with overflow checks 329 */ 330 public static final long divideByUnscaledChecked(DecimalArithmetic arith, long uDecimalDividend, long unscaledDivisor, int scale) { 331 if (scale > Scales.MAX_SCALE) { 332 throw new IllegalArgumentException("Illegal scale, must be <=" + Scales.MAX_SCALE + " but was " + scale); 333 } 334 if (uDecimalDividend == 0 & unscaledDivisor != 0) { 335 return 0; 336 } else if (scale == 0) { 337 return Checked.divideByLong(arith, uDecimalDividend, unscaledDivisor); 338 } else if (scale < 0) { 339 if (Checked.isDivideOverflow(uDecimalDividend, unscaledDivisor)) { 340 return -Pow10.multiplyByPowerOf10Checked(arith, uDecimalDividend, scale); 341 } 342 return Pow10.multiplyByPowerOf10Checked(arith, uDecimalDividend / unscaledDivisor, scale); 343 } 344 final ScaleMetrics divisorMetrics = Scales.getScaleMetrics(scale); 345 return divideChecked(arith.getScaleMetrics(), uDecimalDividend, divisorMetrics, unscaledDivisor); 346 } 347 348 /** 349 * Calculates {@code (uDecimalDividend * scaleFactor) / uDecimalDivisor} 350 * without rounding and with overflow checks. 351 * 352 * @param dividendMetrics 353 * the metrics associated with the dividend 354 * @param uDecimalDividend 355 * the unscaled decimal dividend 356 * @param divisorMetrics 357 * the scale metrics associated with the divisor 358 * @param uDecimalDivisor 359 * the unscaled decimal divisor 360 * @return the division result without rounding and with overflow checks 361 */ 362 private static final long divideChecked(ScaleMetrics dividendMetrics, long uDecimalDividend, ScaleMetrics divisorMetrics, long uDecimalDivisor) { 363 try { 364 // WE WANT: uDecimalDividend * 10^divisorScale / unscaledDivisor 365 if (divisorMetrics.isValidIntegerValue(uDecimalDividend)) { 366 // just do it, multiplication result fits in long (division can only overflow for scale=1) 367 return divisorMetrics.multiplyByScaleFactor(uDecimalDividend) / uDecimalDivisor; 368 } 369 // perform component wise division 370 final long integralPart = Checked.divideLong(uDecimalDividend, uDecimalDivisor); 371 final long remainder = uDecimalDividend - integralPart * uDecimalDivisor; 372 final long fractionalPart; 373 if (divisorMetrics.isValidIntegerValue(remainder)) { 374 // scaling and result can't overflow because of the above condition 375 fractionalPart = divisorMetrics.multiplyByScaleFactor(remainder) / uDecimalDivisor; 376 } else { 377 // result can't overflow because reminder is smaller than 378 // divisor, i.e. -1 < result < 1 379 fractionalPart = scaleTo128divBy64(divisorMetrics, DecimalRounding.DOWN, remainder, uDecimalDivisor); 380 } 381 return Checked.addLong(divisorMetrics.multiplyByScaleFactorExact(integralPart), fractionalPart); 382 } catch (ArithmeticException e) { 383 throw Exceptions.newArithmeticExceptionWithCause("Overflow: " + dividendMetrics.toString(uDecimalDividend) + " / " 384 + divisorMetrics.toString(uDecimalDivisor), e); 385 } 386 } 387 388 /** 389 * Calculates {@code (uDecimalDividend * scaleFactor) / uDecimalDivisor} 390 * with rounding and with overflow checks. 391 * 392 * @param arith 393 * the arithmetic with scale metrics and overflow mode 394 * @param rounding 395 * the decimal rounding to apply if rounding is necessary 396 * @param uDecimalDividend 397 * the unscaled decimal dividend 398 * @param uDecimalDivisor 399 * the unscaled decimal divisor 400 * @return the division result with rounding and with overflow checks 401 */ 402 public static final long divideChecked(DecimalArithmetic arith, DecimalRounding rounding, long uDecimalDividend, long uDecimalDivisor) { 403 // special cases first 404 final SpecialDivisionResult special = SpecialDivisionResult.getFor(arith, uDecimalDividend, uDecimalDivisor); 405 if (special != null) { 406 return special.divide(arith, uDecimalDividend, uDecimalDivisor); 407 } 408 // div by power of 10 409 final ScaleMetrics scaleMetrics = arith.getScaleMetrics(); 410 final ScaleMetrics pow10 = Scales.findByScaleFactor(Math.abs(uDecimalDivisor)); 411 if (pow10 != null) { 412 return Pow10.divideByPowerOf10Checked(arith, rounding, uDecimalDividend, scaleMetrics, uDecimalDivisor > 0, pow10); 413 } 414 return divideChecked(rounding, scaleMetrics, uDecimalDividend, scaleMetrics, uDecimalDivisor); 415 } 416 417 /** 418 * Calculates unchecked division by an unscaled value with the given scale 419 * without rounding and with overflow checks. 420 * 421 * @param arith 422 * the arithmetic associated with the dividend 423 * @param rounding 424 * the ronuding to apply 425 * @param uDecimalDividend 426 * the unscaled decimal dividend 427 * @param unscaledDivisor 428 * the long divisor 429 * @param scale 430 * the scale of the divisor 431 * @return the division result without rounding and with overflow checks 432 */ 433 public static final long divideByUnscaledChecked(DecimalArithmetic arith, DecimalRounding rounding, long uDecimalDividend, long unscaledDivisor, int scale) { 434 if (scale > Scales.MAX_SCALE) { 435 throw new IllegalArgumentException("Illegal scale, must be <=" + Scales.MAX_SCALE + " but was " + scale); 436 } 437 if (uDecimalDividend == 0 & unscaledDivisor != 0) { 438 return 0; 439 } else if (scale == 0) { 440 return divideByLongChecked(arith, rounding, uDecimalDividend, unscaledDivisor); 441 } else if (scale < 0) { 442 if (Checked.isDivideOverflow(uDecimalDividend, unscaledDivisor)) { 443 return -Pow10.multiplyByPowerOf10Checked(arith, RoundingInverse.SIGN_REVERSION.invert(rounding), uDecimalDividend, scale); 444 } 445 //NOTE: rounding twice could be a problem here, e.g. consider HALF_UP with 10.51 and 10.49 446 final long quot; 447 switch (rounding) { 448 case HALF_UP: 449 quot = divideByLongChecked(arith, DecimalRounding.DOWN, uDecimalDividend, unscaledDivisor); 450 break; 451 case HALF_DOWN: 452 quot = divideByLongChecked(arith, DecimalRounding.UP, uDecimalDividend, unscaledDivisor); 453 break; 454 case HALF_EVEN: { 455 //try HALF_UP first 456 final long quotD = divideByLongChecked(arith, DecimalRounding.DOWN, uDecimalDividend, unscaledDivisor); 457 final long powHU = Pow10.multiplyByPowerOf10Checked(arith, DecimalRounding.HALF_UP, quotD, scale); 458 if (0 == (powHU & 0x1)) { 459 //even, we're done 460 return powHU; 461 } 462 //odd, HALF_DOWN may be even in which case it should win 463 final long quotU = divideByLongChecked(arith, DecimalRounding.UP, uDecimalDividend, unscaledDivisor); 464 final long powHD = Pow10.multiplyByPowerOf10Checked(arith, DecimalRounding.HALF_DOWN, quotU, scale); 465 return powHD;//either even or the same as powHU 466 } 467 default: 468 quot = divideByLongChecked(arith, rounding, uDecimalDividend, unscaledDivisor); 469 break; 470 } 471 return Pow10.multiplyByPowerOf10Checked(arith, rounding, quot, scale); 472 } 473 final ScaleMetrics divisorMetrics = Scales.getScaleMetrics(scale); 474 return divideChecked(rounding, arith.getScaleMetrics(), uDecimalDividend, divisorMetrics, unscaledDivisor); 475 } 476 477 /** 478 * Calculates {@code (uDecimalDividend * scaleFactor) / uDecimalDivisor} 479 * with rounding and with overflow checks. 480 * 481 * @param rounding 482 * the ronuding to apply 483 * @param dividendMetrics 484 * the matrics associated with the dividend 485 * @param uDecimalDividend 486 * the unscaled decimal dividend 487 * @param divisorMetrics 488 * the scale metrics associated with the divisor 489 * @param uDecimalDivisor 490 * the unscaled decimal divisor 491 * @return the division result with rounding and with overflow checks 492 */ 493 private static final long divideChecked(DecimalRounding rounding, ScaleMetrics dividendMetrics, long uDecimalDividend, ScaleMetrics divisorMetrics, long uDecimalDivisor) { 494 try { 495 // WE WANT: uDecimalDividend * 10^divisorScale / unscaledDivisor 496 if (divisorMetrics.isValidIntegerValue(uDecimalDividend)) { 497 // just do it, multiplication result fits in long 498 final long scaledDividend = divisorMetrics.multiplyByScaleFactor(uDecimalDividend); 499 final long quot = scaledDividend / uDecimalDivisor;//cannot overflow for scale>1 500 final long rem = scaledDividend - quot * uDecimalDivisor; 501 502 //cannot overflow for scale > 1 because of quot 503 return quot + Rounding.calculateRoundingIncrementForDivision(rounding, quot, rem, uDecimalDivisor); 504 } 505 506 // perform component wise division 507 final long integralPart = Checked.divideLong(uDecimalDividend, uDecimalDivisor); 508 final long remainder = uDecimalDividend - integralPart * uDecimalDivisor; 509 510 if (divisorMetrics.isValidIntegerValue(remainder)) { 511 final long scaledReminder = divisorMetrics.multiplyByScaleFactor(remainder); 512 final long fractionalPart = scaledReminder / uDecimalDivisor;//cannot overflow for scale>1 513 final long subFractionalPart = scaledReminder - fractionalPart * uDecimalDivisor; 514 515 final long result = Checked.addLong(divisorMetrics.multiplyByScaleFactorExact(integralPart), fractionalPart); 516 final long inc = Rounding.calculateRoundingIncrementForDivision(rounding, result, subFractionalPart, uDecimalDivisor); 517 return Checked.addLong(result, inc); 518 } else { 519 final long fractionalPart = Div.scaleTo128divBy64(divisorMetrics, rounding, remainder, uDecimalDivisor); 520 return Checked.addLong(divisorMetrics.multiplyByScaleFactorExact(integralPart), fractionalPart); 521 } 522 } catch (ArithmeticException e) { 523 Exceptions.rethrowIfRoundingNecessary(e); 524 throw Exceptions.newArithmeticExceptionWithCause("Overflow: " + dividendMetrics.toString(uDecimalDividend) + " / " + divisorMetrics.toString(uDecimalDivisor), e); 525 } 526 } 527 528 /** 529 * Calculates {@code uDecimalDividend * scaleFactor / uDecimalDivisor} performing the multiplication into a 128 bit product 530 * and then performing a 128 by 64 bit division. 531 * 532 * @param scaleMetrics the metrics with scale factor to apply when scaling the dividend 533 * @param rounding the rounding to apply if necessary 534 * @param uDecimalDividend the dividend 535 * @param uDecimalDivisor the divisor 536 * @return the unscaled decimal result of the division, rounded if necessary and overflow checked if 537 */ 538 private static final long scaleTo128divBy64(ScaleMetrics scaleMetrics, DecimalRounding rounding, long uDecimalDividend, long uDecimalDivisor) { 539 final boolean negative = (uDecimalDividend ^ uDecimalDivisor) < 0; 540 final long absDividend = Math.abs(uDecimalDividend); 541 final long absDivisor = Math.abs(uDecimalDivisor); 542 543 // multiply by scale factor into a 128bit integer 544 // HD + Knuth's Algorithm M from [Knu2] section 4.3.1. 545 final int lFactor = (int) (absDividend & LONG_MASK); 546 final int hFactor = (int) (absDividend >>> 32); 547 final long w1, w2, w3; 548 long k, t; 549 550 t = scaleMetrics.mulloByScaleFactor(lFactor); 551 w3 = t & LONG_MASK; 552 k = t >>> 32; 553 554 t = scaleMetrics.mulloByScaleFactor(hFactor) + k; 555 w2 = t & LONG_MASK; 556 w1 = t >>> 32; 557 558 t = scaleMetrics.mulhiByScaleFactor(lFactor) + w2; 559 k = t >>> 32; 560 561 final long hScaled = scaleMetrics.mulhiByScaleFactor(hFactor) + w1 + k; 562 final long lScaled = (t << 32) + w3; 563 564 // divide 128 bit product by 64 bit divisor 565 final long hQuotient, lQuotient; 566 if (Unsigned.isLess(hScaled, absDivisor)) { 567 hQuotient = 0; 568 lQuotient = div128by64(rounding, negative, hScaled, lScaled, absDivisor); 569 } else { 570 hQuotient = Unsigned.divide(hScaled, absDivisor); 571 final long rem = hScaled - hQuotient * absDivisor; 572 lQuotient = div128by64(rounding, negative, rem, lScaled, absDivisor); 573 } 574 return lQuotient; 575 } 576 577 /** 578 * PRECONDITION: Unsigned.isLess(u1, v0) 579 * <p> 580 * Divides a 128 bit divisor by a 64 bit dividend and returns the signed 64 581 * bit result. Rounding is applied if {@code rounding != null}, otherwise 582 * the value is truncated. 583 * <p> 584 * From <a 585 * href="http://www.codeproject.com/Tips/785014/UInt-Division-Modulus" 586 * >www.codeproject.com</a>. 587 * 588 * @param neg 589 * true if result is negative 590 * @param u1 591 * high order 64 bits of dividend 592 * @param u0 593 * low order 64 bits of dividend 594 * @param v0 595 * 64 bit divisor 596 * @param rounding 597 * rounding to apply, or null to truncate result 598 * @return the signed quotient, rounded if {@code rounding != null} 599 */ 600 static final long div128by64(final DecimalRounding rounding, final boolean neg, final long u1, final long u0, final long v0) { 601 final long q, r; 602 603 final long un1, un0, vn1, vn0, un32, un21, un10; 604 long q1, q0; 605 606 final int s = Long.numberOfLeadingZeros(v0); 607 608 final long v = v0 << s; 609 vn1 = v >>> 32; 610 vn0 = v & LONG_MASK; 611 612 un32 = (u1 << s) | (u0 >>> (64 - s)) & (-s >> 63); 613 un10 = u0 << s; 614 615 un1 = un10 >>> 32; 616 un0 = un10 & LONG_MASK; 617 618 q1 = div128by64part(un32, un1, vn1, vn0); 619 un21 = (un32 << 32) + (un1 - (q1 * v)); 620 q0 = div128by64part(un21, un0, vn1, vn0); 621 q = (q1 << 32) | q0; 622 623 // apply sign and rounding 624 if (rounding == DecimalRounding.DOWN) { 625 return neg ? -q : q; 626 } 627 628 r = ((un21 << 32) + un0 - q0 * v) >>> s; 629 final TruncatedPart truncatedPart = Rounding.truncatedPartFor(Math.abs(r), v0); 630 final int inc = rounding.calculateRoundingIncrement(neg ? -1 : 1, q, truncatedPart); 631 return (neg ? -q : q) + inc; 632 } 633 634 private static final long div128by64part(final long unCB, final long unA, final long vn1, final long vn0) { 635 // quotient and reminder, first guess 636 long q = unsignedDiv64by32(unCB, vn1); 637 long rhat = unCB - q * vn1; 638 639 // correct, first attempt 640 while (q > LONG_MASK) { 641 q--; 642 rhat += vn1; 643 if (rhat > LONG_MASK) { 644 return q; 645 } 646 } 647 // correct, second attempt 648 long left = q * vn0; 649 long right = (rhat << 32) | unA; 650 while (Unsigned.isGreater(left, right)) { 651 q--; 652 rhat += vn1; 653 if (rhat > LONG_MASK) { 654 return q; 655 } 656 left -= vn0; 657 right = (rhat << 32) | unA; 658 } 659 return q; 660 } 661 662 /** 663 * Returns dividend / divisor, where the dividend and divisor are treated as 664 * unsigned 64-bit quantities. 665 * <p> 666 * From Guava's <a href= 667 * "http://docs.guava-libraries.googlecode.com/git/javadoc/src-html/com/google/common/primitives/UnsignedLongs.html" 668 * >UnsignedLongs</a>. 669 * 670 * @param dividend 671 * the dividend (numerator) 672 * @param divisor 673 * the divisor (denominator) 674 * @return the unsigned quotient {@code dividend / divisor} 675 * @throws ArithmeticException 676 * if divisor is 0 677 */ 678 private static final long unsignedDiv64by32(long dividend, long divisor) { 679 // Optimization - use signed division if dividend < 2^63 680 if (dividend >= 0) { 681 return dividend / divisor; 682 } 683 // Optimization if divisor is even 684 if (0 == (divisor & 0x1)) { 685 return (dividend >>> 1) / (divisor >>> 1); 686 } 687 688 /* 689 * Otherwise, approximate the quotient, check, and correct if necessary. 690 * Our approximation is guaranteed to be either exact or one less than 691 * the correct value. This follows from fact that floor(floor(x)/i) == 692 * floor(x/i) for any real x and integer i != 0. The proof is not quite 693 * trivial. 694 */ 695 final long quotient = ((dividend >>> 1) / divisor) << 1; 696 final long rem = dividend - quotient * divisor; 697 return quotient + (((rem >= divisor) | (rem < 0)) ? 1 : 0); 698 } 699 700 // no instances 701 private Div() { 702 super(); 703 } 704 705}