<commit_before>#include <boost/shared_ptr.hpp>
#include "SpanLength.h"
#include "moses/StaticData.h"
#include "moses/Word.h"
#include "moses/ChartCellLabel.h"
#include "moses/WordsRange.h"
#include "moses/StackVec.h"
#include "moses/TargetPhrase.h"
#include "moses/PP/PhraseProperty.h"
#include "moses/PP/SpanLengthPhraseProperty.h"

using namespace std;

namespace Moses
{
SpanLength::SpanLength(const std::string &line)
:StatelessFeatureFunction(1, line)
,m_smoothingMethod(None)
,m_const(0)
{
  ReadParameters();
}

void SpanLength::Evaluate(const Phrase &source
						, const TargetPhrase &targetPhrase
						, ScoreComponentCollection &scoreBreakdown
						, ScoreComponentCollection &estimatedFutureScore) const
{
  targetPhrase.SetRuleSource(source);
}

void SpanLength::Evaluate(const InputType &input
                                   , const InputPath &inputPath
                                   , const TargetPhrase &targetPhrase
                                   , const StackVec *stackVec
                                   , ScoreComponentCollection &scoreBreakdown
                                   , ScoreComponentCollection *estimatedFutureScore) const
{
  assert(stackVec);

  boost::shared_ptr<PhraseProperty> property;
  bool hasProperty = targetPhrase.GetProperty("SpanLength", property);

  if (!hasProperty) {
	  return;
  }

  PhraseProperty *prop = property.get();
  SpanLengthPhraseProperty *slProp = static_cast<SpanLengthPhraseProperty*>(prop);
  assert(slProp);

  string str = slProp->GetValueString();
  cerr << "str=" << str << endl;

  const Phrase *ruleSource = targetPhrase.GetRuleSource();
  assert(ruleSource);
  cerr << *ruleSource << endl;

  float score = 0;
  for (size_t i = 0; i < stackVec->size(); ++i) {
	  const ChartCellLabel &cell = *stackVec->at(i);
	  const WordsRange &ntRange = cell.GetCoverage();
	  size_t sourceWidth = ntRange.GetNumWordsCovered();
	  float prob = slProp->GetProb(i, sourceWidth, m_const);
	  score += TransformScore(prob);
  }
  scoreBreakdown.PlusEquals(this, score);

}

void SpanLength::SetParameter(const std::string& key, const std::string& value)
{
  if (key == "smoothing") {
	  if (value == "plus-constant") {
		  m_smoothingMethod = PlusConst;
	  }
	  else if (value == "none") {
		  m_smoothingMethod = None;
	  }
	  else {
		  UTIL_THROW(util::Exception, "Unknown smoothing type " << value);
	  }
  }
  else if (key == "constant") {
	  m_const = Scan<float>(value);
  }
  else {
    StatelessFeatureFunction::SetParameter(key, value);
  }
}

}

<commit_msg>delete debugging messages<commit_after>#include <boost/shared_ptr.hpp>
#include "SpanLength.h"
#include "moses/StaticData.h"
#include "moses/Word.h"
#include "moses/ChartCellLabel.h"
#include "moses/WordsRange.h"
#include "moses/StackVec.h"
#include "moses/TargetPhrase.h"
#include "moses/PP/PhraseProperty.h"
#include "moses/PP/SpanLengthPhraseProperty.h"

using namespace std;

namespace Moses
{
SpanLength::SpanLength(const std::string &line)
:StatelessFeatureFunction(1, line)
,m_smoothingMethod(None)
,m_const(0)
{
  ReadParameters();
}

void SpanLength::Evaluate(const Phrase &source
						, const TargetPhrase &targetPhrase
						, ScoreComponentCollection &scoreBreakdown
						, ScoreComponentCollection &estimatedFutureScore) const
{
  targetPhrase.SetRuleSource(source);
}

void SpanLength::Evaluate(const InputType &input
                                   , const InputPath &inputPath
                                   , const TargetPhrase &targetPhrase
                                   , const StackVec *stackVec
                                   , ScoreComponentCollection &scoreBreakdown
                                   , ScoreComponentCollection *estimatedFutureScore) const
{
  assert(stackVec);

  boost::shared_ptr<PhraseProperty> property;
  bool hasProperty = targetPhrase.GetProperty("SpanLength", property);

  if (!hasProperty) {
	  return;
  }

  PhraseProperty *prop = property.get();
  SpanLengthPhraseProperty *slProp = static_cast<SpanLengthPhraseProperty*>(prop);
  assert(slProp);

  string str = slProp->GetValueString();

  const Phrase *ruleSource = targetPhrase.GetRuleSource();
  assert(ruleSource);

  float score = 0;
  for (size_t i = 0; i < stackVec->size(); ++i) {
	  const ChartCellLabel &cell = *stackVec->at(i);
	  const WordsRange &ntRange = cell.GetCoverage();
	  size_t sourceWidth = ntRange.GetNumWordsCovered();
	  float prob = slProp->GetProb(i, sourceWidth, m_const);
	  score += TransformScore(prob);
  }
  scoreBreakdown.PlusEquals(this, score);

}

void SpanLength::SetParameter(const std::string& key, const std::string& value)
{
  if (key == "smoothing") {
	  if (value == "plus-constant") {
		  m_smoothingMethod = PlusConst;
	  }
	  else if (value == "none") {
		  m_smoothingMethod = None;
	  }
	  else {
		  UTIL_THROW(util::Exception, "Unknown smoothing type " << value);
	  }
  }
  else if (key == "constant") {
	  m_const = Scan<float>(value);
  }
  else {
    StatelessFeatureFunction::SetParameter(key, value);
  }
}

}

<|endoftext|>


<commit_before>#include <multihash/hash_type.h>
#include <multihash/multihash.h>
#include <iomanip>
#include "multihash/detail/multihash_impl.h"

namespace multihash {

multihash::multihash() : pImpl(nullptr) {}

multihash::multihash(hash_code code, const std::string_view& digest)
    : pImpl(new impl(code, digest)) {}

multihash::multihash(const multihash& rhs) : pImpl(rhs.pImpl) {}

multihash& multihash::operator=(const multihash& rhs) noexcept {
  auto copy = rhs;
  std::swap(pImpl, copy.pImpl);
  return *this;
}

multihash::~multihash() {}

multihash::multihash(const std::string_view& buffer) {
  pImpl.reset(new impl(buffer));
}

bool multihash::operator==(const multihash& rhs) const {
  if (pImpl == nullptr or rhs.pImpl == nullptr) {
    return pImpl == rhs.pImpl;
  }
  return code() == rhs.code() && digest() == rhs.digest();
}

bool multihash::operator!=(const multihash& rhs) const {
  return !(*this == rhs);
}

bool multihash::operator<(const multihash& rhs) const {
  if (pImpl == nullptr or rhs.pImpl == nullptr) {
    return pImpl < rhs.pImpl;
  }
  auto result = false;
  if (code() == rhs.code()) {
    result = digest() < rhs.digest();
  } else {
    result = code() < rhs.code();
  }
  return result;
}

bool multihash::operator>(const multihash& rhs) const {
  auto result = false;
  if (code() == rhs.code()) {
    result = digest() > rhs.digest();
  } else {
    result = code() > rhs.code();
  }
  return result;
}

hash_code multihash::code() const { return pImpl->code(); }

std::string_view multihash::digest() const { return pImpl->digest(); }

const char* multihash::data() const { return pImpl->data(); }

std::size_t multihash::size() const { return pImpl->size(); }

multihash::operator std::vector<char>() {
  return static_cast<std::vector<char>>(*pImpl);
}

std::ostream& operator<<(std::ostream& os, const multihash& hash) {
  auto data = std::string_view(hash.data(), hash.size());
  for (auto c : data) {
    auto uc = uint8_t(c);
    os << std::hex << std::setfill('0') << std::setw(2);
    os << static_cast<int>(uc);
  }
  return os;
}
}  // namespace multihash
<commit_msg>Re-wrote or as ||<commit_after>#include <multihash/hash_type.h>
#include <multihash/multihash.h>
#include <iomanip>
#include "multihash/detail/multihash_impl.h"

namespace multihash {

multihash::multihash() : pImpl(nullptr) {}

multihash::multihash(hash_code code, const std::string_view& digest)
    : pImpl(new impl(code, digest)) {}

multihash::multihash(const multihash& rhs) : pImpl(rhs.pImpl) {}

multihash& multihash::operator=(const multihash& rhs) noexcept {
  auto copy = rhs;
  std::swap(pImpl, copy.pImpl);
  return *this;
}

multihash::~multihash() {}

multihash::multihash(const std::string_view& buffer) {
  pImpl.reset(new impl(buffer));
}

bool multihash::operator==(const multihash& rhs) const {
  if (pImpl == nullptr || rhs.pImpl == nullptr) {
    return pImpl == rhs.pImpl;
  }
  return code() == rhs.code() && digest() == rhs.digest();
}

bool multihash::operator!=(const multihash& rhs) const {
  return !(*this == rhs);
}

bool multihash::operator<(const multihash& rhs) const {
  if (pImpl == nullptr || rhs.pImpl == nullptr) {
    return pImpl < rhs.pImpl;
  }
  auto result = false;
  if (code() == rhs.code()) {
    result = digest() < rhs.digest();
  } else {
    result = code() < rhs.code();
  }
  return result;
}

bool multihash::operator>(const multihash& rhs) const {
  auto result = false;
  if (code() == rhs.code()) {
    result = digest() > rhs.digest();
  } else {
    result = code() > rhs.code();
  }
  return result;
}

hash_code multihash::code() const { return pImpl->code(); }

std::string_view multihash::digest() const { return pImpl->digest(); }

const char* multihash::data() const { return pImpl->data(); }

std::size_t multihash::size() const { return pImpl->size(); }

multihash::operator std::vector<char>() {
  return static_cast<std::vector<char>>(*pImpl);
}

std::ostream& operator<<(std::ostream& os, const multihash& hash) {
  auto data = std::string_view(hash.data(), hash.size());
  for (auto c : data) {
    auto uc = uint8_t(c);
    os << std::hex << std::setfill('0') << std::setw(2);
    os << static_cast<int>(uc);
  }
  return os;
}
}  // namespace multihash
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2013.  All rights reserved
 */
#ifndef _Stroika_Foundation_Memory_Optional_inl_
#define _Stroika_Foundation_Memory_Optional_inl_    1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
#include   "../Debug/Assertions.h"

namespace   Stroika {
    namespace   Foundation {
        namespace   Memory {

            /*
             ********************************************************************************
             *********************** Optional_DefaultTraits<T> ******************************
             ********************************************************************************
             */
            template    <typename T>
            inline  int Optional_DefaultTraits<T>::Compare (T lhs, T rhs)
            {
                if (lhs < rhs) {
                    return -1;
                }
                else if (rhs < lhs) {
                    return 1;
                }
                Assert (lhs == rhs);
                return 0;
            }

            /*
             ********************************************************************************
             ********************************** Optional<T> *********************************
             ********************************************************************************
             */
            template    <typename T, typename TRAITS>
            inline  Optional<T, TRAITS>::Optional ()
                : fValue_ (nullptr)
            {
            }
            template    <typename T, typename TRAITS>
            inline  Optional<T, TRAITS>::Optional (const T& from)
                : fValue_ (new BlockAllocated<T> (from))
            {
            }
            template    <typename T, typename TRAITS>
            inline  Optional<T, TRAITS>::Optional (T && from)
                : fValue_ (new BlockAllocated<T> (std::move (from)))
            {
            }
            template    <typename T, typename TRAITS>
            inline  Optional<T, TRAITS>::Optional (const Optional<T, TRAITS>& from)
                : fValue_ (from.fValue_ == nullptr ? nullptr : new BlockAllocated<T> (*from.fValue_))
            {
            }
            template    <typename T, typename TRAITS>
            inline  Optional<T, TRAITS>::Optional (Optional<T, TRAITS> && from)
                : fValue_ (from.fValue_)
            {
                from.fValue_ = nullptr;
            }
            template    <typename T, typename TRAITS>
            inline  Optional<T, TRAITS>::~Optional ()
            {
                delete fValue_;
            }
            template    <typename T, typename TRAITS>
            inline  Optional<T, TRAITS>&   Optional<T, TRAITS>::operator= (const T& from)
            {
                delete fValue_;
                fValue_ = nullptr;
                fValue_ = new BlockAllocated<T> (from);
                return *this;
            }
            template    <typename T, typename TRAITS>
            inline  Optional<T, TRAITS>&   Optional<T, TRAITS>::operator= (T && from)
            {
                fValue_ = new BlockAllocated<T> (std::move (from));
                return *this;
            }
            template    <typename T, typename TRAITS>
            inline  Optional<T, TRAITS>&   Optional<T, TRAITS>::operator= (const Optional<T, TRAITS>& from)
            {
                delete fValue_;
                fValue_ = nullptr;
                if (from.fValue_ != nullptr) {
                    fValue_ = new BlockAllocated<T> (*from.fValue_);
                }
                return *this;
            }
            template    <typename T, typename TRAITS>
            inline  Optional<T, TRAITS>&   Optional<T, TRAITS>::operator= (Optional<T, TRAITS> && from)
            {
                delete fValue_;
                fValue_ = from.fValue_;
                from.fValue_ = nullptr;
                return *this;
            }
            template    <typename T, typename TRAITS>
            inline  void    Optional<T, TRAITS>::clear ()
            {
                delete fValue_;
                fValue_ = nullptr;
            }
            template    <typename T, typename TRAITS>
            inline  const T*    Optional<T, TRAITS>::get () const
            {
                return fValue_ == nullptr ? nullptr : fValue_->get ();
            }
            template    <typename T, typename TRAITS>
            inline  bool    Optional<T, TRAITS>::empty () const
            {
                return fValue_ == nullptr;
            }
            template    <typename T, typename TRAITS>
            inline  const T* Optional<T, TRAITS>::operator-> () const
            {
                Require (not empty ())
                AssertNotNull (fValue_);
                EnsureNotNull (fValue_->get ());
                return fValue_->get ();
            }
            template    <typename T, typename TRAITS>
            inline  T* Optional<T, TRAITS>::operator-> ()
            {
                Require (not empty ());
                AssertNotNull (fValue_);
                EnsureNotNull (fValue_->get ());
                return fValue_->get ();
            }
            template    <typename T, typename TRAITS>
            inline  const T& Optional<T, TRAITS>::operator* () const
            {
                Require (not empty ())
                AssertNotNull (fValue_);
                EnsureNotNull (fValue_->get ());
                return *fValue_->get ();
            }
            template    <typename T, typename TRAITS>
            inline  T& Optional<T, TRAITS>::operator* ()
            {
                Require (not empty ())
                AssertNotNull (fValue_);
                EnsureNotNull (fValue_->get ());
                return *fValue_->get ();
            }
            template    <typename T, typename TRAITS>
            inline  int Optional<T, TRAITS>::Compare (const Optional<T>& rhs) const
            {
                if (fValue_ == nullptr) {
                    return (rhs.fValue_ == nullptr) ? 0 : 1; // arbitrary choice - but assume if lhs is empty thats less than any T value
                }
                if (rhs.fValue_ == nullptr) {
                    AssertNotNull (fValue_);
                    return -1;
                }
                AssertNotNull (fValue_);
                AssertNotNull (rhs.fValue_);
                return TRAITS::Compare (static_cast<T> (*fValue_), static_cast<T> (*rhs.fValue_));
            }
            template    <typename T, typename TRAITS>
            inline  bool    Optional<T, TRAITS>::operator< (const Optional<T, TRAITS>& rhs) const
            {
                return Compare (rhs) < 0;
            }
            template    <typename T, typename TRAITS>
            inline  bool    Optional<T, TRAITS>::operator<= (const Optional<T, TRAITS>& rhs) const
            {
                return Compare (rhs) <= 0;
            }
            template    <typename T, typename TRAITS>
            inline  bool    Optional<T, TRAITS>::operator> (const Optional<T, TRAITS>& rhs) const
            {
                return Compare (rhs) > 0;
            }
            template    <typename T, typename TRAITS>
            inline  bool    Optional<T, TRAITS>::operator>= (const Optional<T, TRAITS>& rhs) const
            {
                return Compare (rhs) >= 0;
            }
            template    <typename T, typename TRAITS>
            inline  bool    Optional<T, TRAITS>::operator== (const Optional<T, TRAITS>& rhs) const
            {
                return Compare (rhs) == 0;
            }
            template    <typename T, typename TRAITS>
            inline  bool    Optional<T, TRAITS>::operator!= (const Optional<T, TRAITS>& rhs) const
            {
                return Compare (rhs) != 0;
            }

        }
    }
}
#endif  /*_Stroika_Foundation_Memory_Optional_inl_*/
<commit_msg>comments<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2013.  All rights reserved
 */
#ifndef _Stroika_Foundation_Memory_Optional_inl_
#define _Stroika_Foundation_Memory_Optional_inl_    1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
#include   "../Debug/Assertions.h"

namespace   Stroika {
    namespace   Foundation {
        namespace   Memory {

            /*
             ********************************************************************************
             *********************** Optional_DefaultTraits<T> ******************************
             ********************************************************************************
             */
            template    <typename T>
            inline  int Optional_DefaultTraits<T>::Compare (T lhs, T rhs)
            {
                if (lhs < rhs) {
                    return -1;
                }
                else if (rhs < lhs) {
                    return 1;
                }
                Assert (lhs == rhs);
                return 0;
            }

            /*
             ********************************************************************************
             ********************************** Optional<T> *********************************
             ********************************************************************************
             */
            template    <typename T, typename TRAITS>
            inline  Optional<T, TRAITS>::Optional ()
                : fValue_ (nullptr)
            {
            }
            template    <typename T, typename TRAITS>
            inline  Optional<T, TRAITS>::Optional (const T& from)
                : fValue_ (new BlockAllocated<T> (from))
            {
            }
            template    <typename T, typename TRAITS>
            inline  Optional<T, TRAITS>::Optional (T && from)
                : fValue_ (new BlockAllocated<T> (std::move (from)))
            {
            }
            template    <typename T, typename TRAITS>
            inline  Optional<T, TRAITS>::Optional (const Optional<T, TRAITS>& from)
                : fValue_ (from.fValue_ == nullptr ? nullptr : new BlockAllocated<T> (*from.fValue_))
            {
            }
            template    <typename T, typename TRAITS>
            inline  Optional<T, TRAITS>::Optional (Optional<T, TRAITS> && from)
                : fValue_ (from.fValue_)
            {
                from.fValue_ = nullptr;
            }
            template    <typename T, typename TRAITS>
            inline  Optional<T, TRAITS>::~Optional ()
            {
                delete fValue_;
            }
            template    <typename T, typename TRAITS>
            inline  Optional<T, TRAITS>&   Optional<T, TRAITS>::operator= (const T& from)
            {
                delete fValue_;
                fValue_ = nullptr;
                fValue_ = new BlockAllocated<T> (from);
                return *this;
            }
            template    <typename T, typename TRAITS>
            inline  Optional<T, TRAITS>&   Optional<T, TRAITS>::operator= (T && from)
            {
                fValue_ = new BlockAllocated<T> (std::move (from));
                return *this;
            }
            template    <typename T, typename TRAITS>
            inline  Optional<T, TRAITS>&   Optional<T, TRAITS>::operator= (const Optional<T, TRAITS>& from)
            {
                delete fValue_;
                fValue_ = nullptr;
                if (from.fValue_ != nullptr) {
                    fValue_ = new BlockAllocated<T> (*from.fValue_);
                }
                return *this;
            }
            template    <typename T, typename TRAITS>
            inline  Optional<T, TRAITS>&   Optional<T, TRAITS>::operator= (Optional<T, TRAITS> && from)
            {
                delete fValue_;
                fValue_ = from.fValue_;
                from.fValue_ = nullptr;
                return *this;
            }
            template    <typename T, typename TRAITS>
            inline  void    Optional<T, TRAITS>::clear ()
            {
                delete fValue_;
                fValue_ = nullptr;
            }
            template    <typename T, typename TRAITS>
            inline  const T*    Optional<T, TRAITS>::get () const
            {
                return fValue_ == nullptr ? nullptr : fValue_->get ();
            }
            template    <typename T, typename TRAITS>
            inline  bool    Optional<T, TRAITS>::empty () const
            {
                return fValue_ == nullptr;
            }
            template    <typename T, typename TRAITS>
            inline  const T* Optional<T, TRAITS>::operator-> () const
            {
                Require (not empty ())
                AssertNotNull (fValue_);
                EnsureNotNull (fValue_->get ());
                return fValue_->get ();
            }
            template    <typename T, typename TRAITS>
            inline  T* Optional<T, TRAITS>::operator-> ()
            {
                Require (not empty ());
                AssertNotNull (fValue_);
                EnsureNotNull (fValue_->get ());
                return fValue_->get ();
            }
            template    <typename T, typename TRAITS>
            inline  const T& Optional<T, TRAITS>::operator* () const
            {
                Require (not empty ())
                AssertNotNull (fValue_);
                EnsureNotNull (fValue_->get ());
                return *fValue_->get ();
            }
            template    <typename T, typename TRAITS>
            inline  T& Optional<T, TRAITS>::operator* ()
            {
                Require (not empty ())
                AssertNotNull (fValue_);
                EnsureNotNull (fValue_->get ());
                return *fValue_->get ();
            }
            template    <typename T, typename TRAITS>
            inline  int Optional<T, TRAITS>::Compare (const Optional<T>& rhs) const
            {
                if (fValue_ == nullptr) {
                    return (rhs.fValue_ == nullptr) ? 0 : 1; // arbitrary choice - but assume if lhs is empty thats less than any T value
                }
                if (rhs.fValue_ == nullptr) {
                    AssertNotNull (fValue_);
                    return -1;
                }
                AssertNotNull (fValue_);
                AssertNotNull (rhs.fValue_);
                return TRAITS::Compare (static_cast<T> (*fValue_), static_cast<T> (*rhs.fValue_));
            }
            template    <typename T, typename TRAITS>
            inline  bool    Optional<T, TRAITS>::operator< (const Optional<T, TRAITS>& rhs) const
            {
                return Compare (rhs) < 0;
            }
            template    <typename T, typename TRAITS>
            inline  bool    Optional<T, TRAITS>::operator<= (const Optional<T, TRAITS>& rhs) const
            {
                return Compare (rhs) <= 0;
            }
            template    <typename T, typename TRAITS>
            inline  bool    Optional<T, TRAITS>::operator> (const Optional<T, TRAITS>& rhs) const
            {
                return Compare (rhs) > 0;
            }
            template    <typename T, typename TRAITS>
            inline  bool    Optional<T, TRAITS>::operator>= (const Optional<T, TRAITS>& rhs) const
            {
                return Compare (rhs) >= 0;
            }
            template    <typename T, typename TRAITS>
            inline  bool    Optional<T, TRAITS>::operator== (const Optional<T, TRAITS>& rhs) const
            {
                return Compare (rhs) == 0;
            }
            template    <typename T, typename TRAITS>
            inline  bool    Optional<T, TRAITS>::operator!= (const Optional<T, TRAITS>& rhs) const
            {
                return Compare (rhs) != 0;
            }

        }
    }
}
#endif  /*_Stroika_Foundation_Memory_Optional_inl_*/
<|endoftext|>


<commit_before>//===- LoopVR.cpp - Value Range analysis driven by loop information -------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// FIXME: What does this do?
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "loopvr"
#include "llvm/Analysis/LoopVR.h"
#include "llvm/Constants.h"
#include "llvm/Instructions.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;

char LoopVR::ID = 0;
static RegisterPass<LoopVR> X("loopvr", "Loop Value Ranges", true, true);

/// getRange - determine the range for a particular SCEV within a given Loop
ConstantRange LoopVR::getRange(SCEVHandle S, Loop *L, ScalarEvolution &SE) {
  SCEVHandle T = SE.getBackedgeTakenCount(L);
  if (isa<SCEVCouldNotCompute>(T))
    return ConstantRange(cast<IntegerType>(S->getType())->getBitWidth(), true);

  T = SE.getTruncateOrZeroExtend(T, S->getType());
  return getRange(S, T, SE);
}

/// getRange - determine the range for a particular SCEV with a given trip count
ConstantRange LoopVR::getRange(SCEVHandle S, SCEVHandle T, ScalarEvolution &SE){

  if (SCEVConstant *C = dyn_cast<SCEVConstant>(S))
    return ConstantRange(C->getValue()->getValue());

  ConstantRange FullSet(cast<IntegerType>(S->getType())->getBitWidth(), true);

  // {x,+,y,+,...z}. We detect overflow by checking the size of the set after
  // summing the upper and lower.
  if (SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(S)) {
    ConstantRange X = getRange(Add->getOperand(0), T, SE);
    if (X.isFullSet()) return FullSet;
    for (unsigned i = 1, e = Add->getNumOperands(); i != e; ++i) {
      ConstantRange Y = getRange(Add->getOperand(i), T, SE);
      if (Y.isFullSet()) return FullSet;

      APInt Spread_X = X.getSetSize(), Spread_Y = Y.getSetSize();
      APInt NewLower = X.getLower() + Y.getLower();
      APInt NewUpper = X.getUpper() + Y.getUpper() - 1;
      if (NewLower == NewUpper)
        return FullSet;

      X = ConstantRange(NewLower, NewUpper);
      if (X.getSetSize().ult(Spread_X) || X.getSetSize().ult(Spread_Y))
        return FullSet; // we've wrapped, therefore, full set.
    }
    return X;
  }

  // {x,*,y,*,...,z}. In order to detect overflow, we use k*bitwidth where
  // k is the number of terms being multiplied.
  if (SCEVMulExpr *Mul = dyn_cast<SCEVMulExpr>(S)) {
    ConstantRange X = getRange(Mul->getOperand(0), T, SE);
    if (X.isFullSet()) return FullSet;

    const IntegerType *Ty = IntegerType::get(X.getBitWidth());
    const IntegerType *ExTy = IntegerType::get(X.getBitWidth() *
                                               Mul->getNumOperands());
    ConstantRange XExt = X.zeroExtend(ExTy->getBitWidth());

    for (unsigned i = 1, e = Mul->getNumOperands(); i != e; ++i) {
      ConstantRange Y = getRange(Mul->getOperand(i), T, SE);
      if (Y.isFullSet()) return FullSet;

      ConstantRange YExt = Y.zeroExtend(ExTy->getBitWidth());
      XExt = ConstantRange(XExt.getLower() * YExt.getLower(),
                           ((XExt.getUpper()-1) * (YExt.getUpper()-1)) + 1);
    }
    return XExt.truncate(Ty->getBitWidth());
  }

  // X smax Y smax ... Z is: range(smax(X_smin, Y_smin, ..., Z_smin),
  //                               smax(X_smax, Y_smax, ..., Z_smax))
  // It doesn't matter if one of the SCEVs has FullSet because we're taking
  // a maximum of the minimums across all of them.
  if (SCEVSMaxExpr *SMax = dyn_cast<SCEVSMaxExpr>(S)) {
    ConstantRange X = getRange(SMax->getOperand(0), T, SE);
    if (X.isFullSet()) return FullSet;

    APInt smin = X.getSignedMin(), smax = X.getSignedMax();
    for (unsigned i = 1, e = SMax->getNumOperands(); i != e; ++i) {
      ConstantRange Y = getRange(SMax->getOperand(i), T, SE);
      smin = APIntOps::smax(smin, Y.getSignedMin());
      smax = APIntOps::smax(smax, Y.getSignedMax());
    }
    if (smax + 1 == smin) return FullSet;
    return ConstantRange(smin, smax + 1);
  }

  // X umax Y umax ... Z is: range(umax(X_umin, Y_umin, ..., Z_umin),
  //                               umax(X_umax, Y_umax, ..., Z_umax))
  // It doesn't matter if one of the SCEVs has FullSet because we're taking
  // a maximum of the minimums across all of them.
  if (SCEVUMaxExpr *UMax = dyn_cast<SCEVUMaxExpr>(S)) {
    ConstantRange X = getRange(UMax->getOperand(0), T, SE);
    if (X.isFullSet()) return FullSet;

    APInt umin = X.getUnsignedMin(), umax = X.getUnsignedMax();
    for (unsigned i = 1, e = UMax->getNumOperands(); i != e; ++i) {
      ConstantRange Y = getRange(UMax->getOperand(i), T, SE);
      umin = APIntOps::umax(umin, Y.getUnsignedMin());
      umax = APIntOps::umax(umax, Y.getUnsignedMax());
    }
    if (umax + 1 == umin) return FullSet;
    return ConstantRange(umin, umax + 1);
  }

  // L udiv R. Luckily, there's only ever 2 sides to a udiv.
  if (SCEVUDivExpr *UDiv = dyn_cast<SCEVUDivExpr>(S)) {
    ConstantRange L = getRange(UDiv->getLHS(), T, SE);
    ConstantRange R = getRange(UDiv->getRHS(), T, SE);
    if (L.isFullSet() && R.isFullSet()) return FullSet;

    if (R.getUnsignedMax() == 0) {
      // RHS must be single-element zero. Return an empty set.
      return ConstantRange(R.getBitWidth(), false);
    }

    APInt Lower = L.getUnsignedMin().udiv(R.getUnsignedMax());

    APInt Upper;

    if (R.getUnsignedMin() == 0) {
      // Just because it contains zero, doesn't mean it will also contain one.
      // Use maximalIntersectWith to get the right behaviour.
      ConstantRange NotZero(APInt(L.getBitWidth(), 1),
                            APInt::getNullValue(L.getBitWidth()));
      R = R.maximalIntersectWith(NotZero);
    }

    // But, the maximal intersection might still include zero. If it does, then
    // we know it also included one.
    if (R.contains(APInt::getNullValue(L.getBitWidth())))
      Upper = L.getUnsignedMax();
    else
      Upper = L.getUnsignedMax().udiv(R.getUnsignedMin());

    return ConstantRange(Lower, Upper);
  }

  // ConstantRange already implements the cast operators.

  if (SCEVZeroExtendExpr *ZExt = dyn_cast<SCEVZeroExtendExpr>(S)) {
    T = SE.getTruncateOrZeroExtend(T, ZExt->getOperand()->getType());
    ConstantRange X = getRange(ZExt->getOperand(), T, SE);
    return X.zeroExtend(cast<IntegerType>(ZExt->getType())->getBitWidth());
  }

  if (SCEVSignExtendExpr *SExt = dyn_cast<SCEVSignExtendExpr>(S)) {
    T = SE.getTruncateOrZeroExtend(T, SExt->getOperand()->getType());
    ConstantRange X = getRange(SExt->getOperand(), T, SE);
    return X.signExtend(cast<IntegerType>(SExt->getType())->getBitWidth());
  }

  if (SCEVTruncateExpr *Trunc = dyn_cast<SCEVTruncateExpr>(S)) {
    T = SE.getTruncateOrZeroExtend(T, Trunc->getOperand()->getType());
    ConstantRange X = getRange(Trunc->getOperand(), T, SE);
    if (X.isFullSet()) return FullSet;
    return X.truncate(cast<IntegerType>(Trunc->getType())->getBitWidth());
  }

  if (SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(S)) {
    SCEVConstant *Trip = dyn_cast<SCEVConstant>(T);
    if (!Trip) return FullSet;

    if (AddRec->isAffine()) {
      SCEVHandle StartHandle = AddRec->getStart();
      SCEVHandle StepHandle = AddRec->getOperand(1);

      SCEVConstant *Step = dyn_cast<SCEVConstant>(StepHandle);
      if (!Step) return FullSet;

      uint32_t ExWidth = 2 * Trip->getValue()->getBitWidth();
      APInt TripExt = Trip->getValue()->getValue(); TripExt.zext(ExWidth);
      APInt StepExt = Step->getValue()->getValue(); StepExt.zext(ExWidth);
      if ((TripExt * StepExt).ugt(APInt::getLowBitsSet(ExWidth, ExWidth >> 1)))
        return FullSet;

      SCEVHandle EndHandle = SE.getAddExpr(StartHandle,
                                           SE.getMulExpr(T, StepHandle));
      SCEVConstant *Start = dyn_cast<SCEVConstant>(StartHandle);
      SCEVConstant *End = dyn_cast<SCEVConstant>(EndHandle);
      if (!Start || !End) return FullSet;

      const APInt &StartInt = Start->getValue()->getValue();
      const APInt &EndInt = End->getValue()->getValue();
      const APInt &StepInt = Step->getValue()->getValue();

      if (StepInt.isNegative()) {
        if (EndInt == StartInt + 1) return FullSet;
        return ConstantRange(EndInt, StartInt + 1);
      } else {
        if (StartInt == EndInt + 1) return FullSet;
        return ConstantRange(StartInt, EndInt + 1);
      }
    }
  }

  // TODO: non-affine addrec, udiv, SCEVUnknown (narrowed from elsewhere)?

  return FullSet;
}

bool LoopVR::runOnFunction(Function &F) { Map.clear(); return false; }

void LoopVR::print(std::ostream &os, const Module *) const {
  raw_os_ostream OS(os);
  for (std::map<Value *, ConstantRange *>::const_iterator I = Map.begin(),
       E = Map.end(); I != E; ++I) {
    OS << *I->first << ": " << *I->second << '\n';
  }
}

void LoopVR::releaseMemory() {
  for (std::map<Value *, ConstantRange *>::iterator I = Map.begin(),
       E = Map.end(); I != E; ++I) {
    delete I->second;
  }

  Map.clear();
}

ConstantRange LoopVR::compute(Value *V) {
  if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
    return ConstantRange(CI->getValue());

  Instruction *I = dyn_cast<Instruction>(V);
  if (!I)
    return ConstantRange(cast<IntegerType>(V->getType())->getBitWidth(), false);

  LoopInfo &LI = getAnalysis<LoopInfo>();

  Loop *L = LI.getLoopFor(I->getParent());
  if (!L || L->isLoopInvariant(I))
    return ConstantRange(cast<IntegerType>(V->getType())->getBitWidth(), false);

  ScalarEvolution &SE = getAnalysis<ScalarEvolution>();

  SCEVHandle S = SE.getSCEV(I);
  if (isa<SCEVUnknown>(S) || isa<SCEVCouldNotCompute>(S))
    return ConstantRange(cast<IntegerType>(V->getType())->getBitWidth(), false);

  return ConstantRange(getRange(S, L, SE));
}

ConstantRange LoopVR::get(Value *V) {
  std::map<Value *, ConstantRange *>::iterator I = Map.find(V);
  if (I == Map.end()) {
    ConstantRange *CR = new ConstantRange(compute(V));
    Map[V] = CR;
    return *CR;
  }

  return *I->second;
}

void LoopVR::remove(Value *V) {
  std::map<Value *, ConstantRange *>::iterator I = Map.find(V);
  if (I != Map.end()) {
    delete I->second;
    Map.erase(I);
  }
}

void LoopVR::narrow(Value *V, const ConstantRange &CR) {
  if (CR.isFullSet()) return;

  std::map<Value *, ConstantRange *>::iterator I = Map.find(V);
  if (I == Map.end())
    Map[V] = new ConstantRange(CR);
  else
    Map[V] = new ConstantRange(Map[V]->maximalIntersectWith(CR));
}
<commit_msg>LoopVR is not CFGOnly.<commit_after>//===- LoopVR.cpp - Value Range analysis driven by loop information -------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// FIXME: What does this do?
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "loopvr"
#include "llvm/Analysis/LoopVR.h"
#include "llvm/Constants.h"
#include "llvm/Instructions.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;

char LoopVR::ID = 0;
static RegisterPass<LoopVR> X("loopvr", "Loop Value Ranges", false, true);

/// getRange - determine the range for a particular SCEV within a given Loop
ConstantRange LoopVR::getRange(SCEVHandle S, Loop *L, ScalarEvolution &SE) {
  SCEVHandle T = SE.getBackedgeTakenCount(L);
  if (isa<SCEVCouldNotCompute>(T))
    return ConstantRange(cast<IntegerType>(S->getType())->getBitWidth(), true);

  T = SE.getTruncateOrZeroExtend(T, S->getType());
  return getRange(S, T, SE);
}

/// getRange - determine the range for a particular SCEV with a given trip count
ConstantRange LoopVR::getRange(SCEVHandle S, SCEVHandle T, ScalarEvolution &SE){

  if (SCEVConstant *C = dyn_cast<SCEVConstant>(S))
    return ConstantRange(C->getValue()->getValue());

  ConstantRange FullSet(cast<IntegerType>(S->getType())->getBitWidth(), true);

  // {x,+,y,+,...z}. We detect overflow by checking the size of the set after
  // summing the upper and lower.
  if (SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(S)) {
    ConstantRange X = getRange(Add->getOperand(0), T, SE);
    if (X.isFullSet()) return FullSet;
    for (unsigned i = 1, e = Add->getNumOperands(); i != e; ++i) {
      ConstantRange Y = getRange(Add->getOperand(i), T, SE);
      if (Y.isFullSet()) return FullSet;

      APInt Spread_X = X.getSetSize(), Spread_Y = Y.getSetSize();
      APInt NewLower = X.getLower() + Y.getLower();
      APInt NewUpper = X.getUpper() + Y.getUpper() - 1;
      if (NewLower == NewUpper)
        return FullSet;

      X = ConstantRange(NewLower, NewUpper);
      if (X.getSetSize().ult(Spread_X) || X.getSetSize().ult(Spread_Y))
        return FullSet; // we've wrapped, therefore, full set.
    }
    return X;
  }

  // {x,*,y,*,...,z}. In order to detect overflow, we use k*bitwidth where
  // k is the number of terms being multiplied.
  if (SCEVMulExpr *Mul = dyn_cast<SCEVMulExpr>(S)) {
    ConstantRange X = getRange(Mul->getOperand(0), T, SE);
    if (X.isFullSet()) return FullSet;

    const IntegerType *Ty = IntegerType::get(X.getBitWidth());
    const IntegerType *ExTy = IntegerType::get(X.getBitWidth() *
                                               Mul->getNumOperands());
    ConstantRange XExt = X.zeroExtend(ExTy->getBitWidth());

    for (unsigned i = 1, e = Mul->getNumOperands(); i != e; ++i) {
      ConstantRange Y = getRange(Mul->getOperand(i), T, SE);
      if (Y.isFullSet()) return FullSet;

      ConstantRange YExt = Y.zeroExtend(ExTy->getBitWidth());
      XExt = ConstantRange(XExt.getLower() * YExt.getLower(),
                           ((XExt.getUpper()-1) * (YExt.getUpper()-1)) + 1);
    }
    return XExt.truncate(Ty->getBitWidth());
  }

  // X smax Y smax ... Z is: range(smax(X_smin, Y_smin, ..., Z_smin),
  //                               smax(X_smax, Y_smax, ..., Z_smax))
  // It doesn't matter if one of the SCEVs has FullSet because we're taking
  // a maximum of the minimums across all of them.
  if (SCEVSMaxExpr *SMax = dyn_cast<SCEVSMaxExpr>(S)) {
    ConstantRange X = getRange(SMax->getOperand(0), T, SE);
    if (X.isFullSet()) return FullSet;

    APInt smin = X.getSignedMin(), smax = X.getSignedMax();
    for (unsigned i = 1, e = SMax->getNumOperands(); i != e; ++i) {
      ConstantRange Y = getRange(SMax->getOperand(i), T, SE);
      smin = APIntOps::smax(smin, Y.getSignedMin());
      smax = APIntOps::smax(smax, Y.getSignedMax());
    }
    if (smax + 1 == smin) return FullSet;
    return ConstantRange(smin, smax + 1);
  }

  // X umax Y umax ... Z is: range(umax(X_umin, Y_umin, ..., Z_umin),
  //                               umax(X_umax, Y_umax, ..., Z_umax))
  // It doesn't matter if one of the SCEVs has FullSet because we're taking
  // a maximum of the minimums across all of them.
  if (SCEVUMaxExpr *UMax = dyn_cast<SCEVUMaxExpr>(S)) {
    ConstantRange X = getRange(UMax->getOperand(0), T, SE);
    if (X.isFullSet()) return FullSet;

    APInt umin = X.getUnsignedMin(), umax = X.getUnsignedMax();
    for (unsigned i = 1, e = UMax->getNumOperands(); i != e; ++i) {
      ConstantRange Y = getRange(UMax->getOperand(i), T, SE);
      umin = APIntOps::umax(umin, Y.getUnsignedMin());
      umax = APIntOps::umax(umax, Y.getUnsignedMax());
    }
    if (umax + 1 == umin) return FullSet;
    return ConstantRange(umin, umax + 1);
  }

  // L udiv R. Luckily, there's only ever 2 sides to a udiv.
  if (SCEVUDivExpr *UDiv = dyn_cast<SCEVUDivExpr>(S)) {
    ConstantRange L = getRange(UDiv->getLHS(), T, SE);
    ConstantRange R = getRange(UDiv->getRHS(), T, SE);
    if (L.isFullSet() && R.isFullSet()) return FullSet;

    if (R.getUnsignedMax() == 0) {
      // RHS must be single-element zero. Return an empty set.
      return ConstantRange(R.getBitWidth(), false);
    }

    APInt Lower = L.getUnsignedMin().udiv(R.getUnsignedMax());

    APInt Upper;

    if (R.getUnsignedMin() == 0) {
      // Just because it contains zero, doesn't mean it will also contain one.
      // Use maximalIntersectWith to get the right behaviour.
      ConstantRange NotZero(APInt(L.getBitWidth(), 1),
                            APInt::getNullValue(L.getBitWidth()));
      R = R.maximalIntersectWith(NotZero);
    }

    // But, the maximal intersection might still include zero. If it does, then
    // we know it also included one.
    if (R.contains(APInt::getNullValue(L.getBitWidth())))
      Upper = L.getUnsignedMax();
    else
      Upper = L.getUnsignedMax().udiv(R.getUnsignedMin());

    return ConstantRange(Lower, Upper);
  }

  // ConstantRange already implements the cast operators.

  if (SCEVZeroExtendExpr *ZExt = dyn_cast<SCEVZeroExtendExpr>(S)) {
    T = SE.getTruncateOrZeroExtend(T, ZExt->getOperand()->getType());
    ConstantRange X = getRange(ZExt->getOperand(), T, SE);
    return X.zeroExtend(cast<IntegerType>(ZExt->getType())->getBitWidth());
  }

  if (SCEVSignExtendExpr *SExt = dyn_cast<SCEVSignExtendExpr>(S)) {
    T = SE.getTruncateOrZeroExtend(T, SExt->getOperand()->getType());
    ConstantRange X = getRange(SExt->getOperand(), T, SE);
    return X.signExtend(cast<IntegerType>(SExt->getType())->getBitWidth());
  }

  if (SCEVTruncateExpr *Trunc = dyn_cast<SCEVTruncateExpr>(S)) {
    T = SE.getTruncateOrZeroExtend(T, Trunc->getOperand()->getType());
    ConstantRange X = getRange(Trunc->getOperand(), T, SE);
    if (X.isFullSet()) return FullSet;
    return X.truncate(cast<IntegerType>(Trunc->getType())->getBitWidth());
  }

  if (SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(S)) {
    SCEVConstant *Trip = dyn_cast<SCEVConstant>(T);
    if (!Trip) return FullSet;

    if (AddRec->isAffine()) {
      SCEVHandle StartHandle = AddRec->getStart();
      SCEVHandle StepHandle = AddRec->getOperand(1);

      SCEVConstant *Step = dyn_cast<SCEVConstant>(StepHandle);
      if (!Step) return FullSet;

      uint32_t ExWidth = 2 * Trip->getValue()->getBitWidth();
      APInt TripExt = Trip->getValue()->getValue(); TripExt.zext(ExWidth);
      APInt StepExt = Step->getValue()->getValue(); StepExt.zext(ExWidth);
      if ((TripExt * StepExt).ugt(APInt::getLowBitsSet(ExWidth, ExWidth >> 1)))
        return FullSet;

      SCEVHandle EndHandle = SE.getAddExpr(StartHandle,
                                           SE.getMulExpr(T, StepHandle));
      SCEVConstant *Start = dyn_cast<SCEVConstant>(StartHandle);
      SCEVConstant *End = dyn_cast<SCEVConstant>(EndHandle);
      if (!Start || !End) return FullSet;

      const APInt &StartInt = Start->getValue()->getValue();
      const APInt &EndInt = End->getValue()->getValue();
      const APInt &StepInt = Step->getValue()->getValue();

      if (StepInt.isNegative()) {
        if (EndInt == StartInt + 1) return FullSet;
        return ConstantRange(EndInt, StartInt + 1);
      } else {
        if (StartInt == EndInt + 1) return FullSet;
        return ConstantRange(StartInt, EndInt + 1);
      }
    }
  }

  // TODO: non-affine addrec, udiv, SCEVUnknown (narrowed from elsewhere)?

  return FullSet;
}

bool LoopVR::runOnFunction(Function &F) { Map.clear(); return false; }

void LoopVR::print(std::ostream &os, const Module *) const {
  raw_os_ostream OS(os);
  for (std::map<Value *, ConstantRange *>::const_iterator I = Map.begin(),
       E = Map.end(); I != E; ++I) {
    OS << *I->first << ": " << *I->second << '\n';
  }
}

void LoopVR::releaseMemory() {
  for (std::map<Value *, ConstantRange *>::iterator I = Map.begin(),
       E = Map.end(); I != E; ++I) {
    delete I->second;
  }

  Map.clear();
}

ConstantRange LoopVR::compute(Value *V) {
  if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
    return ConstantRange(CI->getValue());

  Instruction *I = dyn_cast<Instruction>(V);
  if (!I)
    return ConstantRange(cast<IntegerType>(V->getType())->getBitWidth(), false);

  LoopInfo &LI = getAnalysis<LoopInfo>();

  Loop *L = LI.getLoopFor(I->getParent());
  if (!L || L->isLoopInvariant(I))
    return ConstantRange(cast<IntegerType>(V->getType())->getBitWidth(), false);

  ScalarEvolution &SE = getAnalysis<ScalarEvolution>();

  SCEVHandle S = SE.getSCEV(I);
  if (isa<SCEVUnknown>(S) || isa<SCEVCouldNotCompute>(S))
    return ConstantRange(cast<IntegerType>(V->getType())->getBitWidth(), false);

  return ConstantRange(getRange(S, L, SE));
}

ConstantRange LoopVR::get(Value *V) {
  std::map<Value *, ConstantRange *>::iterator I = Map.find(V);
  if (I == Map.end()) {
    ConstantRange *CR = new ConstantRange(compute(V));
    Map[V] = CR;
    return *CR;
  }

  return *I->second;
}

void LoopVR::remove(Value *V) {
  std::map<Value *, ConstantRange *>::iterator I = Map.find(V);
  if (I != Map.end()) {
    delete I->second;
    Map.erase(I);
  }
}

void LoopVR::narrow(Value *V, const ConstantRange &CR) {
  if (CR.isFullSet()) return;

  std::map<Value *, ConstantRange *>::iterator I = Map.find(V);
  if (I == Map.end())
    Map[V] = new ConstantRange(CR);
  else
    Map[V] = new ConstantRange(Map[V]->maximalIntersectWith(CR));
}
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Log$
 * Revision 1.2  2003/11/17 16:18:01  peiyongz
 * Fix to  #4556
 *
 * Revision 1.1.1.1  2002/02/01 22:22:25  peiyongz
 * sane_include
 *
 * Revision 1.4  2000/03/02 19:55:30  roddey
 * This checkin includes many changes done while waiting for the
 * 1.1.0 code to be finished. I can't list them all here, but a list is
 * available elsewhere.
 *
 * Revision 1.3  2000/02/17 03:36:54  rahulj
 * Fixed a cut-paste typo in the comments.
 *
 * Revision 1.2  2000/02/06 07:48:30  rahulj
 * Year 2K copyright swat.
 *
 * Revision 1.1.1.1  1999/11/09 01:06:30  twl
 * Initial checkin
 *
 * Revision 1.2  1999/11/08 20:45:32  rahul
 * Swat for adding in Product name and CVS comment log variable.
 *
 */

// ---------------------------------------------------------------------------
//  SPARC runs in big endian mode
// ---------------------------------------------------------------------------
#define ENDIANMODE_BIG
typedef int FileHandle;

#ifndef SOLARIS
#define SOLARIS
#endif

<commit_msg>Jira[1255], patch from Neil Sharman<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Log$
 * Revision 1.3  2004/08/19 21:24:12  peiyongz
 * Jira[1255], patch from Neil Sharman
 *
 * Revision 1.2  2003/11/17 16:18:01  peiyongz
 * Fix to  #4556
 *
 * Revision 1.1.1.1  2002/02/01 22:22:25  peiyongz
 * sane_include
 *
 * Revision 1.4  2000/03/02 19:55:30  roddey
 * This checkin includes many changes done while waiting for the
 * 1.1.0 code to be finished. I can't list them all here, but a list is
 * available elsewhere.
 *
 * Revision 1.3  2000/02/17 03:36:54  rahulj
 * Fixed a cut-paste typo in the comments.
 *
 * Revision 1.2  2000/02/06 07:48:30  rahulj
 * Year 2K copyright swat.
 *
 * Revision 1.1.1.1  1999/11/09 01:06:30  twl
 * Initial checkin
 *
 * Revision 1.2  1999/11/08 20:45:32  rahul
 * Swat for adding in Product name and CVS comment log variable.
 *
 */

 // ---------------------------------------------------------------------------
 // Detect endian mode
 // ---------------------------------------------------------------------------
#include <sys/isa_defs.h>

#ifdef _LITTLE_ENDIAN
  #define ENDIANMODE_LITTLE
#elif defined(_BIG_ENDIAN)
  #define ENDIANMODE_BIG
#else
  #error : unknown byte order!
#endif

#ifndef SOLARIS
#define SOLARIS
#endif

<|endoftext|>


<commit_before>#include "cli_parser.h"

#include <boost/filesystem.hpp>
#include <iostream>
#include <sstream>
#include <vector>

#include "ParseUtils.h"

#include "log4cxx/logger.h"

namespace po = boost::program_options;

void validate(boost::any& v, const std::vector<std::string>& values, PositiveInteger*, int)
{
	po::validators::check_first_occurrence(v);
	const std::string& s = po::validators::get_single_string(values);

	unsigned int value;
	if( ParseUtils::ParseUInt(value, s.data(), 10) && value > 0 )
	{
		v = boost::any(PositiveInteger(value));
	} else {
		throw po::invalid_option_value(s);
	}
}

void validate(boost::any& v, const std::vector<std::string>& values, StrictlyPositiveInteger*, int)
{
	po::validators::check_first_occurrence(v);
	const std::string& s = po::validators::get_single_string(values);

	unsigned int value;
	if( ParseUtils::ParseUInt(value, s.data(), 10) && value > 0 )
	{
		v = boost::any(StrictlyPositiveInteger(value));
	} else {
		throw po::invalid_option_value(s);
	}
}

void validate(boost::any& v, const std::vector<std::string>& values, Float*, int)
{
	po::validators::check_first_occurrence(v);
	const std::string& s = po::validators::get_single_string(values);

	float value;
	if( ParseUtils::ParseFloat(value, s.data()) )
	{
		v = boost::any(Float(value));
	} else {
		throw po::invalid_option_value(s);
	}
}

void validate(boost::any& v, const std::vector<std::string>& values, Double*, int)
{
	po::validators::check_first_occurrence(v);
	const std::string& s = po::validators::get_single_string(values);

	double value;
	if( ParseUtils::ParseDouble(value, s.data()) )
	{
		v = boost::any(Double(value));
	} else {
		throw po::invalid_option_value(s);
	}
}

template< typename TElemType >
std::ostream &operator<<(std::ostream &s, const std::vector< TElemType >& v)
{
	std::stringstream ss;
	if( !v.empty() )
	{

		typename std::vector< TElemType >::const_iterator it = v.begin(), begin = v.begin(), end = v.end();
		for( ; it < end; ++it )
		{
			if(it != begin)
				ss << " ";
			ss << *it;
		}
	}

	return s << ss.str();
}

CliParser::CliParser()
{}

int CliParser::parse_argv(int argc, char ** argv)
{
	log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger("main"));

	LOG4CXX_INFO(logger, "Parsing command line options");

	typedef std::vector< StrictlyPositiveInteger > HiddenLayerVector;

	po::options_description desc("Command line parameters");
	desc.add_options()
		("help,h",
			"Produce help message")
		("input-image,i",
			po::value< std::string >(&(this->input_image))->required(),
			"Input image (required)")
		("class-image,c",
			po::value< std::vector< std::string > >(&(this->class_images))->required(),
			"Defines a class to be learned from a binary image (at least 2 values required)")
		("export-dir,E",
			po::value< std::string >(&(this->export_dir))->required(),
			"Export directory")
		("export-interval,e",
			po::value< PositiveInteger >(&(this->export_interval))->default_value(0),
			"Export interval during regularization")
		("num-iter,n",
			po::value< PositiveInteger >(&(this->num_iter))->default_value(0),
			"Number of iterations for the regularization")
		("lambda1",
			po::value< Double >(&(this->lambda1))->default_value(1.0),
			"Lambda 1 parameter for regularization")
		("lambda2",
			po::value< Double >(&(this->lambda2))->default_value(1.0),
			"Lambda 2 parameter for regularization")
		("ann-hidden-layer",
			po::value< HiddenLayerVector >()->multitoken()->default_value(HiddenLayerVector(1, 3)),
			"Number of neurons per hidden layer (default: one layer of 3 neurons)")
		("ann-learning-rate",
			po::value< Float >(&(this->ann_learning_rate))->default_value(0.1),
			"Learning rate of the neural networks")
		("ann-max-epoch",
			po::value< StrictlyPositiveInteger >(&(this->ann_max_epoch))->default_value(1000),
			"Maximum number of learning iterations for the neural networks")
		("ann-mse-target",
			po::value< Float >(&(this->ann_mse_target))->default_value(0.0001),
			"Mean squared error targeted by the neural networks learning algorithm")
		;

	po::variables_map vm;

	try {
		po::store(po::command_line_parser(argc, argv).options(desc).run(), vm);

		// Handling --help before notify() in order to allow ->required()
		// http://stackoverflow.com/questions/5395503/required-and-optional-arguments-using-boost-library-program-options#answer-5517755
		if (vm.count("help")) {
			std::cout << "Usage: " << argv[0] << " [options]" << std::endl;
			std::cout << desc;
			return 0;
		}

		po::notify(vm);
	} catch(po::error &err) {
		LOG4CXX_FATAL(logger, err.what());
		return -1;
	}

	LOG4CXX_INFO(logger, "Input image: " << this->input_image);

	if(this->class_images.size() < 2)
	{
		LOG4CXX_FATAL(logger, "You need to provide at least two learning classes");
		return -1;
	} else {
		LOG4CXX_INFO(logger, this->class_images.size() << " learning classes provided");

		for(int i = 0; i < this->class_images.size(); ++i)
		{
			boost::filesystem::path path(this->input_image);
			if(!boost::filesystem::exists(path))
			{
				LOG4CXX_FATAL(logger, "Cannot load class image: \"" << this->class_images[i] << "\" does not exists");
				return -1;
			}

			LOG4CXX_INFO(logger, "Class " << (i + 1) << ": " << this->class_images[i]);
		}
	}

	HiddenLayerVector hidden_layers = vm["ann-hidden-layer"].as< HiddenLayerVector >();
	for(HiddenLayerVector::const_iterator it = hidden_layers.begin(); it < hidden_layers.end(); ++it) {
		this->ann_hidden_layers.push_back((*it).value);
	}

	LOG4CXX_INFO(logger, "Main parameters:");
	LOG4CXX_INFO(logger, "\tExport directory: " << this->export_dir);
	LOG4CXX_INFO(logger, "Regularization parameters:");
	LOG4CXX_INFO(logger, "\tExport interval: " << this->export_interval);
	LOG4CXX_INFO(logger, "\tNumber of iterations: " << this->num_iter);
	LOG4CXX_INFO(logger, "\tLambda2: " << this->lambda2);
	LOG4CXX_INFO(logger, "\tLambda1: " << this->lambda1);
	LOG4CXX_INFO(logger, "Neural networks parameters:");
	{
		std::stringstream m;
		m << this->ann_hidden_layers;
		LOG4CXX_INFO(logger, "\tNumber of hidden neurons per layer: " << m.str());
	}
	LOG4CXX_INFO(logger, "\tLearning rate: " << this->ann_learning_rate);
	LOG4CXX_INFO(logger, "\tMaximum number of iterations: " << this->ann_max_epoch.value);
	LOG4CXX_INFO(logger, "\tMean squared error targeted: " << this->ann_mse_target);

	return 1;
}

const std::string CliParser::get_input_image() const
{
	return this->input_image;
}

const std::vector<std::string> CliParser::get_class_images() const
{
	return this->class_images;
}

const std::string CliParser::get_export_dir() const
{
	return this->export_dir;
}

const int CliParser::get_export_interval() const
{
	return this->export_interval;
}

const int CliParser::get_num_iter() const
{
	return this->num_iter;
}

const double CliParser::get_lambda1() const {
	return this->lambda1;
}

const double CliParser::get_lambda2() const {
	return this->lambda2;
}

const std::vector< unsigned int > CliParser::get_ann_hidden_layers() const {
	return this->ann_hidden_layers;
}

const float CliParser::get_ann_learning_rate() const {
	return this->ann_learning_rate;
}

const unsigned int CliParser::get_ann_max_epoch() const {
	return this->ann_max_epoch;
}

const float CliParser::get_ann_mse_target() const {
	return this->ann_mse_target;
}

<commit_msg>Wrong validation test for PositiveInteger in cli_parser.<commit_after>#include "cli_parser.h"

#include <boost/filesystem.hpp>
#include <iostream>
#include <sstream>
#include <vector>

#include "ParseUtils.h"

#include "log4cxx/logger.h"

namespace po = boost::program_options;

void validate(boost::any& v, const std::vector<std::string>& values, PositiveInteger*, int)
{
	po::validators::check_first_occurrence(v);
	const std::string& s = po::validators::get_single_string(values);

	unsigned int value;
	if( ParseUtils::ParseUInt(value, s.data(), 10) && value >= 0 )
	{
		v = boost::any(PositiveInteger(value));
	} else {
		throw po::invalid_option_value(s);
	}
}

void validate(boost::any& v, const std::vector<std::string>& values, StrictlyPositiveInteger*, int)
{
	po::validators::check_first_occurrence(v);
	const std::string& s = po::validators::get_single_string(values);

	unsigned int value;
	if( ParseUtils::ParseUInt(value, s.data(), 10) && value > 0 )
	{
		v = boost::any(StrictlyPositiveInteger(value));
	} else {
		throw po::invalid_option_value(s);
	}
}

void validate(boost::any& v, const std::vector<std::string>& values, Float*, int)
{
	po::validators::check_first_occurrence(v);
	const std::string& s = po::validators::get_single_string(values);

	float value;
	if( ParseUtils::ParseFloat(value, s.data()) )
	{
		v = boost::any(Float(value));
	} else {
		throw po::invalid_option_value(s);
	}
}

void validate(boost::any& v, const std::vector<std::string>& values, Double*, int)
{
	po::validators::check_first_occurrence(v);
	const std::string& s = po::validators::get_single_string(values);

	double value;
	if( ParseUtils::ParseDouble(value, s.data()) )
	{
		v = boost::any(Double(value));
	} else {
		throw po::invalid_option_value(s);
	}
}

template< typename TElemType >
std::ostream &operator<<(std::ostream &s, const std::vector< TElemType >& v)
{
	std::stringstream ss;
	if( !v.empty() )
	{

		typename std::vector< TElemType >::const_iterator it = v.begin(), begin = v.begin(), end = v.end();
		for( ; it < end; ++it )
		{
			if(it != begin)
				ss << " ";
			ss << *it;
		}
	}

	return s << ss.str();
}

CliParser::CliParser()
{}

int CliParser::parse_argv(int argc, char ** argv)
{
	log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger("main"));

	LOG4CXX_INFO(logger, "Parsing command line options");

	typedef std::vector< StrictlyPositiveInteger > HiddenLayerVector;

	po::options_description desc("Command line parameters");
	desc.add_options()
		("help,h",
			"Produce help message")
		("input-image,i",
			po::value< std::string >(&(this->input_image))->required(),
			"Input image (required)")
		("class-image,c",
			po::value< std::vector< std::string > >(&(this->class_images))->required(),
			"Defines a class to be learned from a binary image (at least 2 values required)")
		("export-dir,E",
			po::value< std::string >(&(this->export_dir))->required(),
			"Export directory")
		("export-interval,e",
			po::value< PositiveInteger >(&(this->export_interval))->default_value(0),
			"Export interval during regularization")
		("num-iter,n",
			po::value< PositiveInteger >(&(this->num_iter))->default_value(0),
			"Number of iterations for the regularization")
		("lambda1",
			po::value< Double >(&(this->lambda1))->default_value(1.0),
			"Lambda 1 parameter for regularization")
		("lambda2",
			po::value< Double >(&(this->lambda2))->default_value(1.0),
			"Lambda 2 parameter for regularization")
		("ann-hidden-layer",
			po::value< HiddenLayerVector >()->multitoken()->default_value(HiddenLayerVector(1, 3)),
			"Number of neurons per hidden layer (default: one layer of 3 neurons)")
		("ann-learning-rate",
			po::value< Float >(&(this->ann_learning_rate))->default_value(0.1),
			"Learning rate of the neural networks")
		("ann-max-epoch",
			po::value< StrictlyPositiveInteger >(&(this->ann_max_epoch))->default_value(1000),
			"Maximum number of learning iterations for the neural networks")
		("ann-mse-target",
			po::value< Float >(&(this->ann_mse_target))->default_value(0.0001),
			"Mean squared error targeted by the neural networks learning algorithm")
		;

	po::variables_map vm;

	try {
		po::store(po::command_line_parser(argc, argv).options(desc).run(), vm);

		// Handling --help before notify() in order to allow ->required()
		// http://stackoverflow.com/questions/5395503/required-and-optional-arguments-using-boost-library-program-options#answer-5517755
		if (vm.count("help")) {
			std::cout << "Usage: " << argv[0] << " [options]" << std::endl;
			std::cout << desc;
			return 0;
		}

		po::notify(vm);
	} catch(po::error &err) {
		LOG4CXX_FATAL(logger, err.what());
		return -1;
	}

	LOG4CXX_INFO(logger, "Input image: " << this->input_image);

	if(this->class_images.size() < 2)
	{
		LOG4CXX_FATAL(logger, "You need to provide at least two learning classes");
		return -1;
	} else {
		LOG4CXX_INFO(logger, this->class_images.size() << " learning classes provided");

		for(int i = 0; i < this->class_images.size(); ++i)
		{
			boost::filesystem::path path(this->input_image);
			if(!boost::filesystem::exists(path))
			{
				LOG4CXX_FATAL(logger, "Cannot load class image: \"" << this->class_images[i] << "\" does not exists");
				return -1;
			}

			LOG4CXX_INFO(logger, "Class " << (i + 1) << ": " << this->class_images[i]);
		}
	}

	HiddenLayerVector hidden_layers = vm["ann-hidden-layer"].as< HiddenLayerVector >();
	for(HiddenLayerVector::const_iterator it = hidden_layers.begin(); it < hidden_layers.end(); ++it) {
		this->ann_hidden_layers.push_back((*it).value);
	}

	LOG4CXX_INFO(logger, "Main parameters:");
	LOG4CXX_INFO(logger, "\tExport directory: " << this->export_dir);
	LOG4CXX_INFO(logger, "Regularization parameters:");
	LOG4CXX_INFO(logger, "\tExport interval: " << this->export_interval);
	LOG4CXX_INFO(logger, "\tNumber of iterations: " << this->num_iter);
	LOG4CXX_INFO(logger, "\tLambda2: " << this->lambda2);
	LOG4CXX_INFO(logger, "\tLambda1: " << this->lambda1);
	LOG4CXX_INFO(logger, "Neural networks parameters:");
	{
		std::stringstream m;
		m << this->ann_hidden_layers;
		LOG4CXX_INFO(logger, "\tNumber of hidden neurons per layer: " << m.str());
	}
	LOG4CXX_INFO(logger, "\tLearning rate: " << this->ann_learning_rate);
	LOG4CXX_INFO(logger, "\tMaximum number of iterations: " << this->ann_max_epoch.value);
	LOG4CXX_INFO(logger, "\tMean squared error targeted: " << this->ann_mse_target);

	return 1;
}

const std::string CliParser::get_input_image() const
{
	return this->input_image;
}

const std::vector<std::string> CliParser::get_class_images() const
{
	return this->class_images;
}

const std::string CliParser::get_export_dir() const
{
	return this->export_dir;
}

const int CliParser::get_export_interval() const
{
	return this->export_interval;
}

const int CliParser::get_num_iter() const
{
	return this->num_iter;
}

const double CliParser::get_lambda1() const {
	return this->lambda1;
}

const double CliParser::get_lambda2() const {
	return this->lambda2;
}

const std::vector< unsigned int > CliParser::get_ann_hidden_layers() const {
	return this->ann_hidden_layers;
}

const float CliParser::get_ann_learning_rate() const {
	return this->ann_learning_rate;
}

const unsigned int CliParser::get_ann_max_epoch() const {
	return this->ann_max_epoch;
}

const float CliParser::get_ann_mse_target() const {
	return this->ann_mse_target;
}

<|endoftext|>


<commit_before><commit_msg>Bugfix<commit_after><|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*
Authors:
Michael Berg <michael.berg@zalf.de>

Maintainers:
Currently maintained by the authors.

This file is part of the util library used by models created at the Institute of
Landscape Systems Analysis at the ZALF.
Copyright (C) Leibniz Centre for Agricultural Landscape Research (ZALF)
*/

#include <sstream>
#include <cmath>
#include <cassert>
#include <iostream>
#include <cstdlib>

/*!
 * @file date.cpp
 */

#include "date.h"

using namespace Tools;
using namespace std;

const std::vector<size_t>* Date::_dim()
{
	static vector<size_t> dim{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
	return &dim;
}

const std::vector<size_t>* Date::_ldim()
{
  static vector<size_t> dim {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  return &dim;
}

//const size_t Date::defaultRelativeBaseYear = 2000;

//! default constructor
Date::Date()
{
  _daysInMonth = isLeapYear() ? _ldim() : _dim();
}

Date::Date(const string& isoDateString)
{
	Date d = fromIsoDateString(isoDateString);
	_d = d.day();
	_m = d.month();
	_y = d.year();
  _daysInMonth = isLeapYear() ? _ldim() : _dim();
}

/*!
 * construct a date with a named month
 * @param day
 * @param month
 * @param year
 * @param useLeapYears date object will support leap yesrs
 */
Date::Date(size_t day,
					 Month month,
					 int year)
	: _d(day)
	, _m(month)
	, _y(year)
{
  _daysInMonth = isLeapYear() ? _ldim() : _dim();
	if(day > daysInMonth(month) || day == 0)
	{
		_d = _m = _y = 0;
	}
}

/*!
 * construct a date from number values
 * @param day
 * @param month
 * @param year
 * @param useLeapYears date object will support leap years
 */
Date::Date(size_t day,
					 size_t month,
					 int year,
					 bool isRelativeDate,
					 size_t relativeBaseYear)
	: _d(day)
	, _m(month)
	, _y(year)
	, _relativeBaseYear(relativeBaseYear)
	, _isRelativeDate(isRelativeDate)
{
  _daysInMonth = isLeapYear() ? _ldim() : _dim();
	if(month > 12 || month == 0 || day > daysInMonth(month) || day == 0)
	{
		_d = _m = _y = 0;
	}
}

Date Date::relativeDate(size_t day,
												size_t month,
												int deltaYears,
												size_t relativeYear)
{
	return Date(day, month, relativeYear + deltaYears, true, relativeYear);
}

Date Date::fromIsoDateString(const std::string& isoDateString)
{
	if(isoDateString.size() == 10)
	{
		auto year = stoul(isoDateString.substr(0, 4));
		auto month = stoul(isoDateString.substr(5, 2));
		auto day = stoul(isoDateString.substr(8, 2));
		//cout << day << "." << month << "." << year << endl;

		return year < 100
			? relativeDate(day, month, year)
			: Date(day, month, year);
	}
	return Date();
}

//! copy constructor
Date::Date(const Date& other)
	: _daysInMonth(other._daysInMonth)
	, _d(other._d)
	, _m(other._m)
	, _y(other._y)
	, _relativeBaseYear(other._relativeBaseYear)
	, _isRelativeDate(other._isRelativeDate)
{}

/*!
 * assignment operator, copies the argument
 * @param other the other date
 * @return this, with the copied argument
 */
Date& Date::operator=(const Date& other)
{
	_daysInMonth = other._daysInMonth;
	_d = other.day();
	_m = other.month();
	_y = other.year();
	_relativeBaseYear = other._relativeBaseYear;
	_isRelativeDate = other._isRelativeDate;
	return *this;
}

/*!
 * @param toDate
 * @return number of days to argument date, excluding the argument date
 * (thus 01.01.2000 to 01.01.2000 = 0 days)
 */
int Date::numberOfDaysTo(const Date& toDate) const
{
	assert((isRelativeDate() && toDate.isRelativeDate())
				 || (!isRelativeDate() && !toDate.isRelativeDate()));

	Date from(*this), to(toDate);
	bool reverse = from > to;
	if(reverse)
		from = toDate, to = *this;

	int nods = 0; //number of days
	if(from.year() == to.year() && from.month() == to.month())
		nods += to.day() - from.day();
	else
	{
		for(size_t y = from.year(); y <= to.year(); y++)
		{
			size_t startMonth = 1, endMonth = 12;
			if(y == from.year())
			{
				startMonth = from.month() + 1;
				nods += daysInMonth(from.month()) - from.day();
			}
			if(y == to.year())
			{
				endMonth = to.month() - 1;
				nods += to.day();
			}
			for(size_t m = startMonth; m >= 1 && m <= 12 && m <= endMonth; m++)
				nods += daysInMonth(m);
		}
	}

	return nods * (reverse ? -1 : 1);
}

Date Date::withDay(size_t d)
{
	Date t(*this);
	t.setDay(d);
	return t;
}

Date Date::withMonth(size_t m)
{
	Date t(*this);
	t.setMonth(m);
	return t;
}

Date Date::withYear(size_t y)
{
	Date t(*this);
	t.setYear(y);
	return t;
}

/*!
 * compare two dates
 * @param other the other date
 * @return true if 'this' date lies before the argument date
 */
bool Date::operator<(const Date& other) const
{
	bool t = day() < other.day();
	//month might be <=
	if(t)
	{
		t = month() <= other.month();
		if(t) //year might be <=
			return year() <= other.year();
		else //year has to be <
			return year() < other.year();
	}
	else
	{ //month has to be <
		t = month() < other.month();
		if(t) //year might be <=
			return year() <= other.year();
		else //year has to be <
			return year() < other.year();
	}

	return false;
}

std::string Date::toIsoDateString(const std::string& wrapInto) const
{
	ostringstream s;
	auto y = year() - (isRelativeDate() ? relativeBaseYear() : 0);

	s << wrapInto;
	if(isRelativeDate())
	{
		if(y < 10)
			s << "000";
		else if(y < 100)
			s << "00";
		else if(y < 1000)
			s << "0";
	}
	s << y
		<< "-" << (month() < 10 ? "0" : "") << month()
		<< "-" << (day() < 10 ? "0" : "") << day() << wrapInto;
	return s.str();
}

/*!
 * @param separator to use for delimit days, month, year
 * @return general string representation
 */
std::string Date::toString(const std::string& separator,
													 bool skipYear) const
{
	ostringstream s;
	s << (day() < 10 ? "0" : "") << day()
		<< separator << (month() < 10 ? "0" : "") << month();
	if(!skipYear)
	{
		if(isRelativeDate())
		{
			size_t deltaYears = year() - _relativeBaseYear;
			s << separator << "year"
				<< (deltaYears > 0 ? "+" : "");
			if(deltaYears != 0)
				s << deltaYears;
		}
		else
			s << separator << year();
	}
	return s.str();
}

/*!
 * @param days
 * @return a copy of 'this' date 'days' before
 */
Date Date::operator-(size_t days) const
{
	if(days < 0)
		return (*this) + (-days);

	Date cd(*this); //current date
	size_t ds = days; //days

	bool isRelativeDate = cd.isRelativeDate();
	size_t relativeBaseYear = cd.relativeBaseYear();

	while(true)
	{
		if(cd.day() <= ds)
		{
			ds -= cd.day();

			if(cd.month() == 1)
				cd = Date(31, dec, cd.year() - 1, isRelativeDate, relativeBaseYear);
			else
				cd = Date(cd.daysInMonth(cd.month() - 1), cd.month() - 1, cd.year(),
									isRelativeDate, relativeBaseYear);
		}
		else
		{
			cd.setDay(cd.day() - ds);
			break;
		}
	}

	return cd;
}

/*!
 * postfix --
 * decrement 'this' date by one day
 * @param dummy to distiguish prefix from postfix
 * @return the old 'this' before decrementation
 */
Date Date::operator--(int)
{
	Date d = *this;
	operator-=(1);
	return d;
}

/*!
 * @param days
 * @return date 'days' ahead of 'this' date
 */
Date Date::operator+(size_t days) const
{
	if(days < 0)
		return (*this) - (-days);

	Date cd(*this); //current date
	size_t ds = days; //days

	bool isRelativeDate = cd.isRelativeDate();
	size_t relativeBaseYear = cd.relativeBaseYear();

	while(true)
	{
		size_t delta = cd.daysInMonth(cd.month()) - cd.day() + 1;
		if(delta <= ds)
		{
			ds -= delta;

			if(cd.month() == 12)
				cd = Date(1, 1, cd.year() + 1, isRelativeDate, relativeBaseYear);
			else
				cd = Date(1, cd.month() + 1, cd.year(), isRelativeDate, relativeBaseYear);
		}
		else
		{
			cd.setDay(cd.day() + ds);
			break;
		}
	}

	return cd;
}

/*!
 * postfix ++
 * increment 'this' date by one day
 * @param dummy to distinguish prefix from postfix
 * @return old 'this' before incrementation
 */
Date Date::operator++(int)
{
	Date d = *this;
	operator+=(1);
	return d;
}

bool Date::isLeapYear() const
{
	return _y % 4 == 0 && (_y % 100 != 0 || _y % 400 == 0);
}

Date Date::toAbsoluteDate(size_t absYear, bool ignoreDeltaYears) const
{
	long int deltaYears = ignoreDeltaYears ? 0 : year() - _relativeBaseYear;
	return Date(day(), month(), absYear == 0 ? year() : absYear + deltaYears);
}

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

/*!
 * function testing the date class
 */
void Tools::testDate()
{
	assert(Date(1, 1, 2001).numberOfDaysTo(Date(2, 1, 2001)) == 1);
	assert(Date(1, 1, 2001).numberOfDaysTo(Date(1, 1, 2001)) == 0);
	assert(Date(1, 1, 2001).numberOfDaysTo(Date(1, 2, 2001)) == 31);

	assert(Date(1, 1, 2001) == Date(1, 1, 2001));
	assert(Date(1, 1, 2001) > Date(31, 12, 2000));
	assert(Date(1, 1, 2001) < Date(2, 1, 2001));
	assert(Date(1, 1, 2001) >= Date(1, 1, 2001));
	assert(Date(1, 1, 2001) >= Date(31, 12, 2000));
	assert(Date(1, 1, 2001) <= Date(1, 1, 2001));
	assert(Date(1, 1, 2001) <= Date(2, 1, 2001));

	Date t(5, 3, 200, true);
	assert(t - 5 == Date(29, 2, 2008));
	assert(t - 10 == Date(24, 2, 2008));
	assert(t - 20 == Date(14, 2, 2008));
	assert(t - 30 == Date(4, 2, 2008));
	assert(t - 100 == Date(26, 11, 2007));
	assert(t - 300 == Date(10, 5, 2007));
	assert(t - 400 == Date(30, 1, 2007));
	assert(t - 1000 == Date(9, 6, 2005));

	t = Date(25, 2, 2008);
	assert(t + 5 == Date(1, 3, 2008));
	assert(t + 10 == Date(6, 3, 2008));
	assert(t + 20 == Date(16, 3, 2008));
	assert(t + 30 == Date(26, 3, 2008));
	assert(t + 100 == Date(4, 6, 2008));
	assert(t + 300 == Date(21, 12, 2008));
	assert(t + 400 == Date(31, 3, 2009));
	assert(t + 1000 == Date(21, 11, 2010));
}
<commit_msg>fixed bug introduced in last change<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*
Authors:
Michael Berg <michael.berg@zalf.de>

Maintainers:
Currently maintained by the authors.

This file is part of the util library used by models created at the Institute of
Landscape Systems Analysis at the ZALF.
Copyright (C) Leibniz Centre for Agricultural Landscape Research (ZALF)
*/

#include <sstream>
#include <cmath>
#include <cassert>
#include <iostream>
#include <cstdlib>

/*!
 * @file date.cpp
 */

#include "date.h"

using namespace Tools;
using namespace std;

const std::vector<size_t>* Date::_dim()
{
	static vector<size_t> dim{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
	return &dim;
}

const std::vector<size_t>* Date::_ldim()
{
  static vector<size_t> dim {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  return &dim;
}

//const size_t Date::defaultRelativeBaseYear = 2000;

//! default constructor
Date::Date()
{
  _daysInMonth = isLeapYear() ? _ldim() : _dim();
}

Date::Date(const string& isoDateString)
{
	Date d = fromIsoDateString(isoDateString);
	_d = d.day();
	_m = d.month();
	_y = d.year();
  _daysInMonth = isLeapYear() ? _ldim() : _dim();
}

/*!
 * construct a date with a named month
 * @param day
 * @param month
 * @param year
 * @param useLeapYears date object will support leap yesrs
 */
Date::Date(size_t day,
					 Month month,
					 int year)
	: _d(day)
	, _m(month)
	, _y(year)
{
  _daysInMonth = isLeapYear() ? _ldim() : _dim();
	if(day > daysInMonth(month) || day == 0)
	{
		_d = _m = _y = 0;
	}
}

/*!
 * construct a date from number values
 * @param day
 * @param month
 * @param year
 * @param useLeapYears date object will support leap years
 */
Date::Date(size_t day,
					 size_t month,
					 int year,
					 bool isRelativeDate,
					 size_t relativeBaseYear)
	: _d(day)
	, _m(month)
	, _y(year)
	, _relativeBaseYear(relativeBaseYear)
	, _isRelativeDate(isRelativeDate)
{
  _daysInMonth = isLeapYear() ? _ldim() : _dim();
	if(month > 12 || month == 0 || day > daysInMonth(month) || day == 0)
	{
		_d = _m = _y = 0;
	}
}

Date Date::relativeDate(size_t day,
												size_t month,
												int deltaYears,
												size_t relativeYear)
{
	return Date(day, month, relativeYear + deltaYears, true, relativeYear);
}

Date Date::fromIsoDateString(const std::string& isoDateString)
{
	if(isoDateString.size() == 10)
	{
		auto year = stoul(isoDateString.substr(0, 4));
		auto month = stoul(isoDateString.substr(5, 2));
		auto day = stoul(isoDateString.substr(8, 2));
		//cout << day << "." << month << "." << year << endl;

		return year < 100
			? relativeDate(day, month, year)
			: Date(day, month, year);
	}
	return Date();
}

//! copy constructor
Date::Date(const Date& other)
	: _daysInMonth(other._daysInMonth)
	, _d(other._d)
	, _m(other._m)
	, _y(other._y)
	, _relativeBaseYear(other._relativeBaseYear)
	, _isRelativeDate(other._isRelativeDate)
{}

/*!
 * assignment operator, copies the argument
 * @param other the other date
 * @return this, with the copied argument
 */
Date& Date::operator=(const Date& other)
{
	_daysInMonth = other._daysInMonth;
	_d = other.day();
	_m = other.month();
	_y = other.year();
	_relativeBaseYear = other._relativeBaseYear;
	_isRelativeDate = other._isRelativeDate;
	return *this;
}

/*!
 * @param toDate
 * @return number of days to argument date, excluding the argument date
 * (thus 01.01.2000 to 01.01.2000 = 0 days)
 */
int Date::numberOfDaysTo(const Date& toDate) const
{
	assert((isRelativeDate() && toDate.isRelativeDate())
				 || (!isRelativeDate() && !toDate.isRelativeDate()));

	Date from(*this), to(toDate);
	bool reverse = from > to;
	if(reverse)
		from = toDate, to = *this;

	int nods = 0; //number of days
	if(from.year() == to.year() && from.month() == to.month())
		nods += to.day() - from.day();
	else
	{
		for(size_t y = from.year(); y <= to.year(); y++)
		{
			size_t startMonth = 1, endMonth = 12;
			if(y == from.year())
			{
				startMonth = from.month() + 1;
				nods += from.daysInMonth(from.month()) - from.day();
			}
			if(y == to.year())
			{
				endMonth = to.month() - 1;
				nods += to.day();
			}
			Date cy(1, 1, y); //current year, needed to count months in leap years correctly
			for(size_t m = startMonth; m >= 1 && m <= 12 && m <= endMonth; m++)
				nods += cy.daysInMonth(m);
		}
	}

	return nods * (reverse ? -1 : 1);
}

Date Date::withDay(size_t d)
{
	Date t(*this);
	t.setDay(d);
	return t;
}

Date Date::withMonth(size_t m)
{
	Date t(*this);
	t.setMonth(m);
	return t;
}

Date Date::withYear(size_t y)
{
	Date t(*this);
	t.setYear(y);
	return t;
}

/*!
 * compare two dates
 * @param other the other date
 * @return true if 'this' date lies before the argument date
 */
bool Date::operator<(const Date& other) const
{
	bool t = day() < other.day();
	//month might be <=
	if(t)
	{
		t = month() <= other.month();
		if(t) //year might be <=
			return year() <= other.year();
		else //year has to be <
			return year() < other.year();
	}
	else
	{ //month has to be <
		t = month() < other.month();
		if(t) //year might be <=
			return year() <= other.year();
		else //year has to be <
			return year() < other.year();
	}

	return false;
}

std::string Date::toIsoDateString(const std::string& wrapInto) const
{
	ostringstream s;
	auto y = year() - (isRelativeDate() ? relativeBaseYear() : 0);

	s << wrapInto;
	if(isRelativeDate())
	{
		if(y < 10)
			s << "000";
		else if(y < 100)
			s << "00";
		else if(y < 1000)
			s << "0";
	}
	s << y
		<< "-" << (month() < 10 ? "0" : "") << month()
		<< "-" << (day() < 10 ? "0" : "") << day() << wrapInto;
	return s.str();
}

/*!
 * @param separator to use for delimit days, month, year
 * @return general string representation
 */
std::string Date::toString(const std::string& separator,
													 bool skipYear) const
{
	ostringstream s;
	s << (day() < 10 ? "0" : "") << day()
		<< separator << (month() < 10 ? "0" : "") << month();
	if(!skipYear)
	{
		if(isRelativeDate())
		{
			size_t deltaYears = year() - _relativeBaseYear;
			s << separator << "year"
				<< (deltaYears > 0 ? "+" : "");
			if(deltaYears != 0)
				s << deltaYears;
		}
		else
			s << separator << year();
	}
	return s.str();
}

/*!
 * @param days
 * @return a copy of 'this' date 'days' before
 */
Date Date::operator-(size_t days) const
{
	if(days < 0)
		return (*this) + (-days);

	Date cd(*this); //current date
	size_t ds = days; //days

	bool isRelativeDate = cd.isRelativeDate();
	size_t relativeBaseYear = cd.relativeBaseYear();

	while(true)
	{
		if(cd.day() <= ds)
		{
			ds -= cd.day();

			if(cd.month() == 1)
				cd = Date(31, dec, cd.year() - 1, isRelativeDate, relativeBaseYear);
			else
				cd = Date(cd.daysInMonth(cd.month() - 1), cd.month() - 1, cd.year(),
									isRelativeDate, relativeBaseYear);
		}
		else
		{
			cd.setDay(cd.day() - ds);
			break;
		}
	}

	return cd;
}

/*!
 * postfix --
 * decrement 'this' date by one day
 * @param dummy to distiguish prefix from postfix
 * @return the old 'this' before decrementation
 */
Date Date::operator--(int)
{
	Date d = *this;
	operator-=(1);
	return d;
}

/*!
 * @param days
 * @return date 'days' ahead of 'this' date
 */
Date Date::operator+(size_t days) const
{
	if(days < 0)
		return (*this) - (-days);

	Date cd(*this); //current date
	size_t ds = days; //days

	bool isRelativeDate = cd.isRelativeDate();
	size_t relativeBaseYear = cd.relativeBaseYear();

	while(true)
	{
		size_t delta = cd.daysInMonth(cd.month()) - cd.day() + 1;
		if(delta <= ds)
		{
			ds -= delta;

			if(cd.month() == 12)
				cd = Date(1, 1, cd.year() + 1, isRelativeDate, relativeBaseYear);
			else
				cd = Date(1, cd.month() + 1, cd.year(), isRelativeDate, relativeBaseYear);
		}
		else
		{
			cd.setDay(cd.day() + ds);
			break;
		}
	}

	return cd;
}

/*!
 * postfix ++
 * increment 'this' date by one day
 * @param dummy to distinguish prefix from postfix
 * @return old 'this' before incrementation
 */
Date Date::operator++(int)
{
	Date d = *this;
	operator+=(1);
	return d;
}

bool Date::isLeapYear() const
{
	return _y % 4 == 0 && (_y % 100 != 0 || _y % 400 == 0);
}

Date Date::toAbsoluteDate(size_t absYear, bool ignoreDeltaYears) const
{
	long int deltaYears = ignoreDeltaYears ? 0 : year() - _relativeBaseYear;
	return Date(day(), month(), absYear == 0 ? year() : absYear + deltaYears);
}

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

/*!
 * function testing the date class
 */
void Tools::testDate()
{
	assert(Date(1, 1, 2001).numberOfDaysTo(Date(2, 1, 2001)) == 1);
	assert(Date(1, 1, 2001).numberOfDaysTo(Date(1, 1, 2001)) == 0);
	assert(Date(1, 1, 2001).numberOfDaysTo(Date(1, 2, 2001)) == 31);

	assert(Date(1, 1, 2001) == Date(1, 1, 2001));
	assert(Date(1, 1, 2001) > Date(31, 12, 2000));
	assert(Date(1, 1, 2001) < Date(2, 1, 2001));
	assert(Date(1, 1, 2001) >= Date(1, 1, 2001));
	assert(Date(1, 1, 2001) >= Date(31, 12, 2000));
	assert(Date(1, 1, 2001) <= Date(1, 1, 2001));
	assert(Date(1, 1, 2001) <= Date(2, 1, 2001));

	Date t(5, 3, 200, true);
	assert(t - 5 == Date(29, 2, 2008));
	assert(t - 10 == Date(24, 2, 2008));
	assert(t - 20 == Date(14, 2, 2008));
	assert(t - 30 == Date(4, 2, 2008));
	assert(t - 100 == Date(26, 11, 2007));
	assert(t - 300 == Date(10, 5, 2007));
	assert(t - 400 == Date(30, 1, 2007));
	assert(t - 1000 == Date(9, 6, 2005));

	t = Date(25, 2, 2008);
	assert(t + 5 == Date(1, 3, 2008));
	assert(t + 10 == Date(6, 3, 2008));
	assert(t + 20 == Date(16, 3, 2008));
	assert(t + 30 == Date(26, 3, 2008));
	assert(t + 100 == Date(4, 6, 2008));
	assert(t + 300 == Date(21, 12, 2008));
	assert(t + 400 == Date(31, 3, 2009));
	assert(t + 1000 == Date(21, 11, 2010));
}
<|endoftext|>