about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAbseil Team <absl-team@google.com>2019-10-16T22·51-0700
committerAndy Soffer <asoffer@google.com>2019-10-17T18·43-0400
commita15364ce4d88534ae2295127e5d8e32aefb6b446 (patch)
treec01afa5f859f563b7bfd8cfdafa6b6fd1fed3aa6
parentab3552a18964e7063c8324f45b3896a6a20b08a8 (diff)
Export of internal Abseil changes
--
d35c72d705155dcd89a92835103540f14c643d10 by Gennadiy Rozental <rogeeff@google.com>:

helpxml changed to report types of flags with built-in value type.

PiperOrigin-RevId: 275131440

--
f3478792943d7dd40a6ef6083a8e5d374f43a65e by Abseil Team <absl-team@google.com>:

Add space padding tests for hex conversions.

PiperOrigin-RevId: 275120155

--
7c2e4725403e173660f33f94af686a75d3722936 by Andy Soffer <asoffer@google.com>:

Fix https://github.com/abseil/abseil-cpp/issues/379
by renaming `roundup` to `round_up`

PiperOrigin-RevId: 275106110

--
84cb30d6ee509961ac4359cfdda1360973b9527d by Laramie Leavitt <lar@google.com>:

Move random_internal::wide_multiply into a file by the same name.

PiperOrigin-RevId: 275059359

--
06d691a8c187b5d899e7863784b23bdcfd580cb2 by Abseil Team <absl-team@google.com>:

Add missing "return" keyword.

PiperOrigin-RevId: 275036408
GitOrigin-RevId: d35c72d705155dcd89a92835103540f14c643d10
Change-Id: Id837b4de6c9cfe18f0a088363754bfe389df985b
-rw-r--r--absl/base/internal/low_level_alloc.cc16
-rw-r--r--absl/flags/flag.h2
-rw-r--r--absl/flags/internal/usage.cc26
-rw-r--r--absl/random/BUILD.bazel1
-rw-r--r--absl/random/CMakeLists.txt34
-rw-r--r--absl/random/internal/BUILD.bazel27
-rw-r--r--absl/random/internal/distribution_impl.h66
-rw-r--r--absl/random/internal/distribution_impl_test.cc42
-rw-r--r--absl/random/internal/wide_multiply.h109
-rw-r--r--absl/random/internal/wide_multiply_test.cc66
-rw-r--r--absl/random/uniform_int_distribution.h1
-rw-r--r--absl/strings/numbers_test.cc3
12 files changed, 275 insertions, 118 deletions
diff --git a/absl/base/internal/low_level_alloc.cc b/absl/base/internal/low_level_alloc.cc
index 64d7aa80b131..f7314ab18998 100644
--- a/absl/base/internal/low_level_alloc.cc
+++ b/absl/base/internal/low_level_alloc.cc
@@ -211,7 +211,7 @@ struct LowLevelAlloc::Arena {
   // Result of sysconf(_SC_PAGESIZE)
   const size_t pagesize;
   // Lowest power of two >= max(16, sizeof(AllocList))
-  const size_t roundup;
+  const size_t round_up;
   // Smallest allocation block size
   const size_t min_size;
   // PRNG state
@@ -336,11 +336,11 @@ size_t GetPageSize() {
 
 size_t RoundedUpBlockSize() {
   // Round up block sizes to a power of two close to the header size.
-  size_t roundup = 16;
-  while (roundup < sizeof(AllocList::Header)) {
-    roundup += roundup;
+  size_t round_up = 16;
+  while (round_up < sizeof(AllocList::Header)) {
+    round_up += round_up;
   }
-  return roundup;
+  return round_up;
 }
 
 }  // namespace
@@ -350,8 +350,8 @@ LowLevelAlloc::Arena::Arena(uint32_t flags_value)
       allocation_count(0),
       flags(flags_value),
       pagesize(GetPageSize()),
-      roundup(RoundedUpBlockSize()),
-      min_size(2 * roundup),
+      round_up(RoundedUpBlockSize()),
+      min_size(2 * round_up),
       random(0) {
   freelist.header.size = 0;
   freelist.header.magic =
@@ -528,7 +528,7 @@ static void *DoAllocWithArena(size_t request, LowLevelAlloc::Arena *arena) {
     ArenaLock section(arena);
     // round up with header
     size_t req_rnd = RoundUp(CheckedAdd(request, sizeof (s->header)),
-                             arena->roundup);
+                             arena->round_up);
     for (;;) {      // loop until we find a suitable region
       // find the minimum levels that a block of this size must have
       int i = LLA_SkiplistLevels(req_rnd, arena->min_size, nullptr) - 1;
diff --git a/absl/flags/flag.h b/absl/flags/flag.h
index 4927757b8fbe..85900ef81b33 100644
--- a/absl/flags/flag.h
+++ b/absl/flags/flag.h
@@ -121,7 +121,7 @@ class Flag {
   bool IsModified() const { return GetImpl()->IsModified(); }
   void SetModified(bool is_modified) { GetImpl()->SetModified(is_modified); }
   bool IsSpecifiedOnCommandLine() const {
-    GetImpl()->IsSpecifiedOnCommandLine();
+    return GetImpl()->IsSpecifiedOnCommandLine();
   }
   absl::string_view Typename() const { return GetImpl()->Typename(); }
   std::string Filename() const { return GetImpl()->Filename(); }
diff --git a/absl/flags/internal/usage.cc b/absl/flags/internal/usage.cc
index 03048514ae0b..181c35c61901 100644
--- a/absl/flags/internal/usage.cc
+++ b/absl/flags/internal/usage.cc
@@ -47,6 +47,27 @@ namespace absl {
 namespace flags_internal {
 namespace {
 
+absl::string_view TypenameForHelp(const flags_internal::CommandLineFlag& flag) {
+  // Only report names of v1 built-in types
+#define HANDLE_V1_BUILTIN_TYPE(t) \
+  if (flag.IsOfType<t>()) {       \
+    return #t;                    \
+  }
+
+  HANDLE_V1_BUILTIN_TYPE(bool);
+  HANDLE_V1_BUILTIN_TYPE(int32_t);
+  HANDLE_V1_BUILTIN_TYPE(int64_t);
+  HANDLE_V1_BUILTIN_TYPE(uint64_t);
+  HANDLE_V1_BUILTIN_TYPE(double);
+#undef HANDLE_V1_BUILTIN_TYPE
+
+  if (flag.IsOfType<std::string>()) {
+    return "string";
+  }
+
+  return "";
+}
+
 // This class is used to emit an XML element with `tag` and `text`.
 // It adds opening and closing tags and escapes special characters in the text.
 // For example:
@@ -186,7 +207,7 @@ void FlagHelpHumanReadable(const flags_internal::CommandLineFlag& flag,
 
   // Flag data type (for V1 flags only).
   if (!flag.IsAbseilFlag() && !flag.IsRetired()) {
-    printer.Write(absl::StrCat("type: ", flag.Typename(), ";"));
+    printer.Write(absl::StrCat("type: ", TypenameForHelp(flag), ";"));
   }
 
   // The listed default value will be the actual default from the flag
@@ -223,6 +244,9 @@ void FlagsHelpImpl(std::ostream& out, flags_internal::FlagKindFilter filter_cb,
   } else {
     // XML schema is not a part of our public API for now.
     out << "<?xml version=\"1.0\"?>\n"
+        << "<!-- This output should be used with care. We do not report type "
+           "names for flags with user defined types -->\n"
+        << "<!-- Prefer flag only_check_args for validating flag inputs -->\n"
         // The document.
         << "<AllFlags>\n"
         // The program name and usage.
diff --git a/absl/random/BUILD.bazel b/absl/random/BUILD.bazel
index 92111827c150..828f1348bacb 100644
--- a/absl/random/BUILD.bazel
+++ b/absl/random/BUILD.bazel
@@ -76,6 +76,7 @@ cc_library(
         "//absl/random/internal:iostream_state_saver",
         "//absl/random/internal:traits",
         "//absl/random/internal:uniform_helper",
+        "//absl/random/internal:wide_multiply",
         "//absl/strings",
         "//absl/types:span",
     ],
diff --git a/absl/random/CMakeLists.txt b/absl/random/CMakeLists.txt
index 151cefa4bf1b..19dd2cabf57a 100644
--- a/absl/random/CMakeLists.txt
+++ b/absl/random/CMakeLists.txt
@@ -65,6 +65,7 @@ absl_cc_library(
     absl::random_internal_iostream_state_saver
     absl::random_internal_traits
     absl::random_internal_uniform_helper
+    absl::random_internal_wide_multiply
     absl::strings
     absl::span
     absl::type_traits
@@ -560,6 +561,22 @@ absl_cc_library(
 # Internal-only target, do not depend on directly.
 absl_cc_library(
   NAME
+    random_internal_wide_multiply
+  HDRS
+    "internal/wide_multiply.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::bits
+    absl::config
+    absl::int128
+)
+
+# Internal-only target, do not depend on directly.
+absl_cc_library(
+  NAME
     random_internal_fastmath
   HDRS
     "internal/fastmath.h"
@@ -1033,3 +1050,20 @@ absl_cc_test(
     absl::random_internal_iostream_state_saver
     gtest_main
 )
+
+# Internal-only target, do not depend on directly.
+absl_cc_test(
+  NAME
+    random_internal_wide_multiply_test
+  SRCS
+      internal/wide_multiply_test.cc
+  COPTS
+    ${ABSL_TEST_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::random_internal_wide_multiply
+    absl::bits
+    absl::int128
+    gtest_main
+)
diff --git a/absl/random/internal/BUILD.bazel b/absl/random/internal/BUILD.bazel
index cd50982d8b36..ec58cecd43e9 100644
--- a/absl/random/internal/BUILD.bazel
+++ b/absl/random/internal/BUILD.bazel
@@ -201,6 +201,19 @@ cc_library(
 )
 
 cc_library(
+    name = "wide_multiply",
+    hdrs = ["wide_multiply.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":traits",
+        "//absl/base:bits",
+        "//absl/base:config",
+        "//absl/numeric:int128",
+    ],
+)
+
+cc_library(
     name = "nonsecure_base",
     hdrs = ["nonsecure_base.h"],
     copts = ABSL_DEFAULT_COPTS,
@@ -598,6 +611,20 @@ cc_test(
     ],
 )
 
+cc_test(
+    name = "wide_multiply_test",
+    size = "small",
+    srcs = ["wide_multiply_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":wide_multiply",
+        "//absl/base:bits",
+        "//absl/numeric:int128",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
 cc_library(
     name = "nanobenchmark",
     srcs = ["nanobenchmark.cc"],
diff --git a/absl/random/internal/distribution_impl.h b/absl/random/internal/distribution_impl.h
index 9b6ffb0fb504..49b3e1a6e33d 100644
--- a/absl/random/internal/distribution_impl.h
+++ b/absl/random/internal/distribution_impl.h
@@ -188,72 +188,6 @@ struct RandU64ToReal<float> {
   }
 };
 
-inline uint128 MultiplyU64ToU128(uint64_t a, uint64_t b) {
-#if defined(ABSL_HAVE_INTRINSIC_INT128)
-  return uint128(static_cast<__uint128_t>(a) * b);
-#elif defined(ABSL_INTERNAL_USE_UMUL128)
-  // uint64_t * uint64_t => uint128 multiply using imul intrinsic on MSVC.
-  uint64_t high = 0;
-  const uint64_t low = _umul128(a, b, &high);
-  return absl::MakeUint128(high, low);
-#else
-  // uint128(a) * uint128(b) in emulated mode computes a full 128-bit x 128-bit
-  // multiply.  However there are many cases where that is not necessary, and it
-  // is only necessary to support a 64-bit x 64-bit = 128-bit multiply.  This is
-  // for those cases.
-  const uint64_t a00 = static_cast<uint32_t>(a);
-  const uint64_t a32 = a >> 32;
-  const uint64_t b00 = static_cast<uint32_t>(b);
-  const uint64_t b32 = b >> 32;
-
-  const uint64_t c00 = a00 * b00;
-  const uint64_t c32a = a00 * b32;
-  const uint64_t c32b = a32 * b00;
-  const uint64_t c64 = a32 * b32;
-
-  const uint32_t carry =
-      static_cast<uint32_t>(((c00 >> 32) + static_cast<uint32_t>(c32a) +
-                             static_cast<uint32_t>(c32b)) >>
-                            32);
-
-  return absl::MakeUint128(c64 + (c32a >> 32) + (c32b >> 32) + carry,
-                           c00 + (c32a << 32) + (c32b << 32));
-#endif
-}
-
-// wide_multiply<T> multiplies two N-bit values to a 2N-bit result.
-template <typename UIntType>
-struct wide_multiply {
-  static constexpr size_t kN = std::numeric_limits<UIntType>::digits;
-  using input_type = UIntType;
-  using result_type = typename random_internal::unsigned_bits<kN * 2>::type;
-
-  static result_type multiply(input_type a, input_type b) {
-    return static_cast<result_type>(a) * b;
-  }
-
-  static input_type hi(result_type r) { return r >> kN; }
-  static input_type lo(result_type r) { return r; }
-
-  static_assert(std::is_unsigned<UIntType>::value,
-                "Class-template wide_multiply<> argument must be unsigned.");
-};
-
-#ifndef ABSL_HAVE_INTRINSIC_INT128
-template <>
-struct wide_multiply<uint64_t> {
-  using input_type = uint64_t;
-  using result_type = uint128;
-
-  static result_type multiply(uint64_t a, uint64_t b) {
-    return MultiplyU64ToU128(a, b);
-  }
-
-  static uint64_t hi(result_type r) { return Uint128High64(r); }
-  static uint64_t lo(result_type r) { return Uint128Low64(r); }
-};
-#endif
-
 }  // namespace random_internal
 }  // namespace absl
 
diff --git a/absl/random/internal/distribution_impl_test.cc b/absl/random/internal/distribution_impl_test.cc
index 09e7a318ccc5..fcc169046d7e 100644
--- a/absl/random/internal/distribution_impl_test.cc
+++ b/absl/random/internal/distribution_impl_test.cc
@@ -461,46 +461,4 @@ TEST(DistributionImplTest, ExhaustiveFloat) {
   }
 }
 
-TEST(DistributionImplTest, MultiplyU64ToU128Test) {
-  using absl::random_internal::MultiplyU64ToU128;
-  constexpr uint64_t k1 = 1;
-  constexpr uint64_t kMax = ~static_cast<uint64_t>(0);
-
-  EXPECT_EQ(absl::uint128(0), MultiplyU64ToU128(0, 0));
-
-  // Max uint64
-  EXPECT_EQ(MultiplyU64ToU128(kMax, kMax),
-            absl::MakeUint128(0xfffffffffffffffe, 0x0000000000000001));
-  EXPECT_EQ(absl::MakeUint128(0, kMax), MultiplyU64ToU128(kMax, 1));
-  EXPECT_EQ(absl::MakeUint128(0, kMax), MultiplyU64ToU128(1, kMax));
-  for (int i = 0; i < 64; ++i) {
-    EXPECT_EQ(absl::MakeUint128(0, kMax) << i,
-              MultiplyU64ToU128(kMax, k1 << i));
-    EXPECT_EQ(absl::MakeUint128(0, kMax) << i,
-              MultiplyU64ToU128(k1 << i, kMax));
-  }
-
-  // 1-bit x 1-bit.
-  for (int i = 0; i < 64; ++i) {
-    for (int j = 0; j < 64; ++j) {
-      EXPECT_EQ(absl::MakeUint128(0, 1) << (i + j),
-                MultiplyU64ToU128(k1 << i, k1 << j));
-      EXPECT_EQ(absl::MakeUint128(0, 1) << (i + j),
-                MultiplyU64ToU128(k1 << i, k1 << j));
-    }
-  }
-
-  // Verified multiplies
-  EXPECT_EQ(MultiplyU64ToU128(0xffffeeeeddddcccc, 0xbbbbaaaa99998888),
-            absl::MakeUint128(0xbbbb9e2692c5dddc, 0xc28f7531048d2c60));
-  EXPECT_EQ(MultiplyU64ToU128(0x0123456789abcdef, 0xfedcba9876543210),
-            absl::MakeUint128(0x0121fa00ad77d742, 0x2236d88fe5618cf0));
-  EXPECT_EQ(MultiplyU64ToU128(0x0123456789abcdef, 0xfdb97531eca86420),
-            absl::MakeUint128(0x0120ae99d26725fc, 0xce197f0ecac319e0));
-  EXPECT_EQ(MultiplyU64ToU128(0x97a87f4f261ba3f2, 0xfedcba9876543210),
-            absl::MakeUint128(0x96fbf1a8ae78d0ba, 0x5a6dd4b71f278320));
-  EXPECT_EQ(MultiplyU64ToU128(0xfedcba9876543210, 0xfdb97531eca86420),
-            absl::MakeUint128(0xfc98c6981a413e22, 0x342d0bbf48948200));
-}
-
 }  // namespace
diff --git a/absl/random/internal/wide_multiply.h b/absl/random/internal/wide_multiply.h
new file mode 100644
index 000000000000..ebbfa1f2c10e
--- /dev/null
+++ b/absl/random/internal/wide_multiply.h
@@ -0,0 +1,109 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_RANDOM_INTERNAL_WIDE_MULTIPLY_H_
+#define ABSL_RANDOM_INTERNAL_WIDE_MULTIPLY_H_
+
+#include <cstdint>
+#include <limits>
+#include <type_traits>
+
+#if (defined(_WIN32) || defined(_WIN64)) && defined(_M_IA64)
+#include <intrin.h>  // NOLINT(build/include_order)
+#pragma intrinsic(_umul128)
+#define ABSL_INTERNAL_USE_UMUL128 1
+#endif
+
+#include "absl/base/config.h"
+#include "absl/base/internal/bits.h"
+#include "absl/numeric/int128.h"
+#include "absl/random/internal/traits.h"
+
+namespace absl {
+namespace random_internal {
+
+// Helper object to multiply two 64-bit values to a 128-bit value.
+// MultiplyU64ToU128 multiplies two 64-bit values to a 128-bit value.
+// If an intrinsic is available, it is used, otherwise use native 32-bit
+// multiplies to construct the result.
+inline uint128 MultiplyU64ToU128(uint64_t a, uint64_t b) {
+#if defined(ABSL_HAVE_INTRINSIC_INT128)
+  return uint128(static_cast<__uint128_t>(a) * b);
+#elif defined(ABSL_INTERNAL_USE_UMUL128)
+  // uint64_t * uint64_t => uint128 multiply using imul intrinsic on MSVC.
+  uint64_t high = 0;
+  const uint64_t low = _umul128(a, b, &high);
+  return absl::MakeUint128(high, low);
+#else
+  // uint128(a) * uint128(b) in emulated mode computes a full 128-bit x 128-bit
+  // multiply.  However there are many cases where that is not necessary, and it
+  // is only necessary to support a 64-bit x 64-bit = 128-bit multiply.  This is
+  // for those cases.
+  const uint64_t a00 = static_cast<uint32_t>(a);
+  const uint64_t a32 = a >> 32;
+  const uint64_t b00 = static_cast<uint32_t>(b);
+  const uint64_t b32 = b >> 32;
+
+  const uint64_t c00 = a00 * b00;
+  const uint64_t c32a = a00 * b32;
+  const uint64_t c32b = a32 * b00;
+  const uint64_t c64 = a32 * b32;
+
+  const uint32_t carry =
+      static_cast<uint32_t>(((c00 >> 32) + static_cast<uint32_t>(c32a) +
+                             static_cast<uint32_t>(c32b)) >>
+                            32);
+
+  return absl::MakeUint128(c64 + (c32a >> 32) + (c32b >> 32) + carry,
+                           c00 + (c32a << 32) + (c32b << 32));
+#endif
+}
+
+// wide_multiply<T> multiplies two N-bit values to a 2N-bit result.
+template <typename UIntType>
+struct wide_multiply {
+  static constexpr size_t kN = std::numeric_limits<UIntType>::digits;
+  using input_type = UIntType;
+  using result_type = typename random_internal::unsigned_bits<kN * 2>::type;
+
+  static result_type multiply(input_type a, input_type b) {
+    return static_cast<result_type>(a) * b;
+  }
+
+  static input_type hi(result_type r) { return r >> kN; }
+  static input_type lo(result_type r) { return r; }
+
+  static_assert(std::is_unsigned<UIntType>::value,
+                "Class-template wide_multiply<> argument must be unsigned.");
+};
+
+#ifndef ABSL_HAVE_INTRINSIC_INT128
+template <>
+struct wide_multiply<uint64_t> {
+  using input_type = uint64_t;
+  using result_type = uint128;
+
+  static result_type multiply(uint64_t a, uint64_t b) {
+    return MultiplyU64ToU128(a, b);
+  }
+
+  static uint64_t hi(result_type r) { return Uint128High64(r); }
+  static uint64_t lo(result_type r) { return Uint128Low64(r); }
+};
+#endif
+
+}  // namespace random_internal
+}  // namespace absl
+
+#endif  // ABSL_RANDOM_INTERNAL_WIDE_MULTIPLY_H_
diff --git a/absl/random/internal/wide_multiply_test.cc b/absl/random/internal/wide_multiply_test.cc
new file mode 100644
index 000000000000..922603f22629
--- /dev/null
+++ b/absl/random/internal/wide_multiply_test.cc
@@ -0,0 +1,66 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/random/internal/wide_multiply.h"
+
+#include "gtest/gtest.h"
+#include "absl/base/internal/bits.h"
+#include "absl/numeric/int128.h"
+
+using absl::random_internal::MultiplyU64ToU128;
+
+namespace {
+
+TEST(WideMultiplyTest, MultiplyU64ToU128Test) {
+  constexpr uint64_t k1 = 1;
+  constexpr uint64_t kMax = ~static_cast<uint64_t>(0);
+
+  EXPECT_EQ(absl::uint128(0), MultiplyU64ToU128(0, 0));
+
+  // Max uint64
+  EXPECT_EQ(MultiplyU64ToU128(kMax, kMax),
+            absl::MakeUint128(0xfffffffffffffffe, 0x0000000000000001));
+  EXPECT_EQ(absl::MakeUint128(0, kMax), MultiplyU64ToU128(kMax, 1));
+  EXPECT_EQ(absl::MakeUint128(0, kMax), MultiplyU64ToU128(1, kMax));
+  for (int i = 0; i < 64; ++i) {
+    EXPECT_EQ(absl::MakeUint128(0, kMax) << i,
+              MultiplyU64ToU128(kMax, k1 << i));
+    EXPECT_EQ(absl::MakeUint128(0, kMax) << i,
+              MultiplyU64ToU128(k1 << i, kMax));
+  }
+
+  // 1-bit x 1-bit.
+  for (int i = 0; i < 64; ++i) {
+    for (int j = 0; j < 64; ++j) {
+      EXPECT_EQ(absl::MakeUint128(0, 1) << (i + j),
+                MultiplyU64ToU128(k1 << i, k1 << j));
+      EXPECT_EQ(absl::MakeUint128(0, 1) << (i + j),
+                MultiplyU64ToU128(k1 << i, k1 << j));
+    }
+  }
+
+  // Verified multiplies
+  EXPECT_EQ(MultiplyU64ToU128(0xffffeeeeddddcccc, 0xbbbbaaaa99998888),
+            absl::MakeUint128(0xbbbb9e2692c5dddc, 0xc28f7531048d2c60));
+  EXPECT_EQ(MultiplyU64ToU128(0x0123456789abcdef, 0xfedcba9876543210),
+            absl::MakeUint128(0x0121fa00ad77d742, 0x2236d88fe5618cf0));
+  EXPECT_EQ(MultiplyU64ToU128(0x0123456789abcdef, 0xfdb97531eca86420),
+            absl::MakeUint128(0x0120ae99d26725fc, 0xce197f0ecac319e0));
+  EXPECT_EQ(MultiplyU64ToU128(0x97a87f4f261ba3f2, 0xfedcba9876543210),
+            absl::MakeUint128(0x96fbf1a8ae78d0ba, 0x5a6dd4b71f278320));
+  EXPECT_EQ(MultiplyU64ToU128(0xfedcba9876543210, 0xfdb97531eca86420),
+            absl::MakeUint128(0xfc98c6981a413e22, 0x342d0bbf48948200));
+}
+
+}  // namespace
diff --git a/absl/random/uniform_int_distribution.h b/absl/random/uniform_int_distribution.h
index 4970486a561a..02aa376555e6 100644
--- a/absl/random/uniform_int_distribution.h
+++ b/absl/random/uniform_int_distribution.h
@@ -38,6 +38,7 @@
 #include "absl/random/internal/fast_uniform_bits.h"
 #include "absl/random/internal/iostream_state_saver.h"
 #include "absl/random/internal/traits.h"
+#include "absl/random/internal/wide_multiply.h"
 
 namespace absl {
 
diff --git a/absl/strings/numbers_test.cc b/absl/strings/numbers_test.cc
index 4edf8891be3a..d964e562b985 100644
--- a/absl/strings/numbers_test.cc
+++ b/absl/strings/numbers_test.cc
@@ -204,6 +204,9 @@ void CheckHex64(uint64_t v) {
   std::string actual = absl::StrCat(absl::Hex(v, absl::kZeroPad16));
   snprintf(expected, sizeof(expected), "%016" PRIx64, static_cast<uint64_t>(v));
   EXPECT_EQ(expected, actual) << " Input " << v;
+  actual = absl::StrCat(absl::Hex(v, absl::kSpacePad16));
+  snprintf(expected, sizeof(expected), "%16" PRIx64, static_cast<uint64_t>(v));
+  EXPECT_EQ(expected, actual) << " Input " << v;
 }
 
 TEST(Numbers, TestFastPrints) {