11cb0ef41Sopenharmony_ci// Copyright 2014 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/base/division-by-constant.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include <stdint.h> 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ci#include "src/base/logging.h" 101cb0ef41Sopenharmony_ci#include "src/base/macros.h" 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_cinamespace v8 { 131cb0ef41Sopenharmony_cinamespace base { 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_citemplate <class T> 161cb0ef41Sopenharmony_ciMagicNumbersForDivision<T> SignedDivisionByConstant(T d) { 171cb0ef41Sopenharmony_ci STATIC_ASSERT(static_cast<T>(0) < static_cast<T>(-1)); 181cb0ef41Sopenharmony_ci DCHECK(d != static_cast<T>(-1) && d != 0 && d != 1); 191cb0ef41Sopenharmony_ci const unsigned bits = static_cast<unsigned>(sizeof(T)) * 8; 201cb0ef41Sopenharmony_ci const T min = (static_cast<T>(1) << (bits - 1)); 211cb0ef41Sopenharmony_ci const bool neg = (min & d) != 0; 221cb0ef41Sopenharmony_ci const T ad = neg ? (0 - d) : d; 231cb0ef41Sopenharmony_ci const T t = min + (d >> (bits - 1)); 241cb0ef41Sopenharmony_ci const T anc = t - 1 - t % ad; // Absolute value of nc 251cb0ef41Sopenharmony_ci unsigned p = bits - 1; // Init. p. 261cb0ef41Sopenharmony_ci T q1 = min / anc; // Init. q1 = 2**p/|nc|. 271cb0ef41Sopenharmony_ci T r1 = min - q1 * anc; // Init. r1 = rem(2**p, |nc|). 281cb0ef41Sopenharmony_ci T q2 = min / ad; // Init. q2 = 2**p/|d|. 291cb0ef41Sopenharmony_ci T r2 = min - q2 * ad; // Init. r2 = rem(2**p, |d|). 301cb0ef41Sopenharmony_ci T delta; 311cb0ef41Sopenharmony_ci do { 321cb0ef41Sopenharmony_ci p = p + 1; 331cb0ef41Sopenharmony_ci q1 = 2 * q1; // Update q1 = 2**p/|nc|. 341cb0ef41Sopenharmony_ci r1 = 2 * r1; // Update r1 = rem(2**p, |nc|). 351cb0ef41Sopenharmony_ci if (r1 >= anc) { // Must be an unsigned comparison here. 361cb0ef41Sopenharmony_ci q1 = q1 + 1; 371cb0ef41Sopenharmony_ci r1 = r1 - anc; 381cb0ef41Sopenharmony_ci } 391cb0ef41Sopenharmony_ci q2 = 2 * q2; // Update q2 = 2**p/|d|. 401cb0ef41Sopenharmony_ci r2 = 2 * r2; // Update r2 = rem(2**p, |d|). 411cb0ef41Sopenharmony_ci if (r2 >= ad) { // Must be an unsigned comparison here. 421cb0ef41Sopenharmony_ci q2 = q2 + 1; 431cb0ef41Sopenharmony_ci r2 = r2 - ad; 441cb0ef41Sopenharmony_ci } 451cb0ef41Sopenharmony_ci delta = ad - r2; 461cb0ef41Sopenharmony_ci } while (q1 < delta || (q1 == delta && r1 == 0)); 471cb0ef41Sopenharmony_ci T mul = q2 + 1; 481cb0ef41Sopenharmony_ci return MagicNumbersForDivision<T>(neg ? (0 - mul) : mul, p - bits, false); 491cb0ef41Sopenharmony_ci} 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_citemplate <class T> 531cb0ef41Sopenharmony_ciMagicNumbersForDivision<T> UnsignedDivisionByConstant(T d, 541cb0ef41Sopenharmony_ci unsigned leading_zeros) { 551cb0ef41Sopenharmony_ci STATIC_ASSERT(static_cast<T>(0) < static_cast<T>(-1)); 561cb0ef41Sopenharmony_ci DCHECK_NE(d, 0); 571cb0ef41Sopenharmony_ci const unsigned bits = static_cast<unsigned>(sizeof(T)) * 8; 581cb0ef41Sopenharmony_ci const T ones = ~static_cast<T>(0) >> leading_zeros; 591cb0ef41Sopenharmony_ci const T min = static_cast<T>(1) << (bits - 1); 601cb0ef41Sopenharmony_ci const T max = ~static_cast<T>(0) >> 1; 611cb0ef41Sopenharmony_ci const T nc = ones - (ones - d) % d; 621cb0ef41Sopenharmony_ci bool a = false; // Init. "add" indicator. 631cb0ef41Sopenharmony_ci unsigned p = bits - 1; // Init. p. 641cb0ef41Sopenharmony_ci T q1 = min / nc; // Init. q1 = 2**p/nc 651cb0ef41Sopenharmony_ci T r1 = min - q1 * nc; // Init. r1 = rem(2**p,nc) 661cb0ef41Sopenharmony_ci T q2 = max / d; // Init. q2 = (2**p - 1)/d. 671cb0ef41Sopenharmony_ci T r2 = max - q2 * d; // Init. r2 = rem(2**p - 1, d). 681cb0ef41Sopenharmony_ci T delta; 691cb0ef41Sopenharmony_ci do { 701cb0ef41Sopenharmony_ci p = p + 1; 711cb0ef41Sopenharmony_ci if (r1 >= nc - r1) { 721cb0ef41Sopenharmony_ci q1 = 2 * q1 + 1; 731cb0ef41Sopenharmony_ci r1 = 2 * r1 - nc; 741cb0ef41Sopenharmony_ci } else { 751cb0ef41Sopenharmony_ci q1 = 2 * q1; 761cb0ef41Sopenharmony_ci r1 = 2 * r1; 771cb0ef41Sopenharmony_ci } 781cb0ef41Sopenharmony_ci if (r2 + 1 >= d - r2) { 791cb0ef41Sopenharmony_ci if (q2 >= max) a = true; 801cb0ef41Sopenharmony_ci q2 = 2 * q2 + 1; 811cb0ef41Sopenharmony_ci r2 = 2 * r2 + 1 - d; 821cb0ef41Sopenharmony_ci } else { 831cb0ef41Sopenharmony_ci if (q2 >= min) a = true; 841cb0ef41Sopenharmony_ci q2 = 2 * q2; 851cb0ef41Sopenharmony_ci r2 = 2 * r2 + 1; 861cb0ef41Sopenharmony_ci } 871cb0ef41Sopenharmony_ci delta = d - 1 - r2; 881cb0ef41Sopenharmony_ci } while (p < bits * 2 && (q1 < delta || (q1 == delta && r1 == 0))); 891cb0ef41Sopenharmony_ci return MagicNumbersForDivision<T>(q2 + 1, p - bits, a); 901cb0ef41Sopenharmony_ci} 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci// ----------------------------------------------------------------------------- 941cb0ef41Sopenharmony_ci// Instantiations. 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_citemplate struct EXPORT_TEMPLATE_DEFINE(V8_BASE_EXPORT) 971cb0ef41Sopenharmony_ci MagicNumbersForDivision<uint32_t>; 981cb0ef41Sopenharmony_citemplate struct EXPORT_TEMPLATE_DEFINE(V8_BASE_EXPORT) 991cb0ef41Sopenharmony_ci MagicNumbersForDivision<uint64_t>; 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_citemplate EXPORT_TEMPLATE_DEFINE(V8_BASE_EXPORT) 1021cb0ef41Sopenharmony_ci MagicNumbersForDivision<uint32_t> SignedDivisionByConstant(uint32_t d); 1031cb0ef41Sopenharmony_citemplate EXPORT_TEMPLATE_DEFINE(V8_BASE_EXPORT) 1041cb0ef41Sopenharmony_ci MagicNumbersForDivision<uint64_t> SignedDivisionByConstant(uint64_t d); 1051cb0ef41Sopenharmony_ci 1061cb0ef41Sopenharmony_citemplate EXPORT_TEMPLATE_DEFINE(V8_BASE_EXPORT) 1071cb0ef41Sopenharmony_ci MagicNumbersForDivision<uint32_t> UnsignedDivisionByConstant( 1081cb0ef41Sopenharmony_ci uint32_t d, unsigned leading_zeros); 1091cb0ef41Sopenharmony_citemplate EXPORT_TEMPLATE_DEFINE(V8_BASE_EXPORT) 1101cb0ef41Sopenharmony_ci MagicNumbersForDivision<uint64_t> UnsignedDivisionByConstant( 1111cb0ef41Sopenharmony_ci uint64_t d, unsigned leading_zeros); 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_ci} // namespace base 1141cb0ef41Sopenharmony_ci} // namespace v8 115