<commit_before>/*
 * 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
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * $Id$
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/util/XMLInitializer.hpp>
#include <xercesc/util/PlatformUtils.hpp>

XERCES_CPP_NAMESPACE_BEGIN

// ---------------------------------------------------------------------------
//  XMLInitializer: Initialization methods
// ---------------------------------------------------------------------------
void XMLInitializer::initializeStaticData()
{
    try
    {
        // Note that in some cases the order of initialization can be
        // important.
        //

        // Core
        //
        initializeEncodingValidator();
        initializeXMLException();
        initializeXMLScanner();
        initializeXMLValidator();

        // Regex
        //
        initializeRangeTokenMap();
        initializeRegularExpression();

        // DTD
        //
        initializeDTDGrammar();

        // Schema
        //
        initializeXSDErrorReporter();
        initializeDatatypeValidatorFactory();
        initializeGeneralAttributeCheck();
        initializeXSValue();
        initializeComplexTypeInfo();

        // DOM
        //
        initializeDOMImplementationRegistry();
        initializeDOMImplementationImpl();
        initializeDOMDocumentTypeImpl();
        initializeDOMNodeListImpl();
        initializeDOMNormalizer();
    }
    catch(...) {
        XMLPlatformUtils::panic(PanicHandler::Panic_AllStaticInitErr);
    }
}

void XMLInitializer::terminateStaticData()
{
    // Terminate in the reverse order of initialization. There shouldn't
    // be any exceptions and if there are, we can't do anything about them
    // since we are no longer initialized (think of it as throwing from
    // a destructor).
    //

    // DOM
    //
    terminateDOMNormalizer();
    terminateDOMNodeListImpl();
    terminateDOMDocumentTypeImpl();
    terminateDOMImplementationImpl();
    terminateDOMImplementationRegistry();

    // Schema
    //
    terminateComplexTypeInfo();
    terminateXSValue();
    terminateGeneralAttributeCheck();
    terminateDatatypeValidatorFactory();
    terminateXSDErrorReporter();

    // DTD
    //
    terminateDTDGrammar();

    // Regex
    //
    terminateRegularExpression();
    terminateRangeTokenMap();

    // Core
    //
    terminateXMLValidator();
    terminateXMLScanner();
    terminateXMLException();
    terminateEncodingValidator();
}

XERCES_CPP_NAMESPACE_END
<commit_msg>Fixed memory leak when reporting an error for XInclude (XERCESC-1962)<commit_after>/*
 * 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
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * $Id$
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/util/XMLInitializer.hpp>
#include <xercesc/util/PlatformUtils.hpp>

XERCES_CPP_NAMESPACE_BEGIN

// ---------------------------------------------------------------------------
//  XMLInitializer: Initialization methods
// ---------------------------------------------------------------------------
void XMLInitializer::initializeStaticData()
{
    try
    {
        // Note that in some cases the order of initialization can be
        // important.
        //

        // Core
        //
        initializeEncodingValidator();
        initializeXMLException();
        initializeXMLScanner();
        initializeXMLValidator();

        // Regex
        //
        initializeRangeTokenMap();
        initializeRegularExpression();

        // DTD
        //
        initializeDTDGrammar();

        // Schema
        //
        initializeXSDErrorReporter();
        initializeDatatypeValidatorFactory();
        initializeGeneralAttributeCheck();
        initializeXSValue();
        initializeComplexTypeInfo();

        // DOM
        //
        initializeDOMImplementationRegistry();
        initializeDOMImplementationImpl();
        initializeDOMDocumentTypeImpl();
        initializeDOMNodeListImpl();
        initializeDOMNormalizer();

        // XInclude
        //
        initializeXInclude();
	}
    catch(...) {
        XMLPlatformUtils::panic(PanicHandler::Panic_AllStaticInitErr);
    }
}

void XMLInitializer::terminateStaticData()
{
    // Terminate in the reverse order of initialization. There shouldn't
    // be any exceptions and if there are, we can't do anything about them
    // since we are no longer initialized (think of it as throwing from
    // a destructor).
    //

    // XInclude
    //
    terminateXInclude();

	// DOM
    //
    terminateDOMNormalizer();
    terminateDOMNodeListImpl();
    terminateDOMDocumentTypeImpl();
    terminateDOMImplementationImpl();
    terminateDOMImplementationRegistry();

    // Schema
    //
    terminateComplexTypeInfo();
    terminateXSValue();
    terminateGeneralAttributeCheck();
    terminateDatatypeValidatorFactory();
    terminateXSDErrorReporter();

    // DTD
    //
    terminateDTDGrammar();

    // Regex
    //
    terminateRegularExpression();
    terminateRangeTokenMap();

    // Core
    //
    terminateXMLValidator();
    terminateXMLScanner();
    terminateXMLException();
    terminateEncodingValidator();
}

XERCES_CPP_NAMESPACE_END
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkTimeStamp.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

  Portions of this code are covered under the VTK copyright.
  See VTKCopyright.txt or http://www.kitware.com/VTKCopyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "itkTimeStamp.h"
#include "itkFastMutexLock.h"
#include "itkWindows.h"

// OSAtomic.h optimizations only used in 10.5 and later
#if defined(__APPLE__)
  #include <AvailabilityMacros.h>
  #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
    #include <libkern/OSAtomic.h>
  #endif
#endif

namespace itk
{

/**
 * Instance creation.
 */
TimeStamp*
TimeStamp
::New()
{
  return new Self;
}

/**
 * Make sure the new time stamp is greater than all others so far.
 */
void
TimeStamp
::Modified()
{
// Windows optimization
#if defined(WIN32) || defined(_WIN32)
  static LONG itkTimeStampTime = 0;
  m_ModifiedTime = (unsigned long)InterlockedIncrement(&itkTimeStampTime);

// Mac optimization
#elif defined(__APPLE__) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)
 #if __LP64__
  // "m_ModifiedTime" is "unsigned long", a type that changess sizes
  // depending on architecture.  The atomic increment is safe, since it
  // operates on a variable of the exact type needed.  The cast does not
  // change the size, but does change signedness, which is not ideal.
  static volatile int64_t itkTimeStampTime = 0;
  m_ModifiedTime = (unsigned long)OSAtomicIncrement64Barrier(&itkTimeStampTime);
 #else
  static volatile int32_t itkTimeStampTime = 0;
  m_ModifiedTime = (unsigned long)OSAtomicIncrement32Barrier(&itkTimeStampTime);
 #endif

// General case
#else
  /**
   * Initialize static member
   */
  static unsigned long itkTimeStampTime = 0;

  /** Used for mutex locking */
  static SimpleFastMutexLock TimeStampMutex;

  TimeStampMutex.Lock();
  m_ModifiedTime = ++itkTimeStampTime;
  TimeStampMutex.Unlock();
#endif

}

} // end namespace itk
<commit_msg>COMP: And... adding guards to that include so that it is only done when       WIN32 is defined.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkTimeStamp.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

  Portions of this code are covered under the VTK copyright.
  See VTKCopyright.txt or http://www.kitware.com/VTKCopyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "itkTimeStamp.h"
#include "itkFastMutexLock.h"

// OSAtomic.h optimizations only used in 10.5 and later
#if defined(__APPLE__)
  #include <AvailabilityMacros.h>
  #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
    #include <libkern/OSAtomic.h>
  #endif
#endif

#if defined(_WIN32)
#include "itkWindows.h"
#endif

namespace itk
{

/**
 * Instance creation.
 */
TimeStamp*
TimeStamp
::New()
{
  return new Self;
}

/**
 * Make sure the new time stamp is greater than all others so far.
 */
void
TimeStamp
::Modified()
{
// Windows optimization
#if defined(WIN32) || defined(_WIN32)
  static LONG itkTimeStampTime = 0;
  m_ModifiedTime = (unsigned long)InterlockedIncrement(&itkTimeStampTime);

// Mac optimization
#elif defined(__APPLE__) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)
 #if __LP64__
  // "m_ModifiedTime" is "unsigned long", a type that changess sizes
  // depending on architecture.  The atomic increment is safe, since it
  // operates on a variable of the exact type needed.  The cast does not
  // change the size, but does change signedness, which is not ideal.
  static volatile int64_t itkTimeStampTime = 0;
  m_ModifiedTime = (unsigned long)OSAtomicIncrement64Barrier(&itkTimeStampTime);
 #else
  static volatile int32_t itkTimeStampTime = 0;
  m_ModifiedTime = (unsigned long)OSAtomicIncrement32Barrier(&itkTimeStampTime);
 #endif

// General case
#else
  /**
   * Initialize static member
   */
  static unsigned long itkTimeStampTime = 0;

  /** Used for mutex locking */
  static SimpleFastMutexLock TimeStampMutex;

  TimeStampMutex.Lock();
  m_ModifiedTime = ++itkTimeStampTime;
  TimeStampMutex.Unlock();
#endif

}

} // end namespace itk
<|endoftext|>


<commit_before>#include "process.h"

// POSIX
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>

// POSIX++
#include <cerrno>
#include <cstdlib>
#include <climits>
#include <cstring>
#include <cassert>

// PDTK
#include <specialized/procstat.h>
#include <specialized/eventbackend.h>
#include <cxxutils/error_helpers.h>
#include <cxxutils/vterm.h>

static std::unordered_map<pid_t, Process*> process_map; // do not try to own Process memory

void Process::init_once(void) noexcept
{
  static bool first = true;
  if(first)
  {
    first = false;
    struct sigaction actions;
    actions.sa_handler = &handler;
    sigemptyset(&actions.sa_mask);
    actions.sa_flags = SA_RESTART | SA_NOCLDSTOP;

    flaw(::sigaction(SIGCHLD, &actions, nullptr) == posix::error_response,
         terminal::critical,
         std::exit(errno),,
         "Unable assign action to a signal: %s", std::strerror(errno))
  }
}

void Process::handler(int signum) noexcept
{
  flaw(signum != SIGCHLD,
       terminal::warning,
       posix::error(std::errc::invalid_argument),,
       "Process::reaper() has been called improperly")

  pid_t pid = posix::error_response; // set value just in case
  int status = 0;
  while((pid = ::waitpid(pid_t(-1), &status, WNOHANG)) > 0) // get the next dead process (if there is one)... while the currently reaped process was valid
  {
    auto process_map_iter = process_map.find(pid); // find dead process
    if(process_map_iter != process_map.end()) // if the dead process exists...
    {
      Process* p = process_map_iter->second;
      if(WIFEXITED(status))
      {
        EventBackend::remove(p->getStdOut(), EventBackend::SimplePollReadFlags);
        EventBackend::remove(p->getStdErr(), EventBackend::SimplePollReadFlags);
        posix::close(p->getStdOut());
        posix::close(p->getStdErr());
        posix::close(p->getStdIn());

        p->m_state = Process::State::Finished;
        if(WIFSIGNALED(status))
          Object::enqueue_copy(p->killed, p->processId(), posix::signal::EId(WTERMSIG(status)));
        else
          Object::enqueue_copy(p->finished, p->processId(), posix::error_t(WEXITSTATUS(status)));
        process_map.erase(process_map_iter); // remove finished process from the process map
      }
      else if(WIFSTOPPED(status))
      {
        p->m_state = Process::State::Stopped;
        Object::enqueue_copy(p->stopped, p->processId());
      }
      else if(WIFCONTINUED(status))
      {
        p->m_state = Process::State::Running;
        Object::enqueue_copy(p->started, p->processId());
      }
    }
  }
}

Process::Process(void) noexcept
  : m_state(State::Initializing)
{
  init_once();
  process_map.emplace(processId(), this); // add self to process map
}

Process::~Process(void) noexcept
{
  EventBackend::remove(getStdOut(), EventBackend::SimplePollReadFlags);
  EventBackend::remove(getStdErr(), EventBackend::SimplePollReadFlags);
}

bool Process::setOption(const std::string& name, const std::string& value) noexcept
{
  m_iobuf.reset();
  return !(m_iobuf << name << value).hadError() && writeStdIn(m_iobuf);
}

bool Process::sendSignal(posix::signal::EId id, int value) const noexcept
{
  return posix::signal::send(processId(), id, value);
}

bool Process::invoke(void) noexcept
{
  posix::success();

  flaw(m_state != State::Initializing,
       terminal::severe,
       posix::error(std::errc::device_or_resource_busy),
       false,
       "Called Process::invoke() on an active process!");

  EventBackend::add(getStdOut(), EventBackend::SimplePollReadFlags,
                    [this](posix::fd_t lambda_fd, native_flags_t) noexcept
                      { Object::enqueue(stdoutMessage, lambda_fd); });

  EventBackend::add(getStdErr(), EventBackend::SimplePollReadFlags,
                    [this](posix::fd_t lambda_fd, native_flags_t) noexcept
                      { Object::enqueue(stderrMessage, lambda_fd); });

  m_iobuf.reset();
  if((m_iobuf << "Launch").hadError() ||
     !writeStdIn(m_iobuf))
    return false;

  m_state = State::Invalid;
  if(state() == State::Running)
    Object::enqueue_copy(started, processId());

  return errno == posix::success_response;
}

Process::State Process::state(void) noexcept
{
  switch(m_state)
  {
    case State::Finished:
    case State::Initializing:
      break;
    default:
      process_state_t data;
      flaw(::procstat(processId(), data) == posix::error_response && m_state != State::Finished,
           terminal::severe,
           m_state = State::Invalid,
           m_state,
           "Process %i does not exist.", processId()); // process must exist (rare case where process could exit durring this call is handled)
      switch (data.state)
      {
        case WaitingInterruptable:
        case WaitingUninterruptable:
          m_state = State::Waiting; break;
        case Zombie : m_state = State::Zombie ; break;
        case Stopped: m_state = State::Stopped; break;
        case Running: m_state = State::Running; break;
        default: break; // invalid state (process exited before it could be stat'd
      }
  }
  return m_state;
}
<commit_msg>catch more and safetly for imcomplete implementations<commit_after>#include "process.h"

// POSIX
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>

// POSIX++
#include <cerrno>
#include <cstdlib>
#include <climits>
#include <cstring>
#include <cassert>

// PDTK
#include <specialized/procstat.h>
#include <specialized/eventbackend.h>
#include <cxxutils/error_helpers.h>
#include <cxxutils/vterm.h>

static std::unordered_map<pid_t, Process*> process_map; // do not try to own Process memory

void Process::init_once(void) noexcept
{
  static bool first = true;
  if(first)
  {
    first = false;
    struct sigaction actions;
    actions.sa_handler = &handler;
    sigemptyset(&actions.sa_mask);
    actions.sa_flags = SA_RESTART | SA_NOCLDSTOP;

    flaw(::sigaction(SIGCHLD, &actions, nullptr) == posix::error_response,
         terminal::critical,
         std::exit(errno),,
         "Unable assign action to a signal: %s", std::strerror(errno))
  }
}

// in case of incomplete implementations
#if !defined(WCONTINUED)
#define WCONTINUED 0
#endif
#if !defined(WIFCONTINUED)
#define WIFCONTINUED(x) false
#endif
#if !defined(WIFSTOPPED)
#define WIFSTOPPED(x) false
#endif
#if !defined(WIFSIGNALED)
#define WIFSIGNALED(x) false
#endif

void Process::handler(int signum) noexcept
{
  flaw(signum != SIGCHLD,
       terminal::warning,
       posix::error(std::errc::invalid_argument),,
       "Process::reaper() has been called improperly")

  pid_t pid = posix::error_response; // set value just in case
  int status = 0;
  while((pid = ::waitpid(pid_t(-1), &status, WNOHANG | WCONTINUED | WUNTRACED)) > 0) // get the next dead process (if there is one)... while the currently reaped process was valid
  {
    auto process_map_iter = process_map.find(pid); // find dead process
    if(process_map_iter != process_map.end()) // if the dead process exists...
    {
      Process* p = process_map_iter->second;
      if(WIFEXITED(status))
      {
        EventBackend::remove(p->getStdOut(), EventBackend::SimplePollReadFlags);
        EventBackend::remove(p->getStdErr(), EventBackend::SimplePollReadFlags);
        posix::close(p->getStdOut());
        posix::close(p->getStdErr());
        posix::close(p->getStdIn());

        p->m_state = Process::State::Finished;
        if(WIFSIGNALED(status))
          Object::enqueue_copy(p->killed, p->processId(), posix::signal::EId(WTERMSIG(status)));
        else
          Object::enqueue_copy(p->finished, p->processId(), posix::error_t(WEXITSTATUS(status)));
        process_map.erase(process_map_iter); // remove finished process from the process map
      }
      else if(WIFSTOPPED(status))
      {
        p->m_state = Process::State::Stopped;
        Object::enqueue_copy(p->stopped, p->processId());
      }
      else if(WIFCONTINUED(status))
      {
        p->m_state = Process::State::Running;
        Object::enqueue_copy(p->started, p->processId());
      }
    }
  }
}

Process::Process(void) noexcept
  : m_state(State::Initializing)
{
  init_once();
  process_map.emplace(processId(), this); // add self to process map
}

Process::~Process(void) noexcept
{
  EventBackend::remove(getStdOut(), EventBackend::SimplePollReadFlags);
  EventBackend::remove(getStdErr(), EventBackend::SimplePollReadFlags);
}

bool Process::setOption(const std::string& name, const std::string& value) noexcept
{
  m_iobuf.reset();
  return !(m_iobuf << name << value).hadError() && writeStdIn(m_iobuf);
}

bool Process::sendSignal(posix::signal::EId id, int value) const noexcept
{
  return posix::signal::send(processId(), id, value);
}

bool Process::invoke(void) noexcept
{
  posix::success();

  flaw(m_state != State::Initializing,
       terminal::severe,
       posix::error(std::errc::device_or_resource_busy),
       false,
       "Called Process::invoke() on an active process!");

  EventBackend::add(getStdOut(), EventBackend::SimplePollReadFlags,
                    [this](posix::fd_t lambda_fd, native_flags_t) noexcept
                      { Object::enqueue(stdoutMessage, lambda_fd); });

  EventBackend::add(getStdErr(), EventBackend::SimplePollReadFlags,
                    [this](posix::fd_t lambda_fd, native_flags_t) noexcept
                      { Object::enqueue(stderrMessage, lambda_fd); });

  m_iobuf.reset();
  if((m_iobuf << "Launch").hadError() ||
     !writeStdIn(m_iobuf))
    return false;

  m_state = State::Invalid;
  if(state() == State::Running)
    Object::enqueue_copy(started, processId());

  return errno == posix::success_response;
}

Process::State Process::state(void) noexcept
{
  switch(m_state)
  {
    case State::Finished:
    case State::Initializing:
      break;
    default:
      process_state_t data;
      flaw(::procstat(processId(), data) == posix::error_response && m_state != State::Finished,
           terminal::severe,
           m_state = State::Invalid,
           m_state,
           "Process %i does not exist.", processId()); // process must exist (rare case where process could exit durring this call is handled)
      switch (data.state)
      {
        case WaitingInterruptable:
        case WaitingUninterruptable:
          m_state = State::Waiting; break;
        case Zombie : m_state = State::Zombie ; break;
        case Stopped: m_state = State::Stopped; break;
        case Running: m_state = State::Running; break;
        default: break; // invalid state (process exited before it could be stat'd
      }
  }
  return m_state;
}
<|endoftext|>


<commit_before>#pragma once

#include "../util.hpp"

template <typename DataStructure> struct HeavyLightDecomposition {
  using T = typename DataStructure::value_type;
  using Update = typename DataStructure::update_type;
  using Monoid = typename DataStructure::monoid_type;
  struct Chain {
    int depth;
    pair<int, int> parent;         // chain number, index
    vector<pair<int, int>> child;  // child chain number, parent index
    vector<int> mapfrom;
    DataStructure up, down;
    Chain(int n, const T &init) : up(n, init), down(n, init) { ; }
  };

  vector<Chain> chains;
  vector<pair<int, int>> mapto;  // raw index -> chain number & index
  vector<vector<int>> mapfrom;   // chain number & index -> raw index

  int root() const { return mapfrom[0][0]; }

  template <typename Graph>
  HeavyLightDecomposition(const Graph &g, const T &init = Monoid::id()) {
    const int n = g.size();
    mapto = vector<pair<int, int>>(n, make_pair(-1, -1));
    mapfrom.clear();
    vector<int> size(n, 0);
    int start = -1;
    for (int i = 0; i < n; i++) {
      if (g[i].size() <= 1) {
        start = i;
        break;
      }
    }
    assert(start != -1);
    size_check_bfs(g, start, size);
    decomposition(g, start, start, 0, 0, 0, size, init);
  }

  void update(int i, const Update &val) {
    pair<int, int> chain_id = mapto[i];
    const int n = chains[chain_id.first].mapfrom.size();
    chains[chain_id.first].up.update(n - i - 1, val);
    chains[chain_id.first].down.update(i, val);
  }

  void update(int s, int t, const Update &update) {
    pair<int, int> chain_s = mapto[s], chain_t = mapto[t];
    while (chain_s.first != chain_t.first) {
      if (chains[chain_s.first].depth > chains[chain_t.first].depth) {
        const int num = chain_s.second + 1;
        const int n = chains[chain_s.first].mapfrom.size();
        chains[chain_s.first].up.update(n - num, n, update);
        chains[chain_s.first].down.update(0, num, update);
        chain_s = chains[chain_s.first].parent;
      }
      else {
        const int num = chain_t.second + 1;
        const int n = chains[chain_t.first].mapfrom.size();
        chains[chain_t.first].up.update(n - num, n, update);
        chains[chain_t.first].down.update(0, num, update);
        chain_t = chains[chain_t.first].parent;
      }
    }
    const int n = chains[chain_s.first].mapfrom.size();
    const int l = min(chain_s.second, chain_t.second);
    const int r = max(chain_s.second, chain_t.second);
    chains[chain_s.first].up.update(n - r - 1, n - l, update);
    chains[chain_s.first].down.update(l, r + 1, update);
  }

  T query(int s, int t) {
    T res1 = Monoid::id(), res2 = Monoid::id();
    pair<int, int> chain_s = mapto[s], chain_t = mapto[t];
    while (chain_s.first != chain_t.first) {
      if (chains[chain_s.first].depth > chains[chain_t.first].depth) {
        const int num = chain_s.second + 1;
        const int n = chains[chain_s.first].mapfrom.size();
        T val = chains[chain_s.first].up.query(n - num, n);
        res1 = Monoid::op(res1, val);
        chain_s = chains[chain_s.first].parent;
      }
      else {
        const int num = chain_t.second + 1;
        T val = chains[chain_t.first].down.query(0, num);
        res2 = Monoid::op(val, res2);
        chain_t = chains[chain_t.first].parent;
      }
    }
    const int n = chains[chain_s.first].mapfrom.size();
    const int l = chain_s.second;
    const int r = chain_t.second;
    T val = l > r ? chains[chain_s.first].up.query(n - l - 1, n - r)
                  : chains[chain_s.first].down.query(l, r + 1);
    return Monoid::op(Monoid::op(res1, val), res2);
  }

  int depth(int t) const { return chains[mapto[t].first].depth; }

private:
  template <typename Graph>
  int decomposition(Graph &g, int from, int parent, int depth, int pnumber,
                    int pindex, const vector<int> &size, const T &init) {
    vector<int> seq;
    bfs(g, from, parent, seq, size);
    const int c = chains.size();
    chains.push_back(Chain(int(seq.size()), init));
    chains[c].depth = depth;
    chains[c].parent = make_pair(pnumber, pindex);
    for (int i = 0; i < int(seq.size()); i++) {
      mapto[seq[i]] = make_pair(c, i);
      chains[c].mapfrom.push_back(seq[i]);
    }
    mapfrom.push_back(chains[c].mapfrom);
    for (int i = 0; i < int(seq.size()); i++) {
      for (auto e : g[seq[i]]) {
        if (mapto[e.to].first != -1) continue;
        int nc = decomposition(g, e.to, seq[i], depth + 1, c, i, size, init);
        chains[c].child.push_back(make_pair(nc, i));
      }
    }
    return c;
  }
  template <typename Graph>
  void size_check_bfs(const Graph &g, int start, vector<int> &size) {
    const int n = g.size();
    queue<pair<int, int>> que;
    que.push(make_pair(start, start));
    int cnt = 0;
    vector<int> order(n, -1);
    while (!que.empty()) {
      int from, parent;
      tie(from, parent) = que.front();
      que.pop();
      order[cnt++] = from;
      for (auto e : g[from]) {
        if (e.to == parent) continue;
        que.push(make_pair(e.to, from));
      }
    }
    assert(cnt == n);
    reverse(begin(order), end(order));
    for (int i = 0; i < n; i++) {
      int from = order[i];
      size[from] = 1;
      for (auto e : g[from]) size[from] += size[e.to];
    }
  }
  template <typename Graph>
  void bfs(const Graph &g, int from, int parent, vector<int> &seq,
           const vector<int> &size) {
    for (;;) {
      seq.push_back(from);
      int best = -1, next = -1;
      for (auto e : g[from]) {
        if (e.to == parent) continue;
        if (best < size[e.to]) {
          best = size[e.to];
          next = e.to;
        }
      }
      if (next == -1) break;
      parent = from;
      from = next;
    }
  }
};
<commit_msg>Fix HLD<commit_after>#pragma once

#include "../template/includes.hpp"

template <typename DataStructure> struct HeavyLightDecomposition {
  using T = typename DataStructure::value_type;
  using Update = typename DataStructure::update_type;
  using Monoid = typename DataStructure::monoid_type;
  struct Chain {
    int depth;
    std::pair<int, int> parent;         // chain number, index
    std::vector<std::pair<int, int>> child;  // child chain number, parent index
    std::vector<int> mapfrom;
    DataStructure up, down;
    Chain(int n, const T &init) : up(n, init), down(n, init) { ; }
  };

  std::vector<Chain> chains;
  std::vector<std::pair<int, int>> mapto;  // raw index -> chain number & index
  std::vector<std::vector<int>> mapfrom;   // chain number & index -> raw index

  int root() const { return mapfrom[0][0]; }

  template <typename Graph>
  HeavyLightDecomposition(const Graph &g, const T &init = Monoid::id()) {
    const int n = g.size();
    mapto = std::vector<std::pair<int, int>>(n, std::make_pair(-1, -1));
    mapfrom.clear();
    std::vector<int> size(n, 0);
    int start = -1;
    for (int i = 0; i < n; i++) {
      if (g[i].size() <= 1) {
        start = i;
        break;
      }
    }
    assert(start != -1);
    size_check_bfs(g, start, size);
    decomposition(g, start, start, 0, 0, 0, size, init);
  }

  void update(int i, const Update &val) {
    std::pair<int, int> chain_id = mapto[i];
    const int n = chains[chain_id.first].mapfrom.size();
    chains[chain_id.first].up.update(n - i - 1, val);
    chains[chain_id.first].down.update(i, val);
  }

  void update(int s, int t, const Update &update) {
    std::pair<int, int> chain_s = mapto[s], chain_t = mapto[t];
    while (chain_s.first != chain_t.first) {
      if (chains[chain_s.first].depth > chains[chain_t.first].depth) {
        const int num = chain_s.second + 1;
        const int n = chains[chain_s.first].mapfrom.size();
        chains[chain_s.first].up.update(n - num, n, update);
        chains[chain_s.first].down.update(0, num, update);
        chain_s = chains[chain_s.first].parent;
      }
      else {
        const int num = chain_t.second + 1;
        const int n = chains[chain_t.first].mapfrom.size();
        chains[chain_t.first].up.update(n - num, n, update);
        chains[chain_t.first].down.update(0, num, update);
        chain_t = chains[chain_t.first].parent;
      }
    }
    const int n = chains[chain_s.first].mapfrom.size();
    const int l = std::min(chain_s.second, chain_t.second);
    const int r = std::max(chain_s.second, chain_t.second);
    chains[chain_s.first].up.update(n - r - 1, n - l, update);
    chains[chain_s.first].down.update(l, r + 1, update);
  }

  T query(int s, int t) {
    T res1 = Monoid::id(), res2 = Monoid::id();
    std::pair<int, int> chain_s = mapto[s], chain_t = mapto[t];
    while (chain_s.first != chain_t.first) {
      if (chains[chain_s.first].depth > chains[chain_t.first].depth) {
        const int num = chain_s.second + 1;
        const int n = chains[chain_s.first].mapfrom.size();
        T val = chains[chain_s.first].up.query(n - num, n);
        res1 = Monoid::op(res1, val);
        chain_s = chains[chain_s.first].parent;
      }
      else {
        const int num = chain_t.second + 1;
        T val = chains[chain_t.first].down.query(0, num);
        res2 = Monoid::op(val, res2);
        chain_t = chains[chain_t.first].parent;
      }
    }
    const int n = chains[chain_s.first].mapfrom.size();
    const int l = chain_s.second;
    const int r = chain_t.second;
    T val = l > r ? chains[chain_s.first].up.query(n - l - 1, n - r)
                  : chains[chain_s.first].down.query(l, r + 1);
    return Monoid::op(Monoid::op(res1, val), res2);
  }

  int depth(int t) const { return chains[mapto[t].first].depth; }

private:
  template <typename Graph>
  int decomposition(Graph &g, int from, int parent, int depth, int pnumber,
                    int pindex, const std::vector<int> &size, const T &init) {
    std::vector<int> seq;
    bfs(g, from, parent, seq, size);
    const int c = chains.size();
    chains.push_back(Chain(int(seq.size()), init));
    chains[c].depth = depth;
    chains[c].parent = std::make_pair(pnumber, pindex);
    for (int i = 0; i < int(seq.size()); i++) {
      mapto[seq[i]] = std::make_pair(c, i);
      chains[c].mapfrom.push_back(seq[i]);
    }
    mapfrom.push_back(chains[c].mapfrom);
    for (int i = 0; i < int(seq.size()); i++) {
      for (auto e : g[seq[i]]) {
        if (mapto[e.to].first != -1) continue;
        int nc = decomposition(g, e.to, seq[i], depth + 1, c, i, size, init);
        chains[c].child.push_back(std::make_pair(nc, i));
      }
    }
    return c;
  }
  template <typename Graph>
  void size_check_bfs(const Graph &g, int start, std::vector<int> &size) {
    const int n = g.size();
    std::queue<std::pair<int, int>> que;
    que.push(std::make_pair(start, start));
    int cnt = 0;
    std::vector<int> order(n, -1);
    while (!que.empty()) {
      int from, parent;
      std::tie(from, parent) = que.front();
      que.pop();
      order[cnt++] = from;
      for (auto e : g[from]) {
        if (e.to == parent) continue;
        que.push(std::make_pair(e.to, from));
      }
    }
    assert(cnt == n);
    reverse(begin(order), end(order));
    for (int i = 0; i < n; i++) {
      int from = order[i];
      size[from] = 1;
      for (auto e : g[from]) size[from] += size[e.to];
    }
  }
  template <typename Graph>
  void bfs(const Graph &g, int from, int parent, std::vector<int> &seq,
           const std::vector<int> &size) {
    for (;;) {
      seq.push_back(from);
      int best = -1, next = -1;
      for (auto e : g[from]) {
        if (e.to == parent) continue;
        if (best < size[e.to]) {
          best = size[e.to];
          next = e.to;
        }
      }
      if (next == -1) break;
      parent = from;
      from = next;
    }
  }
};
<|endoftext|>


<commit_before>/** \brief Utility for generating certain statistics for non-standardized keywords.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2020 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <algorithm>
#include <unordered_map>
#include <unordered_set>
#include <cstdlib>
#include "FileUtil.h"
#include "MARC.h"
#include "TextUtil.h"
#include "util.h"

namespace {

std::string NormalizeKeyword(std::string keyword) {
    TextUtil::CollapseAndTrimWhitespace(&keyword);
    TextUtil::UTF8ToLower(&keyword);
    return keyword;
}

/*
void DumpSetToFile(const std::string &output_filename, const std::unordered_set<std::string> &set) {
    const auto output(FileUtil::OpenOutputFileOrDie(output_filename));
    for (const auto &element : set)
        (*output) << element << '\n';
    LOG_ERROR("wrote " + std::to_string(set.size()) + " elements to \"" + output_filename + "\".");
}
*/

void CollectNormalizedKeywordsAndTranslations(MARC::Reader * const reader,
                                              std::unordered_set<std::string> * const normalized_keywords)
{
    unsigned authority_record_count(0);
    while (const auto record = reader->read()) {
        if (record.getRecordType() != MARC::Record::RecordType::AUTHORITY)
            continue;

        ++authority_record_count;

        MARC::Record::KeywordAndSynonyms keyword_synonyms;
        if (record.getKeywordAndSynonyms(&keyword_synonyms)) {
            normalized_keywords->emplace(NormalizeKeyword(keyword_synonyms.getKeyword()));
            for (const auto &keyword_synonym : keyword_synonyms)
                normalized_keywords->emplace(NormalizeKeyword(keyword_synonym));
        }
    }

//    DumpSetToFile("standardized_keywords.list", *normalized_keywords);

    LOG_INFO("Processed " + std::to_string(authority_record_count) + " authority records and found "
             + std::to_string(normalized_keywords->size()) + " normalized keywords and their translations.");
}

//const std::vector<std::string> non_normalized_keyword_tags{ "600", "610", "630", "648", "650", "651", "653", "655" };
const std::vector<std::string> non_normalized_keyword_tags{ "650" };

void ProcessField(const MARC::Record::Field &field, const std::unordered_set<std::string> &normalized_keywords,
                  std::unordered_map<std::string, unsigned> * const unmatched_keywords_to_counts_map,
                  unsigned * const matched_count, unsigned * const not_matched_count)
{
    const auto subfields(field.getSubfields());
    for (const auto subfield_and_code : subfields) {
        if (subfield_and_code.code_ != 'a')
            continue;

        const auto non_normalized_keyword(NormalizeKeyword(subfield_and_code.value_));
        if (non_normalized_keyword.empty())
            continue;

        if (normalized_keywords.find(non_normalized_keyword) != normalized_keywords.cend())
            ++*matched_count;
        else {
            auto keyword_and_count(unmatched_keywords_to_counts_map->find(non_normalized_keyword));
            if (keyword_and_count != unmatched_keywords_to_counts_map->end())
                ++(keyword_and_count->second);
            else
                unmatched_keywords_to_counts_map->emplace(non_normalized_keyword, 1);
            ++*not_matched_count;
        }
    }
}

void ProcessTitleRecords(MARC::Reader * const marc_reader, const std::unordered_set<std::string> &normalized_keywords,
                         std::unordered_map<std::string, unsigned> * const unmatched_keywords_to_counts_map,
                         unsigned * const matched_count, unsigned * const not_matched_count)
{
    unsigned record_count(0);
    while (const MARC::Record record = marc_reader->read()) {
        ++record_count;
        for (const auto &tag : non_normalized_keyword_tags) {
            for (const auto &field : record.getTagRange(tag))
                ProcessField(field, normalized_keywords, unmatched_keywords_to_counts_map, matched_count, not_matched_count);
        }
    }

    LOG_INFO("Data set contains " + std::to_string(record_count) + " MARC record(s) of which ");
}

void ListUnmatchedKeywords(File * const output,
                           const std::unordered_map<std::string, unsigned> &unmatched_keywords_to_counts_map)
{
    std::vector<std::pair<std::string, unsigned>> unmatched_keywords_and_counts(unmatched_keywords_to_counts_map.cbegin(),
                                                                                unmatched_keywords_to_counts_map.cend());
    std::sort(unmatched_keywords_and_counts.begin(), unmatched_keywords_and_counts.end(),
              [](const auto &a, const auto &b){ return a.second > b.second; });// Sort in descending order of counts.

    for (const auto [keyword, count] : unmatched_keywords_and_counts)
        (*output) << keyword << " -> " << count << '\n';
}

} // unnamed namespace

int Main(int argc, char *argv[]) {
    if (argc != 4)
        ::Usage("authority_records title_records keyword_stats_output");

    const auto authority_reader(MARC::Reader::Factory(argv[1]));
    std::unordered_set<std::string> normalized_keywords;
    CollectNormalizedKeywordsAndTranslations(authority_reader.get(), &normalized_keywords);

    const auto title_reader(MARC::Reader::Factory(argv[2]));
    std::unordered_map<std::string, unsigned> unmatched_keywords_to_counts_map;
    unsigned matched_count, not_matched_count;
    ProcessTitleRecords(title_reader.get(), normalized_keywords, &unmatched_keywords_to_counts_map,
                        &matched_count, &not_matched_count);
    const double matched_percentage(100.0 * double(matched_count) / double(matched_count + not_matched_count));
    LOG_INFO("Found " + std::to_string(matched_percentage)
             + "% of the non-standardized keywords matched known, standardized keywords.");

    const auto output(FileUtil::OpenOutputFileOrDie(argv[3]));
    ListUnmatchedKeywords(output.get(), unmatched_keywords_to_counts_map);

    return EXIT_SUCCESS;
}
<commit_msg>Removed debugging code.<commit_after>/** \brief Utility for generating certain statistics for non-standardized keywords.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2020 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <algorithm>
#include <unordered_map>
#include <unordered_set>
#include <cstdlib>
#include "FileUtil.h"
#include "MARC.h"
#include "TextUtil.h"
#include "util.h"

namespace {

std::string NormalizeKeyword(std::string keyword) {
    TextUtil::CollapseAndTrimWhitespace(&keyword);
    TextUtil::UTF8ToLower(&keyword);
    return keyword;
}

void CollectNormalizedKeywordsAndTranslations(MARC::Reader * const reader,
                                              std::unordered_set<std::string> * const normalized_keywords)
{
    unsigned authority_record_count(0);
    while (const auto record = reader->read()) {
        if (record.getRecordType() != MARC::Record::RecordType::AUTHORITY)
            continue;

        ++authority_record_count;

        MARC::Record::KeywordAndSynonyms keyword_synonyms;
        if (record.getKeywordAndSynonyms(&keyword_synonyms)) {
            normalized_keywords->emplace(NormalizeKeyword(keyword_synonyms.getKeyword()));
            for (const auto &keyword_synonym : keyword_synonyms)
                normalized_keywords->emplace(NormalizeKeyword(keyword_synonym));
        }
    }

    LOG_INFO("Processed " + std::to_string(authority_record_count) + " authority records and found "
             + std::to_string(normalized_keywords->size()) + " normalized keywords and their translations.");
}

const std::vector<std::string> non_normalized_keyword_tags{ "650" };

void ProcessField(const MARC::Record::Field &field, const std::unordered_set<std::string> &normalized_keywords,
                  std::unordered_map<std::string, unsigned> * const unmatched_keywords_to_counts_map,
                  unsigned * const matched_count, unsigned * const not_matched_count)
{
    const auto subfields(field.getSubfields());
    for (const auto subfield_and_code : subfields) {
        if (subfield_and_code.code_ != 'a')
            continue;

        const auto non_normalized_keyword(NormalizeKeyword(subfield_and_code.value_));
        if (non_normalized_keyword.empty())
            continue;

        if (normalized_keywords.find(non_normalized_keyword) != normalized_keywords.cend())
            ++*matched_count;
        else {
            auto keyword_and_count(unmatched_keywords_to_counts_map->find(non_normalized_keyword));
            if (keyword_and_count != unmatched_keywords_to_counts_map->end())
                ++(keyword_and_count->second);
            else
                unmatched_keywords_to_counts_map->emplace(non_normalized_keyword, 1);
            ++*not_matched_count;
        }
    }
}

void ProcessTitleRecords(MARC::Reader * const marc_reader, const std::unordered_set<std::string> &normalized_keywords,
                         std::unordered_map<std::string, unsigned> * const unmatched_keywords_to_counts_map,
                         unsigned * const matched_count, unsigned * const not_matched_count)
{
    unsigned record_count(0);
    while (const MARC::Record record = marc_reader->read()) {
        ++record_count;
        for (const auto &tag : non_normalized_keyword_tags) {
            for (const auto &field : record.getTagRange(tag))
                ProcessField(field, normalized_keywords, unmatched_keywords_to_counts_map, matched_count, not_matched_count);
        }
    }

    LOG_INFO("Data set contains " + std::to_string(record_count) + " MARC record(s) of which ");
}

void ListUnmatchedKeywords(File * const output,
                           const std::unordered_map<std::string, unsigned> &unmatched_keywords_to_counts_map)
{
    std::vector<std::pair<std::string, unsigned>> unmatched_keywords_and_counts(unmatched_keywords_to_counts_map.cbegin(),
                                                                                unmatched_keywords_to_counts_map.cend());
    std::sort(unmatched_keywords_and_counts.begin(), unmatched_keywords_and_counts.end(),
              [](const auto &a, const auto &b){ return a.second > b.second; });// Sort in descending order of counts.

    for (const auto [keyword, count] : unmatched_keywords_and_counts)
        (*output) << keyword << " -> " << count << '\n';
}

} // unnamed namespace

int Main(int argc, char *argv[]) {
    if (argc != 4)
        ::Usage("authority_records title_records keyword_stats_output");

    const auto authority_reader(MARC::Reader::Factory(argv[1]));
    std::unordered_set<std::string> normalized_keywords;
    CollectNormalizedKeywordsAndTranslations(authority_reader.get(), &normalized_keywords);

    const auto title_reader(MARC::Reader::Factory(argv[2]));
    std::unordered_map<std::string, unsigned> unmatched_keywords_to_counts_map;
    unsigned matched_count, not_matched_count;
    ProcessTitleRecords(title_reader.get(), normalized_keywords, &unmatched_keywords_to_counts_map,
                        &matched_count, &not_matched_count);
    const double matched_percentage(100.0 * double(matched_count) / double(matched_count + not_matched_count));
    LOG_INFO("Found " + std::to_string(matched_percentage)
             + "% of the non-standardized keywords matched known, standardized keywords.");

    const auto output(FileUtil::OpenOutputFileOrDie(argv[3]));
    ListUnmatchedKeywords(output.get(), unmatched_keywords_to_counts_map);

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
 * -----------------------------------------------------------------------------
 * This source file is part of OGRE
 * (Object-oriented Graphics Rendering Engine)
 * For the latest info, see http://www.ogre3d.org/
 *
 * Copyright (c) 2000-2013 Torus Knot Software Ltd
 *
 * 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 OR COPYRIGHT HOLDERS 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.
 * -----------------------------------------------------------------------------
 */

#include "OgreLodBuffer.h"
#include "OgreHardwareBufferManager.h"
#include "OgreVector3.h"
#include "OgreSubMesh.h"

namespace Ogre
{

	void LodIndexBuffer::fillBuffer( Ogre::IndexData* data )
	{
		const HardwareIndexBufferSharedPtr& hwIndexBuffer = data->indexBuffer;
		indexSize = hwIndexBuffer->getIndexSize();
		indexCount = data->indexCount;
		if (indexCount > 0) {
			unsigned char* pBuffer = (unsigned char*) hwIndexBuffer->lock(HardwareBuffer::HBL_READ_ONLY);
			size_t offset = data->indexStart * indexSize;
			indexBuffer = Ogre::SharedPtr<unsigned char>(new unsigned char[indexCount * indexSize]);
			indexStart = 0;
			indexBufferSize = 0;
			memcpy(indexBuffer.get(), pBuffer + offset, indexCount * indexSize);
			hwIndexBuffer->unlock();
		}
	}

	void LodVertexBuffer::fillBuffer( Ogre::VertexData* data )
	{
		// Locate position element and the buffer to go with it.
		const VertexElement* elemPos = data->vertexDeclaration->findElementBySemantic(VES_POSITION);

		// Only float supported.
		OgreAssert(elemPos->getSize() == 12, "");

		HardwareVertexBufferSharedPtr vbuf = data->vertexBufferBinding->getBuffer(elemPos->getSource());

		vertexCount = data->vertexCount;

		if (vertexCount > 0) {
			vertexBuffer = Ogre::SharedPtr<Vector3>(new Vector3[vertexCount]);

			// Lock the buffer for reading.
			unsigned char* vStart = static_cast<unsigned char*>(vbuf->lock(HardwareBuffer::HBL_READ_ONLY));
			unsigned char* vertex = vStart;
			int vSize = vbuf->getVertexSize();

			const VertexElement* elemNormal = 0;
			HardwareVertexBufferSharedPtr vNormalBuf;
			unsigned char* vNormal;
			Vector3* pNormalOut;
			int vNormalSize;
			bool useVertexNormals = true;
			elemNormal = data->vertexDeclaration->findElementBySemantic(VES_NORMAL);
			useVertexNormals = useVertexNormals && (elemNormal != 0);
			if(useVertexNormals){
				vertexNormalBuffer = Ogre::SharedPtr<Vector3>(new Vector3[vertexCount]);
				pNormalOut = vertexNormalBuffer.get();
				if(elemNormal->getSource() == elemPos->getSource()){
					vNormalBuf = vbuf;
					vNormal = vStart;
				}  else {
					vNormalBuf = data->vertexBufferBinding->getBuffer(elemNormal->getSource());
					assert(vNormalBuf->getSizeInBytes() == vbuf->getSizeInBytes());
					assert(vNormalBuf->getVertexSize() == vbuf->getVertexSize());
					vNormal = static_cast<unsigned char*>(vNormalBuf->lock(HardwareBuffer::HBL_READ_ONLY));
				}
				vNormalSize = vNormalBuf->getVertexSize();
			}

			// Loop through all vertices and insert them to the Unordered Map.
			Vector3* pOut = vertexBuffer.get();
			Vector3* pEnd = pOut + vertexCount;
			for (; pOut < pEnd; pOut++) {
				float* pFloat;
				elemPos->baseVertexPointerToElement(vertex, &pFloat);
				pOut->x = *pFloat;
				pOut->y = *(++pFloat);
				pOut->z = *(++pFloat);
				vertex += vSize;
				if(elemNormal){
					elemNormal->baseVertexPointerToElement(vNormal, &pFloat);
					pNormalOut->x = *pFloat;
					pNormalOut->y = *(++pFloat);
					pNormalOut->z = *(++pFloat);
					pNormalOut++;
					vNormal += vNormalSize;
				}
			}
			vbuf->unlock();
			if(elemNormal && elemNormal->getSource() != elemPos->getSource()){
				vNormalBuf->unlock();
			}
		}
	}

	void LodInputBuffer::fillBuffer( Ogre::MeshPtr mesh )
	{
		meshName = mesh->getName();
		boundingSphereRadius = mesh->getBoundingSphereRadius();
		bool sharedVerticesAdded = false;
		unsigned short submeshCount = mesh->getNumSubMeshes();
		submesh.resize(submeshCount);
		for (unsigned short i = 0; i < submeshCount; i++) {
			const SubMesh* ogresubmesh = mesh->getSubMesh(i);
			LodInputBuffer::Submesh& outsubmesh = submesh[i];
			outsubmesh.indexBuffer.fillBuffer(ogresubmesh->indexData);
			outsubmesh.useSharedVertexBuffer = ogresubmesh->useSharedVertices;
			if (!outsubmesh.useSharedVertexBuffer) {
				outsubmesh.vertexBuffer.fillBuffer(ogresubmesh->vertexData);
			} else if (!sharedVerticesAdded) {
				sharedVerticesAdded = true;
				sharedVertexBuffer.fillBuffer(mesh->sharedVertexData);
			}
		}
	}

 }
<commit_msg>Compare index count first in LodBuffers.<commit_after>/*
 * -----------------------------------------------------------------------------
 * This source file is part of OGRE
 * (Object-oriented Graphics Rendering Engine)
 * For the latest info, see http://www.ogre3d.org/
 *
 * Copyright (c) 2000-2013 Torus Knot Software Ltd
 *
 * 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 OR COPYRIGHT HOLDERS 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.
 * -----------------------------------------------------------------------------
 */

#include "OgreLodBuffer.h"
#include "OgreHardwareBufferManager.h"
#include "OgreVector3.h"
#include "OgreSubMesh.h"

namespace Ogre
{

	void LodIndexBuffer::fillBuffer( Ogre::IndexData* data )
	{
		indexCount = data->indexCount;
		if (indexCount > 0) {
			const HardwareIndexBufferSharedPtr& hwIndexBuffer = data->indexBuffer;
			indexSize = hwIndexBuffer->getIndexSize();
			unsigned char* pBuffer = (unsigned char*) hwIndexBuffer->lock(HardwareBuffer::HBL_READ_ONLY);
			size_t offset = data->indexStart * indexSize;
			indexBuffer = Ogre::SharedPtr<unsigned char>(new unsigned char[indexCount * indexSize]);
			indexStart = 0;
			indexBufferSize = 0;
			memcpy(indexBuffer.get(), pBuffer + offset, indexCount * indexSize);
			hwIndexBuffer->unlock();
		}
	}

	void LodVertexBuffer::fillBuffer( Ogre::VertexData* data )
	{
		vertexCount = data->vertexCount;
		if (vertexCount > 0) {
			// Locate position element and the buffer to go with it.
			const VertexElement* elemPos = data->vertexDeclaration->findElementBySemantic(VES_POSITION);

			// Only float supported.
			OgreAssert(elemPos->getSize() == 12, "");

			HardwareVertexBufferSharedPtr vbuf = data->vertexBufferBinding->getBuffer(elemPos->getSource());
			vertexBuffer = Ogre::SharedPtr<Vector3>(new Vector3[vertexCount]);

			// Lock the buffer for reading.
			unsigned char* vStart = static_cast<unsigned char*>(vbuf->lock(HardwareBuffer::HBL_READ_ONLY));
			unsigned char* vertex = vStart;
			int vSize = vbuf->getVertexSize();

			const VertexElement* elemNormal = 0;
			HardwareVertexBufferSharedPtr vNormalBuf;
			unsigned char* vNormal;
			Vector3* pNormalOut;
			int vNormalSize;
			bool useVertexNormals = true;
			elemNormal = data->vertexDeclaration->findElementBySemantic(VES_NORMAL);
			useVertexNormals = useVertexNormals && (elemNormal != 0);
			if(useVertexNormals){
				vertexNormalBuffer = Ogre::SharedPtr<Vector3>(new Vector3[vertexCount]);
				pNormalOut = vertexNormalBuffer.get();
				if(elemNormal->getSource() == elemPos->getSource()){
					vNormalBuf = vbuf;
					vNormal = vStart;
				}  else {
					vNormalBuf = data->vertexBufferBinding->getBuffer(elemNormal->getSource());
					assert(vNormalBuf->getSizeInBytes() == vbuf->getSizeInBytes());
					assert(vNormalBuf->getVertexSize() == vbuf->getVertexSize());
					vNormal = static_cast<unsigned char*>(vNormalBuf->lock(HardwareBuffer::HBL_READ_ONLY));
				}
				vNormalSize = vNormalBuf->getVertexSize();
			}

			// Loop through all vertices and insert them to the Unordered Map.
			Vector3* pOut = vertexBuffer.get();
			Vector3* pEnd = pOut + vertexCount;
			for (; pOut < pEnd; pOut++) {
				float* pFloat;
				elemPos->baseVertexPointerToElement(vertex, &pFloat);
				pOut->x = *pFloat;
				pOut->y = *(++pFloat);
				pOut->z = *(++pFloat);
				vertex += vSize;
				if(elemNormal){
					elemNormal->baseVertexPointerToElement(vNormal, &pFloat);
					pNormalOut->x = *pFloat;
					pNormalOut->y = *(++pFloat);
					pNormalOut->z = *(++pFloat);
					pNormalOut++;
					vNormal += vNormalSize;
				}
			}
			vbuf->unlock();
			if(elemNormal && elemNormal->getSource() != elemPos->getSource()){
				vNormalBuf->unlock();
			}
		}
	}

	void LodInputBuffer::fillBuffer( Ogre::MeshPtr mesh )
	{
		meshName = mesh->getName();
		boundingSphereRadius = mesh->getBoundingSphereRadius();
		bool sharedVerticesAdded = false;
		unsigned short submeshCount = mesh->getNumSubMeshes();
		submesh.resize(submeshCount);
		for (unsigned short i = 0; i < submeshCount; i++) {
			const SubMesh* ogresubmesh = mesh->getSubMesh(i);
			LodInputBuffer::Submesh& outsubmesh = submesh[i];
			outsubmesh.indexBuffer.fillBuffer(ogresubmesh->indexData);
			outsubmesh.useSharedVertexBuffer = ogresubmesh->useSharedVertices;
			if (!outsubmesh.useSharedVertexBuffer) {
				outsubmesh.vertexBuffer.fillBuffer(ogresubmesh->vertexData);
			} else if (!sharedVerticesAdded) {
				sharedVerticesAdded = true;
				sharedVertexBuffer.fillBuffer(mesh->sharedVertexData);
			}
		}
	}

 }
<|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_ERR_CHECK_FINITE_HPP
#define STAN_MATH_PRIM_ERR_CHECK_FINITE_HPP

#include <stan/math/prim/err/elementwise_check.hpp>

namespace stan {
namespace math {

/**
 * Check if each element of the eigen variable y is finite.
 *
 * @tparam T_y type of y
 * @param function function name (for error messages)
 * @param name variable name (for error messages)
 * @param y variable to check
 * @throw domain_error if y is infinity, -infinity, or NaN
 */
template <typename T_y, require_eigen_t<T_y>* = nullptr>
inline void check_finite(const char* function, const char* name, const T_y& y) {
  if(!value_of_rec(y).allFinite()) {
    auto is_good = [](const auto& y) { return std::isfinite(y); };
    elementwise_check(is_good, function, name, y, ", but must be finite!");
  }
}

/**
 * Check if y is finite.
 * This function is vectorized and will check each element of
 * y.
 * @tparam T_y type of y
 * @param function function name (for error messages)
 * @param name variable name (for error messages)
 * @param y variable to check
 * @throw domain_error if y is infinity, -infinity, or NaN
 */
template <typename T_y, require_not_eigen_t<T_y>* = nullptr>
inline void check_finite(const char* function, const char* name, const T_y& y) {
  auto is_good = [](const auto& y) { return std::isfinite(y); };
  elementwise_check(is_good, function, name, y, ", but must be finite!");
}

}  // namespace math
}  // namespace stan

#endif
<commit_msg>[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final)<commit_after>#ifndef STAN_MATH_PRIM_ERR_CHECK_FINITE_HPP
#define STAN_MATH_PRIM_ERR_CHECK_FINITE_HPP

#include <stan/math/prim/err/elementwise_check.hpp>

namespace stan {
namespace math {

/**
 * Check if each element of the eigen variable y is finite.
 *
 * @tparam T_y type of y
 * @param function function name (for error messages)
 * @param name variable name (for error messages)
 * @param y variable to check
 * @throw domain_error if y is infinity, -infinity, or NaN
 */
template <typename T_y, require_eigen_t<T_y>* = nullptr>
inline void check_finite(const char* function, const char* name, const T_y& y) {
  if (!value_of_rec(y).allFinite()) {
    auto is_good = [](const auto& y) { return std::isfinite(y); };
    elementwise_check(is_good, function, name, y, ", but must be finite!");
  }
}

/**
 * Check if y is finite.
 * This function is vectorized and will check each element of
 * y.
 * @tparam T_y type of y
 * @param function function name (for error messages)
 * @param name variable name (for error messages)
 * @param y variable to check
 * @throw domain_error if y is infinity, -infinity, or NaN
 */
template <typename T_y, require_not_eigen_t<T_y>* = nullptr>
inline void check_finite(const char* function, const char* name, const T_y& y) {
  auto is_good = [](const auto& y) { return std::isfinite(y); };
  elementwise_check(is_good, function, name, y, ", but must be finite!");
}

}  // namespace math
}  // namespace stan

#endif
<|endoftext|>


<commit_before>#include "RoundRobin.h"

using namespace CppRoundRobin;

RoundRobin::RoundRobin(int schedulerPeriod)
{
	this->schedulerPeriod = schedulerPeriod;
	isTimerFired = false;
}

bool RoundRobin::AddTask(std::shared_ptr<RoundRobinTask> task)
{
	if (task.get()->Period() >= schedulerPeriod)
	{
		Tasks.push_back(RoundRobinTaskHooks(task));
		return true;
	}

	return false;
}

void RoundRobin::Run(void) {
	taskTimer.Start(this);
	// Never plan to leave this loop unless there is a problem
	try {
		for (;;) {
			if (isTimerFired) {
				isTimerFired = false;
				for (auto &task : Tasks)
				{
					task.IncrementCounter();

					if (task.Counter() >= task.TaskPeriod() / schedulerPeriod) {
						task.ResetCounter();
						task.RunTask();
					}
				}
			}
			else {
				// This is considered the idle task, haven't decided how to handle this yet for user implementation
			}
		}
	}
	catch (...) {
		taskTimer.End();
	}
}

void RoundRobin::TimerFired(void)
{
	this->isTimerFired = true;
}

RoundRobin::RoundRobinTaskHooks::RoundRobinTaskHooks(std::shared_ptr<RoundRobinTask> task)
{
	this->task = task;
	counter = static_cast<int>(0);
}

RoundRobin::RoundRobinTimer::RoundRobinTimer()
{
	hTimerQueue = nullptr;
	hTimer = nullptr;
}

RoundRobin::RoundRobinTimer::~RoundRobinTimer()
{
}

void CALLBACK TimerRoutine(PVOID lpParam, BOOLEAN TimerOrWaitFired)
{
	RoundRobin* robin = static_cast<RoundRobin*>(lpParam);

	robin->TimerFired();
}

void RoundRobin::RoundRobinTimer::Start(RoundRobin* robin)
{
	hTimerQueue = CreateTimerQueue();
	CreateTimerQueueTimer(&hTimer, hTimerQueue, (WAITORTIMERCALLBACK)TimerRoutine, robin, robin->GetPeriod(), robin->GetPeriod(), 0);
}

void RoundRobin::RoundRobinTimer::End()
{
	DeleteTimerQueue(hTimerQueue);
}<commit_msg>missed throw<commit_after>#include "RoundRobin.h"

using namespace CppRoundRobin;

RoundRobin::RoundRobin(int schedulerPeriod)
{
	this->schedulerPeriod = schedulerPeriod;
	isTimerFired = false;
}

bool RoundRobin::AddTask(std::shared_ptr<RoundRobinTask> task)
{
	if (task.get()->Period() >= schedulerPeriod)
	{
		Tasks.push_back(RoundRobinTaskHooks(task));
		return true;
	}

	return false;
}

void RoundRobin::Run(void) {
	taskTimer.Start(this);
	// Never plan to leave this loop unless there is a problem
	try {
		for (;;) {
			if (isTimerFired) {
				isTimerFired = false;
				for (auto &task : Tasks)
				{
					task.IncrementCounter();

					if (task.Counter() >= task.TaskPeriod() / schedulerPeriod) {
						task.ResetCounter();
						task.RunTask();
					}
				}
			}
			else {
				// This is considered the idle task, haven't decided how to handle this yet for user implementation
			}
		}
	}
	catch (...) {
		taskTimer.End();
		throw;
	}
}

void RoundRobin::TimerFired(void)
{
	this->isTimerFired = true;
}

RoundRobin::RoundRobinTaskHooks::RoundRobinTaskHooks(std::shared_ptr<RoundRobinTask> task)
{
	this->task = task;
	counter = static_cast<int>(0);
}

RoundRobin::RoundRobinTimer::RoundRobinTimer()
{
	hTimerQueue = nullptr;
	hTimer = nullptr;
}

RoundRobin::RoundRobinTimer::~RoundRobinTimer()
{
}

void CALLBACK TimerRoutine(PVOID lpParam, BOOLEAN TimerOrWaitFired)
{
	RoundRobin* robin = static_cast<RoundRobin*>(lpParam);

	robin->TimerFired();
}

void RoundRobin::RoundRobinTimer::Start(RoundRobin* robin)
{
	hTimerQueue = CreateTimerQueue();
	CreateTimerQueueTimer(&hTimer, hTimerQueue, (WAITORTIMERCALLBACK)TimerRoutine, robin, robin->GetPeriod(), robin->GetPeriod(), 0);
}

void RoundRobin::RoundRobinTimer::End()
{
	DeleteTimerQueue(hTimerQueue);
}<|endoftext|>


<commit_before>/* $Id$ */
/* --------------------------------------------------------------------------
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell

CppAD is distributed under multiple licenses. This distribution is under
the terms of the
                    Common Public License Version 1.0.

A copy of this license is included in the COPYING file of this distribution.
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
-------------------------------------------------------------------------- */

/*
$begin sparse_jacobian.cpp$$
$spell
	Cpp
	Jacobian
$$

$section Sparse Jacobian: Example and Test$$

$index Jacobian, sparse$$
$index example, sparse Jacobian$$
$index test, sparse Jacobian$$
$index spare, Jacobian example$$

$code
$verbatim%example/sparse_jacobian.cpp%0%// BEGIN PROGRAM%// END PROGRAM%1%$$
$$

$end
*/
// BEGIN PROGRAM

# include <cppad/cppad.hpp>
namespace { // ---------------------------------------------------------
bool reverse()
{	bool ok = true;
	using CppAD::AD;
	using CppAD::NearEqual;
	typedef CPPAD_TEST_VECTOR< AD<double> > a_vector;
	typedef CPPAD_TEST_VECTOR<double>       d_vector;
	typedef CPPAD_TEST_VECTOR<size_t>       i_vector;
	size_t i, j, k, ell;
	double eps = 10. * CppAD::epsilon<double>();

	// domain space vector
	size_t n = 4;
	a_vector  a_x(n);
	for(j = 0; j < n; j++)
		a_x[j] = AD<double> (0);

	// declare independent variables and starting recording
	CppAD::Independent(a_x);

	size_t m = 3;
	a_vector  a_y(m);
	a_y[0] = a_x[0] + a_x[1];
	a_y[1] = a_x[2] + a_x[3];
	a_y[2] = a_x[0] + a_x[1] + a_x[2] + a_x[3] * a_x[3] / 2.;

	// create f: x -> y and stop tape recording
	CppAD::ADFun<double> f(a_x, a_y);

	// new value for the independent variable vector
	d_vector x(n);
	for(j = 0; j < n; j++)
		x[j] = double(j);

	// Jacobian of y without sparsity pattern
	d_vector jac(m * n);
	jac = f.SparseJacobian(x);
	/*
	      [ 1 1 0 0  ]
	jac = [ 0 0 1 1  ]
	      [ 1 1 1 x_3]
	*/
	d_vector check(m * n);
	check[0] = 1.; check[1] = 1.; check[2]  = 0.; check[3]  = 0.;
	check[4] = 0.; check[5] = 0.; check[6]  = 1.; check[7]  = 1.;
	check[8] = 1.; check[9] = 1.; check[10] = 1.; check[11] = x[3];
	for(ell = 0; ell < check.size(); ell++)
		ok &=  NearEqual(check[ell], jac[ell], eps, eps );

	// using packed boolean sparsity patterns
	CppAD::vectorBool s_b(m * m), p_b(m * n);
	for(i = 0; i < m; i++)
	{	for(ell = 0; ell < m; ell++)
			s_b[i * m + ell] = false;
		s_b[i * m + i] = true;
	}
	p_b   = f.RevSparseJac(m, s_b);
	jac   = f.SparseJacobian(x, p_b);
	for(ell = 0; ell < check.size(); ell++)
		ok &=  NearEqual(check[ell], jac[ell], eps, eps );

	// using vector of sets sparsity patterns
	std::vector< std::set<size_t> > s_s(m),  p_s(m);
	for(i = 0; i < m; i++)
		s_s[i].insert(i);
	p_s   = f.RevSparseJac(m, s_s);
	jac   = f.SparseJacobian(x, p_s);
	for(ell = 0; ell < check.size(); ell++)
		ok &=  NearEqual(check[ell], jac[ell], eps, eps );

	// using row and column indices to compute non-zero in rows 1 and 2
	// (skip row 0).
	size_t K = 6;
	i_vector r(K), c(K);
	jac.resize(K);
	k = 0;
	for(j = 0; j < n; j++)
	{	for(i = 1; i < m; i++)
		{	ell = i * n + j;
			if( p_b[ell] )
			{	ok &= check[ell] != 0.;
				r[k] = i;
				c[k] = j;
				k++;
			}
		}
	}
	ok &= k == K;

	// empty work structure
	CppAD::sparse_jacobian_work work;

	// could use p_b
	size_t n_sweep = f.SparseJacobianReverse(x, p_s, r, c, jac, work);
	for(k = 0; k < K; k++)
	{    ell = r[k] * n + c[k];
		ok &= NearEqual(check[ell], jac[k], eps, eps);
	}
	ok &= n_sweep == 2;

	// now recompute at a different x value (using work from previous call)
	check[11] = x[3] = 10.;
	n_sweep = f.SparseJacobianReverse(x, p_s, r, c, jac, work);
	for(k = 0; k < K; k++)
	{    ell = r[k] * n + c[k];
		ok &= NearEqual(check[ell], jac[k], eps, eps);
	}
	ok &= n_sweep == 2;

	return ok;
}

bool forward()
{	bool ok = true;
	using CppAD::AD;
	using CppAD::NearEqual;
	typedef CPPAD_TEST_VECTOR< AD<double> > a_vector;
	typedef CPPAD_TEST_VECTOR<double>       d_vector;
	typedef CPPAD_TEST_VECTOR<size_t>       i_vector;
	size_t i, j, k, ell;
	double eps = 10. * CppAD::epsilon<double>();

	// domain space vector
	size_t n = 3;
	a_vector  a_x(n);
	for(j = 0; j < n; j++)
		a_x[j] = AD<double> (0);

	// declare independent variables and starting recording
	CppAD::Independent(a_x);

	size_t m = 4;
	a_vector  a_y(m);
	a_y[0] = a_x[0] + a_x[2];
	a_y[1] = a_x[0] + a_x[2];
	a_y[2] = a_x[1] + a_x[2];
	a_y[3] = a_x[1] + a_x[2] * a_x[2] / 2.;

	// create f: x -> y and stop tape recording
	CppAD::ADFun<double> f(a_x, a_y);

	// new value for the independent variable vector
	d_vector x(n);
	for(j = 0; j < n; j++)
		x[j] = double(j);

	// Jacobian of y without sparsity pattern
	d_vector jac(m * n);
	jac = f.SparseJacobian(x);
	/*
	      [ 1 0 1   ]
	jac = [ 1 0 1   ]
	      [ 0 1 1   ]
	      [ 0 1 x_2 ]
	*/
	d_vector check(m * n);
	check[0] = 1.; check[1]  = 0.; check[2]  = 1.;
	check[3] = 1.; check[4]  = 0.; check[5]  = 1.;
	check[6] = 0.; check[7]  = 1.; check[8]  = 1.;
	check[9] = 0.; check[10] = 1.; check[11] = x[2];
	for(ell = 0; ell < check.size(); ell++)
		ok &=  NearEqual(check[ell], jac[ell], eps, eps );

	// test using packed boolean vectors for sparsity pattern
	CppAD::vectorBool r_b(n * n), p_b(m * n);
	for(j = 0; j < n; j++)
	{	for(ell = 0; ell < n; ell++)
			r_b[j * n + ell] = false;
		r_b[j * n + j] = true;
	}
	p_b = f.ForSparseJac(n, r_b);
	jac = f.SparseJacobian(x, p_b);
	for(ell = 0; ell < check.size(); ell++)
		ok &=  NearEqual(check[ell], jac[ell], eps, eps );

	// test using vector of sets for sparsity pattern
	std::vector< std::set<size_t> > r_s(n), p_s(m);
	for(j = 0; j < n; j++)
		r_s[j].insert(j);
	p_s = f.ForSparseJac(n, r_s);
	jac = f.SparseJacobian(x, p_s);
	for(ell = 0; ell < check.size(); ell++)
		ok &=  NearEqual(check[ell], jac[ell], eps, eps );

	// using row and column indices to compute non-zero elements excluding
	// row 0 and column 0.
	size_t K = 5;
	i_vector r(K), c(K);
	jac.resize(K);
	k = 0;
	for(i = 1; i < m; i++)
	{	for(j = 1; j < n; j++)
		{	ell = i * n + j;
			if( p_b[ell] )
			{	ok &= check[ell] != 0.;
				r[k] = i;
				c[k] = j;
				k++;
			}
		}
	}
	ok &= k == K;

	// empty work structure
	CppAD::sparse_jacobian_work work;

	// could use p_s
	size_t n_sweep = f.SparseJacobianForward(x, p_b, r, c, jac, work);
	for(k = 0; k < K; k++)
	{    ell = r[k] * n + c[k];
		ok &= NearEqual(check[ell], jac[k], eps, eps);
	}
	ok &= n_sweep == 2;

	// now recompute at a different x value (using work from previous call)
	check[11] = x[2] = 10.;
	n_sweep = f.SparseJacobianForward(x, p_s, r, c, jac, work);
	for(k = 0; k < K; k++)
	{    ell = r[k] * n + c[k];
		ok &= NearEqual(check[ell], jac[k], eps, eps);
	}
	ok &= n_sweep == 2;

	return ok;
}
} // End empty namespace

bool sparse_jacobian(void)
{	bool ok = true;
	ok &= forward();
	ok &= reverse();

	return ok;
}
// END PROGRAM
<commit_msg>sparse_jacobian.cpp: Change (r,c) indices to (row, col).<commit_after>/* $Id$ */
/* --------------------------------------------------------------------------
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell

CppAD is distributed under multiple licenses. This distribution is under
the terms of the
                    Common Public License Version 1.0.

A copy of this license is included in the COPYING file of this distribution.
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
-------------------------------------------------------------------------- */

/*
$begin sparse_jacobian.cpp$$
$spell
	Cpp
	Jacobian
$$

$section Sparse Jacobian: Example and Test$$

$index Jacobian, sparse$$
$index example, sparse Jacobian$$
$index test, sparse Jacobian$$
$index spare, Jacobian example$$

$code
$verbatim%example/sparse_jacobian.cpp%0%// BEGIN PROGRAM%// END PROGRAM%1%$$
$$

$end
*/
// BEGIN PROGRAM

# include <cppad/cppad.hpp>
namespace { // ---------------------------------------------------------
bool reverse()
{	bool ok = true;
	using CppAD::AD;
	using CppAD::NearEqual;
	typedef CPPAD_TEST_VECTOR< AD<double> > a_vector;
	typedef CPPAD_TEST_VECTOR<double>       d_vector;
	typedef CPPAD_TEST_VECTOR<size_t>       i_vector;
	size_t i, j, k, ell;
	double eps = 10. * CppAD::epsilon<double>();

	// domain space vector
	size_t n = 4;
	a_vector  a_x(n);
	for(j = 0; j < n; j++)
		a_x[j] = AD<double> (0);

	// declare independent variables and starting recording
	CppAD::Independent(a_x);

	size_t m = 3;
	a_vector  a_y(m);
	a_y[0] = a_x[0] + a_x[1];
	a_y[1] = a_x[2] + a_x[3];
	a_y[2] = a_x[0] + a_x[1] + a_x[2] + a_x[3] * a_x[3] / 2.;

	// create f: x -> y and stop tape recording
	CppAD::ADFun<double> f(a_x, a_y);

	// new value for the independent variable vector
	d_vector x(n);
	for(j = 0; j < n; j++)
		x[j] = double(j);

	// Jacobian of y without sparsity pattern
	d_vector jac(m * n);
	jac = f.SparseJacobian(x);
	/*
	      [ 1 1 0 0  ]
	jac = [ 0 0 1 1  ]
	      [ 1 1 1 x_3]
	*/
	d_vector check(m * n);
	check[0] = 1.; check[1] = 1.; check[2]  = 0.; check[3]  = 0.;
	check[4] = 0.; check[5] = 0.; check[6]  = 1.; check[7]  = 1.;
	check[8] = 1.; check[9] = 1.; check[10] = 1.; check[11] = x[3];
	for(ell = 0; ell < check.size(); ell++)
		ok &=  NearEqual(check[ell], jac[ell], eps, eps );

	// using packed boolean sparsity patterns
	CppAD::vectorBool s_b(m * m), p_b(m * n);
	for(i = 0; i < m; i++)
	{	for(ell = 0; ell < m; ell++)
			s_b[i * m + ell] = false;
		s_b[i * m + i] = true;
	}
	p_b   = f.RevSparseJac(m, s_b);
	jac   = f.SparseJacobian(x, p_b);
	for(ell = 0; ell < check.size(); ell++)
		ok &=  NearEqual(check[ell], jac[ell], eps, eps );

	// using vector of sets sparsity patterns
	std::vector< std::set<size_t> > s_s(m),  p_s(m);
	for(i = 0; i < m; i++)
		s_s[i].insert(i);
	p_s   = f.RevSparseJac(m, s_s);
	jac   = f.SparseJacobian(x, p_s);
	for(ell = 0; ell < check.size(); ell++)
		ok &=  NearEqual(check[ell], jac[ell], eps, eps );

	// using row and column indices to compute non-zero in rows 1 and 2
	// (skip row 0).
	size_t K = 6;
	i_vector row(K), col(K);
	jac.resize(K);
	k = 0;
	for(j = 0; j < n; j++)
	{	for(i = 1; i < m; i++)
		{	ell = i * n + j;
			if( p_b[ell] )
			{	ok &= check[ell] != 0.;
				row[k] = i;
				col[k] = j;
				k++;
			}
		}
	}
	ok &= k == K;

	// empty work structure
	CppAD::sparse_jacobian_work work;

	// could use p_b
	size_t n_sweep = f.SparseJacobianReverse(x, p_s, row, col, jac, work);
	for(k = 0; k < K; k++)
	{    ell = row[k] * n + col[k];
		ok &= NearEqual(check[ell], jac[k], eps, eps);
	}
	ok &= n_sweep == 2;

	// now recompute at a different x value (using work from previous call)
	check[11] = x[3] = 10.;
	n_sweep = f.SparseJacobianReverse(x, p_s, row, col, jac, work);
	for(k = 0; k < K; k++)
	{    ell = row[k] * n + col[k];
		ok &= NearEqual(check[ell], jac[k], eps, eps);
	}
	ok &= n_sweep == 2;

	return ok;
}

bool forward()
{	bool ok = true;
	using CppAD::AD;
	using CppAD::NearEqual;
	typedef CPPAD_TEST_VECTOR< AD<double> > a_vector;
	typedef CPPAD_TEST_VECTOR<double>       d_vector;
	typedef CPPAD_TEST_VECTOR<size_t>       i_vector;
	size_t i, j, k, ell;
	double eps = 10. * CppAD::epsilon<double>();

	// domain space vector
	size_t n = 3;
	a_vector  a_x(n);
	for(j = 0; j < n; j++)
		a_x[j] = AD<double> (0);

	// declare independent variables and starting recording
	CppAD::Independent(a_x);

	size_t m = 4;
	a_vector  a_y(m);
	a_y[0] = a_x[0] + a_x[2];
	a_y[1] = a_x[0] + a_x[2];
	a_y[2] = a_x[1] + a_x[2];
	a_y[3] = a_x[1] + a_x[2] * a_x[2] / 2.;

	// create f: x -> y and stop tape recording
	CppAD::ADFun<double> f(a_x, a_y);

	// new value for the independent variable vector
	d_vector x(n);
	for(j = 0; j < n; j++)
		x[j] = double(j);

	// Jacobian of y without sparsity pattern
	d_vector jac(m * n);
	jac = f.SparseJacobian(x);
	/*
	      [ 1 0 1   ]
	jac = [ 1 0 1   ]
	      [ 0 1 1   ]
	      [ 0 1 x_2 ]
	*/
	d_vector check(m * n);
	check[0] = 1.; check[1]  = 0.; check[2]  = 1.;
	check[3] = 1.; check[4]  = 0.; check[5]  = 1.;
	check[6] = 0.; check[7]  = 1.; check[8]  = 1.;
	check[9] = 0.; check[10] = 1.; check[11] = x[2];
	for(ell = 0; ell < check.size(); ell++)
		ok &=  NearEqual(check[ell], jac[ell], eps, eps );

	// test using packed boolean vectors for sparsity pattern
	CppAD::vectorBool r_b(n * n), p_b(m * n);
	for(j = 0; j < n; j++)
	{	for(ell = 0; ell < n; ell++)
			r_b[j * n + ell] = false;
		r_b[j * n + j] = true;
	}
	p_b = f.ForSparseJac(n, r_b);
	jac = f.SparseJacobian(x, p_b);
	for(ell = 0; ell < check.size(); ell++)
		ok &=  NearEqual(check[ell], jac[ell], eps, eps );

	// test using vector of sets for sparsity pattern
	std::vector< std::set<size_t> > r_s(n), p_s(m);
	for(j = 0; j < n; j++)
		r_s[j].insert(j);
	p_s = f.ForSparseJac(n, r_s);
	jac = f.SparseJacobian(x, p_s);
	for(ell = 0; ell < check.size(); ell++)
		ok &=  NearEqual(check[ell], jac[ell], eps, eps );

	// using row and column indices to compute non-zero elements excluding
	// row 0 and column 0.
	size_t K = 5;
	i_vector row(K), col(K);
	jac.resize(K);
	k = 0;
	for(i = 1; i < m; i++)
	{	for(j = 1; j < n; j++)
		{	ell = i * n + j;
			if( p_b[ell] )
			{	ok &= check[ell] != 0.;
				row[k] = i;
				col[k] = j;
				k++;
			}
		}
	}
	ok &= k == K;

	// empty work structure
	CppAD::sparse_jacobian_work work;

	// could use p_s
	size_t n_sweep = f.SparseJacobianForward(x, p_b, row, col, jac, work);
	for(k = 0; k < K; k++)
	{    ell = row[k] * n + col[k];
		ok &= NearEqual(check[ell], jac[k], eps, eps);
	}
	ok &= n_sweep == 2;

	// now recompute at a different x value (using work from previous call)
	check[11] = x[2] = 10.;
	n_sweep = f.SparseJacobianForward(x, p_s, row, col, jac, work);
	for(k = 0; k < K; k++)
	{    ell = row[k] * n + col[k];
		ok &= NearEqual(check[ell], jac[k], eps, eps);
	}
	ok &= n_sweep == 2;

	return ok;
}
} // End empty namespace

bool sparse_jacobian(void)
{	bool ok = true;
	ok &= forward();
	ok &= reverse();

	return ok;
}
// END PROGRAM
<|endoftext|>


<commit_before>/*
 *  This file is parte of grammargen. A tool to generate sequences of
 *  characters from a given grammar.
 *  Copyright (C) 2015 Raphael Santos, http://www.raphaelss.com
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <cstdio>
#include <stdexcept>
#include <string>
#include "grammar.hpp"

struct op {
  void operator()(char c) {
    std::putchar(c);
  }

  void operator()(const std::string &c) {
    std::fwrite(c.data(), c.size(), sizeof(std::string::value_type), stdout);
  }
};

int main(int argc, char **argv) {
  int n;
  if (argc < 3 || argc % 3 != 0 || (n = std::stoi(argv[1])) < 0) {
    fprintf(stderr, "Usage: %s axiom number_of_iterations [rules]\n"
                    "       rule = probability char string\n", argv[0]);
    return 1;
  }
  Grammar g(argv[2]);
  argc -= 3;
  argv += 3;
  double prob;
  while (argc) {
    try {
      if ((prob = std::stod(argv[0])) <= 0) {
        throw std::invalid_argument("not a positive number");
      }
    } catch (const std::invalid_argument &e) {
      fprintf(stderr, "grammargen error: %s is not a positive number\n",
              argv[0]);
      return 1;
    }
    g.addRule(argv[1][0], argv[2], prob);
    argc -= 3;
    argv += 3;
  }
  gen_seq<op>(g, n, g.axiom);
  putchar('\n');
  return 0;
}
<commit_msg>Fix usage message and namespace issues<commit_after>/*
 *  This file is parte of grammargen. A tool to generate sequences of
 *  characters from a given grammar.
 *  Copyright (C) 2015 Raphael Santos, http://www.raphaelss.com
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <cstdio>
#include <stdexcept>
#include <string>
#include "grammar.hpp"

struct op {
  void operator()(char c) {
    std::putchar(c);
  }

  void operator()(const std::string &c) {
    std::fwrite(c.data(), c.size(), sizeof(std::string::value_type), stdout);
  }
};

int main(int argc, char **argv) {
  int n;
  if (argc < 3 || argc % 3 != 0 || (n = std::stoi(argv[1])) < 0) {
    std::fprintf(stderr, "Usage: %s number_of_iterations axiom [rules]\n"
                         "       rule = probability char string\n", argv[0]);
    return 1;
  }
  Grammar g(argv[2]);
  argc -= 3;
  argv += 3;
  double prob;
  while (argc) {
    try {
      if ((prob = std::stod(argv[0])) <= 0) {
        throw std::invalid_argument("not a positive number");
      }
    } catch (const std::invalid_argument &e) {
      std::fprintf(stderr, "grammargen error: %s is not a positive number\n",
                   argv[0]);
      return 1;
    }
    g.addRule(argv[1][0], argv[2], prob);
    argc -= 3;
    argv += 3;
  }
  gen_seq<op>(g, n, g.axiom);
  putchar('\n');
  return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
 */

#pragma once

#include <cassert>
#include <bitset>
#include <algorithm>
#include <uavcan/error.hpp>
#include <uavcan/stdint.hpp>
#include <uavcan/data_type.hpp>
#include <uavcan/util/compile_time.hpp>
#include <uavcan/linked_list.hpp>
#if UAVCAN_DEBUG
# include <uavcan/debug.hpp>
#endif

namespace uavcan
{

typedef std::bitset<DataTypeID::Max + 1> DataTypeIDMask;

class UAVCAN_EXPORT GlobalDataTypeRegistry : Noncopyable
{
    struct Entry : public LinkedListNode<Entry>
    {
        DataTypeDescriptor descriptor;

        Entry() { }

        Entry(DataTypeKind kind, DataTypeID id, const DataTypeSignature& signature, const char* name)
            : descriptor(kind, id, signature, name)
        { }
    };

    struct EntryInsertionComparator
    {
        const DataTypeID id;
        EntryInsertionComparator(Entry* dtd) : id(dtd->descriptor.getID()) { }
        bool operator()(const Entry* entry) const
        {
            assert(entry);
            return entry->descriptor.getID() > id;
        }
    };

public:
    enum RegistResult
    {
        RegistResultOk,
        RegistResultCollision,
        RegistResultInvalidParams,
        RegistResultFrozen
    };

private:
    typedef LinkedListRoot<Entry> List;
    mutable List msgs_;
    mutable List srvs_;
    bool frozen_;

    /**
     * We can't use function local static variable for singleton because of code size issues:
     *     http://stackoverflow.com/questions/22985570
     */
    static GlobalDataTypeRegistry singleton;

    GlobalDataTypeRegistry() : frozen_(false) { }

    List* selectList(DataTypeKind kind) const;

    RegistResult remove(Entry* dtd);
    RegistResult registImpl(Entry* dtd);

public:
    static GlobalDataTypeRegistry& instance();

    /// Last call wins
    template <typename Type>
    RegistResult regist(DataTypeID id);

    /// Further calls to regist<>() will fail
    void freeze();
    bool isFrozen() const { return frozen_; }

    const DataTypeDescriptor* find(DataTypeKind kind, const char* name) const;
    const DataTypeDescriptor* find(DataTypeKind kind, DataTypeID dtid) const;

    DataTypeSignature computeAggregateSignature(DataTypeKind kind, DataTypeIDMask& inout_id_mask) const;

    void getDataTypeIDMask(DataTypeKind kind, DataTypeIDMask& mask) const;

    unsigned getNumMessageTypes() const { return msgs_.getLength(); }
    unsigned getNumServiceTypes() const { return srvs_.getLength(); }

#if UAVCAN_DEBUG
    /// Required for unit testing
    void reset()
    {
        UAVCAN_TRACE("GlobalDataTypeRegistry", "Reset; was frozen: %i, num msgs: %u, num srvs: %u",
                     int(frozen_), getNumMessageTypes(), getNumServiceTypes());
        frozen_ = false;
        while (msgs_.get())
        {
            msgs_.remove(msgs_.get());
        }
        while (srvs_.get())
        {
            srvs_.remove(srvs_.get());
        }
    }
#endif
};

template <typename Type>
struct UAVCAN_EXPORT DefaultDataTypeRegistrator
{
    DefaultDataTypeRegistrator()
    {
        const GlobalDataTypeRegistry::RegistResult res =
            GlobalDataTypeRegistry::instance().regist<Type>(Type::DefaultDataTypeID);

        if (res != GlobalDataTypeRegistry::RegistResultOk)
        {
            handleFatalError("Type registration failed");
        }
    }
};

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

/*
 * GlobalDataTypeRegistry
 */
template <typename Type>
GlobalDataTypeRegistry::RegistResult GlobalDataTypeRegistry::regist(DataTypeID id)
{
    if (isFrozen())
    {
        return RegistResultFrozen;
    }

    static Entry entry;
    {
        const RegistResult remove_res = remove(&entry);
        if (remove_res != RegistResultOk)
        {
            return remove_res;
        }
    }
    entry = Entry(DataTypeKind(Type::DataTypeKind), id, Type::getDataTypeSignature(), Type::getDataTypeFullName());
    {
        const RegistResult remove_res = remove(&entry);
        if (remove_res != RegistResultOk)
        {
            return remove_res;
        }
    }
    return registImpl(&entry);
}

}
<commit_msg>Compact Entry constructor for GlobalDataTypeRegistry::regist<>()<commit_after>/*
 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
 */

#pragma once

#include <cassert>
#include <bitset>
#include <algorithm>
#include <uavcan/error.hpp>
#include <uavcan/stdint.hpp>
#include <uavcan/data_type.hpp>
#include <uavcan/util/compile_time.hpp>
#include <uavcan/linked_list.hpp>
#if UAVCAN_DEBUG
# include <uavcan/debug.hpp>
#endif

namespace uavcan
{

typedef std::bitset<DataTypeID::Max + 1> DataTypeIDMask;

class UAVCAN_EXPORT GlobalDataTypeRegistry : Noncopyable
{
    struct Entry : public LinkedListNode<Entry>
    {
        DataTypeDescriptor descriptor;

        Entry() { }

        Entry(DataTypeKind kind, DataTypeID id, const DataTypeSignature& signature, const char* name)
            : descriptor(kind, id, signature, name)
        { }
    };

    struct EntryInsertionComparator
    {
        const DataTypeID id;
        EntryInsertionComparator(Entry* dtd) : id(dtd->descriptor.getID()) { }
        bool operator()(const Entry* entry) const
        {
            assert(entry);
            return entry->descriptor.getID() > id;
        }
    };

public:
    enum RegistResult
    {
        RegistResultOk,
        RegistResultCollision,
        RegistResultInvalidParams,
        RegistResultFrozen
    };

private:
    typedef LinkedListRoot<Entry> List;
    mutable List msgs_;
    mutable List srvs_;
    bool frozen_;

    /**
     * We can't use function local static variable for singleton because of code size issues:
     *     http://stackoverflow.com/questions/22985570
     */
    static GlobalDataTypeRegistry singleton;

    GlobalDataTypeRegistry() : frozen_(false) { }

    List* selectList(DataTypeKind kind) const;

    RegistResult remove(Entry* dtd);
    RegistResult registImpl(Entry* dtd);

public:
    static GlobalDataTypeRegistry& instance();

    /// Last call wins
    template <typename Type>
    RegistResult regist(DataTypeID id);

    /// Further calls to regist<>() will fail
    void freeze();
    bool isFrozen() const { return frozen_; }

    const DataTypeDescriptor* find(DataTypeKind kind, const char* name) const;
    const DataTypeDescriptor* find(DataTypeKind kind, DataTypeID dtid) const;

    DataTypeSignature computeAggregateSignature(DataTypeKind kind, DataTypeIDMask& inout_id_mask) const;

    void getDataTypeIDMask(DataTypeKind kind, DataTypeIDMask& mask) const;

    unsigned getNumMessageTypes() const { return msgs_.getLength(); }
    unsigned getNumServiceTypes() const { return srvs_.getLength(); }

#if UAVCAN_DEBUG
    /// Required for unit testing
    void reset()
    {
        UAVCAN_TRACE("GlobalDataTypeRegistry", "Reset; was frozen: %i, num msgs: %u, num srvs: %u",
                     int(frozen_), getNumMessageTypes(), getNumServiceTypes());
        frozen_ = false;
        while (msgs_.get())
        {
            msgs_.remove(msgs_.get());
        }
        while (srvs_.get())
        {
            srvs_.remove(srvs_.get());
        }
    }
#endif
};

template <typename Type>
struct UAVCAN_EXPORT DefaultDataTypeRegistrator
{
    DefaultDataTypeRegistrator()
    {
        const GlobalDataTypeRegistry::RegistResult res =
            GlobalDataTypeRegistry::instance().regist<Type>(Type::DefaultDataTypeID);

        if (res != GlobalDataTypeRegistry::RegistResultOk)
        {
            handleFatalError("Type registration failed");
        }
    }
};

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

/*
 * GlobalDataTypeRegistry
 */
template <typename Type>
GlobalDataTypeRegistry::RegistResult GlobalDataTypeRegistry::regist(DataTypeID id)
{
    if (isFrozen())
    {
        return RegistResultFrozen;
    }

    static union EntryUnion
    {
        uint8_t buffer[sizeof(Entry)];
        long long _aligner_1;
        long double _aligner_2;
    } storage;
    static bool constructed = false;
    if (!constructed)
    {
        new (storage.buffer) Entry();
        constructed = true;
    }

    Entry* const entry = reinterpret_cast<Entry*>(storage.buffer);

    {
        const RegistResult remove_res = remove(entry);
        if (remove_res != RegistResultOk)
        {
            return remove_res;
        }
    }
    new (storage.buffer) Entry(DataTypeKind(Type::DataTypeKind), id, Type::getDataTypeSignature(), Type::getDataTypeFullName());
    {
        const RegistResult remove_res = remove(entry);
        if (remove_res != RegistResultOk)
        {
            return remove_res;
        }
    }
    return registImpl(entry);
}

}
<|endoftext|>


<commit_before>/* <x0/request.hpp>
 *
 * This file is part of the x0 web server project and is released under LGPL-3.
 *
 * (c) 2009 Chrisitan Parpart <trapni@gentoo.org>
 */

#ifndef x0_http_request_hpp
#define x0_http_request_hpp (1)

#include <x0/io/fileinfo.hpp>
#include <x0/buffer.hpp>
#include <x0/header.hpp>
#include <x0/strutils.hpp>
#include <x0/types.hpp>
#include <x0/api.hpp>
#include <string>
#include <vector>
#include <boost/tuple/tuple.hpp>
#include <boost/logic/tribool.hpp>

namespace x0 {

class plugin;

//! \addtogroup core
//@{

/**
 * \brief a client HTTP reuqest object, holding the parsed x0 request data.
 *
 * \see header, response, connection, server
 */
struct X0_API request
{
public:
	explicit request(x0::connection& connection);

	x0::connection& connection;					///< the TCP/IP connection this request has been sent through

	// request properties
	buffer_ref method;							///< HTTP request method, e.g. HEAD, GET, POST, PUT, etc.
	buffer_ref uri;								///< parsed request uri
	buffer_ref path;							///< decoded path-part
	fileinfo_ptr fileinfo;						///< the final entity to be served, for example the full path to the file on disk.
	buffer_ref query;							///< decoded query-part
	int http_version_major;						///< HTTP protocol version major part that this request was formed in
	int http_version_minor;						///< HTTP protocol version minor part that this request was formed in
	std::vector<x0::request_header> headers;	///< request headers
	std::string body;							///< body

	/** retrieve value of a given request header */
	buffer_ref header(const std::string& name) const;

	// accumulated request data
	buffer_ref username;						///< username this client has authenticated with.
	std::string document_root;					///< the document root directory for this request.

//	std::string if_modified_since;		//!< "If-Modified-Since" request header value, if specified.
//	std::shared_ptr<range_def> range;	//!< parsed "Range" request header

	// custom data bindings
	std::map<plugin *, custom_data_ptr> custom_data;

	// utility methods
	bool supports_protocol(int major, int minor) const;
	std::string hostid() const;
};

// {{{ request impl
inline request::request(x0::connection& conn) :
	connection(conn)
{
}

inline bool request::supports_protocol(int major, int minor) const
{
	if (major == http_version_major && minor <= http_version_minor)
		return true;

	if (major < http_version_major)
		return true;

	return false;
}
// }}}

//@}

} // namespace x0

#endif
<commit_msg>comment-foo<commit_after>/* <x0/request.hpp>
 *
 * This file is part of the x0 web server project and is released under LGPL-3.
 *
 * (c) 2009 Chrisitan Parpart <trapni@gentoo.org>
 */

#ifndef x0_http_request_hpp
#define x0_http_request_hpp (1)

#include <x0/io/fileinfo.hpp>
#include <x0/buffer.hpp>
#include <x0/header.hpp>
#include <x0/strutils.hpp>
#include <x0/types.hpp>
#include <x0/api.hpp>
#include <string>
#include <vector>
#include <boost/tuple/tuple.hpp>
#include <boost/logic/tribool.hpp>

namespace x0 {

class plugin;

//! \addtogroup core
//@{

/**
 * \brief a client HTTP reuqest object, holding the parsed x0 request data.
 *
 * \see header, response, connection, server
 */
struct X0_API request
{
public:
	explicit request(x0::connection& connection);

	x0::connection& connection;					///< the TCP/IP connection this request has been sent through

	// request properties
	buffer_ref method;							///< HTTP request method, e.g. HEAD, GET, POST, PUT, etc.
	buffer_ref uri;								///< parsed request uri
	buffer_ref path;							///< decoded path-part
	fileinfo_ptr fileinfo;						///< the final entity to be served, for example the full path to the file on disk.
	buffer_ref query;							///< decoded query-part
	int http_version_major;						///< HTTP protocol version major part that this request was formed in
	int http_version_minor;						///< HTTP protocol version minor part that this request was formed in
	std::vector<x0::request_header> headers;	///< request headers
	std::string body;							///< body

	/** retrieve value of a given request header */
	buffer_ref header(const std::string& name) const;

	// accumulated request data
	buffer_ref username;						///< username this client has authenticated with.
	std::string document_root;					///< the document root directory for this request.

//	std::string if_modified_since;				//!< "If-Modified-Since" request header value, if specified.
//	std::shared_ptr<range_def> range;			//!< parsed "Range" request header

	// custom data bindings
	std::map<plugin *, custom_data_ptr> custom_data;

	// utility methods
	bool supports_protocol(int major, int minor) const;
	std::string hostid() const;
};

// {{{ request impl
inline request::request(x0::connection& conn) :
	connection(conn)
{
}

inline bool request::supports_protocol(int major, int minor) const
{
	if (major == http_version_major && minor <= http_version_minor)
		return true;

	if (major < http_version_major)
		return true;

	return false;
}
// }}}

//@}

} // namespace x0

#endif
<|endoftext|>