<commit_before>#include "../common/std_headers.h"
#include "./haltonseq.h"

// The 45 odd primes up to 200. It's hard to imagine wanting more than 45 axes
static vector<u_int> haltonAxes {
  3,5,7,11,13,17,19,23,27,29,31,37,41,43,47,
    53,59,61,67,71,73,79,83,89,97,
    101,103,107,109,113,127,131,137,139,149,
    151,157,163,167,173,179,181,191,193,197,199};

/*
  Return the (i)th number in the halton sequence of the given (radix)
  This approximates a uniform distribution in [0..1]
*/
double unipolarHaltonAxis(u_int i, u_int radix)
{
  if (i == 0) return 0.0;
  int digit = int(i % radix);

  double digitValue = digit;
  double placeValue = 1.0/radix;

  return (digitValue + unipolarHaltonAxis(i/radix, radix)) * placeValue;
}

/*
  Return a (ncols)-tuple of the (i)th halton sequence
*/
arma::vec unipolarHaltonRow(u_int i, size_t nCols)
{
  assert (nCols <= haltonAxes.size());
  arma::vec ret(nCols);
  for (size_t ci = 0; ci < nCols; ci++) {
    ret[ci] = unipolarHaltonAxis(i, haltonAxes[i]);
  }
  return ret;
}

/*
  Return the (i)th number in the bipolar halton sequence of the given (radix)
  This approximates a uniform distribution in [-1..1]
*/
double bipolarHaltonAxis(u_int i, u_int radix)
{
  if (i == 0) return 0.0;
  int digit = int(i % radix);

  double digitValue = (1 - (digit%2) * 2) * ((digit + 1) / 2) * 2.0;
  double placeValue = 1.0/radix;

  return (digitValue + bipolarHaltonAxis(i/radix, radix)) * placeValue;
}

arma::vec bipolarHaltonRow(u_int i, size_t nCols)
{
  assert (nCols <= haltonAxes.size());
  arma::vec ret(nCols);
  for (size_t ci = 0; ci < nCols; ci++) {
    ret[ci] = bipolarHaltonAxis(i, haltonAxes[i]);
  }
  return ret;
}

/*
  Transform two uniformly distributed variables on [0..1] to two normally distributed variables
  with mean 0 and variance 1.
  See http://en.wikipedia.org/wiki/Box-Muller_transform
*/
static arma::cx_double boxMullerTransform(double u1, double u2) {
  double factor = sqrt(-2.0 * log(u1));
  double theta = 2.0 * M_PI * u2;
  return arma::cx_double(cos(theta) * factor, sin(theta) * factor);
}

arma::vec gaussianHaltonRow(u_int i, size_t nCols)
{
  assert (nCols <= haltonAxes.size());
  arma::vec ret(nCols);
  for (size_t ci = 0; ci < nCols; ci+=2) {
    double u1 = unipolarHaltonAxis(i+1, haltonAxes[ci+0]);
    double u2 = unipolarHaltonAxis(i+1, haltonAxes[ci+1]);
    arma::cx_double z = boxMullerTransform(u1, u2);
    ret[ci] = z.real();
    if (ci+1 < nCols) ret[ci+1] = z.imag();
  }
  return ret;
}
<commit_msg>Delete haltonseq.cc<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/file_util.h"
#include "base/sys_info.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"

typedef PlatformTest SysInfoTest;

TEST_F(SysInfoTest, NumProcs) {
  // We aren't actually testing that it's correct, just that it's sane.
  EXPECT_GE(base::SysInfo::NumberOfProcessors(), 1);
}

TEST_F(SysInfoTest, AmountOfMem) {
  // We aren't actually testing that it's correct, just that it's sane.
  EXPECT_GT(base::SysInfo::AmountOfPhysicalMemory(), 0);
  EXPECT_GT(base::SysInfo::AmountOfPhysicalMemoryMB(), 0);
}

TEST_F(SysInfoTest, AmountOfFreeDiskSpace) {
  // We aren't actually testing that it's correct, just that it's sane.
  FilePath tmp_path;
  ASSERT_TRUE(file_util::GetTempDir(&tmp_path));
  EXPECT_GT(base::SysInfo::AmountOfFreeDiskSpace(tmp_path), 0)
            << tmp_path.value();
}

#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
TEST_F(SysInfoTest, OperatingSystemVersionNumbers) {
  int32 os_major_version = -1;
  int32 os_minor_version = -1;
  int32 os_bugfix_version = -1;
  base::SysInfo::OperatingSystemVersionNumbers(&os_major_version,
                                               &os_minor_version,
                                               &os_bugfix_version);
  EXPECT_GT(os_major_version, -1);
  EXPECT_GT(os_minor_version, -1);
  EXPECT_GT(os_bugfix_version, -1);
}
#endif

TEST_F(SysInfoTest, GetPrimaryDisplayDimensions) {
  // We aren't actually testing that it's correct, just that it's sane.
  int width, height;
  base::SysInfo::GetPrimaryDisplayDimensions(&width, &height);
  EXPECT_GE(width, 10);
  EXPECT_GE(height, 10);
}

TEST_F(SysInfoTest, DisplayCount) {
  // We aren't actually testing that it's correct, just that it's sane.
  EXPECT_GE(base::SysInfo::DisplayCount(), 1);
}

#if defined(OS_CHROMEOS)
TEST_F(SysInfoTest, GoogleChromeOSVersionNumbers) {
  int32 os_major_version = -1;
  int32 os_minor_version = -1;
  int32 os_bugfix_version = -1;
  std::string lsb_release("FOO=1234123.34.5\n");
  lsb_release.append(base::SysInfo::GetLinuxStandardBaseVersionKey());
  lsb_release.append("=1.2.3.4\n");
  base::SysInfo::ParseLsbRelease(lsb_release,
                                 &os_major_version,
                                 &os_minor_version,
                                 &os_bugfix_version);
  EXPECT_EQ(1, os_major_version);
  EXPECT_EQ(2, os_minor_version);
  EXPECT_EQ(3, os_bugfix_version);
}

TEST_F(SysInfoTest, GoogleChromeOSVersionNumbersFirst) {
  int32 os_major_version = -1;
  int32 os_minor_version = -1;
  int32 os_bugfix_version = -1;
  std::string lsb_release(base::SysInfo::GetLinuxStandardBaseVersionKey());
  lsb_release.append("=1.2.3.4\n");
  lsb_release.append("FOO=1234123.34.5\n");
  base::SysInfo::ParseLsbRelease(lsb_release,
                                 &os_major_version,
                                 &os_minor_version,
                                 &os_bugfix_version);
  EXPECT_EQ(1, os_major_version);
  EXPECT_EQ(2, os_minor_version);
  EXPECT_EQ(3, os_bugfix_version);
}

TEST_F(SysInfoTest, GoogleChromeOSNoVersionNumbers) {
  int32 os_major_version = -1;
  int32 os_minor_version = -1;
  int32 os_bugfix_version = -1;
  std::string lsb_release("FOO=1234123.34.5\n");
  base::SysInfo::ParseLsbRelease(lsb_release,
                                 &os_major_version,
                                 &os_minor_version,
                                 &os_bugfix_version);
  EXPECT_EQ(-1, os_major_version);
  EXPECT_EQ(-1, os_minor_version);
  EXPECT_EQ(-1, os_bugfix_version);
}

#endif  // OS_CHROMEOS
<commit_msg>Fix sys_info_unittest<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/file_util.h"
#include "base/sys_info.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"

typedef PlatformTest SysInfoTest;

TEST_F(SysInfoTest, NumProcs) {
  // We aren't actually testing that it's correct, just that it's sane.
  EXPECT_GE(base::SysInfo::NumberOfProcessors(), 1);
}

TEST_F(SysInfoTest, AmountOfMem) {
  // We aren't actually testing that it's correct, just that it's sane.
  EXPECT_GT(base::SysInfo::AmountOfPhysicalMemory(), 0);
  EXPECT_GT(base::SysInfo::AmountOfPhysicalMemoryMB(), 0);
}

TEST_F(SysInfoTest, AmountOfFreeDiskSpace) {
  // We aren't actually testing that it's correct, just that it's sane.
  FilePath tmp_path;
  ASSERT_TRUE(file_util::GetTempDir(&tmp_path));
  EXPECT_GT(base::SysInfo::AmountOfFreeDiskSpace(tmp_path), 0)
            << tmp_path.value();
}

#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
TEST_F(SysInfoTest, OperatingSystemVersionNumbers) {
  int32 os_major_version = -1;
  int32 os_minor_version = -1;
  int32 os_bugfix_version = -1;
  base::SysInfo::OperatingSystemVersionNumbers(&os_major_version,
                                               &os_minor_version,
                                               &os_bugfix_version);
  EXPECT_GT(os_major_version, -1);
  EXPECT_GT(os_minor_version, -1);
  EXPECT_GT(os_bugfix_version, -1);
}
#endif

TEST_F(SysInfoTest, GetPrimaryDisplayDimensions) {
  // We aren't actually testing that it's correct, just that it's sane.
  int width, height;
  base::SysInfo::GetPrimaryDisplayDimensions(&width, &height);
  EXPECT_GE(width, 10);
  EXPECT_GE(height, 10);
}

TEST_F(SysInfoTest, DisplayCount) {
  // We aren't actually testing that it's correct, just that it's sane.
  EXPECT_GE(base::SysInfo::DisplayCount(), 1);
}

#if defined(OS_CHROMEOS)
TEST_F(SysInfoTest, GoogleChromeOSVersionNumbers) {
  int32 os_major_version = -1;
  int32 os_minor_version = -1;
  int32 os_bugfix_version = -1;
  std::string lsb_release("FOO=1234123.34.5\n");
  lsb_release.append(base::SysInfo::GetLinuxStandardBaseVersionKey());
  lsb_release.append("=1.2.3.4\n");
  base::SysInfo::ParseLsbRelease(lsb_release,
                                 &os_major_version,
                                 &os_minor_version,
                                 &os_bugfix_version);
  EXPECT_EQ(2, os_major_version);
  EXPECT_EQ(3, os_minor_version);
  EXPECT_EQ(4, os_bugfix_version);
}

TEST_F(SysInfoTest, GoogleChromeOSVersionNumbersFirst) {
  int32 os_major_version = -1;
  int32 os_minor_version = -1;
  int32 os_bugfix_version = -1;
  std::string lsb_release(base::SysInfo::GetLinuxStandardBaseVersionKey());
  lsb_release.append("=1.2.3.4\n");
  lsb_release.append("FOO=1234123.34.5\n");
  base::SysInfo::ParseLsbRelease(lsb_release,
                                 &os_major_version,
                                 &os_minor_version,
                                 &os_bugfix_version);
  EXPECT_EQ(2, os_major_version);
  EXPECT_EQ(3, os_minor_version);
  EXPECT_EQ(4, os_bugfix_version);
}

TEST_F(SysInfoTest, GoogleChromeOSNoVersionNumbers) {
  int32 os_major_version = -1;
  int32 os_minor_version = -1;
  int32 os_bugfix_version = -1;
  std::string lsb_release("FOO=1234123.34.5\n");
  base::SysInfo::ParseLsbRelease(lsb_release,
                                 &os_major_version,
                                 &os_minor_version,
                                 &os_bugfix_version);
  EXPECT_EQ(-1, os_major_version);
  EXPECT_EQ(-1, os_minor_version);
  EXPECT_EQ(-1, os_bugfix_version);
}

#endif  // OS_CHROMEOS
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <windows.h>
#include <mmsystem.h>
#include <process.h>

#include "base/time.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

class MockTimeTicks : public TimeTicks {
 public:
  static DWORD Ticker() {
    return static_cast<int>(InterlockedIncrement(&ticker_));
  }

  static void InstallTicker() {
    old_tick_function_ = SetMockTickFunction(&Ticker);
    ticker_ = -5;
  }

  static void UninstallTicker() {
    SetMockTickFunction(old_tick_function_);
  }

 private:
  static volatile LONG ticker_;
  static TickFunctionType old_tick_function_;
};

volatile LONG MockTimeTicks::ticker_;
MockTimeTicks::TickFunctionType MockTimeTicks::old_tick_function_;

HANDLE g_rollover_test_start;

unsigned __stdcall RolloverTestThreadMain(void* param) {
  int64 counter = reinterpret_cast<int64>(param);
  DWORD rv = WaitForSingleObject(g_rollover_test_start, INFINITE);
  EXPECT_EQ(rv, WAIT_OBJECT_0);

  TimeTicks last = TimeTicks::Now();
  for (int index = 0; index < counter; index++) {
    TimeTicks now = TimeTicks::Now();
    int64 milliseconds = (now - last).InMilliseconds();
    // This is a tight loop; we could have looped faster than our
    // measurements, so the time might be 0 millis.
    EXPECT_GE(milliseconds, 0);
    EXPECT_LT(milliseconds, 250);
    last = now;
  }
  return 0;
}

}  // namespace

TEST(TimeTicks, WinRollover) {
  // The internal counter rolls over at ~49days.  We'll use a mock
  // timer to test this case.
  // Basic test algorithm:
  //   1) Set clock to rollover - N
  //   2) Create N threads
  //   3) Start the threads
  //   4) Each thread loops through TimeTicks() N times
  //   5) Each thread verifies integrity of result.

  const int kThreads = 8;
  // Use int64 so we can cast into a void* without a compiler warning.
  const int64 kChecks = 10;

  // It takes a lot of iterations to reproduce the bug!
  // (See bug 1081395)
  for (int loop = 0; loop < 4096; loop++) {
    // Setup
    MockTimeTicks::InstallTicker();
    g_rollover_test_start = CreateEvent(0, TRUE, FALSE, 0);
    HANDLE threads[kThreads];

    for (int index = 0; index < kThreads; index++) {
      void* argument = reinterpret_cast<void*>(kChecks);
      unsigned thread_id;
      threads[index] = reinterpret_cast<HANDLE>(
        _beginthreadex(NULL, 0, RolloverTestThreadMain, argument, 0,
          &thread_id));
      EXPECT_NE((HANDLE)NULL, threads[index]);
    }

    // Start!
    SetEvent(g_rollover_test_start);

    // Wait for threads to finish
    for (int index = 0; index < kThreads; index++) {
      DWORD rv = WaitForSingleObject(threads[index], INFINITE);
      EXPECT_EQ(rv, WAIT_OBJECT_0);
    }

    CloseHandle(g_rollover_test_start);

    // Teardown
    MockTimeTicks::UninstallTicker();
  }
}

TEST(TimeTicks, SubMillisecondTimers) {
  // Loop for a bit getting timers quickly.  We want to
  // see at least one case where we get a new sample in
  // less than one millisecond.
  bool saw_submillisecond_timer = false;
  int64 min_timer = 1000;
  TimeTicks last_time = TimeTicks::HighResNow();
  for (int index = 0; index < 1000; index++) {
    TimeTicks now = TimeTicks::HighResNow();
    TimeDelta delta = now - last_time;
    if (delta.InMicroseconds() > 0 &&
        delta.InMicroseconds() < 1000) {
      if (min_timer > delta.InMicroseconds())
        min_timer = delta.InMicroseconds();
      saw_submillisecond_timer = true;
    }
    last_time = now;
  }
  EXPECT_TRUE(saw_submillisecond_timer);
  printf("Min timer is: %dus\n", min_timer);
}

TEST(TimeTicks, TimeGetTimeCaps) {
  // Test some basic assumptions that we expect about how timeGetDevCaps works.

  TIMECAPS caps;
  MMRESULT status = timeGetDevCaps(&caps, sizeof(caps));
  EXPECT_EQ(TIMERR_NOERROR, status);
  if (status != TIMERR_NOERROR) {
    printf("Could not get timeGetDevCaps\n");
    return;
  }

  EXPECT_GE(static_cast<int>(caps.wPeriodMin), 1);
  EXPECT_GT(static_cast<int>(caps.wPeriodMax), 1);
  EXPECT_GE(static_cast<int>(caps.wPeriodMin), 1);
  EXPECT_GT(static_cast<int>(caps.wPeriodMax), 1);
  printf("timeGetTime range is %d to %dms\n", caps.wPeriodMin,
    caps.wPeriodMax);
}

TEST(TimeTicks, QueryPerformanceFrequency) {
  // Test some basic assumptions that we expect about QPC.

  LARGE_INTEGER frequency;
  BOOL rv = QueryPerformanceFrequency(&frequency);
  EXPECT_EQ(TRUE, rv);
  EXPECT_GT(frequency.QuadPart, 1000000);  // Expect at least 1MHz
  printf("QueryPerformanceFrequency is %5.2fMHz\n",
    frequency.QuadPart / 1000000.0);
}

TEST(TimeTicks, TimerPerformance) {
  // Verify that various timer mechanisms can always complete quickly.
  // Note:  This is a somewhat arbitrary test.
  const int kLoops = 10000;
  const int kMaxTime = 10;  // Maximum acceptible milliseconds for test.

  typedef TimeTicks (*TestFunc)();
  struct TestCase {
    TestFunc func;
    char *description;
  };
  // Cheating a bit here:  assumes sizeof(TimeTicks) == sizeof(Time)
  // in order to create a single test case list.
  COMPILE_ASSERT(sizeof(TimeTicks) == sizeof(Time),
                 test_only_works_with_same_sizes);
  TestCase cases[] = {
    { reinterpret_cast<TestFunc>(Time::Now), "Time::Now" },
    { TimeTicks::Now, "TimeTicks::Now" },
    { TimeTicks::HighResNow, "TimeTicks::HighResNow" },
    { NULL, "" }
  };

  int test_case = 0;
  while (cases[test_case].func) {
    TimeTicks start = TimeTicks::HighResNow();
    for (int index = 0; index < kLoops; index++)
      cases[test_case].func();
    TimeTicks stop = TimeTicks::HighResNow();
    EXPECT_LT((stop - start).InMilliseconds(), kMaxTime);
    printf("%s: %1.2fus per call\n", cases[test_case].description,
      (stop - start).InMillisecondsF() * 1000 / kLoops);
    test_case++;
  }
}
<commit_msg>Increase min throttle on the new timer performance test. This is an arbitrary timer, but these tests run slower than I expected on the bbots.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <windows.h>
#include <mmsystem.h>
#include <process.h>

#include "base/time.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

class MockTimeTicks : public TimeTicks {
 public:
  static DWORD Ticker() {
    return static_cast<int>(InterlockedIncrement(&ticker_));
  }

  static void InstallTicker() {
    old_tick_function_ = SetMockTickFunction(&Ticker);
    ticker_ = -5;
  }

  static void UninstallTicker() {
    SetMockTickFunction(old_tick_function_);
  }

 private:
  static volatile LONG ticker_;
  static TickFunctionType old_tick_function_;
};

volatile LONG MockTimeTicks::ticker_;
MockTimeTicks::TickFunctionType MockTimeTicks::old_tick_function_;

HANDLE g_rollover_test_start;

unsigned __stdcall RolloverTestThreadMain(void* param) {
  int64 counter = reinterpret_cast<int64>(param);
  DWORD rv = WaitForSingleObject(g_rollover_test_start, INFINITE);
  EXPECT_EQ(rv, WAIT_OBJECT_0);

  TimeTicks last = TimeTicks::Now();
  for (int index = 0; index < counter; index++) {
    TimeTicks now = TimeTicks::Now();
    int64 milliseconds = (now - last).InMilliseconds();
    // This is a tight loop; we could have looped faster than our
    // measurements, so the time might be 0 millis.
    EXPECT_GE(milliseconds, 0);
    EXPECT_LT(milliseconds, 250);
    last = now;
  }
  return 0;
}

}  // namespace

TEST(TimeTicks, WinRollover) {
  // The internal counter rolls over at ~49days.  We'll use a mock
  // timer to test this case.
  // Basic test algorithm:
  //   1) Set clock to rollover - N
  //   2) Create N threads
  //   3) Start the threads
  //   4) Each thread loops through TimeTicks() N times
  //   5) Each thread verifies integrity of result.

  const int kThreads = 8;
  // Use int64 so we can cast into a void* without a compiler warning.
  const int64 kChecks = 10;

  // It takes a lot of iterations to reproduce the bug!
  // (See bug 1081395)
  for (int loop = 0; loop < 4096; loop++) {
    // Setup
    MockTimeTicks::InstallTicker();
    g_rollover_test_start = CreateEvent(0, TRUE, FALSE, 0);
    HANDLE threads[kThreads];

    for (int index = 0; index < kThreads; index++) {
      void* argument = reinterpret_cast<void*>(kChecks);
      unsigned thread_id;
      threads[index] = reinterpret_cast<HANDLE>(
        _beginthreadex(NULL, 0, RolloverTestThreadMain, argument, 0,
          &thread_id));
      EXPECT_NE((HANDLE)NULL, threads[index]);
    }

    // Start!
    SetEvent(g_rollover_test_start);

    // Wait for threads to finish
    for (int index = 0; index < kThreads; index++) {
      DWORD rv = WaitForSingleObject(threads[index], INFINITE);
      EXPECT_EQ(rv, WAIT_OBJECT_0);
    }

    CloseHandle(g_rollover_test_start);

    // Teardown
    MockTimeTicks::UninstallTicker();
  }
}

TEST(TimeTicks, SubMillisecondTimers) {
  // Loop for a bit getting timers quickly.  We want to
  // see at least one case where we get a new sample in
  // less than one millisecond.
  bool saw_submillisecond_timer = false;
  int64 min_timer = 1000;
  TimeTicks last_time = TimeTicks::HighResNow();
  for (int index = 0; index < 1000; index++) {
    TimeTicks now = TimeTicks::HighResNow();
    TimeDelta delta = now - last_time;
    if (delta.InMicroseconds() > 0 &&
        delta.InMicroseconds() < 1000) {
      if (min_timer > delta.InMicroseconds())
        min_timer = delta.InMicroseconds();
      saw_submillisecond_timer = true;
    }
    last_time = now;
  }
  EXPECT_TRUE(saw_submillisecond_timer);
  printf("Min timer is: %dus\n", min_timer);
}

TEST(TimeTicks, TimeGetTimeCaps) {
  // Test some basic assumptions that we expect about how timeGetDevCaps works.

  TIMECAPS caps;
  MMRESULT status = timeGetDevCaps(&caps, sizeof(caps));
  EXPECT_EQ(TIMERR_NOERROR, status);
  if (status != TIMERR_NOERROR) {
    printf("Could not get timeGetDevCaps\n");
    return;
  }

  EXPECT_GE(static_cast<int>(caps.wPeriodMin), 1);
  EXPECT_GT(static_cast<int>(caps.wPeriodMax), 1);
  EXPECT_GE(static_cast<int>(caps.wPeriodMin), 1);
  EXPECT_GT(static_cast<int>(caps.wPeriodMax), 1);
  printf("timeGetTime range is %d to %dms\n", caps.wPeriodMin,
    caps.wPeriodMax);
}

TEST(TimeTicks, QueryPerformanceFrequency) {
  // Test some basic assumptions that we expect about QPC.

  LARGE_INTEGER frequency;
  BOOL rv = QueryPerformanceFrequency(&frequency);
  EXPECT_EQ(TRUE, rv);
  EXPECT_GT(frequency.QuadPart, 1000000);  // Expect at least 1MHz
  printf("QueryPerformanceFrequency is %5.2fMHz\n",
    frequency.QuadPart / 1000000.0);
}

TEST(TimeTicks, TimerPerformance) {
  // Verify that various timer mechanisms can always complete quickly.
  // Note:  This is a somewhat arbitrary test.
  const int kLoops = 10000;
  // Due to the fact that these run on bbots, which are horribly slow,
  // we can't really make any guarantees about minimum runtime.
  // Really, we want these to finish in ~10ms, and that is generous.
  const int kMaxTime = 35;  // Maximum acceptible milliseconds for test.

  typedef TimeTicks (*TestFunc)();
  struct TestCase {
    TestFunc func;
    char *description;
  };
  // Cheating a bit here:  assumes sizeof(TimeTicks) == sizeof(Time)
  // in order to create a single test case list.
  COMPILE_ASSERT(sizeof(TimeTicks) == sizeof(Time),
                 test_only_works_with_same_sizes);
  TestCase cases[] = {
    { reinterpret_cast<TestFunc>(Time::Now), "Time::Now" },
    { TimeTicks::Now, "TimeTicks::Now" },
    { TimeTicks::HighResNow, "TimeTicks::HighResNow" },
    { NULL, "" }
  };

  int test_case = 0;
  while (cases[test_case].func) {
    TimeTicks start = TimeTicks::HighResNow();
    for (int index = 0; index < kLoops; index++)
      cases[test_case].func();
    TimeTicks stop = TimeTicks::HighResNow();
    EXPECT_LT((stop - start).InMilliseconds(), kMaxTime);
    printf("%s: %1.2fus per call\n", cases[test_case].description,
      (stop - start).InMillisecondsF() * 1000 / kLoops);
    test_case++;
  }
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009-2010 TECHNOGERMA Systems France and/or its subsidiary(-ies).
** Contact: Technogerma Systems France Information (contact@technogerma.fr)
**
** This file is part of the CAMP library.
**
** CAMP is free software: you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** CAMP is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with CAMP.  If not, see <http://www.gnu.org/licenses/>.
**
****************************************************************************/

#ifndef CAMP_QT_QTFUNCTION_HPP
#define CAMP_QT_QTFUNCTION_HPP

#include <camp/qt/qthelper.hpp>
#include <camp/function.hpp>
#include <camp/userobject.hpp>
#include <camp/value.hpp>
#include <QMetaMethod>
#include <QVariant>
#include <QString>

namespace camp_ext
{
/**
 * \brief Specialization of camp::Function implemented using a Qt method
 *
 * This class is instanciated and returned by QtMapper<T>.
 *
 * \sa QtMapper
 */
template <typename T>
class QtFunction : public camp::Function
{
public:

    /**
     * \brief Construct the property from a QMetaProperty
     *
     * \param metaProperty Qt meta property
     */
    QtFunction(const QMetaMethod& metaMethod)
        : camp::Function(functionName(metaMethod), returnType(metaMethod), argTypes(metaMethod))
        , m_metaMethod(metaMethod)
    {
    }

    /**
     * \see Function::execute
     */
    virtual camp::Value execute(const camp::UserObject& object, const camp::Args& args) const
    {
        QVariant value(QtHelper::variantType(QMetaType::type(m_metaMethod.typeName())));
        QGenericReturnArgument ret(m_metaMethod.typeName(), value.data());

        switch (args.count())
        {
            case 0:
            {
                m_metaMethod.invoke(object.get<T*>(), Qt::DirectConnection, ret);
                break;
            }

            case 1:
            {
                QVariant arg1 = QtHelper::valueToVariant(args[0]);
                m_metaMethod.invoke(object.get<T*>(), Qt::DirectConnection, ret
                                  , QGenericArgument(arg1.typeName(), arg1.data()));
                break;
            }

            case 2:
            {
                QVariant arg1 = QtHelper::valueToVariant(args[0]);
                QVariant arg2 = QtHelper::valueToVariant(args[1]);
                m_metaMethod.invoke(object.get<T*>(), Qt::DirectConnection, ret
                                  , QGenericArgument(arg1.typeName(), arg1.data())
                                  , QGenericArgument(arg2.typeName(), arg2.data()));
                break;
            }

            case 3:
            {
                QVariant arg1 = QtHelper::valueToVariant(args[0]);
                QVariant arg2 = QtHelper::valueToVariant(args[1]);
                QVariant arg3 = QtHelper::valueToVariant(args[2]);
                m_metaMethod.invoke(object.get<T*>(), Qt::DirectConnection, ret
                                  , QGenericArgument(arg1.typeName(), arg1.data())
                                  , QGenericArgument(arg2.typeName(), arg2.data())
                                  , QGenericArgument(arg3.typeName(), arg3.data()));
                break;
            }

            case 4:
            {
                QVariant arg1 = QtHelper::valueToVariant(args[0]);
                QVariant arg2 = QtHelper::valueToVariant(args[1]);
                QVariant arg3 = QtHelper::valueToVariant(args[2]);
                QVariant arg4 = QtHelper::valueToVariant(args[3]);
                m_metaMethod.invoke(object.get<T*>(), Qt::DirectConnection, ret
                                  , QGenericArgument(arg1.typeName(), arg1.data())
                                  , QGenericArgument(arg2.typeName(), arg2.data())
                                  , QGenericArgument(arg3.typeName(), arg3.data())
                                  , QGenericArgument(arg4.typeName(), arg4.data()));
                break;
            }

            case 5:
            {
                QVariant arg1 = QtHelper::valueToVariant(args[0]);
                QVariant arg2 = QtHelper::valueToVariant(args[1]);
                QVariant arg3 = QtHelper::valueToVariant(args[2]);
                QVariant arg4 = QtHelper::valueToVariant(args[3]);
                QVariant arg5 = QtHelper::valueToVariant(args[4]);
                m_metaMethod.invoke(object.get<T*>(), Qt::DirectConnection, ret
                                  , QGenericArgument(arg1.typeName(), arg1.data())
                                  , QGenericArgument(arg2.typeName(), arg2.data())
                                  , QGenericArgument(arg3.typeName(), arg3.data())
                                  , QGenericArgument(arg4.typeName(), arg4.data())
                                  , QGenericArgument(arg5.typeName(), arg5.data()));
                break;
            }
        }

        return QtHelper::variantToValue(value);
    }

private:

    /**
     * \brief Extract the name of a meta method
     *
     * \param metaMethod Qt meta method
     *
     * \return Name of the meta method
     */
    static std::string functionName(const QMetaMethod& metaMethod)
    {
        QString signature = metaMethod.signature();
        return signature.left(signature.indexOf('(')).toStdString();
    }

    /**
     * \brief Extract the return type of a meta method
     *
     * \param metaMethod Qt meta method
     *
     * \return Return type of the meta method
     */
    static camp::Type returnType(const QMetaMethod& metaMethod)
    {
        return QtHelper::type(metaMethod.typeName());
    }

    /**
     * \brief Extract the arguments types of a meta method
     *
     * \param metaMethod Qt meta method
     *
     * \return Arguments types of the meta method
     */
    static std::vector<camp::Type> argTypes(const QMetaMethod& metaMethod)
    {
        std::vector<camp::Type> types;

        QList<QByteArray> args = metaMethod.parameterTypes();
        Q_FOREACH(QByteArray arg, args)
        {
            types.push_back(QtHelper::type(arg));
        }

        return types;
    }

private:

    QMetaMethod m_metaMethod; ///< Internal Qt method
};

} // namespace camp_ext

#endif // CAMP_QT_QTFUNCTION_HPP
<commit_msg>Fix wrong comment<commit_after>/****************************************************************************
**
** Copyright (C) 2009-2010 TECHNOGERMA Systems France and/or its subsidiary(-ies).
** Contact: Technogerma Systems France Information (contact@technogerma.fr)
**
** This file is part of the CAMP library.
**
** CAMP is free software: you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** CAMP is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with CAMP.  If not, see <http://www.gnu.org/licenses/>.
**
****************************************************************************/

#ifndef CAMP_QT_QTFUNCTION_HPP
#define CAMP_QT_QTFUNCTION_HPP

#include <camp/qt/qthelper.hpp>
#include <camp/function.hpp>
#include <camp/userobject.hpp>
#include <camp/value.hpp>
#include <QMetaMethod>
#include <QVariant>
#include <QString>

namespace camp_ext
{
/**
 * \brief Specialization of camp::Function implemented using a Qt method
 *
 * This class is instanciated and returned by QtMapper<T>.
 *
 * \sa QtMapper
 */
template <typename T>
class QtFunction : public camp::Function
{
public:

    /**
     * \brief Construct the function from a QMetaMethod
     *
     * \param metaMethod Qt meta method
     */
    QtFunction(const QMetaMethod& metaMethod)
        : camp::Function(functionName(metaMethod), returnType(metaMethod), argTypes(metaMethod))
        , m_metaMethod(metaMethod)
    {
    }

    /**
     * \see Function::execute
     */
    virtual camp::Value execute(const camp::UserObject& object, const camp::Args& args) const
    {
        QVariant value(QtHelper::variantType(QMetaType::type(m_metaMethod.typeName())));
        QGenericReturnArgument ret(m_metaMethod.typeName(), value.data());

        switch (args.count())
        {
            case 0:
            {
                m_metaMethod.invoke(object.get<T*>(), Qt::DirectConnection, ret);
                break;
            }

            case 1:
            {
                QVariant arg1 = QtHelper::valueToVariant(args[0]);
                m_metaMethod.invoke(object.get<T*>(), Qt::DirectConnection, ret
                                  , QGenericArgument(arg1.typeName(), arg1.data()));
                break;
            }

            case 2:
            {
                QVariant arg1 = QtHelper::valueToVariant(args[0]);
                QVariant arg2 = QtHelper::valueToVariant(args[1]);
                m_metaMethod.invoke(object.get<T*>(), Qt::DirectConnection, ret
                                  , QGenericArgument(arg1.typeName(), arg1.data())
                                  , QGenericArgument(arg2.typeName(), arg2.data()));
                break;
            }

            case 3:
            {
                QVariant arg1 = QtHelper::valueToVariant(args[0]);
                QVariant arg2 = QtHelper::valueToVariant(args[1]);
                QVariant arg3 = QtHelper::valueToVariant(args[2]);
                m_metaMethod.invoke(object.get<T*>(), Qt::DirectConnection, ret
                                  , QGenericArgument(arg1.typeName(), arg1.data())
                                  , QGenericArgument(arg2.typeName(), arg2.data())
                                  , QGenericArgument(arg3.typeName(), arg3.data()));
                break;
            }

            case 4:
            {
                QVariant arg1 = QtHelper::valueToVariant(args[0]);
                QVariant arg2 = QtHelper::valueToVariant(args[1]);
                QVariant arg3 = QtHelper::valueToVariant(args[2]);
                QVariant arg4 = QtHelper::valueToVariant(args[3]);
                m_metaMethod.invoke(object.get<T*>(), Qt::DirectConnection, ret
                                  , QGenericArgument(arg1.typeName(), arg1.data())
                                  , QGenericArgument(arg2.typeName(), arg2.data())
                                  , QGenericArgument(arg3.typeName(), arg3.data())
                                  , QGenericArgument(arg4.typeName(), arg4.data()));
                break;
            }

            case 5:
            {
                QVariant arg1 = QtHelper::valueToVariant(args[0]);
                QVariant arg2 = QtHelper::valueToVariant(args[1]);
                QVariant arg3 = QtHelper::valueToVariant(args[2]);
                QVariant arg4 = QtHelper::valueToVariant(args[3]);
                QVariant arg5 = QtHelper::valueToVariant(args[4]);
                m_metaMethod.invoke(object.get<T*>(), Qt::DirectConnection, ret
                                  , QGenericArgument(arg1.typeName(), arg1.data())
                                  , QGenericArgument(arg2.typeName(), arg2.data())
                                  , QGenericArgument(arg3.typeName(), arg3.data())
                                  , QGenericArgument(arg4.typeName(), arg4.data())
                                  , QGenericArgument(arg5.typeName(), arg5.data()));
                break;
            }
        }

        return QtHelper::variantToValue(value);
    }

private:

    /**
     * \brief Extract the name of a meta method
     *
     * \param metaMethod Qt meta method
     *
     * \return Name of the meta method
     */
    static std::string functionName(const QMetaMethod& metaMethod)
    {
        QString signature = metaMethod.signature();
        return signature.left(signature.indexOf('(')).toStdString();
    }

    /**
     * \brief Extract the return type of a meta method
     *
     * \param metaMethod Qt meta method
     *
     * \return Return type of the meta method
     */
    static camp::Type returnType(const QMetaMethod& metaMethod)
    {
        return QtHelper::type(metaMethod.typeName());
    }

    /**
     * \brief Extract the arguments types of a meta method
     *
     * \param metaMethod Qt meta method
     *
     * \return Arguments types of the meta method
     */
    static std::vector<camp::Type> argTypes(const QMetaMethod& metaMethod)
    {
        std::vector<camp::Type> types;

        QList<QByteArray> args = metaMethod.parameterTypes();
        Q_FOREACH(QByteArray arg, args)
        {
            types.push_back(QtHelper::type(arg));
        }

        return types;
    }

private:

    QMetaMethod m_metaMethod; ///< Internal Qt method
};

} // namespace camp_ext

#endif // CAMP_QT_QTFUNCTION_HPP
<|endoftext|>


<commit_before>/**
 * These codes are licensed under the Unlicense.
 * http://unlicense.org
 */

#ifndef COMMATA_GUARD_E8F031F6_10D8_4585_9012_CFADC2F95BA7
#define COMMATA_GUARD_E8F031F6_10D8_4585_9012_CFADC2F95BA7

#include <cassert>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <exception>
#include <iterator>
#include <limits>
#include <memory>
#include <optional>
#include <ostream>
#include <sstream>
#include <streambuf>
#include <string>
#include <type_traits>
#include <utility>

#include "formatted_output.hpp"
#include "typing_aid.hpp"

namespace commata {

class text_error_info;

class text_error :
    public std::exception
{
    struct what_holder
    {
        virtual ~what_holder() {}
        virtual const char* what() const noexcept = 0;
    };

    template <class Tr, class Allocator>
    class string_holder : public what_holder
    {
        std::basic_string<char, Tr, Allocator> s_;

    public:
        template <class T>
        explicit string_holder(T&& s) : s_(std::forward<T>(s))
        {}

        string_holder(const string_holder&) = delete;
        ~string_holder() = default;

        const char* what() const noexcept override
        {
            return s_.c_str();
        }
    };

    std::shared_ptr<what_holder> what_;
    std::pair<std::size_t, std::size_t> pos_;

public:
    static constexpr std::size_t npos = static_cast<std::size_t>(-1);

    text_error() noexcept :
        pos_(npos, npos)
    {}

    template <class Tr>
    explicit text_error(std::basic_string_view<char, Tr> what_arg) :
        text_error(std::string(what_arg.cbegin(), what_arg.cend()))
    {}

    template <class Tr, class Allocator>
    explicit text_error(std::basic_string<char, Tr, Allocator>&& what_arg) :
        what_(std::make_shared<string_holder<Tr, Allocator>>(
                std::move(what_arg))),
        pos_(npos, npos)
    {}

    explicit text_error(const char* what_arg) :
        text_error(std::string(what_arg))
    {}

    text_error(const text_error& other) = default;
    text_error(text_error&& other) = default;

    text_error& operator=(const text_error& other) noexcept
    {
        std::exception::operator=(other);
        what_ = other.what_;
        pos_ = other.pos_;
        // According to C++17 23.4.2 (1), pair's copy assignment does not throw
        // but are not marked as noexcept
        return *this;
    }

    text_error& operator=(text_error&& other) = default;

    const char* what() const noexcept override
    {
        return what_ ? what_->what() : "";
    }

    text_error& set_physical_position(
        std::size_t line = npos, std::size_t col = npos) noexcept
    {
        pos_ = std::make_pair(line, col);
        return *this;
    }

    const std::pair<std::size_t, std::size_t>* get_physical_position() const
        noexcept
    {
        return (pos_ != std::make_pair(npos, npos)) ? &pos_ : nullptr;
    }

    text_error_info info(std::size_t base = 1U) const noexcept;
};

class text_error_info
{
    const text_error* ex_;
    std::size_t base_;

public:
    text_error_info(const text_error& ex, std::size_t base) noexcept :
        ex_(std::addressof(ex)), base_(base)
    {}

    text_error_info(const text_error_info& ex) = default;
    text_error_info& operator=(const text_error_info& ex) = default;

    const text_error& error() const noexcept
    {
        return *ex_;
    }

    std::size_t get_base() const noexcept
    {
        return base_;
    }
};

inline text_error_info text_error::info(std::size_t base) const noexcept
{
    return text_error_info(*this, base);
}

namespace detail::ex {

using length_t = std::common_type_t<std::make_unsigned_t<std::streamsize>,
                                    std::size_t>;

constexpr std::streamsize nmax = std::numeric_limits<std::streamsize>::max();
constexpr length_t unmax = static_cast<length_t>(nmax);

// Prints a non-negative integer value in the decimal system
// into a sufficient-length buffer
template <std::size_t N>
std::size_t print_pos(char (&s)[N], std::size_t pos, std::size_t base)
{
    const auto len = (pos != text_error::npos)
                  && (text_error::npos - base >= pos) ?
        std::snprintf(s, N, "%zu", pos + base) :
        std::snprintf(s, N, "n/a");
    assert((len > 0 ) && (static_cast<std::size_t>(len) < N));
    return static_cast<std::size_t>(len);
}

template <class T>
std::optional<T> add(T a, T b)
{
    if (std::numeric_limits<T>::max() - a >= b) {
        return a + b;
    } else {
        return std::nullopt;
    }
}

template <class T, class... Ts>
std::optional<T> add(T a, T b, Ts... cs)
{
    if (const auto bcs = add<T>(b, cs...)) {
        return add<T>(a, *bcs);
    } else {
        return std::nullopt;
    }
}

struct literals
{
    constexpr static char and_line           [] = "; line ";
    constexpr static char text_error_at_line [] = "Text error at line ";
    constexpr static char column             [] = " column ";
};

template <class Ch, class Tr>
class sputn_engine
{
    const std::ctype<Ch>* facet_;
    std::exception_ptr ex_;

public:
    explicit sputn_engine(std::basic_ostream<Ch, Tr>& os) noexcept :
        facet_(nullptr), ex_(nullptr)
    {
        // noexcept-ness counts; we must throw exceptions only when the sentry
        // exists and beholds us
        try {
            facet_ = &std::use_facet<std::ctype<Ch>>(os.getloc());
        } catch (...) {
            ex_ = std::current_exception();
        }
    }

    bool operator()(std::basic_streambuf<Ch, Tr>* sb,
        const char* s, std::size_t n) const
    {
        if (ex_) {
            std::rethrow_exception(ex_);
        }
        for (std::size_t i = 0; i < n; ++i) {
            if (sb->sputc(facet_->widen(s[i])) == Tr::eof()) {
                return false;
            }
        }
        return true;
    }

    template <std::size_t N>
    bool operator()(std::basic_streambuf<Ch, Tr>* sb, const char(&s)[N]) const
    {
        // s shall be null terminated, so s[N - 1] is null
        assert(s[N - 1] == Ch());
        return (*this)(sb, s, N - 1);
    }
};

template <class Tr>
class sputn_engine<char, Tr>
{
public:
    explicit sputn_engine(std::basic_ostream<char, Tr>&) noexcept
    {}

    bool operator()(std::basic_streambuf<char, Tr>* sb,
        const char* s, std::size_t n) const
    {
        if constexpr (std::numeric_limits<std::size_t>::max() > unmax) {
            while (n > unmax) {
                if (sb->sputn(s, nmax) != nmax) {
                    return false;
                }
                s += unmax;
                n -= static_cast<std::size_t>(unmax);
                    // safe because n > unmax
            }
        }
        return sb->sputn(s, n) == static_cast<std::streamsize>(n);
    }

    template <std::size_t N>
    bool operator()(std::basic_streambuf<char, Tr>* sb,
        const char(&s)[N]) const
    {
        // s shall be null terminated, so s[N - 1] is null
        assert(s[N - 1] == char());
        return (*this)(sb, s, N - 1);
    }
};

template <class Ch, class Tr>
sputn_engine(std::basic_ostream<Ch, Tr>&) -> sputn_engine<Ch, Tr>;

} // end detail::ex

template <class Ch, class Tr>
std::basic_ostream<Ch, Tr>& operator<<(
    std::basic_ostream<Ch, Tr>& os, const text_error_info& i)
{
    using namespace detail::ex;

    const auto p = i.error().get_physical_position();

    if (!p) {
        return os << i.error().what();
    }

    // line
    char l[std::numeric_limits<std::size_t>::digits10 + 2];
    const auto l_len = print_pos(l, p->first, i.get_base());

    // column
    char c[std::size(l)];
    const auto c_len = print_pos(c, p->second, i.get_base());

    // what
    const char* const w = i.error().what();
    const auto w_len = std::strlen(w);

    auto n = add<length_t>(w_len, l_len, c_len,
        ((w_len > 0) ?
            std::size(literals::and_line) :
            std::size(literals::text_error_at_line)),
        std::size(literals::column) - 2);    // 2 is for two EOSs
    if (!n || (*n > unmax)) {
        // more than largest possible padding length, when 'no padding'
        // does the trick
        n = 0;
    }

    sputn_engine sputn(os);

    return detail::formatted_output(os, static_cast<std::streamsize>(*n),
        [sputn, w, w_len, l = &l[0], l_len, c = &c[0], c_len]
        (auto* sb) {
            if (w_len > 0) {
                if (!sputn(sb, w, w_len)
                 || !sputn(sb, literals::and_line)) {
                    return false;
                }
            } else if (!sputn(sb, literals::text_error_at_line)) {
                return false;
            }
            return sputn(sb, l, l_len)
                && sputn(sb, literals::column)
                && sputn(sb, c, c_len);
        });
}

inline std::string to_string(const text_error_info& i)
{
    std::ostringstream s;
    s << i;
    return std::move(s).str();
}

inline std::wstring to_wstring(const text_error_info& i)
{
    std::wostringstream s;
    s << i;
    return std::move(s).str();
}

}

#endif
<commit_msg>Take advantage of string's ctor taking string_view for text_error's ctor<commit_after>/**
 * These codes are licensed under the Unlicense.
 * http://unlicense.org
 */

#ifndef COMMATA_GUARD_E8F031F6_10D8_4585_9012_CFADC2F95BA7
#define COMMATA_GUARD_E8F031F6_10D8_4585_9012_CFADC2F95BA7

#include <cassert>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <exception>
#include <iterator>
#include <limits>
#include <memory>
#include <optional>
#include <ostream>
#include <sstream>
#include <streambuf>
#include <string>
#include <type_traits>
#include <utility>

#include "formatted_output.hpp"
#include "typing_aid.hpp"

namespace commata {

class text_error_info;

class text_error :
    public std::exception
{
    struct what_holder
    {
        virtual ~what_holder() {}
        virtual const char* what() const noexcept = 0;
    };

    template <class Tr, class Allocator>
    class string_holder : public what_holder
    {
        std::basic_string<char, Tr, Allocator> s_;

    public:
        template <class T>
        explicit string_holder(T&& s) : s_(std::forward<T>(s))
        {}

        string_holder(const string_holder&) = delete;
        ~string_holder() = default;

        const char* what() const noexcept override
        {
            return s_.c_str();
        }
    };

    std::shared_ptr<what_holder> what_;
    std::pair<std::size_t, std::size_t> pos_;

public:
    static constexpr std::size_t npos = static_cast<std::size_t>(-1);

    text_error() noexcept :
        pos_(npos, npos)
    {}

    template <class Tr>
    explicit text_error(std::basic_string_view<char, Tr> what_arg) :
        text_error(std::string(what_arg))
    {}

    template <class Tr, class Allocator>
    explicit text_error(std::basic_string<char, Tr, Allocator>&& what_arg) :
        what_(std::make_shared<string_holder<Tr, Allocator>>(
                std::move(what_arg))),
        pos_(npos, npos)
    {}

    explicit text_error(const char* what_arg) :
        text_error(std::string(what_arg))
    {}

    text_error(const text_error& other) = default;
    text_error(text_error&& other) = default;

    text_error& operator=(const text_error& other) noexcept
    {
        std::exception::operator=(other);
        what_ = other.what_;
        pos_ = other.pos_;
        // According to C++17 23.4.2 (1), pair's copy assignment does not throw
        // but are not marked as noexcept
        return *this;
    }

    text_error& operator=(text_error&& other) = default;

    const char* what() const noexcept override
    {
        return what_ ? what_->what() : "";
    }

    text_error& set_physical_position(
        std::size_t line = npos, std::size_t col = npos) noexcept
    {
        pos_ = std::make_pair(line, col);
        return *this;
    }

    const std::pair<std::size_t, std::size_t>* get_physical_position() const
        noexcept
    {
        return (pos_ != std::make_pair(npos, npos)) ? &pos_ : nullptr;
    }

    text_error_info info(std::size_t base = 1U) const noexcept;
};

class text_error_info
{
    const text_error* ex_;
    std::size_t base_;

public:
    text_error_info(const text_error& ex, std::size_t base) noexcept :
        ex_(std::addressof(ex)), base_(base)
    {}

    text_error_info(const text_error_info& ex) = default;
    text_error_info& operator=(const text_error_info& ex) = default;

    const text_error& error() const noexcept
    {
        return *ex_;
    }

    std::size_t get_base() const noexcept
    {
        return base_;
    }
};

inline text_error_info text_error::info(std::size_t base) const noexcept
{
    return text_error_info(*this, base);
}

namespace detail::ex {

using length_t = std::common_type_t<std::make_unsigned_t<std::streamsize>,
                                    std::size_t>;

constexpr std::streamsize nmax = std::numeric_limits<std::streamsize>::max();
constexpr length_t unmax = static_cast<length_t>(nmax);

// Prints a non-negative integer value in the decimal system
// into a sufficient-length buffer
template <std::size_t N>
std::size_t print_pos(char (&s)[N], std::size_t pos, std::size_t base)
{
    const auto len = (pos != text_error::npos)
                  && (text_error::npos - base >= pos) ?
        std::snprintf(s, N, "%zu", pos + base) :
        std::snprintf(s, N, "n/a");
    assert((len > 0 ) && (static_cast<std::size_t>(len) < N));
    return static_cast<std::size_t>(len);
}

template <class T>
std::optional<T> add(T a, T b)
{
    if (std::numeric_limits<T>::max() - a >= b) {
        return a + b;
    } else {
        return std::nullopt;
    }
}

template <class T, class... Ts>
std::optional<T> add(T a, T b, Ts... cs)
{
    if (const auto bcs = add<T>(b, cs...)) {
        return add<T>(a, *bcs);
    } else {
        return std::nullopt;
    }
}

struct literals
{
    constexpr static char and_line           [] = "; line ";
    constexpr static char text_error_at_line [] = "Text error at line ";
    constexpr static char column             [] = " column ";
};

template <class Ch, class Tr>
class sputn_engine
{
    const std::ctype<Ch>* facet_;
    std::exception_ptr ex_;

public:
    explicit sputn_engine(std::basic_ostream<Ch, Tr>& os) noexcept :
        facet_(nullptr), ex_(nullptr)
    {
        // noexcept-ness counts; we must throw exceptions only when the sentry
        // exists and beholds us
        try {
            facet_ = &std::use_facet<std::ctype<Ch>>(os.getloc());
        } catch (...) {
            ex_ = std::current_exception();
        }
    }

    bool operator()(std::basic_streambuf<Ch, Tr>* sb,
        const char* s, std::size_t n) const
    {
        if (ex_) {
            std::rethrow_exception(ex_);
        }
        for (std::size_t i = 0; i < n; ++i) {
            if (sb->sputc(facet_->widen(s[i])) == Tr::eof()) {
                return false;
            }
        }
        return true;
    }

    template <std::size_t N>
    bool operator()(std::basic_streambuf<Ch, Tr>* sb, const char(&s)[N]) const
    {
        // s shall be null terminated, so s[N - 1] is null
        assert(s[N - 1] == Ch());
        return (*this)(sb, s, N - 1);
    }
};

template <class Tr>
class sputn_engine<char, Tr>
{
public:
    explicit sputn_engine(std::basic_ostream<char, Tr>&) noexcept
    {}

    bool operator()(std::basic_streambuf<char, Tr>* sb,
        const char* s, std::size_t n) const
    {
        if constexpr (std::numeric_limits<std::size_t>::max() > unmax) {
            while (n > unmax) {
                if (sb->sputn(s, nmax) != nmax) {
                    return false;
                }
                s += unmax;
                n -= static_cast<std::size_t>(unmax);
                    // safe because n > unmax
            }
        }
        return sb->sputn(s, n) == static_cast<std::streamsize>(n);
    }

    template <std::size_t N>
    bool operator()(std::basic_streambuf<char, Tr>* sb,
        const char(&s)[N]) const
    {
        // s shall be null terminated, so s[N - 1] is null
        assert(s[N - 1] == char());
        return (*this)(sb, s, N - 1);
    }
};

template <class Ch, class Tr>
sputn_engine(std::basic_ostream<Ch, Tr>&) -> sputn_engine<Ch, Tr>;

} // end detail::ex

template <class Ch, class Tr>
std::basic_ostream<Ch, Tr>& operator<<(
    std::basic_ostream<Ch, Tr>& os, const text_error_info& i)
{
    using namespace detail::ex;

    const auto p = i.error().get_physical_position();

    if (!p) {
        return os << i.error().what();
    }

    // line
    char l[std::numeric_limits<std::size_t>::digits10 + 2];
    const auto l_len = print_pos(l, p->first, i.get_base());

    // column
    char c[std::size(l)];
    const auto c_len = print_pos(c, p->second, i.get_base());

    // what
    const char* const w = i.error().what();
    const auto w_len = std::strlen(w);

    auto n = add<length_t>(w_len, l_len, c_len,
        ((w_len > 0) ?
            std::size(literals::and_line) :
            std::size(literals::text_error_at_line)),
        std::size(literals::column) - 2);    // 2 is for two EOSs
    if (!n || (*n > unmax)) {
        // more than largest possible padding length, when 'no padding'
        // does the trick
        n = 0;
    }

    sputn_engine sputn(os);

    return detail::formatted_output(os, static_cast<std::streamsize>(*n),
        [sputn, w, w_len, l = &l[0], l_len, c = &c[0], c_len]
        (auto* sb) {
            if (w_len > 0) {
                if (!sputn(sb, w, w_len)
                 || !sputn(sb, literals::and_line)) {
                    return false;
                }
            } else if (!sputn(sb, literals::text_error_at_line)) {
                return false;
            }
            return sputn(sb, l, l_len)
                && sputn(sb, literals::column)
                && sputn(sb, c, c_len);
        });
}

inline std::string to_string(const text_error_info& i)
{
    std::ostringstream s;
    s << i;
    return std::move(s).str();
}

inline std::wstring to_wstring(const text_error_info& i)
{
    std::wostringstream s;
    s << i;
    return std::move(s).str();
}

}

#endif
<|endoftext|>


<commit_before>///
/// @file   pod_vector.cpp
/// @brief  Plain old data vector, like std::vector but does not
///         default initialize memory.
///
/// Copyright (C) 2022 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primesieve/pod_vector.hpp>

#include <cstdlib>
#include <iostream>
#include <random>
#include <numeric>
#include <utility>

using std::size_t;
using primesieve::pod_vector;

void check(bool OK)
{
  std::cout << "   " << (OK ? "OK" : "ERROR") << "\n";
  if (!OK)
    std::exit(1);
}

int main()
{
  // The pod_vector class uses std::vector internally. For
  // performance reasons we want vector::resize() not to
  // free memory when resizing to a smaller size. The C++
  // standard seems to indirectly guarantee this behavior,
  // but it is not 100% clear. So this tests verifies this
  // behavior.

  // Allocate from 1 KiB to 128 MiB
  for (size_t i = 10; i <= 27; i++)
  {
    pod_vector<char> vect;
    vect.resize(size_t(1) << i);
    auto capacity1 = vect.capacity();
    vect.resize(100);
    auto capacity2 = vect.capacity();

    std::cout << "vect.resize(100).capacity = " << capacity1;
    check(capacity1 == capacity2);
  }

  {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<std::size_t> dist(100, 200);

    std::size_t n = dist(gen);
    pod_vector<size_t> vect;

    for (size_t i = 0; i <= n; i++)
      vect.push_back(i);

    for (size_t i = 0; i <= n; i++)
    {
      std::cout << "vect.push_back(" << i << ") = " << i;
      check(vect[i] == i);
    }
  }

  {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<std::size_t> dist(100, 200);

    std::size_t size = dist(gen);

    // pod_vector does not default initialize POD types
    // but it does initialize classes and structs with constructors.
    struct pod_t
    {
      pod_t() = default;
      pod_t(int i, int j) : a(i), b(j) { }
      int a = 100;
      int b = 200;
    };

    pod_vector<pod_t> vect(size);

    for (size_t i = 0; i < size; i++)
    {
      std::cout << "vect[i].a = " << vect[i].a;
      check(vect[i].a == 100);
      std::cout << "vect[i].b = " << vect[i].b;
      check(vect[i].b == 200);
    }

    vect.emplace_back(7, 8);
    std::cout << "vect.emplace_back(7, 8) = " << vect.back().a;
    check(vect.back().a == 7);
    std::cout << "vect.emplace_back(7, 8) = " << vect.back().b;
    check(vect.back().b == 8);
  }

  {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<std::size_t> dist(10000, 20000);

    std::size_t n = dist(gen);
    pod_vector<int> vect;
    vect.reserve(n);

    std::cout << "Vect size after reserve: " << vect.size();
    check(vect.size() == 0);
    std::cout << "Vect empty after reserve: " << vect.empty();
    check(vect.empty() == true);
    std::cout << "Vect capacity after reserve: " << vect.capacity();
    check(vect.capacity() == n);

    vect.reserve(n / 2);
    std::cout << "Vect size after reserve/2: " << vect.size();
    check(vect.size() == 0);
    std::cout << "Vect empty after reserve/2: " << vect.empty();
    check(vect.empty() == true);
    std::cout << "Vect capacity after reserve/2: " << vect.capacity();
    check(vect.capacity() == n);

    vect.resize(n);
    std::cout << "Vect size after resize: " << vect.size();
    check(vect.size() == n);
    std::cout << "Vect capacity after resize: " << vect.capacity();
    check(vect.capacity() == n);

    vect.resize(n / 2);
    std::cout << "Vect size after resize/2: " << vect.size();
    check(vect.size() == n / 2);
    std::cout << "Vect capacity after resize/2: " << vect.capacity();
    check(vect.capacity() == n);

    vect.resize(n * 2);
    std::cout << "Vect size after resize*2: " << vect.size();
    check(vect.size() == n * 2);
    std::cout << "Vect capacity after resize*2: " << vect.capacity();
    check(vect.capacity() >= n * 2);
  }

  {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<int> dist(10000, 20000);

    int size = dist(gen);
    pod_vector<int> vect(size);
    std::fill_n(&vect[0], size, 123);

    // Test if resize does not default initilize
    vect.resize(0);
    vect.resize(size);
    int sum = std::accumulate(&vect[0], &vect[0] + vect.size(), 0);
    std::cout << "Vect sum after resize: " << sum;
    check(sum == 123 * size);
    std::cout << "Vect.end(): " << vect.end();
    check(vect.end() == vect.begin() + vect.size());

    // Test reallocation (old content must be copied into new vector)
    vect.resize(vect.size() * 2);
    sum = std::accumulate(&vect[0], &vect[0] + size, 0);
    std::cout << "Vect sum after reallocation: " << sum;
    check(sum == 123 * size);
  }

  {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<int> dist(10000, 20000);

    int size = dist(gen);
    pod_vector<int> vect(size);
    std::fill_n(&vect[0], size, 123);

    pod_vector<int> vect2 = std::move(vect);
    std::cout << "Vect1 empty after std::move: " << vect.empty();
    check(vect.empty() == true);
    int sum = std::accumulate(vect2.begin(), vect2.end(), 0);
    std::cout << "Vect2 sum after std::move: " << sum;
    check(sum == 123 * size);
  }

  std::cout << std::endl;
  std::cout << "All tests passed successfully!" << std::endl;

  return 0;
}
<commit_msg>Add more tests<commit_after>///
/// @file   pod_vector.cpp
/// @brief  Plain old data vector, like std::vector but does not
///         default initialize memory.
///
/// Copyright (C) 2022 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primesieve/pod_vector.hpp>

#include <cstdlib>
#include <iostream>
#include <random>
#include <numeric>
#include <utility>

using std::size_t;
using primesieve::pod_vector;

void check(bool OK)
{
  std::cout << "   " << (OK ? "OK" : "ERROR") << "\n";
  if (!OK)
    std::exit(1);
}

int main()
{
  // The pod_vector class uses std::vector internally. For
  // performance reasons we want vector::resize() not to
  // free memory when resizing to a smaller size. The C++
  // standard seems to indirectly guarantee this behavior,
  // but it is not 100% clear. So this tests verifies this
  // behavior.

  // Allocate from 1 KiB to 128 MiB
  for (size_t i = 10; i <= 27; i++)
  {
    pod_vector<char> vect;
    vect.resize(size_t(1) << i);
    auto capacity1 = vect.capacity();
    vect.resize(100);
    auto capacity2 = vect.capacity();

    std::cout << "vect.resize(100).capacity = " << capacity1;
    check(capacity1 == capacity2);
  }

  {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<std::size_t> dist(100, 200);

    std::size_t n = dist(gen);
    pod_vector<size_t> vect;

    for (size_t i = 0; i <= n; i++)
      vect.push_back(i);

    for (size_t i = 0; i <= n; i++)
    {
      std::cout << "vect.push_back(" << i << ") = " << i;
      check(vect[i] == i);
    }
  }

  {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<std::size_t> dist(100, 200);

    std::size_t size = dist(gen);

    // pod_vector does not default initialize POD types
    // but it does initialize classes and structs with constructors.
    struct pod_t
    {
      pod_t() = default;
      pod_t(int i, int j) : a(i), b(j) { }
      int a = 100;
      int b = 200;
    };

    pod_vector<pod_t> vect(size);

    for (size_t i = 0; i < size; i++)
    {
      std::cout << "vect[i].a = " << vect[i].a;
      check(vect[i].a == 100);
      std::cout << "vect[i].b = " << vect[i].b;
      check(vect[i].b == 200);
    }

    vect.emplace_back(7, 8);
    std::cout << "vect.emplace_back(7, 8) = " << vect.back().a;
    check(vect.back().a == 7);
    std::cout << "vect.emplace_back(7, 8) = " << vect.back().b;
    check(vect.back().b == 8);
  }

  {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<std::size_t> dist(10000, 20000);

    std::size_t n = dist(gen);
    pod_vector<int> vect;
    vect.resize(0);

    std::cout << "Vect size after resize(0): " << vect.size();
    check(vect.size() == 0);
    std::cout << "Vect capacity after resize(0): " << vect.capacity();
    check(vect.capacity() == 0);

    vect.reserve(n);

    std::cout << "Vect size after reserve(n): " << vect.size();
    check(vect.size() == 0);
    std::cout << "Vect empty after reserve(n): " << vect.empty();
    check(vect.empty() == true);
    std::cout << "Vect capacity after reserve(n): " << vect.capacity();
    check(vect.capacity() == n);

    vect.reserve(n / 2);
    std::cout << "Vect size after reserve(n/2): " << vect.size();
    check(vect.size() == 0);
    std::cout << "Vect empty after reserve(n/2): " << vect.empty();
    check(vect.empty() == true);
    std::cout << "Vect capacity after reserve(n/2): " << vect.capacity();
    check(vect.capacity() == n);

    vect.resize(n);
    std::cout << "Vect size after resize(n): " << vect.size();
    check(vect.size() == n);
    std::cout << "Vect capacity after resize(n): " << vect.capacity();
    check(vect.capacity() == n);

    vect.resize(n);
    std::cout << "Vect size after 2nd resize(n): " << vect.size();
    check(vect.size() == n);
    std::cout << "Vect capacity after 2nd resize(n): " << vect.capacity();
    check(vect.capacity() == n);

    vect.resize(n / 2);
    std::cout << "Vect size after resize(n/2): " << vect.size();
    check(vect.size() == n / 2);
    std::cout << "Vect capacity after resize(n/2): " << vect.capacity();
    check(vect.capacity() == n);

    vect.resize(0);
    std::cout << "Vect size after resize(0): " << vect.size();
    check(vect.size() == 0);
    std::cout << "Vect capacity after resize(0): " << vect.capacity();
    check(vect.capacity() == n);

    vect.resize(n * 2);
    std::cout << "Vect size after resize(n*2): " << vect.size();
    check(vect.size() == n * 2);
    std::cout << "Vect capacity after resize(n*2): " << vect.capacity();
    check(vect.capacity() >= n * 2);
  }

  {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<int> dist(10000, 20000);

    int size = dist(gen);
    pod_vector<int> vect(size);
    std::fill_n(&vect[0], size, 123);

    // Test if resize does not default initilize
    vect.resize(0);
    vect.resize(size);
    int sum = std::accumulate(&vect[0], &vect[0] + vect.size(), 0);
    std::cout << "Vect sum after resize: " << sum;
    check(sum == 123 * size);
    std::cout << "Vect.end(): " << vect.end();
    check(vect.end() == vect.begin() + vect.size());

    // Test reallocation (old content must be copied into new vector)
    vect.resize(vect.size() * 2);
    sum = std::accumulate(&vect[0], &vect[0] + size, 0);
    std::cout << "Vect sum after reallocation: " << sum;
    check(sum == 123 * size);
  }

  {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<int> dist(10000, 20000);

    int size = dist(gen);
    pod_vector<int> vect(size);
    std::fill_n(&vect[0], size, 123);

    pod_vector<int> vect2 = std::move(vect);
    std::cout << "Vect1 empty after std::move: " << vect.empty();
    check(vect.empty() == true);
    int sum = std::accumulate(vect2.begin(), vect2.end(), 0);
    std::cout << "Vect2 sum after std::move: " << sum;
    check(sum == 123 * size);
  }

  std::cout << std::endl;
  std::cout << "All tests passed successfully!" << std::endl;

  return 0;
}
<|endoftext|>


<commit_before>// author: Maciej Chałapuk
// license: Apache2
// vim: ts=2 sw=2 expandtab
#include "fatum/queue/blocking.hpp"

#include <functional>

#include <gmock/gmock.h>
#include <gtest/gtest.h>

namespace test {

template <typename T>
class fatum_Queue : public ::testing::Test {
};

struct IntFactory {
  typedef int ItemType;
  IntFactory() : next(0) {}
  int operator() () { return next++; }
 private:
  int next;
};

template <class QueueType_, class ItemFactoryType_>
struct TypeParam {
  typedef QueueType_ QueueType;
  typedef ItemFactoryType_ ItemFactoryType;
  typedef typename ItemFactoryType::ItemType ItemType;
};

} // namespace test

using namespace test;
using namespace testing;

TYPED_TEST_CASE_P(fatum_Queue);

TYPED_TEST_P(fatum_Queue, test_pushed_item_can_be_pulled) {
  typename TypeParam::QueueType tested_queue;
  typename TypeParam::ItemFactoryType create_item;

  auto tested_item = create_item();
  tested_queue.push(tested_item);
  tested_queue.pop([&tested_item](typename TypeParam::ItemType &item) {
		    ASSERT_EQ(tested_item, item);
		  });
}

REGISTER_TYPED_TEST_CASE_P(fatum_Queue,
                           test_pushed_item_can_be_pulled);

typedef ::testing::Types<
    TypeParam<fatum::queue::Blocking<int>, IntFactory>
    > fatum_QueueTypes;
INSTANTIATE_TYPED_TEST_CASE_P(fatum_QueueParameterized,
                              fatum_Queue,
                              fatum_QueueTypes);

<commit_msg>+ fatum_Queue::test_3_pushed_items_can_be_pulled<commit_after>// author: Maciej Chałapuk
// license: Apache2
// vim: ts=2 sw=2 expandtab
#include "fatum/queue/blocking.hpp"

#include <functional>

#include <gmock/gmock.h>
#include <gtest/gtest.h>

namespace test {

template <typename T>
class fatum_Queue : public ::testing::Test {
};

struct IntFactory {
  typedef int ItemType;
  IntFactory() : next(0) {}
  int operator() () { return next++; }
 private:
  int next;
};

template <class QueueType_, class ItemFactoryType_>
struct TypeParam {
  typedef QueueType_ QueueType;
  typedef ItemFactoryType_ ItemFactoryType;
  typedef typename ItemFactoryType::ItemType ItemType;
};

} // namespace test

using namespace test;
using namespace testing;

TYPED_TEST_CASE_P(fatum_Queue);

TYPED_TEST_P(fatum_Queue, test_pushed_item_can_be_pulled) {
  typename TypeParam::QueueType tested_queue;
  typename TypeParam::ItemFactoryType create_item;

  auto tested_item = create_item();
  tested_queue.push(tested_item);
  tested_queue.pop([&tested_item](typename TypeParam::ItemType &item) {
		    ASSERT_EQ(tested_item, item);
		  });
}

TYPED_TEST_P(fatum_Queue, test_3_pushed_items_can_be_pulled) {
  typename TypeParam::QueueType tested_queue;
  typename TypeParam::ItemFactoryType create_item;

  auto tested_item0 = create_item();
  auto tested_item1 = create_item();
  auto tested_item2 = create_item();
  tested_queue.push(tested_item0);
  tested_queue.push(tested_item1);
  tested_queue.push(tested_item2);

  typedef typename TypeParam::ItemType ItemType;
  std::set<ItemType> popped_items;
  tested_queue.pop([&popped_items](ItemType &item) {
		    popped_items.insert(item);
		  });

  ASSERT_TRUE(popped_items.find(tested_item0) != popped_items.end());
  ASSERT_TRUE(popped_items.find(tested_item1) != popped_items.end());
  ASSERT_TRUE(popped_items.find(tested_item2) != popped_items.end());
}

REGISTER_TYPED_TEST_CASE_P(fatum_Queue,
                           test_pushed_item_can_be_pulled,
                           test_3_pushed_items_can_be_pulled);

typedef ::testing::Types<
    TypeParam<fatum::queue::Blocking<int>, IntFactory>
    > fatum_QueueTypes;
INSTANTIATE_TYPED_TEST_CASE_P(fatum_QueueParameterized,
                              fatum_Queue,
                              fatum_QueueTypes);

<|endoftext|>


<commit_before>// Copyright 2016-2020 Francesco Biscani (bluescarni@gmail.com)
//
// This file is part of the mp++ library.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include <utility>

#include <mp++/config.hpp>
#include <mp++/detail/mpfr.hpp>
#include <mp++/real.hpp>

#include "catch.hpp"
#include "test_utils.hpp"

using namespace mppp;

TEST_CASE("real sqrt")
{
    real r0{0};
    r0.sqrt();
    REQUIRE(r0.get_prec() == detail::real_deduce_precision(0));
    REQUIRE(r0.zero_p());
    real rop;
    REQUIRE(sqrt(rop, r0).zero_p());
    REQUIRE(rop.get_prec() == detail::real_deduce_precision(0));
    REQUIRE(sqrt(r0).zero_p());
    REQUIRE(sqrt(std::move(r0)).zero_p());
    REQUIRE(!r0.get_mpfr_t()->_mpfr_d);
    r0 = real{16, 128};
    REQUIRE(sqrt(r0) == 4);
    REQUIRE(sqrt(r0).get_prec() == 128);
    rop = real{12, 40};
    sqrt(rop, r0);
    REQUIRE(rop == 4);
    REQUIRE(rop.get_prec() == 128);
    r0.sqrt();
    REQUIRE(r0 == 4);
    REQUIRE(r0.get_prec() == 128);
    // Negative value.
    r0 = real{-16, 128};
    REQUIRE(sqrt(r0).nan_p());
}

TEST_CASE("real rec_sqrt")
{
    real r0{1};
    r0.rec_sqrt();
    REQUIRE(r0.get_prec() == detail::real_deduce_precision(0));
    REQUIRE(r0 == 1);
    real rop;
    REQUIRE(rec_sqrt(rop, r0) == 1);
    REQUIRE(rop.get_prec() == detail::real_deduce_precision(0));
    REQUIRE(rec_sqrt(r0) == 1);
    REQUIRE(rec_sqrt(std::move(r0)) == 1);
    REQUIRE(!r0.get_mpfr_t()->_mpfr_d);
    r0 = real{16, 128};
    REQUIRE(rec_sqrt(r0) == 1 / real{4});
    REQUIRE(rec_sqrt(r0).get_prec() == 128);
    rop = real{12, 40};
    rec_sqrt(rop, r0);
    REQUIRE(rop == 1 / real{4});
    REQUIRE(rop.get_prec() == 128);
    r0.rec_sqrt();
    REQUIRE(r0 == 1 / real{4});
    REQUIRE(r0.get_prec() == 128);
    // Special cases.
    REQUIRE((rec_sqrt(real{0}) == real{"+inf", 32}));
    REQUIRE((rec_sqrt(-real{0}) == real{"+inf", 32}));
    REQUIRE((rec_sqrt(real{"+inf", 32}) == 0));
    REQUIRE(!(rec_sqrt(real{"+inf", 32}).signbit()));
    REQUIRE((rec_sqrt(real{"-3", 32}).nan_p()));
    REQUIRE((rec_sqrt(real{"-inf", 32}).nan_p()));
}

TEST_CASE("real cbrt")
{
    real r0{0};
    r0.cbrt();
    REQUIRE(r0.get_prec() == detail::real_deduce_precision(0));
    REQUIRE(r0.zero_p());
    real rop;
    REQUIRE(cbrt(rop, r0).zero_p());
    REQUIRE(rop.get_prec() == detail::real_deduce_precision(0));
    REQUIRE(cbrt(r0).zero_p());
    REQUIRE(cbrt(std::move(r0)).zero_p());
    REQUIRE(!r0.get_mpfr_t()->_mpfr_d);
    r0 = real{-27, 128};
    REQUIRE(cbrt(r0) == -3);
    REQUIRE(cbrt(r0).get_prec() == 128);
    rop = real{12, 40};
    cbrt(rop, r0);
    REQUIRE(rop == -3);
    REQUIRE(rop.get_prec() == 128);
    r0.cbrt();
    REQUIRE(r0 == -3);
    REQUIRE(r0.get_prec() == 128);
}

#if MPFR_VERSION_MAJOR >= 4

TEST_CASE("real rootn_ui")
{
    real r0{0};
    real rop;
    REQUIRE(rootn_ui(rop, r0, 3).zero_p());
    REQUIRE(rop.get_prec() == detail::real_deduce_precision(0));
    REQUIRE(rootn_ui(r0, 3).zero_p());
    REQUIRE(rootn_ui(std::move(r0), 3).zero_p());
    REQUIRE(!r0.get_mpfr_t()->_mpfr_d);
    r0 = real{-27, 128};
    REQUIRE(rootn_ui(r0, 3) == -3);
    REQUIRE(rootn_ui(r0, 3).get_prec() == 128);
    rop = real{12, 40};
    rootn_ui(rop, r0, 3);
    REQUIRE(rop == -3);
    REQUIRE(rop.get_prec() == 128);
    rootn_ui(r0, r0, 3);
    REQUIRE(r0 == -3);
    REQUIRE(r0.get_prec() == 128);
    // Special cases.
    REQUIRE(rootn_ui(real{123}, 0).nan_p());
    REQUIRE((rootn_ui(real{"-inf", 45}, 3) == real{"-inf", 45}));
    REQUIRE(rootn_ui(real{-123}, 8).nan_p());
    REQUIRE(!rootn_ui(real{"+0", 60}, 3).signbit());
    REQUIRE(rootn_ui(real{"-0", 60}, 3).signbit());
    REQUIRE(!rootn_ui(real{"+0", 60}, 4).signbit());
    REQUIRE(!rootn_ui(real{"-0", 60}, 4).signbit());
}

#endif

#if defined(MPPP_WITH_ARB)

TEST_CASE("real sqrt1pm1")
{
    real r0{0};
    r0.sqrt1pm1();
    REQUIRE(r0.get_prec() == detail::real_deduce_precision(0));
    REQUIRE(r0.zero_p());
    real rop;
    REQUIRE(sqrt1pm1(rop, r0).zero_p());
    REQUIRE(rop.get_prec() == detail::real_deduce_precision(0));
    REQUIRE(sqrt1pm1(r0).zero_p());
    REQUIRE(sqrt1pm1(std::move(r0)).zero_p());
    REQUIRE(!r0.is_valid());
    r0 = real{15, 128};
    REQUIRE(sqrt1pm1(r0) == 3);
    REQUIRE(sqrt1pm1(r0).get_prec() == 128);
    rop = real{12, 40};
    sqrt1pm1(rop, r0);
    REQUIRE(rop == 3);
    REQUIRE(rop.get_prec() == 128);
    r0.sqrt1pm1();
    REQUIRE(r0 == 3);
    REQUIRE(r0.get_prec() == 128);
    // Negative value.
    r0 = real{-16, 128};
    REQUIRE(sqrt1pm1(r0).nan_p());
    REQUIRE(sqrt1pm1(r0).get_prec() == 128);
    REQUIRE(sqrt1pm1(real{-16, 129}).nan_p());
    REQUIRE(sqrt1pm1(real{-16, 129}).get_prec() == 129);

    // Test infinity.
    REQUIRE(sqrt1pm1(real{"inf", 243}).inf_p());
    REQUIRE(sqrt1pm1(real{"inf", 243}) > 0);
    REQUIRE(sqrt1pm1(real{"inf", 243}).get_prec() == 243);
    REQUIRE(sqrt1pm1(real{"-inf", 243}).nan_p());
    REQUIRE(sqrt1pm1(real{"-inf", 243}).get_prec() == 243);

    // Test nan.
    REQUIRE(sqrt1pm1(real{"nan", 244}).nan_p());
    REQUIRE(sqrt1pm1(real{"nan", 244}).get_prec() == 244);

    // Test a known result.
    REQUIRE(
        abs(sqrt1pm1(1.1_r512)
            - 0.449137674618943857371866415716977172314013287475897308869592480711814437265368042171256319200361749775304608312117024175586888785578864947776625773207505235_r512)
        < mppp::pow(2_r512, -510));
}

#endif
<commit_msg>Small test additions for real.<commit_after>// Copyright 2016-2020 Francesco Biscani (bluescarni@gmail.com)
//
// This file is part of the mp++ library.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include <utility>

#include <mp++/config.hpp>
#include <mp++/detail/mpfr.hpp>
#include <mp++/real.hpp>

#include "catch.hpp"
#include "test_utils.hpp"

using namespace mppp;

TEST_CASE("real sqrt")
{
    real r0{0};
    r0.sqrt();
    REQUIRE(std::is_same<real &, decltype(r0.sqrt())>::value);
    REQUIRE(r0.get_prec() == detail::real_deduce_precision(0));
    REQUIRE(r0.zero_p());
    real rop;
    REQUIRE(sqrt(rop, r0).zero_p());
    REQUIRE(std::is_same<real &, decltype(sqrt(rop, r0))>::value);
    REQUIRE(rop.get_prec() == detail::real_deduce_precision(0));
    REQUIRE(sqrt(r0).zero_p());
    REQUIRE(std::is_same<real, decltype(sqrt(r0))>::value);
    REQUIRE(sqrt(std::move(r0)).zero_p());
    REQUIRE(!r0.get_mpfr_t()->_mpfr_d);
    r0 = real{16, 128};
    REQUIRE(sqrt(r0) == 4);
    REQUIRE(sqrt(r0).get_prec() == 128);
    rop = real{12, 40};
    sqrt(rop, r0);
    REQUIRE(rop == 4);
    REQUIRE(rop.get_prec() == 128);
    r0.sqrt();
    REQUIRE(r0 == 4);
    REQUIRE(r0.get_prec() == 128);
    // Negative value.
    r0 = real{-16, 128};
    REQUIRE(sqrt(r0).nan_p());
}

TEST_CASE("real rec_sqrt")
{
    real r0{1};
    r0.rec_sqrt();
    REQUIRE(r0.get_prec() == detail::real_deduce_precision(0));
    REQUIRE(r0 == 1);
    real rop;
    REQUIRE(rec_sqrt(rop, r0) == 1);
    REQUIRE(rop.get_prec() == detail::real_deduce_precision(0));
    REQUIRE(rec_sqrt(r0) == 1);
    REQUIRE(rec_sqrt(std::move(r0)) == 1);
    REQUIRE(!r0.get_mpfr_t()->_mpfr_d);
    r0 = real{16, 128};
    REQUIRE(rec_sqrt(r0) == 1 / real{4});
    REQUIRE(rec_sqrt(r0).get_prec() == 128);
    rop = real{12, 40};
    rec_sqrt(rop, r0);
    REQUIRE(rop == 1 / real{4});
    REQUIRE(rop.get_prec() == 128);
    r0.rec_sqrt();
    REQUIRE(r0 == 1 / real{4});
    REQUIRE(r0.get_prec() == 128);
    // Special cases.
    REQUIRE((rec_sqrt(real{0}) == real{"+inf", 32}));
    REQUIRE((rec_sqrt(-real{0}) == real{"+inf", 32}));
    REQUIRE((rec_sqrt(real{"+inf", 32}) == 0));
    REQUIRE(!(rec_sqrt(real{"+inf", 32}).signbit()));
    REQUIRE((rec_sqrt(real{"-3", 32}).nan_p()));
    REQUIRE((rec_sqrt(real{"-inf", 32}).nan_p()));
}

TEST_CASE("real cbrt")
{
    real r0{0};
    r0.cbrt();
    REQUIRE(r0.get_prec() == detail::real_deduce_precision(0));
    REQUIRE(r0.zero_p());
    real rop;
    REQUIRE(cbrt(rop, r0).zero_p());
    REQUIRE(rop.get_prec() == detail::real_deduce_precision(0));
    REQUIRE(cbrt(r0).zero_p());
    REQUIRE(cbrt(std::move(r0)).zero_p());
    REQUIRE(!r0.get_mpfr_t()->_mpfr_d);
    r0 = real{-27, 128};
    REQUIRE(cbrt(r0) == -3);
    REQUIRE(cbrt(r0).get_prec() == 128);
    rop = real{12, 40};
    cbrt(rop, r0);
    REQUIRE(rop == -3);
    REQUIRE(rop.get_prec() == 128);
    r0.cbrt();
    REQUIRE(r0 == -3);
    REQUIRE(r0.get_prec() == 128);
}

#if MPFR_VERSION_MAJOR >= 4

TEST_CASE("real rootn_ui")
{
    real r0{0};
    real rop;
    REQUIRE(rootn_ui(rop, r0, 3).zero_p());
    REQUIRE(rop.get_prec() == detail::real_deduce_precision(0));
    REQUIRE(rootn_ui(r0, 3).zero_p());
    REQUIRE(rootn_ui(std::move(r0), 3).zero_p());
    REQUIRE(!r0.get_mpfr_t()->_mpfr_d);
    r0 = real{-27, 128};
    REQUIRE(rootn_ui(r0, 3) == -3);
    REQUIRE(rootn_ui(r0, 3).get_prec() == 128);
    rop = real{12, 40};
    rootn_ui(rop, r0, 3);
    REQUIRE(rop == -3);
    REQUIRE(rop.get_prec() == 128);
    rootn_ui(r0, r0, 3);
    REQUIRE(r0 == -3);
    REQUIRE(r0.get_prec() == 128);
    // Special cases.
    REQUIRE(rootn_ui(real{123}, 0).nan_p());
    REQUIRE((rootn_ui(real{"-inf", 45}, 3) == real{"-inf", 45}));
    REQUIRE(rootn_ui(real{-123}, 8).nan_p());
    REQUIRE(!rootn_ui(real{"+0", 60}, 3).signbit());
    REQUIRE(rootn_ui(real{"-0", 60}, 3).signbit());
    REQUIRE(!rootn_ui(real{"+0", 60}, 4).signbit());
    REQUIRE(!rootn_ui(real{"-0", 60}, 4).signbit());
}

#endif

#if defined(MPPP_WITH_ARB)

TEST_CASE("real sqrt1pm1")
{
    real r0{0};
    r0.sqrt1pm1();
    REQUIRE(r0.get_prec() == detail::real_deduce_precision(0));
    REQUIRE(r0.zero_p());
    real rop;
    REQUIRE(sqrt1pm1(rop, r0).zero_p());
    REQUIRE(rop.get_prec() == detail::real_deduce_precision(0));
    REQUIRE(sqrt1pm1(r0).zero_p());
    REQUIRE(sqrt1pm1(std::move(r0)).zero_p());
    REQUIRE(!r0.is_valid());
    r0 = real{15, 128};
    REQUIRE(sqrt1pm1(r0) == 3);
    REQUIRE(sqrt1pm1(r0).get_prec() == 128);
    rop = real{12, 40};
    sqrt1pm1(rop, r0);
    REQUIRE(rop == 3);
    REQUIRE(rop.get_prec() == 128);
    r0.sqrt1pm1();
    REQUIRE(r0 == 3);
    REQUIRE(r0.get_prec() == 128);
    // Negative value.
    r0 = real{-16, 128};
    REQUIRE(sqrt1pm1(r0).nan_p());
    REQUIRE(sqrt1pm1(r0).get_prec() == 128);
    REQUIRE(sqrt1pm1(real{-16, 129}).nan_p());
    REQUIRE(sqrt1pm1(real{-16, 129}).get_prec() == 129);

    // Test infinity.
    REQUIRE(sqrt1pm1(real{"inf", 243}).inf_p());
    REQUIRE(sqrt1pm1(real{"inf", 243}) > 0);
    REQUIRE(sqrt1pm1(real{"inf", 243}).get_prec() == 243);
    REQUIRE(sqrt1pm1(real{"-inf", 243}).nan_p());
    REQUIRE(sqrt1pm1(real{"-inf", 243}).get_prec() == 243);

    // Test nan.
    REQUIRE(sqrt1pm1(real{"nan", 244}).nan_p());
    REQUIRE(sqrt1pm1(real{"nan", 244}).get_prec() == 244);

    // Test a known result.
    REQUIRE(
        abs(sqrt1pm1(1.1_r512)
            - 0.449137674618943857371866415716977172314013287475897308869592480711814437265368042171256319200361749775304608312117024175586888785578864947776625773207505235_r512)
        < mppp::pow(2_r512, -510));
}

#endif
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef ETL_IMPL_TRANSPOSE_HPP
#define ETL_IMPL_TRANSPOSE_HPP

#include "../config.hpp"
#include "../traits_lite.hpp"

#ifdef ETL_MKL_MODE
#include "mkl.h"
#endif

/**
 * Implementations of matrix transposition.
 *    1. Simple implementation using for loop
 *    2. Implementations using MKL
 *
 * Square and rectangular implementation are separated.
 */

namespace etl {

namespace detail {

template<typename C, typename Enable = void>
struct inplace_square_transpose {
    template<typename CC>
    static void apply(CC&& c){
        using std::swap;

        const auto N = etl::dim<0>(c);

        for(std::size_t i = 0; i < N - 1; ++i){
            for(std::size_t j = i + 1; j < N; ++j){
                swap(c(i, j), c(j, i));
            }
        }
    }
};

//TODO This implementation is really too slow

template<typename C, typename Enable = void>
struct inplace_rectangular_transpose {
    template<typename CC>
    static void apply(CC&& mat){
        using std::swap;

        const auto N = etl::dim<0>(mat);
        const auto M = etl::dim<1>(mat);

        auto data = mat.memory_start();

        for(std::size_t k = 0; k < N*M; k++) {
            auto idx = k;
            do {
                idx = (idx % N) * M + (idx / N);
            } while(idx < k);
            std::swap(data[k], data[idx]);
        }
    }
};

#ifdef ETL_MKL_MODE

template<typename C>
struct inplace_square_transpose<C, std::enable_if_t<has_direct_access<C>::value && is_single_precision<C>::value>> {
    template<typename CC>
    static void apply(CC&& c){
        mkl_simatcopy('R', 'T', etl::dim<0>(c), etl::dim<1>(c), 1.0f, c.memory_start(), etl::dim<1>(c), etl::dim<1>(c));
    }
};

template<typename C>
struct inplace_square_transpose<C, std::enable_if_t<has_direct_access<C>::value && is_double_precision<C>::value>> {
    template<typename CC>
    static void apply(CC&& c){
        mkl_dimatcopy('R', 'T', etl::dim<0>(c), etl::dim<1>(c), 1.0f, c.memory_start(), etl::dim<1>(c), etl::dim<1>(c));
    }
};

#endif

} //end of namespace detail

} //end of namespace etl

#endif
<commit_msg>Experimental MKL transpose<commit_after>//=======================================================================
// Copyright (c) 2014-2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef ETL_IMPL_TRANSPOSE_HPP
#define ETL_IMPL_TRANSPOSE_HPP

#include "../config.hpp"
#include "../traits_lite.hpp"

#ifdef ETL_MKL_MODE
#include "mkl_trans.h"
#endif

/**
 * Implementations of matrix transposition.
 *    1. Simple implementation using for loop
 *    2. Implementations using MKL
 *
 * Square and rectangular implementation are separated.
 */

namespace etl {

namespace detail {

template<typename C, typename Enable = void>
struct inplace_square_transpose {
    template<typename CC>
    static void apply(CC&& c){
        using std::swap;

        const auto N = etl::dim<0>(c);

        for(std::size_t i = 0; i < N - 1; ++i){
            for(std::size_t j = i + 1; j < N; ++j){
                swap(c(i, j), c(j, i));
            }
        }
    }
};

//TODO This implementation is really too slow

template<typename C, typename Enable = void>
struct inplace_rectangular_transpose {
    template<typename CC>
    static void apply(CC&& mat){
        using std::swap;

        const auto N = etl::dim<0>(mat);
        const auto M = etl::dim<1>(mat);

        auto data = mat.memory_start();

        for(std::size_t k = 0; k < N*M; k++) {
            auto idx = k;
            do {
                idx = (idx % N) * M + (idx / N);
            } while(idx < k);
            std::swap(data[k], data[idx]);
        }
    }
};

#ifdef ETL_MKL_MODE

template<typename C>
struct inplace_square_transpose<C, std::enable_if_t<has_direct_access<C>::value && is_single_precision<C>::value>> {
    template<typename CC>
    static void apply(CC&& c){
        mkl_simatcopy('R', 'T', etl::dim<0>(c), etl::dim<1>(c), 1.0f, c.memory_start(), etl::dim<1>(c), etl::dim<1>(c));
    }
};

template<typename C>
struct inplace_square_transpose<C, std::enable_if_t<has_direct_access<C>::value && is_double_precision<C>::value>> {
    template<typename CC>
    static void apply(CC&& c){
        mkl_dimatcopy('R', 'T', etl::dim<0>(c), etl::dim<1>(c), 1.0f, c.memory_start(), etl::dim<1>(c), etl::dim<1>(c));
    }
};

template<typename C>
struct inplace_rectangular_transpose<C, std::enable_if_t<has_direct_access<C>::value && is_single_precision<C>::value>> {
    template<typename CC>
    static void apply(CC&& c){
        mkl_simatcopy('R', 'T', etl::dim<0>(c), etl::dim<1>(c), 1.0f, c.memory_start(), etl::dim<1>(c), etl::dim<1>(c));
    }
};

template<typename C>
struct inplace_rectangular_transpose<C, std::enable_if_t<has_direct_access<C>::value && is_double_precision<C>::value>> {
    template<typename CC>
    static void apply(CC&& c){
        mkl_dimatcopy('R', 'T', etl::dim<0>(c), etl::dim<1>(c), 1.0f, c.memory_start(), etl::dim<1>(c), etl::dim<1>(c));
    }
};

#endif

} //end of namespace detail

} //end of namespace etl

#endif
<|endoftext|>


<commit_before>///
/// @file  S2_easy_mpi_libdivide.cpp
/// @brief This is an optimized version of S2_easy which uses
///        libdivide. libdivide allows to replace expensive integer
///        divides with comparatively cheap multiplication and
///        bitshifts.
///
/// Copyright (C) 2016 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <PiTable.hpp>
#include <primecount-internal.hpp>
#include <generate.hpp>
#include <int128.hpp>
#include <min_max.hpp>
#include <mpi_reduce_sum.hpp>
#include <pmath.hpp>
#include <S2Status.hpp>

#include <libdivide.h>
#include <stdint.h>
#include <vector>

#ifdef _OPENMP
  #include <omp.h>
#endif

using namespace std;
using namespace primecount;

namespace {

typedef libdivide::divider<uint64_t> libdivide_u64_t;

template <typename Primes>
vector<libdivide_u64_t>
generate_fast_divisors(Primes& primes)
{
  return vector<libdivide_u64_t>(primes.begin(), primes.end());
}

template <typename T>
inline bool is_libdivide(T x)
{
  return x <= numeric_limits<uint64_t>::max();
}

/// Calculate the contribution of the clustered easy leaves
/// and the sparse easy leaves.
/// @param T  either int64_t or uint128_t.
///
template <typename T, typename Primes>
T S2_easy_mpi_master(T x,
                     int64_t y,
                     int64_t z,
                     int64_t c,
                     Primes& primes,
                     int threads)
{
  T s2_easy = 0;
  int64_t x13 = iroot<3>(x);
  int64_t thread_threshold = 1000;
  threads = validate_threads(threads, x13, thread_threshold);
  vector<libdivide_u64_t> fastdiv = generate_fast_divisors(primes);

  PiTable pi(y);
  int64_t pi_sqrty = pi[isqrt(y)];
  int64_t pi_x13 = pi[x13];
  S2Status status(x);

  int proc_id = mpi_proc_id();
  int procs = mpi_num_procs();

  #pragma omp parallel for schedule(dynamic) num_threads(threads) reduction(+: s2_easy)
  for (int64_t b = max(c, pi_sqrty) + 1 + proc_id; b <= pi_x13; b += procs)
  {
    int64_t prime = primes[b];
    T x2 = x / prime;
    int64_t min_trivial = min(x2 / prime, y);
    int64_t min_clustered = (int64_t) isqrt(x2);
    int64_t min_sparse = z / prime;
    int64_t min_hard = max(y / prime, prime);

    min_clustered = in_between(min_hard, min_clustered, y);
    min_sparse = in_between(min_hard, min_sparse, y);

    int64_t l = pi[min_trivial];
    int64_t pi_min_clustered = pi[min_clustered];
    int64_t pi_min_sparse = pi[min_sparse];

    T sum = 0;

    if (is_libdivide(x2))
    {
      uint64_t x2_u64 = (uint64_t) x2;

      // Find all clustered easy leaves:
      // n = primes[b] * primes[l]
      // x / n <= y && phi(x / n, b - 1) == phi(x / m, b - 1)
      // where phi(x / n, b - 1) = pi(x / n) - b + 2
      while (l > pi_min_clustered)
      {
        int64_t xn = x2_u64 / fastdiv[l];
        int64_t phi_xn = pi[xn] - b + 2;
        int64_t xm = x2_u64 / fastdiv[b + phi_xn - 1];
        xm = max(xm, min_clustered);
        int64_t l2 = pi[xm];
        sum += phi_xn * (l - l2);
        l = l2;
      }

      // Find all sparse easy leaves:
      // n = primes[b] * primes[l]
      // x / n <= y && phi(x / n, b - 1) = pi(x / n) - b + 2
      for (; l > pi_min_sparse; l--)
      {
        int64_t xn = x2_u64 / fastdiv[l];
        sum += pi[xn] - b + 2;
      }
    }
    else
    {
      // Find all clustered easy leaves:
      // n = primes[b] * primes[l]
      // x / n <= y && phi(x / n, b - 1) == phi(x / m, b - 1)
      // where phi(x / n, b - 1) = pi(x / n) - b + 2
      while (l > pi_min_clustered)
      {
        int64_t xn = (int64_t) (x2 / primes[l]);
        int64_t phi_xn = pi[xn] - b + 2;
        int64_t xm = (int64_t) (x2 / primes[b + phi_xn - 1]);
        xm = max(xm, min_clustered);
        int64_t l2 = pi[xm];
        sum += phi_xn * (l - l2);
        l = l2;
      }

      // Find all sparse easy leaves:
      // n = primes[b] * primes[l]
      // x / n <= y && phi(x / n, b - 1) = pi(x / n) - b + 2
      for (; l > pi_min_sparse; l--)
      {
        int64_t xn = (int64_t) (x2 / primes[l]);
        sum += pi[xn] - b + 2;
      }
    }

    if (print_status())
      status.print(b, pi_x13);

    s2_easy += sum;
  }

  s2_easy = mpi_reduce_sum(s2_easy);

  return s2_easy;
}

} // namespace

namespace primecount {

int64_t S2_easy_mpi(int64_t x,
                    int64_t y,
                    int64_t z,
                    int64_t c,
                    int threads)
{
  print("");
  print("=== S2_easy_mpi(x, y) ===");
  print("Computation of the easy special leaves");
  print(x, y, c, threads);

  double time = get_wtime();
  vector<int32_t> primes = generate_primes<int32_t>(y);
  int64_t s2_easy = S2_easy_mpi_master((intfast64_t) x, y, z, c, primes, threads);

  print("S2_easy", s2_easy, time);
  return s2_easy;
}

#ifdef HAVE_INT128_T

int128_t S2_easy_mpi(int128_t x,
                     int64_t y,
                     int64_t z,
                     int64_t c,
                     int threads)
{
  print("");
  print("=== S2_easy_mpi(x, y) ===");
  print("Computation of the easy special leaves");
  print(x, y, c, threads);

  double time = get_wtime();
  int128_t s2_easy;

  // uses less memory
  if (y <= std::numeric_limits<uint32_t>::max())
  {
    vector<uint32_t> primes = generate_primes<uint32_t>(y);
    s2_easy = S2_easy_mpi_master((intfast128_t) x, y, z, c, primes, threads);
  }
  else
  {
    vector<int64_t> primes = generate_primes<int64_t>(y);
    s2_easy = S2_easy_mpi_master((intfast128_t) x, y, z, c, primes, threads);
  }

  print("S2_easy", s2_easy, time);
  return s2_easy;
}

#endif

} // namespace primecount
<commit_msg>Comment<commit_after>///
/// @file  S2_easy_mpi_libdivide.cpp
/// @brief This is an optimized version of S2_easy which uses
///        libdivide. libdivide allows to replace expensive integer
///        divides with comparatively cheap multiplication and
///        bitshifts.
///
/// Copyright (C) 2016 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <PiTable.hpp>
#include <primecount-internal.hpp>
#include <generate.hpp>
#include <int128.hpp>
#include <min_max.hpp>
#include <mpi_reduce_sum.hpp>
#include <pmath.hpp>
#include <S2Status.hpp>

#include <libdivide.h>
#include <stdint.h>
#include <vector>

#ifdef _OPENMP
  #include <omp.h>
#endif

using namespace std;
using namespace primecount;

namespace {

typedef libdivide::divider<uint64_t> libdivide_u64_t;

template <typename Primes>
vector<libdivide_u64_t>
generate_fast_divisors(Primes& primes)
{
  return vector<libdivide_u64_t>(primes.begin(), primes.end());
}

template <typename T>
inline bool is_libdivide(T x)
{
  return x <= numeric_limits<uint64_t>::max();
}

/// Calculate the contribution of the clustered easy
/// leaves and the sparse easy leaves.
///
template <typename T, typename Primes>
T S2_easy_mpi_master(T x,
                     int64_t y,
                     int64_t z,
                     int64_t c,
                     Primes& primes,
                     int threads)
{
  T s2_easy = 0;
  int64_t x13 = iroot<3>(x);
  int64_t thread_threshold = 1000;
  threads = validate_threads(threads, x13, thread_threshold);
  vector<libdivide_u64_t> fastdiv = generate_fast_divisors(primes);

  PiTable pi(y);
  int64_t pi_sqrty = pi[isqrt(y)];
  int64_t pi_x13 = pi[x13];
  S2Status status(x);

  int proc_id = mpi_proc_id();
  int procs = mpi_num_procs();

  #pragma omp parallel for schedule(dynamic) num_threads(threads) reduction(+: s2_easy)
  for (int64_t b = max(c, pi_sqrty) + 1 + proc_id; b <= pi_x13; b += procs)
  {
    int64_t prime = primes[b];
    T x2 = x / prime;
    int64_t min_trivial = min(x2 / prime, y);
    int64_t min_clustered = (int64_t) isqrt(x2);
    int64_t min_sparse = z / prime;
    int64_t min_hard = max(y / prime, prime);

    min_clustered = in_between(min_hard, min_clustered, y);
    min_sparse = in_between(min_hard, min_sparse, y);

    int64_t l = pi[min_trivial];
    int64_t pi_min_clustered = pi[min_clustered];
    int64_t pi_min_sparse = pi[min_sparse];

    T sum = 0;

    if (is_libdivide(x2))
    {
      uint64_t x2_u64 = (uint64_t) x2;

      // Find all clustered easy leaves:
      // n = primes[b] * primes[l]
      // x / n <= y && phi(x / n, b - 1) == phi(x / m, b - 1)
      // where phi(x / n, b - 1) = pi(x / n) - b + 2
      while (l > pi_min_clustered)
      {
        int64_t xn = x2_u64 / fastdiv[l];
        int64_t phi_xn = pi[xn] - b + 2;
        int64_t xm = x2_u64 / fastdiv[b + phi_xn - 1];
        xm = max(xm, min_clustered);
        int64_t l2 = pi[xm];
        sum += phi_xn * (l - l2);
        l = l2;
      }

      // Find all sparse easy leaves:
      // n = primes[b] * primes[l]
      // x / n <= y && phi(x / n, b - 1) = pi(x / n) - b + 2
      for (; l > pi_min_sparse; l--)
      {
        int64_t xn = x2_u64 / fastdiv[l];
        sum += pi[xn] - b + 2;
      }
    }
    else
    {
      // Find all clustered easy leaves:
      // n = primes[b] * primes[l]
      // x / n <= y && phi(x / n, b - 1) == phi(x / m, b - 1)
      // where phi(x / n, b - 1) = pi(x / n) - b + 2
      while (l > pi_min_clustered)
      {
        int64_t xn = (int64_t) (x2 / primes[l]);
        int64_t phi_xn = pi[xn] - b + 2;
        int64_t xm = (int64_t) (x2 / primes[b + phi_xn - 1]);
        xm = max(xm, min_clustered);
        int64_t l2 = pi[xm];
        sum += phi_xn * (l - l2);
        l = l2;
      }

      // Find all sparse easy leaves:
      // n = primes[b] * primes[l]
      // x / n <= y && phi(x / n, b - 1) = pi(x / n) - b + 2
      for (; l > pi_min_sparse; l--)
      {
        int64_t xn = (int64_t) (x2 / primes[l]);
        sum += pi[xn] - b + 2;
      }
    }

    if (print_status())
      status.print(b, pi_x13);

    s2_easy += sum;
  }

  s2_easy = mpi_reduce_sum(s2_easy);

  return s2_easy;
}

} // namespace

namespace primecount {

int64_t S2_easy_mpi(int64_t x,
                    int64_t y,
                    int64_t z,
                    int64_t c,
                    int threads)
{
  print("");
  print("=== S2_easy_mpi(x, y) ===");
  print("Computation of the easy special leaves");
  print(x, y, c, threads);

  double time = get_wtime();
  vector<int32_t> primes = generate_primes<int32_t>(y);
  int64_t s2_easy = S2_easy_mpi_master((intfast64_t) x, y, z, c, primes, threads);

  print("S2_easy", s2_easy, time);
  return s2_easy;
}

#ifdef HAVE_INT128_T

int128_t S2_easy_mpi(int128_t x,
                     int64_t y,
                     int64_t z,
                     int64_t c,
                     int threads)
{
  print("");
  print("=== S2_easy_mpi(x, y) ===");
  print("Computation of the easy special leaves");
  print(x, y, c, threads);

  double time = get_wtime();
  int128_t s2_easy;

  // uses less memory
  if (y <= std::numeric_limits<uint32_t>::max())
  {
    vector<uint32_t> primes = generate_primes<uint32_t>(y);
    s2_easy = S2_easy_mpi_master((intfast128_t) x, y, z, c, primes, threads);
  }
  else
  {
    vector<int64_t> primes = generate_primes<int64_t>(y);
    s2_easy = S2_easy_mpi_master((intfast128_t) x, y, z, c, primes, threads);
  }

  print("S2_easy", s2_easy, time);
  return s2_easy;
}

#endif

} // namespace primecount
<|endoftext|>