<commit_before>///
/// @file  S2_easy.cpp
/// @brief Calculate the contribution of the clustered easy leaves
///        and the sparse easy leaves in parallel using OpenMP
///        (Deleglise-Rivat algorithm).
///
/// Copyright (C) 2014 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 <int128.hpp>
#include <min_max.hpp>
#include <pmath.hpp>
#include <S2Status.hpp>

#include <stdint.h>
#include <algorithm>
#include <iostream>
#include <vector>

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

using namespace std;
using namespace primecount;

namespace {
namespace S2_easy {

/// Calculate the contribution of the clustered easy leaves and
/// sparse easy leaves corresponding to primes[b] i.e.:
/// n = primes[b] * primes[l] with x / n <= y.
/// @param x2 = x / primes[b].
///
template <typename T1, typename T2, typename T3>
T1 S2_easy(T1 x2,
           int64_t y,
           int64_t z,
           int64_t b,
           T2& pi,
           vector<T3>& primes)
{
  T1 s2_easy = 0;
  int64_t prime = primes[b];
  int64_t min_trivial_leaf = min(x2 / prime, y);
  int64_t min_clustered_easy_leaf = (int64_t) isqrt(x2);
  int64_t min_sparse_easy_leaf = z / prime;
  int64_t min_hard_leaf = max(y / prime, prime);

  min_sparse_easy_leaf = max(min_sparse_easy_leaf, min_hard_leaf);
  min_clustered_easy_leaf = max(min_clustered_easy_leaf, min_hard_leaf);
  int64_t l = pi[min_trivial_leaf];

  // 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 (primes[l] > min_clustered_easy_leaf)
  {
    int64_t xn = (int64_t) (x2 / primes[l]);
    int64_t phi_xn = pi[xn] - b + 2;
    int64_t last_prime = primes[b + phi_xn - 1];
    int64_t xm = max((int64_t) (x2 / last_prime), min_clustered_easy_leaf);
    int64_t l2 = pi[xm];
    s2_easy += 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 (; primes[l] > min_sparse_easy_leaf; l--)
  {
    int64_t xn = (int64_t) (x2 / primes[l]);
    s2_easy += pi[xn] - b + 2;
  }

  return s2_easy;
}

/// Strategy pattern, chooses an S2_easy() implementation.
template <typename T1, typename T2, typename T3>
T1 strategy(T1 x,
            int64_t y,
            int64_t z,
            int64_t b,
            T2& pi,
            vector<T3>& primes)
{
  T1 x2 = x / primes[b];

  // Avoid slow 128-bit divisions
  if (x2 <= std::numeric_limits<uint64_t>::max())
    return S2_easy((uint64_t) x2, y, z, b, pi, primes);

  return S2_easy(x2, y, z, b, pi, primes);
}

/// Calculate the contribution of the clustered easy leaves
/// and the sparse easy leaves.
/// @param T  either int64_t or uint128_t.
///
template <typename T1, typename T2, typename T3>
T1 S2_easy(T1 x,
           int64_t y,
           int64_t z,
           int64_t c,
           T2& pi,
           vector<T3>& primes,
           int threads)
{
  if (print_status())
  {
    cout << endl;
    cout << "=== S2_easy(x, y) ===" << endl;
    cout << "Computation of the easy special leaves" << endl;
  }

  int64_t pi_sqrty = pi[isqrt(y)];
  int64_t pi_x13 = pi[iroot<3>(x)];
  T1 s2_easy = 0;
  double time = get_wtime();
  S2Status status;

  #pragma omp parallel for schedule(dynamic, 1) num_threads(threads) reduction(+: s2_easy)
  for (int64_t b = max(c, pi_sqrty) + 1; b <= pi_x13; b++)
  {
    s2_easy += strategy(x, y, z, b, pi, primes);

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

  if (print_status())
    print_result("S2_easy", s2_easy, time);

  return s2_easy;
}

} // namespace S2_easy
} // namespace

namespace primecount {

int64_t S2_easy(int64_t x,
                int64_t y,
                int64_t z,
                int64_t c,
                vector<int32_t>& pi,
                vector<int32_t>& primes,
                int threads)
{
  return S2_easy::S2_easy((intfast64_t) x, y, z, c, pi, primes, threads);
}

int64_t S2_easy(int64_t x,
                int64_t y,
                int64_t z,
                int64_t c,
                PiTable& pi,
                vector<int32_t>& primes,
                int threads)
{
  return S2_easy::S2_easy((intfast64_t) x, y, z, c, pi, primes, threads);
}

#ifdef HAVE_INT128_T

int128_t S2_easy(int128_t x,
                 int64_t y,
                 int64_t z,
                 int64_t c,
                 PiTable& pi,
                 vector<uint32_t>& primes,
                 int threads)
{
  return S2_easy::S2_easy((intfast128_t) x, y, z, c, pi, primes, threads);
}

int128_t S2_easy(int128_t x,
                 int64_t y,
                 int64_t z,
                 int64_t c,
                 PiTable& pi,
                 vector<int64_t>& primes,
                 int threads)
{
  return S2_easy::S2_easy((intfast128_t) x, y, z, c, pi, primes, threads);
}

#endif

} // namespace primecount
<commit_msg>Use same return type as S2_easy()<commit_after>///
/// @file  S2_easy.cpp
/// @brief Calculate the contribution of the clustered easy leaves
///        and the sparse easy leaves in parallel using OpenMP
///        (Deleglise-Rivat algorithm).
///
/// Copyright (C) 2014 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 <int128.hpp>
#include <min_max.hpp>
#include <pmath.hpp>
#include <S2Status.hpp>

#include <stdint.h>
#include <algorithm>
#include <iostream>
#include <vector>

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

using namespace std;
using namespace primecount;

namespace {
namespace S2_easy {

/// Calculate the contribution of the clustered easy leaves and
/// sparse easy leaves corresponding to primes[b] i.e.:
/// n = primes[b] * primes[l] with x / n <= y.
/// @param x2 = x / primes[b].
///
template <typename T1, typename T2, typename T3, typename R = T1>
R S2_easy(T1 x2,
          int64_t y,
          int64_t z,
          int64_t b,
          T2& pi,
          vector<T3>& primes)
{
  R s2_easy = 0;
  int64_t prime = primes[b];
  int64_t min_trivial_leaf = min(x2 / prime, y);
  int64_t min_clustered_easy_leaf = (int64_t) isqrt(x2);
  int64_t min_sparse_easy_leaf = z / prime;
  int64_t min_hard_leaf = max(y / prime, prime);

  min_sparse_easy_leaf = max(min_sparse_easy_leaf, min_hard_leaf);
  min_clustered_easy_leaf = max(min_clustered_easy_leaf, min_hard_leaf);
  int64_t l = pi[min_trivial_leaf];

  // 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 (primes[l] > min_clustered_easy_leaf)
  {
    int64_t xn = (int64_t) (x2 / primes[l]);
    int64_t phi_xn = pi[xn] - b + 2;
    int64_t last_prime = primes[b + phi_xn - 1];
    int64_t xm = max((int64_t) (x2 / last_prime), min_clustered_easy_leaf);
    int64_t l2 = pi[xm];
    s2_easy += 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 (; primes[l] > min_sparse_easy_leaf; l--)
  {
    int64_t xn = (int64_t) (x2 / primes[l]);
    s2_easy += pi[xn] - b + 2;
  }

  return s2_easy;
}

/// Strategy pattern, chooses an S2_easy() implementation.
template <typename T1, typename T2, typename T3>
T1 S2_strategy(T1 x,
               int64_t y,
               int64_t z,
               int64_t b,
               T2& pi,
               vector<T3>& primes)
{
  T1 x2 = x / primes[b];

  // Avoid slow 128-bit divisions
  if (x2 <= std::numeric_limits<intfast64_t>::max())
    return S2_easy<T1>((intfast64_t) x2, y, z, b, pi, primes);

  return S2_easy(x2, y, z, b, pi, primes);
}

/// Calculate the contribution of the clustered easy leaves
/// and the sparse easy leaves.
/// @param T  either int64_t or uint128_t.
///
template <typename T1, typename T2, typename T3>
T1 S2_easy(T1 x,
           int64_t y,
           int64_t z,
           int64_t c,
           T2& pi,
           vector<T3>& primes,
           int threads)
{
  if (print_status())
  {
    cout << endl;
    cout << "=== S2_easy(x, y) ===" << endl;
    cout << "Computation of the easy special leaves" << endl;
  }

  int64_t pi_sqrty = pi[isqrt(y)];
  int64_t pi_x13 = pi[iroot<3>(x)];
  T1 s2_easy = 0;
  double time = get_wtime();
  S2Status status;

  #pragma omp parallel for schedule(dynamic, 1) num_threads(threads) reduction(+: s2_easy)
  for (int64_t b = max(c, pi_sqrty) + 1; b <= pi_x13; b++)
  {
    s2_easy += S2_strategy(x, y, z, b, pi, primes);

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

  if (print_status())
    print_result("S2_easy", s2_easy, time);

  return s2_easy;
}

} // namespace S2_easy
} // namespace

namespace primecount {

int64_t S2_easy(int64_t x,
                int64_t y,
                int64_t z,
                int64_t c,
                vector<int32_t>& pi,
                vector<int32_t>& primes,
                int threads)
{
  return S2_easy::S2_easy((intfast64_t) x, y, z, c, pi, primes, threads);
}

int64_t S2_easy(int64_t x,
                int64_t y,
                int64_t z,
                int64_t c,
                PiTable& pi,
                vector<int32_t>& primes,
                int threads)
{
  return S2_easy::S2_easy((intfast64_t) x, y, z, c, pi, primes, threads);
}

#ifdef HAVE_INT128_T

int128_t S2_easy(int128_t x,
                 int64_t y,
                 int64_t z,
                 int64_t c,
                 PiTable& pi,
                 vector<uint32_t>& primes,
                 int threads)
{
  return S2_easy::S2_easy((intfast128_t) x, y, z, c, pi, primes, threads);
}

int128_t S2_easy(int128_t x,
                 int64_t y,
                 int64_t z,
                 int64_t c,
                 PiTable& pi,
                 vector<int64_t>& primes,
                 int threads)
{
  return S2_easy::S2_easy((intfast128_t) x, y, z, c, pi, primes, threads);
}

#endif

} // namespace primecount
<|endoftext|>


<commit_before>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2010, 2011, 2012, 2013, 2014
Raffaello D. Di Napoli

This file is part of Application-Building Components (henceforth referred to as ABC).

ABC is free software: you can redistribute it and/or modify it under the terms of the GNU General
Public License as published by the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.

ABC 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 General Public
License for more details.

You should have received a copy of the GNU General Public License along with ABC. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#include <abc.hxx>
#include <abc/io/text/file.hxx>
#include <abc/io/binary/file.hxx>

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::io::text globals

namespace abc {
namespace io {
namespace text {

static std::shared_ptr<binbuf_writer> g_ptwStdErr;
static std::shared_ptr<binbuf_reader> g_ptrStdIn;
static std::shared_ptr<binbuf_writer> g_ptwStdOut;

/** Instantiates a text::base specialization appropriate for the specified binary I/O object,
returning a shared pointer to it. If the binary I/O object does not implement buffering, a buffered
I/O wrapper is instanciated as well.

pbb
   Pointer to a binary I/O object.
return
   Shared pointer to the newly created object.
*/
static std::shared_ptr<binbuf_base> _construct(
   std::shared_ptr<binary::base> pbb, abc::text::encoding enc, abc::text::line_terminator lterm
) {
   ABC_TRACE_FN((/*pbb, */enc, lterm));

   // Choose what type of text I/O object to create based on what type of binary I/O object we got.

   // Check if it’s a buffered I/O object.
   auto pbbr(std::dynamic_pointer_cast<binary::buffered_reader>(pbb));
   auto pbbw(std::dynamic_pointer_cast<binary::buffered_writer>(pbb));
   if (!pbbr && !pbbw) {
      // Not a buffered I/O object? Get one then, and try again with the casts.
      auto pbbb(binary::buffer(pbb));
      pbbr = std::dynamic_pointer_cast<binary::buffered_reader>(pbbb);
      pbbw = std::dynamic_pointer_cast<binary::buffered_writer>(pbbb);
   }

   // Now we must have a buffered reader or writer, or pbb is not something we can use.
   if (pbbr) {
      return std::make_shared<binbuf_reader>(std::move(pbbr), enc, lterm);
   }
   if (pbbw) {
      return std::make_shared<binbuf_writer>(std::move(pbbw), enc, lterm);
   }
   // TODO: use a better exception class.
   ABC_THROW(argument_error, ());
}

/** Detects the encoding to use for a standard text I/O file, with the help of an optional
environment variable.

TODO: document this behavior and the related enviroment variables.

TODO: change to use a global “environment” map object instead of this ad-hoc code.

TODO: make the below code only pick up variables meant for this PID. This should eventually be made
more general, as a way for an ABC-based parent process to communicate with an ABC-based child
process. Thought maybe a better way is to pass a command-line argument that triggers ABC-specific
behavior, so that it’s inherently PID-specific.

pszEnvVarName
   Environment variable name that, if set, specifies the encoding to be used.
return
   Encoding appropriate for the requested standard I/O file.
*/
static std::shared_ptr<binbuf_base> _construct_stdio(
   std::shared_ptr<binary::base> pbb, char_t const * pszEnvVarName
) {
   ABC_TRACE_FN((/*pbb, */pszEnvVarName));

#if ABC_HOST_API_POSIX
   istr sEnc;
   if (char_t const * pszEnvVarValue = ::getenv(pszEnvVarName)) {
      sEnc = istr(unsafe, pszEnvVarValue);
   }
#elif ABC_HOST_API_WIN32 //if ABC_HOST_API_POSIX
   smstr<64> sEnc;
   sEnc.grow_for([pszEnvVarName] (char_t * pch, size_t cchMax) -> size_t {
      // ::GetEnvironmentVariable() returns < cchMax (length without NUL) if the buffer was large
      // enough, or the required size (length including NUL) otherwise.
      return ::GetEnvironmentVariable(pszEnvVarName, pch, DWORD(cchMax));
   });
#else //if ABC_HOST_API_POSIX … elif ABC_HOST_API_WIN32
   #error HOST_API
#endif //if ABC_HOST_API_POSIX … elif ABC_HOST_API_WIN32 … else
   abc::text::encoding enc(abc::text::encoding::unknown);
   if (sEnc) {
      try {
         enc = abc::text::encoding(sEnc);
      } catch (domain_error const &) {
         // Ignore this invalid encoding setting, and default to auto-detection.
         // TODO: display a warning about ABC_STDERR_ENCODING being ignored.
      }
   }
   return _construct(std::move(pbb), enc, abc::text::line_terminator::unknown);
}

std::shared_ptr<binbuf_writer> stderr() {
   ABC_TRACE_FN(());

   // TODO: mutex!
   if (!g_ptwStdErr) {
      g_ptwStdErr = std::dynamic_pointer_cast<binbuf_writer>(
         _construct_stdio(binary::stderr(), SL("ABC_STDERR_ENCODING"))
      );
   }
   return g_ptwStdErr;
}

std::shared_ptr<binbuf_reader> stdin() {
   ABC_TRACE_FN(());

   // TODO: mutex!
   if (!g_ptrStdIn) {
      g_ptrStdIn = std::dynamic_pointer_cast<binbuf_reader>(
         _construct_stdio(binary::stdin(), SL("ABC_STDIN_ENCODING"))
      );
   }
   return g_ptrStdIn;
}

std::shared_ptr<binbuf_writer> stdout() {
   ABC_TRACE_FN(());

   // TODO: mutex!
   if (!g_ptwStdOut) {
      g_ptwStdOut = std::dynamic_pointer_cast<binbuf_writer>(
         _construct_stdio(binary::stdout(), SL("ABC_STDOUT_ENCODING"))
      );
   }
   return g_ptwStdOut;
}

std::shared_ptr<binbuf_base> open(
   file_path const & fp, access_mode am, abc::text::encoding enc /*= abc::text::encoding::unknown*/,
   abc::text::line_terminator lterm /*= abc::text::line_terminator::unknown*/
) {
   ABC_TRACE_FN((fp, am, enc, lterm));

   return _construct(binary::open(fp, am), enc, lterm);
}

} //namespace text
} //namespace io
} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////

<commit_msg>Force host encoding for console I/O<commit_after>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2010, 2011, 2012, 2013, 2014
Raffaello D. Di Napoli

This file is part of Application-Building Components (henceforth referred to as ABC).

ABC is free software: you can redistribute it and/or modify it under the terms of the GNU General
Public License as published by the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.

ABC 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 General Public
License for more details.

You should have received a copy of the GNU General Public License along with ABC. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#include <abc.hxx>
#include <abc/io/text/file.hxx>
#include <abc/io/binary/file.hxx>

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::io::text globals

namespace abc {
namespace io {
namespace text {

static std::shared_ptr<binbuf_writer> g_ptwStdErr;
static std::shared_ptr<binbuf_reader> g_ptrStdIn;
static std::shared_ptr<binbuf_writer> g_ptwStdOut;

/** Instantiates a text::base specialization appropriate for the specified binary I/O object,
returning a shared pointer to it. If the binary I/O object does not implement buffering, a buffered
I/O wrapper is instanciated as well.

pbb
   Pointer to a binary I/O object.
return
   Shared pointer to the newly created object.
*/
static std::shared_ptr<binbuf_base> _construct(
   std::shared_ptr<binary::base> pbb, abc::text::encoding enc, abc::text::line_terminator lterm
) {
   ABC_TRACE_FN((/*pbb, */enc, lterm));

   // Choose what type of text I/O object to create based on what type of binary I/O object we got.

   // Check if it’s a buffered I/O object.
   auto pbbr(std::dynamic_pointer_cast<binary::buffered_reader>(pbb));
   auto pbbw(std::dynamic_pointer_cast<binary::buffered_writer>(pbb));
   if (!pbbr && !pbbw) {
      // Not a buffered I/O object? Get one then, and try again with the casts.
      auto pbbb(binary::buffer(pbb));
      pbbr = std::dynamic_pointer_cast<binary::buffered_reader>(pbbb);
      pbbw = std::dynamic_pointer_cast<binary::buffered_writer>(pbbb);
   }

   // Now we must have a buffered reader or writer, or pbb is not something we can use.
   if (pbbr) {
      return std::make_shared<binbuf_reader>(std::move(pbbr), enc, lterm);
   }
   if (pbbw) {
      return std::make_shared<binbuf_writer>(std::move(pbbw), enc, lterm);
   }
   // TODO: use a better exception class.
   ABC_THROW(argument_error, ());
}

/** Detects the encoding to use for a standard text I/O file, with the help of an optional
environment variable.

TODO: document this behavior and the related enviroment variables.

TODO: change to use a global “environment” map object instead of this ad-hoc code.

TODO: make the below code only pick up variables meant for this PID. This should eventually be made
more general, as a way for an ABC-based parent process to communicate with an ABC-based child
process. Thought maybe a better way is to pass a command-line argument that triggers ABC-specific
behavior, so that it’s inherently PID-specific.

pszEnvVarName
   Environment variable name that, if set, specifies the encoding to be used.
return
   Encoding appropriate for the requested standard I/O file.
*/
static std::shared_ptr<binbuf_base> _construct_stdio(
   std::shared_ptr<binary::base> pbb, char_t const * pszEnvVarName
) {
   ABC_TRACE_FN((/*pbb, */pszEnvVarName));

   abc::text::encoding enc;
   if (std::dynamic_pointer_cast<binary::console_file_base>(pbb)) {
      // Console files can only perform I/O in the host platform’s encoding, so force the correct
      // encoding here.
      enc = abc::text::encoding::host;
   } else {
      // In all other cases, allow selecting the encoding via environment variable.
#if ABC_HOST_API_POSIX
      istr sEnc;
      if (char_t const * pszEnvVarValue = ::getenv(pszEnvVarName)) {
         sEnc = istr(unsafe, pszEnvVarValue);
      }
#elif ABC_HOST_API_WIN32 //if ABC_HOST_API_POSIX
      smstr<64> sEnc;
      sEnc.grow_for([pszEnvVarName] (char_t * pch, size_t cchMax) -> size_t {
         // ::GetEnvironmentVariable() returns < cchMax (length without NUL) if the buffer was large
         // enough, or the required size (length including NUL) otherwise.
         return ::GetEnvironmentVariable(pszEnvVarName, pch, DWORD(cchMax));
      });
#else //if ABC_HOST_API_POSIX … elif ABC_HOST_API_WIN32
   #error HOST_API
#endif //if ABC_HOST_API_POSIX … elif ABC_HOST_API_WIN32 … else
      enc = abc::text::encoding::unknown;
      if (sEnc) {
         try {
            enc = abc::text::encoding(sEnc);
         } catch (domain_error const &) {
            // Ignore this invalid encoding setting, and default to auto-detection.
            // TODO: display a warning about ABC_STDERR_ENCODING being ignored.
         }
      }
   }
   return _construct(std::move(pbb), enc, abc::text::line_terminator::unknown);
}

std::shared_ptr<binbuf_writer> stderr() {
   ABC_TRACE_FN(());

   // TODO: mutex!
   if (!g_ptwStdErr) {
      g_ptwStdErr = std::dynamic_pointer_cast<binbuf_writer>(
         _construct_stdio(binary::stderr(), SL("ABC_STDERR_ENCODING"))
      );
   }
   return g_ptwStdErr;
}

std::shared_ptr<binbuf_reader> stdin() {
   ABC_TRACE_FN(());

   // TODO: mutex!
   if (!g_ptrStdIn) {
      g_ptrStdIn = std::dynamic_pointer_cast<binbuf_reader>(
         _construct_stdio(binary::stdin(), SL("ABC_STDIN_ENCODING"))
      );
   }
   return g_ptrStdIn;
}

std::shared_ptr<binbuf_writer> stdout() {
   ABC_TRACE_FN(());

   // TODO: mutex!
   if (!g_ptwStdOut) {
      g_ptwStdOut = std::dynamic_pointer_cast<binbuf_writer>(
         _construct_stdio(binary::stdout(), SL("ABC_STDOUT_ENCODING"))
      );
   }
   return g_ptwStdOut;
}

std::shared_ptr<binbuf_base> open(
   file_path const & fp, access_mode am, abc::text::encoding enc /*= abc::text::encoding::unknown*/,
   abc::text::line_terminator lterm /*= abc::text::line_terminator::unknown*/
) {
   ABC_TRACE_FN((fp, am, enc, lterm));

   return _construct(binary::open(fp, am), enc, lterm);
}

} //namespace text
} //namespace io
} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////

<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * 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/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <vcl/svapp.hxx>
#include <vcl/timer.hxx>
#include <vcl/settings.hxx>
#include <vcl/window.hxx>
#include <vcl/cursor.hxx>

#include <window.h>

#include <tools/poly.hxx>

struct ImplCursorData
{
    AutoTimer       maTimer;            // Timer
    Point           maPixPos;           // Pixel-Position
    Point           maPixRotOff;        // Pixel-Offset-Position
    Size            maPixSize;          // Pixel-Size
    long            mnPixSlant;         // Pixel-Slant
    short           mnOrientation;      // Pixel-Orientation
    CursorDirection mnDirection;        // indicates writing direction
    sal_uInt16      mnStyle;            // Cursor-Style
    bool            mbCurVisible;       // Ist Cursor aktuell sichtbar
    VclPtr<vcl::Window> mpWindow;           // Zugeordnetes Windows
};

static void ImplCursorInvert( ImplCursorData* pData )
{
    vcl::Window* pWindow  = pData->mpWindow;
    bool    bMapMode = pWindow->IsMapModeEnabled();
    pWindow->EnableMapMode( false );
    InvertFlags nInvertStyle;
    if ( pData->mnStyle & CURSOR_SHADOW )
        nInvertStyle = InvertFlags::N50;
    else
        nInvertStyle = InvertFlags::NONE;

    Rectangle aRect( pData->maPixPos, pData->maPixSize );
    if ( pData->mnDirection != CursorDirection::NONE || pData->mnOrientation || pData->mnPixSlant )
    {
        Polygon aPoly( aRect );
        if( aPoly.GetSize() == 5 )
        {
            aPoly[1].X() += 1;  // include the right border
            aPoly[2].X() += 1;
            if ( pData->mnPixSlant )
            {
                Point aPoint = aPoly.GetPoint( 0 );
                aPoint.X() += pData->mnPixSlant;
                aPoly.SetPoint( aPoint, 0 );
                aPoly.SetPoint( aPoint, 4 );
                aPoint = aPoly.GetPoint( 1 );
                aPoint.X() += pData->mnPixSlant;
                aPoly.SetPoint( aPoint, 1 );
            }

            // apply direction flag after slant to use the correct shape
            if ( pData->mnDirection != CursorDirection::NONE)
            {
                Point pAry[7];
                int delta = 3*aRect.getWidth()+1;
                if( pData->mnDirection == CursorDirection::LTR )
                {
                    // left-to-right
                    pAry[0] = aPoly.GetPoint( 0 );
                    pAry[1] = aPoly.GetPoint( 1 );
                    pAry[2] = pAry[1];
                    pAry[2].X() += delta;
                    pAry[3] =  pAry[1];
                    pAry[3].Y() += delta;
                    pAry[4] = aPoly.GetPoint( 2 );
                    pAry[5] = aPoly.GetPoint( 3 );
                    pAry[6] = aPoly.GetPoint( 4 );
                }
                else if( pData->mnDirection == CursorDirection::RTL )
                {
                    // right-to-left
                    pAry[0] = aPoly.GetPoint( 0 );
                    pAry[1] = aPoly.GetPoint( 1 );
                    pAry[2] = aPoly.GetPoint( 2 );
                    pAry[3] = aPoly.GetPoint( 3 );
                    pAry[4] = pAry[0];
                    pAry[4].Y() += delta;
                    pAry[5] =  pAry[0];
                    pAry[5].X() -= delta;
                    pAry[6] = aPoly.GetPoint( 4 );
                }
                aPoly = Polygon( 7, pAry);
            }

            if ( pData->mnOrientation )
                aPoly.Rotate( pData->maPixRotOff, pData->mnOrientation );
            pWindow->Invert( aPoly, nInvertStyle );
        }
    }
    else
        pWindow->Invert( aRect, nInvertStyle );
    pWindow->EnableMapMode( bMapMode );
}

void vcl::Cursor::ImplDraw()
{
    if ( mpData && mpData->mpWindow && !mpData->mbCurVisible )
    {
        vcl::Window* pWindow         = mpData->mpWindow;
        mpData->maPixPos        = pWindow->LogicToPixel( maPos );
        mpData->maPixSize       = pWindow->LogicToPixel( maSize );
        mpData->mnPixSlant      = pWindow->LogicToPixel( Size( mnSlant, 0 ) ).Width();
        mpData->mnOrientation   = mnOrientation;
        mpData->mnDirection     = mnDirection;

        // correct the position with the offset
        mpData->maPixRotOff = mpData->maPixPos;

        // use width (as set in Settings) if size is 0,
        if ( !mpData->maPixSize.Width() )
            mpData->maPixSize.Width() = pWindow->GetSettings().GetStyleSettings().GetCursorSize();

        // calculate output area and display
        ImplCursorInvert( mpData );
        mpData->mbCurVisible = true;
    }
}

void vcl::Cursor::ImplRestore()
{
    assert( mpData && mpData->mbCurVisible );

    ImplCursorInvert( mpData );
    mpData->mbCurVisible = false;
}

void vcl::Cursor::ImplDoShow( bool bDrawDirect, bool bRestore )
{
    if ( mbVisible )
    {
        vcl::Window* pWindow;
        if ( mpWindow )
            pWindow = mpWindow;
        else
        {
            // show the cursor, if there is an active window and the cursor
            // has been selected in this window
            pWindow = Application::GetFocusWindow();
            if ( !pWindow || (pWindow->mpWindowImpl->mpCursor != this) || pWindow->mpWindowImpl->mbInPaint
                || !pWindow->mpWindowImpl->mpFrameData->mbHasFocus )
                pWindow = NULL;
        }

        if ( pWindow )
        {
            if ( !mpData )
            {
                mpData = new ImplCursorData;
                mpData->mbCurVisible = false;
                mpData->maTimer.SetTimeoutHdl( LINK( this, Cursor, ImplTimerHdl ) );
            }

            mpData->mpWindow    = pWindow;
            mpData->mnStyle     = mnStyle;
            if ( bDrawDirect || bRestore )
                ImplDraw();

            if ( !mpWindow && ! ( ! bDrawDirect && mpData->maTimer.IsActive()) )
            {
                mpData->maTimer.SetTimeout( pWindow->GetSettings().GetStyleSettings().GetCursorBlinkTime() );
                if ( mpData->maTimer.GetTimeout() != STYLE_CURSOR_NOBLINKTIME )
                    mpData->maTimer.Start();
                else if ( !mpData->mbCurVisible )
                    ImplDraw();
            }
        }
    }
}

bool vcl::Cursor::ImplDoHide( bool bSuspend )
{
    bool bWasCurVisible = false;
    if ( mpData && mpData->mpWindow )
    {
        bWasCurVisible = mpData->mbCurVisible;
        if ( mpData->mbCurVisible )
            ImplRestore();

        if ( !bSuspend )
        {
            mpData->maTimer.Stop();
            mpData->mpWindow = NULL;
        }
    }
    return bWasCurVisible;
}

void vcl::Cursor::ImplShow( bool bDrawDirect )
{
    ImplDoShow( bDrawDirect, false );
}

void vcl::Cursor::ImplHide( bool i_bStopTimer )
{
    assert( i_bStopTimer );
    ImplDoHide( !i_bStopTimer );
}

void vcl::Cursor::ImplResume( bool bRestore )
{
    ImplDoShow( false, bRestore );
}

bool vcl::Cursor::ImplSuspend()
{
    return ImplDoHide( true );
}

void vcl::Cursor::ImplNew()
{
    if ( mbVisible && mpData && mpData->mpWindow )
    {
        if ( mpData->mbCurVisible )
            ImplRestore();

        ImplDraw();
        if ( !mpWindow )
        {
            if ( mpData->maTimer.GetTimeout() != STYLE_CURSOR_NOBLINKTIME )
                mpData->maTimer.Start();
        }
    }
}

IMPL_LINK_NOARG_TYPED(vcl::Cursor, ImplTimerHdl, Timer *, void)
{
    if ( mpData->mbCurVisible )
        ImplRestore();
    else
        ImplDraw();
}

vcl::Cursor::Cursor()
{
    mpData          = NULL;
    mpWindow        = NULL;
    mnSlant         = 0;
    mnOrientation   = 0;
    mnDirection     = CursorDirection::NONE;
    mnStyle         = 0;
    mbVisible       = false;
}

vcl::Cursor::Cursor( const Cursor& rCursor ) :
    maSize( rCursor.maSize ),
    maPos( rCursor.maPos )
{
    mpData          = NULL;
    mpWindow        = NULL;
    mnSlant         = rCursor.mnSlant;
    mnOrientation   = rCursor.mnOrientation;
    mnDirection     = rCursor.mnDirection;
    mnStyle         = 0;
    mbVisible       = rCursor.mbVisible;
}

vcl::Cursor::~Cursor()
{
    if ( mpData )
    {
        if ( mpData->mbCurVisible )
            ImplRestore();

        delete mpData;
    }
}

void vcl::Cursor::SetStyle( sal_uInt16 nStyle )
{
    if ( mnStyle != nStyle )
    {
        mnStyle = nStyle;
        ImplNew();
    }
}

void vcl::Cursor::Show()
{
    if ( !mbVisible )
    {
        mbVisible = true;
        ImplShow();
    }
}

void vcl::Cursor::Hide()
{
    if ( mbVisible )
    {
        mbVisible = false;
        ImplHide( true );
    }
}

void vcl::Cursor::SetWindow( vcl::Window* pWindow )
{
    if ( mpWindow.get() != pWindow )
    {
        mpWindow = pWindow;
        ImplNew();
    }
}

void vcl::Cursor::SetPos( const Point& rPoint )
{
    if ( maPos != rPoint )
    {
        maPos = rPoint;
        ImplNew();
    }
}

void vcl::Cursor::SetSize( const Size& rSize )
{
    if ( maSize != rSize )
    {
        maSize = rSize;
        ImplNew();
    }
}

void vcl::Cursor::SetWidth( long nNewWidth )
{
    if ( maSize.Width() != nNewWidth )
    {
        maSize.Width() = nNewWidth;
        ImplNew();
    }
}

void vcl::Cursor::SetOrientation( short nNewOrientation )
{
    if ( mnOrientation != nNewOrientation )
    {
        mnOrientation = nNewOrientation;
        ImplNew();
    }
}

void vcl::Cursor::SetDirection( CursorDirection nNewDirection )
{
    if ( mnDirection != nNewDirection )
    {
        mnDirection = nNewDirection;
        ImplNew();
    }
}

vcl::Cursor& vcl::Cursor::operator=( const vcl::Cursor& rCursor )
{
    maPos           = rCursor.maPos;
    maSize          = rCursor.maSize;
    mnSlant         = rCursor.mnSlant;
    mnOrientation   = rCursor.mnOrientation;
    mnDirection     = rCursor.mnDirection;
    mbVisible       = rCursor.mbVisible;
    ImplNew();

    return *this;
}

bool vcl::Cursor::operator==( const vcl::Cursor& rCursor ) const
{
    return
        ((maPos         == rCursor.maPos)           &&
         (maSize        == rCursor.maSize)          &&
         (mnSlant       == rCursor.mnSlant)         &&
         (mnOrientation == rCursor.mnOrientation)   &&
         (mnDirection   == rCursor.mnDirection)     &&
         (mbVisible     == rCursor.mbVisible))
        ;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>tdf#92982 vcl::Cursor: handle rendercontext<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * 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/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <vcl/svapp.hxx>
#include <vcl/timer.hxx>
#include <vcl/settings.hxx>
#include <vcl/window.hxx>
#include <vcl/cursor.hxx>

#include <window.h>

#include <tools/poly.hxx>

struct ImplCursorData
{
    AutoTimer       maTimer;            // Timer
    Point           maPixPos;           // Pixel-Position
    Point           maPixRotOff;        // Pixel-Offset-Position
    Size            maPixSize;          // Pixel-Size
    long            mnPixSlant;         // Pixel-Slant
    short           mnOrientation;      // Pixel-Orientation
    CursorDirection mnDirection;        // indicates writing direction
    sal_uInt16      mnStyle;            // Cursor-Style
    bool            mbCurVisible;       // Ist Cursor aktuell sichtbar
    VclPtr<vcl::Window> mpWindow;           // Zugeordnetes Windows
};

static void ImplCursorInvert( ImplCursorData* pData )
{
    vcl::Window* pWindow  = pData->mpWindow;
    vcl::RenderContext* pRenderContext = pWindow->GetOutDev();
    bool    bMapMode = pRenderContext->IsMapModeEnabled();
    pRenderContext->EnableMapMode( false );
    InvertFlags nInvertStyle;
    if ( pData->mnStyle & CURSOR_SHADOW )
        nInvertStyle = InvertFlags::N50;
    else
        nInvertStyle = InvertFlags::NONE;

    Rectangle aRect( pData->maPixPos, pData->maPixSize );
    if ( pData->mnDirection != CursorDirection::NONE || pData->mnOrientation || pData->mnPixSlant )
    {
        Polygon aPoly( aRect );
        if( aPoly.GetSize() == 5 )
        {
            aPoly[1].X() += 1;  // include the right border
            aPoly[2].X() += 1;
            if ( pData->mnPixSlant )
            {
                Point aPoint = aPoly.GetPoint( 0 );
                aPoint.X() += pData->mnPixSlant;
                aPoly.SetPoint( aPoint, 0 );
                aPoly.SetPoint( aPoint, 4 );
                aPoint = aPoly.GetPoint( 1 );
                aPoint.X() += pData->mnPixSlant;
                aPoly.SetPoint( aPoint, 1 );
            }

            // apply direction flag after slant to use the correct shape
            if ( pData->mnDirection != CursorDirection::NONE)
            {
                Point pAry[7];
                int delta = 3*aRect.getWidth()+1;
                if( pData->mnDirection == CursorDirection::LTR )
                {
                    // left-to-right
                    pAry[0] = aPoly.GetPoint( 0 );
                    pAry[1] = aPoly.GetPoint( 1 );
                    pAry[2] = pAry[1];
                    pAry[2].X() += delta;
                    pAry[3] =  pAry[1];
                    pAry[3].Y() += delta;
                    pAry[4] = aPoly.GetPoint( 2 );
                    pAry[5] = aPoly.GetPoint( 3 );
                    pAry[6] = aPoly.GetPoint( 4 );
                }
                else if( pData->mnDirection == CursorDirection::RTL )
                {
                    // right-to-left
                    pAry[0] = aPoly.GetPoint( 0 );
                    pAry[1] = aPoly.GetPoint( 1 );
                    pAry[2] = aPoly.GetPoint( 2 );
                    pAry[3] = aPoly.GetPoint( 3 );
                    pAry[4] = pAry[0];
                    pAry[4].Y() += delta;
                    pAry[5] =  pAry[0];
                    pAry[5].X() -= delta;
                    pAry[6] = aPoly.GetPoint( 4 );
                }
                aPoly = Polygon( 7, pAry);
            }

            if ( pData->mnOrientation )
                aPoly.Rotate( pData->maPixRotOff, pData->mnOrientation );
            pRenderContext->Invert( aPoly, nInvertStyle );
        }
    }
    else
        pRenderContext->Invert( aRect, nInvertStyle );
    pRenderContext->EnableMapMode( bMapMode );
}

void vcl::Cursor::ImplDraw()
{
    if ( mpData && mpData->mpWindow && !mpData->mbCurVisible )
    {
        vcl::Window* pWindow         = mpData->mpWindow;
        mpData->maPixPos        = pWindow->LogicToPixel( maPos );
        mpData->maPixSize       = pWindow->LogicToPixel( maSize );
        mpData->mnPixSlant      = pWindow->LogicToPixel( Size( mnSlant, 0 ) ).Width();
        mpData->mnOrientation   = mnOrientation;
        mpData->mnDirection     = mnDirection;

        // correct the position with the offset
        mpData->maPixRotOff = mpData->maPixPos;

        // use width (as set in Settings) if size is 0,
        if ( !mpData->maPixSize.Width() )
            mpData->maPixSize.Width() = pWindow->GetSettings().GetStyleSettings().GetCursorSize();

        // calculate output area and display
        ImplCursorInvert( mpData );
        mpData->mbCurVisible = true;
    }
}

void vcl::Cursor::ImplRestore()
{
    assert( mpData && mpData->mbCurVisible );

    ImplCursorInvert( mpData );
    mpData->mbCurVisible = false;
}

void vcl::Cursor::ImplDoShow( bool bDrawDirect, bool bRestore )
{
    if ( mbVisible )
    {
        vcl::Window* pWindow;
        if ( mpWindow )
            pWindow = mpWindow;
        else
        {
            // show the cursor, if there is an active window and the cursor
            // has been selected in this window
            pWindow = Application::GetFocusWindow();
            if ( !pWindow || (pWindow->mpWindowImpl->mpCursor != this) || pWindow->mpWindowImpl->mbInPaint
                || !pWindow->mpWindowImpl->mpFrameData->mbHasFocus )
                pWindow = NULL;
        }

        if ( pWindow )
        {
            if ( !mpData )
            {
                mpData = new ImplCursorData;
                mpData->mbCurVisible = false;
                mpData->maTimer.SetTimeoutHdl( LINK( this, Cursor, ImplTimerHdl ) );
            }

            mpData->mpWindow    = pWindow;
            mpData->mnStyle     = mnStyle;
            if ( bDrawDirect || bRestore )
                ImplDraw();

            if ( !mpWindow && ! ( ! bDrawDirect && mpData->maTimer.IsActive()) )
            {
                mpData->maTimer.SetTimeout( pWindow->GetSettings().GetStyleSettings().GetCursorBlinkTime() );
                if ( mpData->maTimer.GetTimeout() != STYLE_CURSOR_NOBLINKTIME )
                    mpData->maTimer.Start();
                else if ( !mpData->mbCurVisible )
                    ImplDraw();
            }
        }
    }
}

bool vcl::Cursor::ImplDoHide( bool bSuspend )
{
    bool bWasCurVisible = false;
    if ( mpData && mpData->mpWindow )
    {
        bWasCurVisible = mpData->mbCurVisible;
        if ( mpData->mbCurVisible )
            ImplRestore();

        if ( !bSuspend )
        {
            mpData->maTimer.Stop();
            mpData->mpWindow = NULL;
        }
    }
    return bWasCurVisible;
}

void vcl::Cursor::ImplShow( bool bDrawDirect )
{
    ImplDoShow( bDrawDirect, false );
}

void vcl::Cursor::ImplHide( bool i_bStopTimer )
{
    assert( i_bStopTimer );
    ImplDoHide( !i_bStopTimer );
}

void vcl::Cursor::ImplResume( bool bRestore )
{
    ImplDoShow( false, bRestore );
}

bool vcl::Cursor::ImplSuspend()
{
    return ImplDoHide( true );
}

void vcl::Cursor::ImplNew()
{
    if ( mbVisible && mpData && mpData->mpWindow )
    {
        if ( mpData->mbCurVisible )
            ImplRestore();

        ImplDraw();
        if ( !mpWindow )
        {
            if ( mpData->maTimer.GetTimeout() != STYLE_CURSOR_NOBLINKTIME )
                mpData->maTimer.Start();
        }
    }
}

IMPL_LINK_NOARG_TYPED(vcl::Cursor, ImplTimerHdl, Timer *, void)
{
    if ( mpData->mbCurVisible )
        ImplRestore();
    else
        ImplDraw();
}

vcl::Cursor::Cursor()
{
    mpData          = NULL;
    mpWindow        = NULL;
    mnSlant         = 0;
    mnOrientation   = 0;
    mnDirection     = CursorDirection::NONE;
    mnStyle         = 0;
    mbVisible       = false;
}

vcl::Cursor::Cursor( const Cursor& rCursor ) :
    maSize( rCursor.maSize ),
    maPos( rCursor.maPos )
{
    mpData          = NULL;
    mpWindow        = NULL;
    mnSlant         = rCursor.mnSlant;
    mnOrientation   = rCursor.mnOrientation;
    mnDirection     = rCursor.mnDirection;
    mnStyle         = 0;
    mbVisible       = rCursor.mbVisible;
}

vcl::Cursor::~Cursor()
{
    if ( mpData )
    {
        if ( mpData->mbCurVisible )
            ImplRestore();

        delete mpData;
    }
}

void vcl::Cursor::SetStyle( sal_uInt16 nStyle )
{
    if ( mnStyle != nStyle )
    {
        mnStyle = nStyle;
        ImplNew();
    }
}

void vcl::Cursor::Show()
{
    if ( !mbVisible )
    {
        mbVisible = true;
        ImplShow();
    }
}

void vcl::Cursor::Hide()
{
    if ( mbVisible )
    {
        mbVisible = false;
        ImplHide( true );
    }
}

void vcl::Cursor::SetWindow( vcl::Window* pWindow )
{
    if ( mpWindow.get() != pWindow )
    {
        mpWindow = pWindow;
        ImplNew();
    }
}

void vcl::Cursor::SetPos( const Point& rPoint )
{
    if ( maPos != rPoint )
    {
        maPos = rPoint;
        ImplNew();
    }
}

void vcl::Cursor::SetSize( const Size& rSize )
{
    if ( maSize != rSize )
    {
        maSize = rSize;
        ImplNew();
    }
}

void vcl::Cursor::SetWidth( long nNewWidth )
{
    if ( maSize.Width() != nNewWidth )
    {
        maSize.Width() = nNewWidth;
        ImplNew();
    }
}

void vcl::Cursor::SetOrientation( short nNewOrientation )
{
    if ( mnOrientation != nNewOrientation )
    {
        mnOrientation = nNewOrientation;
        ImplNew();
    }
}

void vcl::Cursor::SetDirection( CursorDirection nNewDirection )
{
    if ( mnDirection != nNewDirection )
    {
        mnDirection = nNewDirection;
        ImplNew();
    }
}

vcl::Cursor& vcl::Cursor::operator=( const vcl::Cursor& rCursor )
{
    maPos           = rCursor.maPos;
    maSize          = rCursor.maSize;
    mnSlant         = rCursor.mnSlant;
    mnOrientation   = rCursor.mnOrientation;
    mnDirection     = rCursor.mnDirection;
    mbVisible       = rCursor.mbVisible;
    ImplNew();

    return *this;
}

bool vcl::Cursor::operator==( const vcl::Cursor& rCursor ) const
{
    return
        ((maPos         == rCursor.maPos)           &&
         (maSize        == rCursor.maSize)          &&
         (mnSlant       == rCursor.mnSlant)         &&
         (mnOrientation == rCursor.mnOrientation)   &&
         (mnDirection   == rCursor.mnDirection)     &&
         (mbVisible     == rCursor.mbVisible))
        ;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/***********************************************************************
     filename:   CEGUITreeItem.cpp
     created:	5-13-07
     author:		Jonathan Welch (Based on Code by David Durant)
 *************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#ifdef HAVE_CONFIG_H
#   include "config.h"
#endif

#include "elements/CEGUITree.h"
#include "elements/CEGUITreeItem.h"
#include "CEGUISystem.h"
#include "CEGUIImagesetManager.h"
#include "CEGUIImageset.h"
#include "CEGUIFontManager.h"
#include "CEGUIFont.h"
#include "CEGUIWindow.h"
#include "CEGUIImage.h"
#include <algorithm>

#if defined (CEGUI_USE_FRIBIDI)
    #include "CEGUIFribidiVisualMapping.h"
#elif defined (CEGUI_USE_MINIBIDI)
    #include "CEGUIMinibidiVisualMapping.h"
#else
    #include "CEGUIBiDiVisualMapping.h"
#endif

// Start of CEGUI namespace section
namespace CEGUI
{
//----------------------------------------------------------------------------//
BasicRenderedStringParser TreeItem::d_stringParser;

/*************************************************************************
    Constants
*************************************************************************/
const colour TreeItem::DefaultSelectionColour = 0xFF4444AA;
const colour TreeItem::DefaultTextColour = 0xFFFFFFFF;

/*************************************************************************
    Base class constructor
*************************************************************************/
TreeItem::TreeItem(const String& text, uint item_id, void* item_data,
                   bool disabled, bool auto_delete) :
#ifndef CEGUI_BIDI_SUPPORT
    d_bidiVisualMapping(0),
#elif defined (CEGUI_USE_FRIBIDI)
    d_bidiVisualMapping(new FribidiVisualMapping),
#elif defined (CEGUI_USE_MINIBIDI)
    d_bidiVisualMapping(new MinibidiVisualMapping),
#else
    #error "BIDI Configuration is inconsistant, check your config!"
#endif
    d_bidiDataValid(false),
    d_itemID(item_id),
    d_itemData(item_data),
    d_selected(false),
    d_disabled(disabled),
    d_autoDelete(auto_delete),
    d_buttonLocation(Rect(0,0,0,0)),
    d_owner(0),
    d_selectCols(DefaultSelectionColour, DefaultSelectionColour,
                 DefaultSelectionColour, DefaultSelectionColour),
    d_selectBrush(0),
    d_textCols(DefaultTextColour, DefaultTextColour,
               DefaultTextColour, DefaultTextColour),
    d_font(0),
    d_iconImage(0),
    d_isOpen(false),
    d_renderedStringValid(false)
{
    setText(text);
}

/*************************************************************************
    Set the selection highlighting brush image.
*************************************************************************/
void TreeItem::setSelectionBrushImage(const String& imageset,
                                      const String& image)
{
    setSelectionBrushImage(
        &ImagesetManager::getSingleton().get(imageset).getImage(image));
}

/*************************************************************************
    Return a ColourRect object describing the colours in 'cols' after
    having their alpha component modulated by the value 'alpha'.
*************************************************************************/
ColourRect TreeItem::getModulateAlphaColourRect(const ColourRect& cols,
                                                float alpha) const
{
    return ColourRect
    (
     calculateModulatedAlphaColour(cols.d_top_left, alpha),
     calculateModulatedAlphaColour(cols.d_top_right, alpha),
     calculateModulatedAlphaColour(cols.d_bottom_left, alpha),
     calculateModulatedAlphaColour(cols.d_bottom_right, alpha)
     );
}

/*************************************************************************
    Return a colour value describing the colour specified by 'col' after
    having its alpha component modulated by the value 'alpha'.
*************************************************************************/
colour TreeItem::calculateModulatedAlphaColour(colour col, float alpha) const
{
    colour temp(col);
    temp.setAlpha(temp.getAlpha() * alpha);
    return temp;
}

/*************************************************************************
    Return a pointer to the font being used by this TreeItem
*************************************************************************/
Font* TreeItem::getFont(void) const
{
    // prefer out own font
    if (d_font != 0)
        return d_font;
    // try our owner window's font setting
    // (may be null if owner uses non existant default font)
    else if (d_owner != 0)
        return d_owner->getFont();
    // no owner, just use the default (which may be NULL anyway)
    else
        return System::getSingleton().getDefaultFont();
}

/*************************************************************************
    Set the font to be used by this TreeItem
*************************************************************************/
void TreeItem::setFont(const String& font_name)
{
    setFont(&FontManager::getSingleton().get(font_name));
}

//----------------------------------------------------------------------------//
void TreeItem::setFont(Font* font)
{
    d_font = font;

    d_renderedStringValid = false;
}

//----------------------------------------------------------------------------//

/*************************************************************************
    Return the rendered pixel size of this tree item.
*************************************************************************/
Size TreeItem::getPixelSize(void) const
{
    Font* fnt = getFont();

    if (!fnt)
        return Size(0, 0);

    if (!d_renderedStringValid)
        parseTextString();

    Size sz(0.0f, 0.0f);

    for (size_t i = 0; i < d_renderedString.getLineCount(); ++i)
    {
        const Size line_sz(d_renderedString.getPixelSize(i));
        sz.d_height += line_sz.d_height;

        if (line_sz.d_width > sz.d_width)
            sz.d_width = line_sz.d_width;
    }

    return sz;
}

/*************************************************************************
    Add the given TreeItem to this item's list.
*************************************************************************/
void TreeItem::addItem(TreeItem* item)
{
    if (item != 0)
    {
        Tree* parentWindow = (Tree*)getOwnerWindow();

        // establish ownership
        item->setOwnerWindow(parentWindow);

        // if sorting is enabled, re-sort the tree
        if (parentWindow->isSortEnabled())
        {
            d_listItems.insert(
                std::upper_bound(d_listItems.begin(),
                                 d_listItems.end(), item, &lbi_less),
                item);
        }
        // not sorted, just stick it on the end.
        else
        {
            d_listItems.push_back(item);
        }

        WindowEventArgs args(parentWindow);
        parentWindow->onListContentsChanged(args);
    }
}

/*************************************************************************
    Remove the given TreeItem from this item's list.
*************************************************************************/
void TreeItem::removeItem(const TreeItem* item)
{
    if (item)
    {
        Tree* parentWindow = (Tree*)getOwnerWindow();

        LBItemList::iterator pos = std::find(d_listItems.begin(),
                                             d_listItems.end(),
                                             item);
        if (pos != d_listItems.end())
        {
            (*pos)->setOwnerWindow(0);
            d_listItems.erase(pos);

            if (item == parentWindow->d_lastSelected)
                parentWindow->d_lastSelected = 0;

            if (item->isAutoDeleted())
                delete item;

            WindowEventArgs args(parentWindow);
            parentWindow->onListContentsChanged(args);
        }
    }
}

TreeItem *TreeItem::getTreeItemFromIndex(size_t itemIndex)
{
    if (itemIndex > d_listItems.size())
        return 0;

    return d_listItems[itemIndex];
}

/*************************************************************************
    Draw the tree item in its current state.
*************************************************************************/
void TreeItem::draw(GeometryBuffer& buffer, const Rect &targetRect,
                    float alpha, const Rect *clipper) const
{
    Rect finalRect(targetRect);

    if (d_iconImage != 0)
    {
        Rect finalPos(finalRect);
        finalPos.setWidth(targetRect.getHeight());
        finalPos.setHeight(targetRect.getHeight());
        d_iconImage->draw(buffer, finalPos, clipper,
                          ColourRect(colour(1,1,1,alpha)));
        finalRect.d_left += targetRect.getHeight();
    }

    if (d_selected && d_selectBrush != 0)
        d_selectBrush->draw(buffer, finalRect, clipper,
                            getModulateAlphaColourRect(d_selectCols, alpha));

    Font* font = getFont();

    if (!font)
        return;

    Vector2 draw_pos(finalRect.getPosition());
    draw_pos.d_y -= (font->getLineSpacing() - font->getBaseline()) * 0.5f;

    if (!d_renderedStringValid)
        parseTextString();

    const ColourRect final_colours(
        getModulateAlphaColourRect(ColourRect(0xFFFFFFFF), alpha));

    for (size_t i = 0; i < d_renderedString.getLineCount(); ++i)
    {
        d_renderedString.draw(i, buffer, draw_pos, &final_colours, clipper, 0.0f);
        draw_pos.d_y += d_renderedString.getPixelSize(i).d_height;
    }
}

/*************************************************************************
    Set the colours used for selection highlighting.
*************************************************************************/
void TreeItem::setSelectionColours(colour top_left_colour,
                                   colour top_right_colour,
                                   colour bottom_left_colour,
                                   colour bottom_right_colour)
{
    d_selectCols.d_top_left		= top_left_colour;
    d_selectCols.d_top_right	= top_right_colour;
    d_selectCols.d_bottom_left	= bottom_left_colour;
    d_selectCols.d_bottom_right	= bottom_right_colour;
}

/*************************************************************************
    Set the colours used for text rendering.
*************************************************************************/
void TreeItem::setTextColours(colour top_left_colour,
                              colour top_right_colour,
                              colour bottom_left_colour,
                              colour bottom_right_colour)
{
    d_textCols.d_top_left		= top_left_colour;
    d_textCols.d_top_right		= top_right_colour;
    d_textCols.d_bottom_left	= bottom_left_colour;
    d_textCols.d_bottom_right	= bottom_right_colour;

    d_renderedStringValid = false;
}

//----------------------------------------------------------------------------//
void TreeItem::setText( const String& text )
{
    d_textLogical = text;
    d_bidiDataValid = false;
}

//----------------------------------------------------------------------------//
void TreeItem::parseTextString() const
{
    d_renderedString =
        d_stringParser.parse(getTextVisual(), getFont(), &d_textCols);
    d_renderedStringValid = true;
}

//----------------------------------------------------------------------------//
const String& TreeItem::getTextVisual() const
{
    // no bidi support
    if (!d_bidiVisualMapping)
        return d_textLogical;

    if (!d_bidiDataValid)
    {
        d_bidiVisualMapping->updateVisual(d_textLogical);
        d_bidiDataValid = true;
    }

    return d_bidiVisualMapping->getTextVisual();
}

//----------------------------------------------------------------------------//

} // End of  CEGUI namespace section
<commit_msg>FIX: TreeItem rendered string was not being invaliated in the setText function and one of the setTextColours overloads.  See: http://www.cegui.org.uk/mantis/view.php?id=347<commit_after>/***********************************************************************
     filename:   CEGUITreeItem.cpp
     created:	5-13-07
     author:		Jonathan Welch (Based on Code by David Durant)
 *************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#ifdef HAVE_CONFIG_H
#   include "config.h"
#endif

#include "elements/CEGUITree.h"
#include "elements/CEGUITreeItem.h"
#include "CEGUISystem.h"
#include "CEGUIImagesetManager.h"
#include "CEGUIImageset.h"
#include "CEGUIFontManager.h"
#include "CEGUIFont.h"
#include "CEGUIWindow.h"
#include "CEGUIImage.h"
#include <algorithm>

#if defined (CEGUI_USE_FRIBIDI)
    #include "CEGUIFribidiVisualMapping.h"
#elif defined (CEGUI_USE_MINIBIDI)
    #include "CEGUIMinibidiVisualMapping.h"
#else
    #include "CEGUIBiDiVisualMapping.h"
#endif

// Start of CEGUI namespace section
namespace CEGUI
{
//----------------------------------------------------------------------------//
BasicRenderedStringParser TreeItem::d_stringParser;

/*************************************************************************
    Constants
*************************************************************************/
const colour TreeItem::DefaultSelectionColour = 0xFF4444AA;
const colour TreeItem::DefaultTextColour = 0xFFFFFFFF;

/*************************************************************************
    Base class constructor
*************************************************************************/
TreeItem::TreeItem(const String& text, uint item_id, void* item_data,
                   bool disabled, bool auto_delete) :
#ifndef CEGUI_BIDI_SUPPORT
    d_bidiVisualMapping(0),
#elif defined (CEGUI_USE_FRIBIDI)
    d_bidiVisualMapping(new FribidiVisualMapping),
#elif defined (CEGUI_USE_MINIBIDI)
    d_bidiVisualMapping(new MinibidiVisualMapping),
#else
    #error "BIDI Configuration is inconsistant, check your config!"
#endif
    d_bidiDataValid(false),
    d_itemID(item_id),
    d_itemData(item_data),
    d_selected(false),
    d_disabled(disabled),
    d_autoDelete(auto_delete),
    d_buttonLocation(Rect(0,0,0,0)),
    d_owner(0),
    d_selectCols(DefaultSelectionColour, DefaultSelectionColour,
                 DefaultSelectionColour, DefaultSelectionColour),
    d_selectBrush(0),
    d_textCols(DefaultTextColour, DefaultTextColour,
               DefaultTextColour, DefaultTextColour),
    d_font(0),
    d_iconImage(0),
    d_isOpen(false),
    d_renderedStringValid(false)
{
    setText(text);
}

/*************************************************************************
    Set the selection highlighting brush image.
*************************************************************************/
void TreeItem::setSelectionBrushImage(const String& imageset,
                                      const String& image)
{
    setSelectionBrushImage(
        &ImagesetManager::getSingleton().get(imageset).getImage(image));
}

/*************************************************************************
    Return a ColourRect object describing the colours in 'cols' after
    having their alpha component modulated by the value 'alpha'.
*************************************************************************/
ColourRect TreeItem::getModulateAlphaColourRect(const ColourRect& cols,
                                                float alpha) const
{
    return ColourRect
    (
     calculateModulatedAlphaColour(cols.d_top_left, alpha),
     calculateModulatedAlphaColour(cols.d_top_right, alpha),
     calculateModulatedAlphaColour(cols.d_bottom_left, alpha),
     calculateModulatedAlphaColour(cols.d_bottom_right, alpha)
     );
}

/*************************************************************************
    Return a colour value describing the colour specified by 'col' after
    having its alpha component modulated by the value 'alpha'.
*************************************************************************/
colour TreeItem::calculateModulatedAlphaColour(colour col, float alpha) const
{
    colour temp(col);
    temp.setAlpha(temp.getAlpha() * alpha);
    return temp;
}

/*************************************************************************
    Return a pointer to the font being used by this TreeItem
*************************************************************************/
Font* TreeItem::getFont(void) const
{
    // prefer out own font
    if (d_font != 0)
        return d_font;
    // try our owner window's font setting
    // (may be null if owner uses non existant default font)
    else if (d_owner != 0)
        return d_owner->getFont();
    // no owner, just use the default (which may be NULL anyway)
    else
        return System::getSingleton().getDefaultFont();
}

/*************************************************************************
    Set the font to be used by this TreeItem
*************************************************************************/
void TreeItem::setFont(const String& font_name)
{
    setFont(&FontManager::getSingleton().get(font_name));
}

//----------------------------------------------------------------------------//
void TreeItem::setFont(Font* font)
{
    d_font = font;

    d_renderedStringValid = false;
}

//----------------------------------------------------------------------------//

/*************************************************************************
    Return the rendered pixel size of this tree item.
*************************************************************************/
Size TreeItem::getPixelSize(void) const
{
    Font* fnt = getFont();

    if (!fnt)
        return Size(0, 0);

    if (!d_renderedStringValid)
        parseTextString();

    Size sz(0.0f, 0.0f);

    for (size_t i = 0; i < d_renderedString.getLineCount(); ++i)
    {
        const Size line_sz(d_renderedString.getPixelSize(i));
        sz.d_height += line_sz.d_height;

        if (line_sz.d_width > sz.d_width)
            sz.d_width = line_sz.d_width;
    }

    return sz;
}

/*************************************************************************
    Add the given TreeItem to this item's list.
*************************************************************************/
void TreeItem::addItem(TreeItem* item)
{
    if (item != 0)
    {
        Tree* parentWindow = (Tree*)getOwnerWindow();

        // establish ownership
        item->setOwnerWindow(parentWindow);

        // if sorting is enabled, re-sort the tree
        if (parentWindow->isSortEnabled())
        {
            d_listItems.insert(
                std::upper_bound(d_listItems.begin(),
                                 d_listItems.end(), item, &lbi_less),
                item);
        }
        // not sorted, just stick it on the end.
        else
        {
            d_listItems.push_back(item);
        }

        WindowEventArgs args(parentWindow);
        parentWindow->onListContentsChanged(args);
    }
}

/*************************************************************************
    Remove the given TreeItem from this item's list.
*************************************************************************/
void TreeItem::removeItem(const TreeItem* item)
{
    if (item)
    {
        Tree* parentWindow = (Tree*)getOwnerWindow();

        LBItemList::iterator pos = std::find(d_listItems.begin(),
                                             d_listItems.end(),
                                             item);
        if (pos != d_listItems.end())
        {
            (*pos)->setOwnerWindow(0);
            d_listItems.erase(pos);

            if (item == parentWindow->d_lastSelected)
                parentWindow->d_lastSelected = 0;

            if (item->isAutoDeleted())
                delete item;

            WindowEventArgs args(parentWindow);
            parentWindow->onListContentsChanged(args);
        }
    }
}

TreeItem *TreeItem::getTreeItemFromIndex(size_t itemIndex)
{
    if (itemIndex > d_listItems.size())
        return 0;

    return d_listItems[itemIndex];
}

/*************************************************************************
    Draw the tree item in its current state.
*************************************************************************/
void TreeItem::draw(GeometryBuffer& buffer, const Rect &targetRect,
                    float alpha, const Rect *clipper) const
{
    Rect finalRect(targetRect);

    if (d_iconImage != 0)
    {
        Rect finalPos(finalRect);
        finalPos.setWidth(targetRect.getHeight());
        finalPos.setHeight(targetRect.getHeight());
        d_iconImage->draw(buffer, finalPos, clipper,
                          ColourRect(colour(1,1,1,alpha)));
        finalRect.d_left += targetRect.getHeight();
    }

    if (d_selected && d_selectBrush != 0)
        d_selectBrush->draw(buffer, finalRect, clipper,
                            getModulateAlphaColourRect(d_selectCols, alpha));

    Font* font = getFont();

    if (!font)
        return;

    Vector2 draw_pos(finalRect.getPosition());
    draw_pos.d_y -= (font->getLineSpacing() - font->getBaseline()) * 0.5f;

    if (!d_renderedStringValid)
        parseTextString();

    const ColourRect final_colours(
        getModulateAlphaColourRect(ColourRect(0xFFFFFFFF), alpha));

    for (size_t i = 0; i < d_renderedString.getLineCount(); ++i)
    {
        d_renderedString.draw(i, buffer, draw_pos, &final_colours, clipper, 0.0f);
        draw_pos.d_y += d_renderedString.getPixelSize(i).d_height;
    }
}

/*************************************************************************
    Set the colours used for selection highlighting.
*************************************************************************/
void TreeItem::setSelectionColours(colour top_left_colour,
                                   colour top_right_colour,
                                   colour bottom_left_colour,
                                   colour bottom_right_colour)
{
    d_selectCols.d_top_left		= top_left_colour;
    d_selectCols.d_top_right	= top_right_colour;
    d_selectCols.d_bottom_left	= bottom_left_colour;
    d_selectCols.d_bottom_right	= bottom_right_colour;
}

/*************************************************************************
    Set the colours used for text rendering.
*************************************************************************/
void TreeItem::setTextColours(colour top_left_colour,
                              colour top_right_colour,
                              colour bottom_left_colour,
                              colour bottom_right_colour)
{
    d_textCols.d_top_left		= top_left_colour;
    d_textCols.d_top_right		= top_right_colour;
    d_textCols.d_bottom_left	= bottom_left_colour;
    d_textCols.d_bottom_right	= bottom_right_colour;

    d_renderedStringValid = false;
}

//----------------------------------------------------------------------------//
void TreeItem::setText( const String& text )
{
    d_textLogical = text;
    d_bidiDataValid = false;
    d_renderedStringValid = false;
}

//----------------------------------------------------------------------------//
void TreeItem::parseTextString() const
{
    d_renderedString =
        d_stringParser.parse(getTextVisual(), getFont(), &d_textCols);
    d_renderedStringValid = true;
}

//----------------------------------------------------------------------------//
const String& TreeItem::getTextVisual() const
{
    // no bidi support
    if (!d_bidiVisualMapping)
        return d_textLogical;

    if (!d_bidiDataValid)
    {
        d_bidiVisualMapping->updateVisual(d_textLogical);
        d_bidiDataValid = true;
    }

    return d_bidiVisualMapping->getTextVisual();
}

//----------------------------------------------------------------------------//

} // End of  CEGUI namespace section
<|endoftext|>


<commit_before><commit_msg>Fix selectable.<commit_after><|endoftext|>


<commit_before><commit_msg>VSCode test<commit_after><|endoftext|>


<commit_before>/* Copyright 2015 Realm Inc - All Rights Reserved
 * Proprietary and Confidential
 */

#include "../platform.hpp"
 #include "../js_init.h"
#include <string>

std::string s_default_realm_directory;

namespace realm {

void set_default_realm_file_directory(std::string dir) {
    s_default_realm_directory = dir;
}

std::string default_realm_file_directory()
{
	return s_default_realm_directory;
}

void ensure_directory_exists_for_file(const std::string &fileName)
{
}

void remove_realm_files_from_directory(const std::string &directory)
{
}

}
<commit_msg>implementation for remove files<commit_after>/* Copyright 2015 Realm Inc - All Rights Reserved
 * Proprietary and Confidential
 */

#include "../platform.hpp"
 #include "../js_init.h"
#include <string>
#include <stdlib.h>

std::string s_default_realm_directory;

namespace realm {

void set_default_realm_file_directory(std::string dir) {
    s_default_realm_directory = dir;
}

std::string default_realm_file_directory()
{
	return s_default_realm_directory;
}

void ensure_directory_exists_for_file(const std::string &fileName)
{
    std::string cmd = "rm " + s_default_realm_directory + "/*.realm " +
                              s_default_realm_directory + "/*.realm.lock";
    system(cmd.c_str());
}

void remove_realm_files_from_directory(const std::string &directory)
{
}

}
<|endoftext|>


<commit_before>/** @file distributed_tree.test.cc
 *
 *  A "stress" test driver for distributed trees.
 *
 *  @author Dongryeol Lee (dongryel@cc.gatech.edu)
 */

#include <boost/mpi.hpp>
#include <omp.h>
#include <time.h>
#include "core/metric_kernels/lmetric.h"
#include "core/parallel/random_dataset_generator.h"
#include "core/table/empty_query_result.h"
#include "core/table/distributed_table.h"
#include "core/tree/gen_kdtree.h"
#include "core/tree/gen_metric_tree.h"
#include "core/parallel/vanilla_distributed_tree_builder.h"
#include "core/math/math_lib.h"

namespace core {
namespace tree {

template<typename DistributedTableType>
class TestDistributedTree {
  public:
    typedef typename DistributedTableType::TableType TableType;

    typedef typename TableType::TreeType TreeType;

  private:

    bool TestLocalTree_(TreeType *node) {
      if((! node->is_leaf()) && node->count() == 0) {
        printf("A non-leaf node has zero points!\n");
        return false;
      }

      if(! node->is_leaf()) {
        return TestLocalTree_(node->left()) && TestLocalTree_(node->right());
      }
      return true;
    }

  public:

    int StressTestMain(boost::mpi::communicator &world) {
      for(int i = 0; i < 10; i++) {

        // Only the master broadcasts the dimension;
        int num_dimensions;
        if(world.rank() == 0) {
          num_dimensions = core::math::RandInt(2, 3);
        }
        boost::mpi::broadcast(world, num_dimensions, 0);
        int num_points = core::math::RandInt(3000, 8000);
        if(StressTest(world, num_dimensions, num_points) == false) {
          printf("Failed!\n");
          exit(0);
        }
        printf("\n");
      }
      return 0;
    }

    bool StressTest(
      boost::mpi::communicator &world, int num_dimensions, int num_points) {

      std::cout << "Number of dimensions: " << num_dimensions << "\n";
      std::cout << "Number of points: " << num_points << "\n";

      // Push in the reference dataset name.
      std::stringstream reference_file_name_sstr;
      reference_file_name_sstr << "random_dataset.csv" << world.rank();
      std::string references_in = reference_file_name_sstr.str();

      // Generate the random dataset and save it.
      TableType random_table;
      core::parallel::RandomDatasetGenerator::Generate(
        num_dimensions, num_points, world.rank(),
        std::string("none"), false, &random_table);
      random_table.Save(references_in);

      DistributedTableType distributed_table;
      distributed_table.Init(references_in, world);
      core::parallel::VanillaDistributedTreeBuilder <
      DistributedTableType > builder;
      builder.Init(distributed_table);
      core::metric_kernels::LMetric<2> l2_metric;
      int leaf_size = core::math::RandInt(20, 40);
      builder.Build(world, l2_metric, leaf_size);

      // Tes the local tree.
      return TestLocalTree_(distributed_table.local_table()->get_tree());
    }
};
}
}

int main(int argc, char *argv[]) {

  omp_set_num_threads(1);

  // Initialize boost MPI.
  boost::mpi::environment env(argc, argv);
  boost::mpi::communicator world;

  // The general metric tree type.
  typedef core::tree::GenMetricTree<core::tree::AbstractStatistic>
  GenMetricTreeSpecType;
  typedef core::table::DistributedTable <
  GenMetricTreeSpecType, core::table::EmptyQueryResult >
  GenMetricTreeDistributedTableType;
  typedef typename GenMetricTreeDistributedTableType::TableType GenMetricTreeTableType;

  // The general kd tree type.
  typedef core::tree::GenKdTree<core::tree::AbstractStatistic>
  GenKdTreeSpecType;
  typedef core::table::DistributedTable <
  GenKdTreeSpecType, core::table::EmptyQueryResult >
  GenKdTreeDistributedTableType;
  typedef typename GenKdTreeDistributedTableType::TableType GenKdTreeTableType;

  // Call the tests.
  printf("Testing the general metric trees:\n");
  core::tree::TestDistributedTree<GenMetricTreeDistributedTableType>
  gen_metric_tree_test;
  gen_metric_tree_test.StressTestMain(world);
  printf("Testing the general kd trees:\n");
  core::tree::TestDistributedTree<GenKdTreeDistributedTableType>
  gen_kdtree_test;
  gen_kdtree_test.StressTestMain(world);

  std::cout << "All tests passed!\n";
  return 0;
}
<commit_msg>Distributed tree test compiles now.<commit_after>/** @file distributed_tree.test.cc
 *
 *  A "stress" test driver for distributed trees.
 *
 *  @author Dongryeol Lee (dongryel@cc.gatech.edu)
 */

#include <boost/mpi.hpp>
#include <omp.h>
#include <time.h>
#include "core/metric_kernels/lmetric.h"
#include "core/parallel/random_dataset_generator.h"
#include "core/table/empty_query_result.h"
#include "core/table/distributed_table.h"
#include "core/tree/gen_kdtree.h"
#include "core/tree/gen_metric_tree.h"
#include "core/parallel/vanilla_distributed_tree_builder.h"
#include "core/math/math_lib.h"

namespace core {
namespace tree {

template<typename DistributedTableType>
class TestDistributedTree {
  public:
    typedef typename DistributedTableType::TableType TableType;

    typedef typename TableType::TreeType TreeType;

  private:

    bool TestLocalTree_(TreeType *node) {
      if((! node->is_leaf()) && node->count() == 0) {
        printf("A non-leaf node has zero points!\n");
        return false;
      }

      if(! node->is_leaf()) {
        return TestLocalTree_(node->left()) && TestLocalTree_(node->right());
      }
      return true;
    }

  public:

    int StressTestMain(boost::mpi::communicator &world) {
      for(int i = 0; i < 1; i++) {

        // Only the master broadcasts the dimension;
        int num_dimensions;
        if(world.rank() == 0) {
          num_dimensions = core::math::RandInt(10, 11);
        }
        boost::mpi::broadcast(world, num_dimensions, 0);
        int num_points = core::math::RandInt(1000000, 1000001);
        if(StressTest(world, num_dimensions, num_points) == false) {
          printf("Failed!\n");
          exit(0);
        }
        printf("\n");
      }
      return 0;
    }

    bool StressTest(
      boost::mpi::communicator &world, int num_dimensions, int num_points) {

      std::cout << "Number of dimensions: " << num_dimensions << "\n";
      std::cout << "Number of points: " << num_points << "\n";

      // Push in the reference dataset name.
      std::stringstream reference_file_name_sstr;
      reference_file_name_sstr << "random_dataset.csv" << world.rank();
      std::string references_in = reference_file_name_sstr.str();

      // Generate the random dataset and save it.
      TableType random_table;
      core::parallel::RandomDatasetGenerator::Generate(
        num_dimensions, num_points, world.rank(),
        std::string("none"), false, &random_table);
      random_table.Save(references_in);
      int leaf_size = core::math::RandInt(20, 40);
      core::metric_kernels::LMetric<2> l2_metric;

      {
        // First, build with only one thread.
        printf("First building with only one thread...\n");
        omp_set_num_threads(1);
        DistributedTableType distributed_table;
        distributed_table.Init(references_in, world);
        core::parallel::VanillaDistributedTreeBuilder <
        DistributedTableType > builder;
        builder.Init(distributed_table);
        builder.Build(world, l2_metric, leaf_size, 0);
      }

      // Next, build with four threads.
      printf("Now building with four threads...\n");
      omp_set_num_threads(4);
      DistributedTableType distributed_table;
      distributed_table.Init(references_in, world);
      core::parallel::VanillaDistributedTreeBuilder <
      DistributedTableType > builder;
      builder.Init(distributed_table);
      builder.Build(world, l2_metric, leaf_size, 0);

      // Tes the local tree.
      return TestLocalTree_(distributed_table.local_table()->get_tree());
    }
};
}
}

int main(int argc, char *argv[]) {

  // Initialize boost MPI.
  boost::mpi::environment env(argc, argv);
  boost::mpi::communicator world;

  // The general metric tree type.
  typedef core::tree::GenMetricTree<core::tree::AbstractStatistic>
  GenMetricTreeSpecType;
  typedef core::table::DistributedTable <
  GenMetricTreeSpecType, core::table::EmptyQueryResult >
  GenMetricTreeDistributedTableType;
  typedef typename GenMetricTreeDistributedTableType::TableType GenMetricTreeTableType;

  // The general kd tree type.
  typedef core::tree::GenKdTree<core::tree::AbstractStatistic>
  GenKdTreeSpecType;
  typedef core::table::DistributedTable <
  GenKdTreeSpecType, core::table::EmptyQueryResult >
  GenKdTreeDistributedTableType;
  typedef typename GenKdTreeDistributedTableType::TableType GenKdTreeTableType;

  // Call the tests.
  printf("Testing the general metric trees:\n");
  core::tree::TestDistributedTree<GenMetricTreeDistributedTableType>
  gen_metric_tree_test;
  gen_metric_tree_test.StressTestMain(world);
  printf("Testing the general kd trees:\n");
  core::tree::TestDistributedTree<GenKdTreeDistributedTableType>
  gen_kdtree_test;
  gen_kdtree_test.StressTestMain(world);

  std::cout << "All tests passed!\n";
  return 0;
}
<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2006 Christian Gehl
 * Copyright (C) 2006-2008 Fraunhofer Institute FIRST
 */

#include "lib/config.h"
#include "lib/common.h"
#include "lib/io.h"
#include "distance/GeodesicMetric.h"
#include "features/Features.h"
#include "features/RealFeatures.h"

CGeodesicMetric::CGeodesicMetric()
: CSimpleDistance<DREAL>()
{
}

CGeodesicMetric::CGeodesicMetric(CRealFeatures* l, CRealFeatures* r)
: CSimpleDistance<DREAL>()
{
	init(l, r);
}

CGeodesicMetric::~CGeodesicMetric()
{
	cleanup();
}

bool CGeodesicMetric::init(CFeatures* l, CFeatures* r)
{
	bool result=CSimpleDistance<DREAL>::init(l,r);

	return result;
}

void CGeodesicMetric::cleanup()
{
}

bool CGeodesicMetric::load_init(FILE* src)
{
	return false;
}

bool CGeodesicMetric::save_init(FILE* dest)
{
	return false;
}

DREAL CGeodesicMetric::compute(INT idx_a, INT idx_b)
{
	INT alen, blen;
	bool afree, bfree;

	double* avec=((CRealFeatures*) lhs)->get_feature_vector(idx_a, alen, afree);
	double* bvec=((CRealFeatures*) rhs)->get_feature_vector(idx_b, blen, bfree);

	ASSERT(alen==blen);

	DREAL s=0;
	DREAL d=0;
	{
		for (INT i=0; i<alen; i++)
		{
			d+=CMath::sqrt(fabs(avec[i])*fabs(bvec[i]));
			s+=avec[i]+bvec[i];
		}
	}

	((CRealFeatures*) lhs)->free_feature_vector(avec, idx_a, afree);
	((CRealFeatures*) rhs)->free_feature_vector(bvec, idx_b, bfree);

	if(s==0)
		return 0;
	if(d>1)
		return 0;

	return acos(d);
}
<commit_msg>-changed distance function to arcos( x*y/sqrt( (x*x) * (y*y) ) ) -distance can handle data, which has not be normalized<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2006-2008 Christian Gehl
 * Copyright (C) 2006-2008 Fraunhofer Institute FIRST
 */

#include "lib/config.h"
#include "lib/common.h"
#include "lib/io.h"
#include "distance/GeodesicMetric.h"
#include "features/Features.h"
#include "features/RealFeatures.h"

CGeodesicMetric::CGeodesicMetric()
: CSimpleDistance<DREAL>()
{
}

CGeodesicMetric::CGeodesicMetric(CRealFeatures* l, CRealFeatures* r)
: CSimpleDistance<DREAL>()
{
	init(l, r);
}

CGeodesicMetric::~CGeodesicMetric()
{
	cleanup();
}

bool CGeodesicMetric::init(CFeatures* l, CFeatures* r)
{
	bool result=CSimpleDistance<DREAL>::init(l,r);

	return result;
}

void CGeodesicMetric::cleanup()
{
}

bool CGeodesicMetric::load_init(FILE* src)
{
	return false;
}

bool CGeodesicMetric::save_init(FILE* dest)
{
	return false;
}

DREAL CGeodesicMetric::compute(INT idx_a, INT idx_b)
{
	INT alen, blen;
	bool afree, bfree;

	double* avec=((CRealFeatures*) lhs)->get_feature_vector(idx_a, alen, afree);
	double* bvec=((CRealFeatures*) rhs)->get_feature_vector(idx_b, blen, bfree);

	ASSERT(alen==blen);

	DREAL s=0;
	DREAL d=0;
	DREAL nx=0;
	DREAL ny=0;
	{
		for (INT i=0; i<alen; i++)
		{
			d+=avec[i]*bvec[i];
			nx+=avec[i]*avec[i];
			ny+=bvec[i]*bvec[i];
			s+=avec[i]+bvec[i];
		}
	}

	((CRealFeatures*) lhs)->free_feature_vector(avec, idx_a, afree);
	((CRealFeatures*) rhs)->free_feature_vector(bvec, idx_b, bfree);

	if(s==0)
		return 0;

	return acos(d/CMath::sqrt(nx*ny));
}
<|endoftext|>