Skip to content

Commit

Permalink
Use __int128 in multiply9x9 if available
Browse files Browse the repository at this point in the history
This reduces the time per number from around 19ns to less than 11ns if
the compiler exposes this non-standard extension. Add test to make sure
that the portable fallback path gives the same results.
  • Loading branch information
hahnjo committed Nov 23, 2020
1 parent 2856d17 commit e37bfe3
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 5 deletions.
18 changes: 14 additions & 4 deletions math/mathcore/src/mulmod.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,20 @@ void multiply9x9(const uint64_t *in1, const uint64_t *in2, uint64_t *out)
if (k < 0 || k >= 9)
continue;

uint64_t upper1 = in1[j] >> 32;
uint64_t lower1 = static_cast<uint32_t>(in1[j]);
uint64_t fac1 = in1[j];
uint64_t fac2 = in2[k];
#if defined(__SIZEOF_INT128__) && !defined(ROOT_NO_INT128)
unsigned __int128 prod = fac1;
prod = prod * fac2;

uint64_t upper2 = in2[k] >> 32;
uint64_t lower2 = static_cast<uint32_t>(in2[k]);
uint64_t upper = prod >> 64;
uint64_t lower = static_cast<uint64_t>(prod);
#else
uint64_t upper1 = fac1 >> 32;
uint64_t lower1 = static_cast<uint32_t>(fac1);

uint64_t upper2 = fac2 >> 32;
uint64_t lower2 = static_cast<uint32_t>(fac2);

// Multiply 32-bit parts, each product has a maximum value of
// (2 ** 32 - 1) ** 2 = 2 ** 64 - 2 * 2 ** 32 + 1.
Expand Down Expand Up @@ -98,6 +107,7 @@ void multiply9x9(const uint64_t *in1, const uint64_t *in2, uint64_t *out)
// (2 ** 64 - 1) ** 2 = 2 ** 128 - 2 * 2 ** 64 + 1
// with the upper bits matching the 2 ** 64 - 2 of the first case.
upper += middle_upper;
#endif

// Add to current, remember carry.
current += lower;
Expand Down
3 changes: 2 additions & 1 deletion math/mathcore/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ ROOT_ADD_GTEST(GradientUnit testGradient.cxx LIBRARIES Core MathCore Hist )

ROOT_ADD_GTEST(GradientFittingUnit testGradientFitting.cxx LIBRARIES Core MathCore Hist)

ROOT_ADD_GTEST(MulmodUnit mulmod.cxx)
ROOT_ADD_GTEST(MulmodUnitOpt mulmod_opt.cxx)
ROOT_ADD_GTEST(MulmodUnitNoInt128 mulmod_noint128.cxx)

ROOT_ADD_GTEST(RanluxppEngineTests RanluxppEngine.cxx
LIBRARIES Core MathCore)
Expand Down
File renamed without changes.
13 changes: 13 additions & 0 deletions math/mathcore/test/mulmod_noint128.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// @(#)root/mathcore:$Id$
// Author: Jonas Hahnfeld 11/2020

/*************************************************************************
* Copyright (C) 1995-2020, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/

#define ROOT_NO_INT128
#include "mulmod.icc"
12 changes: 12 additions & 0 deletions math/mathcore/test/mulmod_opt.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// @(#)root/mathcore:$Id$
// Author: Jonas Hahnfeld 11/2020

/*************************************************************************
* Copyright (C) 1995-2020, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/

#include "mulmod.icc"

0 comments on commit e37bfe3

Please sign in to comment.