<commit_before>namespace mant {
  template <typename T, typename U = double>
  class OptimisationProblem : public Printable {
    static_assert(arma::is_supported_elem_type<T>::value, "The parameter type T must be supported by Armadillo C++, i.e. an arithmetic types, except bool.");
    static_assert(std::is_floating_point<U>::value, "The codomain type U must be a floating point type.");

    public:
      const std::size_t numberOfDimensions_;

      explicit OptimisationProblem(
        const std::size_t numberOfDimensions) noexcept;

      void setLowerBounds(
        const arma::Col<T>& lowerBounds);

      void setUpperBounds(
        const arma::Col<T>& upperBounds);

      arma::Col<T> getLowerBounds() const noexcept;

      arma::Col<T> getUpperBounds() const noexcept;

      U getSoftConstraintsValue(
        const arma::Col<T>& parameter);

      arma::Col<unsigned int> isWithinLowerBounds(
        const arma::Col<T>& parameter);

      arma::Col<unsigned int> isWithinUpperBounds(
        const arma::Col<T>& parameter);

      bool isSatisfyingSoftConstraints(
        const arma::Col<T>& parameter);

      bool isSatisfyingConstraints(
        const arma::Col<T>& parameter);

      void setParameterPermutation(
          const arma::Col<unsigned int>& parameterPermutation);

      void setParameterScaling(
        const arma::Col<T>& parameterScaling);

      void setParameterTranslation(
          const arma::Col<T>& parameterTranslation);

      void setParameterRotation(
        const arma::Mat<T>& parameterRotation);

      void setObjectiveValueScaling(
        const U objectiveValueScaling) noexcept;

      void setObjectiveValueTranslation(
        const U objectiveValueTranslation) noexcept;

      void setAcceptableObjectiveValue(
          const U acceptableObjectiveValue) noexcept;

      U getAcceptableObjectiveValue() const noexcept;

      U getObjectiveValue(
        const arma::Col<T>& parameter);

      unsigned long long getNumberOfEvaluations() const noexcept;

      unsigned long long getNumberOfDistinctEvaluations() const noexcept;

      void reset() noexcept;

      std::unordered_map<arma::Col<T>, U, Hash<T>, IsEqual<T>> getCachedObjectiveValues() const noexcept;

      virtual ~OptimisationProblem() = default;

    protected:
      arma::Col<T> lowerBounds_;
      arma::Col<T> upperBounds_;

      arma::Col<unsigned int> parameterPermutation_;
      arma::Col<T> parameterScaling_;
      arma::Col<T> parameterTranslation_;
      arma::Mat<T> parameterRotation_;

      U objectiveValueScaling_;
      U objectiveValueTranslation_;

      U acceptableObjectiveValue_;

      unsigned long long numberOfEvaluations_;
      unsigned long long numberOfDistinctEvaluations_;

      arma::Col<T> getDiversifiedParameter(
        const arma::Col<T>& parameter) const noexcept;

      virtual U getSoftConstraintsValueImplementation(
        const arma::Col<T>& parameter) const noexcept;

      virtual U getObjectiveValueImplementation(
        const arma::Col<T>& parameter) const noexcept = 0;

      std::unordered_map<arma::Col<T>, U, Hash<T>, IsEqual<T>> cachedObjectiveValues_;

#if defined(MANTELLA_USE_PARALLEL_ALGORITHMS)
      // Grants direct access to the otherwise hidden .serialise() and .deserialise(...) methods.
      friend class OptimisationAlgorithm;

      // The type is intentionally fixed to ease usage with MPI_DOUBLE.
      std::vector<double> serialise() const noexcept;

      // The type is intentionally fixed to ease usage with MPI_DOUBLE.
      void deserialise(
          const std::vector<double>& serialisedOptimisationProblem);
#endif
  };

  //
  // Implementation
  //

  template <typename T, typename U>
  OptimisationProblem<T, U>::OptimisationProblem(
      const std::size_t numberOfDimensions) noexcept
    : numberOfDimensions_(numberOfDimensions) {
    reset();

    // A vector with all elements set to the lowest representable value.
    setLowerBounds(arma::zeros<arma::Col<T>>(numberOfDimensions_) - std::numeric_limits<T>::max());
    // A vector with all elements set to the largest representable value.
    setUpperBounds(arma::zeros<arma::Col<T>>(numberOfDimensions_) + std::numeric_limits<T>::max());

    // (0, ..., numberOfDimensions - 1)
    setParameterPermutation(arma::linspace<arma::Col<unsigned int>>(0u, numberOfDimensions_ - 1u, numberOfDimensions));

    if (std::is_floating_point<T>::value) {
      setParameterScaling(arma::ones<arma::Col<T>>(numberOfDimensions_));
      setParameterTranslation(arma::zeros<arma::Col<T>>(numberOfDimensions_));
      setParameterRotation(arma::eye<arma::Mat<T>>(numberOfDimensions_, numberOfDimensions_));
    }

    setObjectiveValueScaling(static_cast<U>(1.0L));
    setObjectiveValueTranslation(static_cast<U>(0.0L));
    setAcceptableObjectiveValue(std::numeric_limits<U>::lowest());
  }

  template <typename T, typename U>
  void OptimisationProblem<T, U>::setLowerBounds(
      const arma::Col<T>& lowerBounds) {
    verify(lowerBounds.n_elem == numberOfDimensions_, "The number of elements must be equal to the number of dimensions.");

    lowerBounds_ = lowerBounds;
  }

  template <typename T, typename U>
  void OptimisationProblem<T, U>::setUpperBounds(
      const arma::Col<T>& upperBounds) {
    verify(upperBounds.n_elem == numberOfDimensions_, "The number of elements must be equal to the number of dimensions.");

    upperBounds_ = upperBounds;
  }

  template <typename T, typename U>
  arma::Col<T> OptimisationProblem<T, U>::getLowerBounds() const noexcept {
    return lowerBounds_;
  }

  template <typename T, typename U>
  arma::Col<T> OptimisationProblem<T, U>::getUpperBounds() const noexcept {
    return upperBounds_;
  }

  template <typename T, typename U>
  U OptimisationProblem<T, U>::getSoftConstraintsValue(
      const arma::Col<T>& parameter) {
    verify(parameter.n_elem == numberOfDimensions_, "The number of elements must be equal to the number of dimensions.");

    const U& softConstraintValue = getSoftConstraintsValueImplementation(parameter);

    // All soft-constraint values must be greater than or equal to 0.
    assert(softConstraintValue >= static_cast<U>(0.0L));

    return objectiveValueScaling_ * softConstraintValue;
  }

  template <typename T, typename U>
  arma::Col<unsigned int> OptimisationProblem<T, U>::isWithinLowerBounds(
      const arma::Col<T>& parameter) {
    verify(parameter.n_elem == numberOfDimensions_, "The number of elements must be equal to the number of dimensions.");

    return parameter < lowerBounds_;
  }

  template <typename T, typename U>
  arma::Col<unsigned int> OptimisationProblem<T, U>::isWithinUpperBounds(
      const arma::Col<T>& parameter) {
    verify(parameter.n_elem == numberOfDimensions_, "The number of elements must be equal to the number of dimensions.");

    return  parameter > upperBounds_;
  }

  template <typename T, typename U>
  bool OptimisationProblem<T, U>::isSatisfyingSoftConstraints(
      const arma::Col<T>& parameter) {
    verify(parameter.n_elem == numberOfDimensions_, "The number of elements must be equal to the number of dimensions.");

    return (getSoftConstraintsValue(parameter) == static_cast<U>(0.0L));
  }

  template <typename T, typename U>
  bool OptimisationProblem<T, U>::isSatisfyingConstraints(
      const arma::Col<T>& parameter) {
    verify(parameter.n_elem == numberOfDimensions_, "The number of elements must be equal to the number of dimensions.");

    return (!arma::any(isWithinLowerBounds(parameter)) && !arma::any(isWithinUpperBounds(parameter)) && isSatisfyingSoftConstraints(parameter));
  }

  template <typename T, typename U>
  void OptimisationProblem<T, U>::setParameterPermutation(
      const arma::Col<unsigned int>& parameterPermutation) {
    verify(parameterPermutation.n_elem == numberOfDimensions_, "The number of elements must be equal to the number of dimensions");
    verify(isPermutation(parameterPermutation, 0u, numberOfDimensions_ - 1u), "The parameter must be a permutation.");

    parameterPermutation_ = parameterPermutation;

    // Resets all counters and caches, as the problem could be changed.
    reset();
  }

  template <typename T, typename U>
  void OptimisationProblem<T, U>::setParameterScaling(
      const arma::Col<T>& parameterScaling) {
    verify(parameterScaling.n_elem == numberOfDimensions_, "The number of elements must be equal to the number of dimensions.");

    parameterScaling_ = parameterScaling;

    // Resets all counters and caches, as the problem could be changed.
    reset();
  }

  template <typename T, typename U>
  void OptimisationProblem<T, U>::setParameterTranslation(
      const arma::Col<T>& parameterTranslation) {
    verify(parameterTranslation.n_elem == numberOfDimensions_, "The number of elements must be equal to the number of dimensions.");

    parameterTranslation_ = parameterTranslation;

    // Resets all counters and caches, as the problem could be changed.
    reset();
  }

  template <typename T, typename U>
  void OptimisationProblem<T, U>::setParameterRotation(
      const arma::Mat<T>& parameterRotation) {
    verify(parameterRotation.n_rows == numberOfDimensions_, "The number of rows must be equal to the number of dimensions.");
    verify(isRotationMatrix(parameterRotation), "The parameter must be a rotation matrix.");

    parameterRotation_ = parameterRotation;

    // Resets all counters and caches, as the problem could be changed.
    reset();
  }

  template <typename T, typename U>
  void OptimisationProblem<T, U>::OptimisationProblem::setObjectiveValueScaling(
      const U objectiveValueScaling) noexcept {
    objectiveValueScaling_ = objectiveValueScaling;

    // Resets all counters and caches, as the problem could be changed.
    reset();
  }

  template <typename T, typename U>
  void OptimisationProblem<T, U>::setObjectiveValueTranslation(
      const U objectiveValueTranslation) noexcept {
    objectiveValueTranslation_ = objectiveValueTranslation;

    // Resets all counters and caches, as the problem could be changed.
    reset();
  }

  template <typename T, typename U>
  void OptimisationProblem<T, U>::setAcceptableObjectiveValue(
      const U acceptableObjectiveValue) noexcept {
    acceptableObjectiveValue_ = acceptableObjectiveValue;
  }

  template <typename T, typename U>
  U OptimisationProblem<T, U>::getAcceptableObjectiveValue() const noexcept {
    return acceptableObjectiveValue_;
  }

  template <typename T, typename U>
  U OptimisationProblem<T, U>::getObjectiveValue(
      const arma::Col<T>& parameter)
  {
    verify(parameter.n_elem == numberOfDimensions_, "The number of elements must be equal to the number of dimensions.");

    // Always increase the number of evaluations.
    ++numberOfEvaluations_;

#if defined(MANTELLA_USE_CACHES)
    // Check if the result is already cached.
    const auto& index = cachedObjectiveValues_.find(parameter);
    if (index == cachedObjectiveValues_.cend()) {
      // Increase the number of distinct evaluations only if we actually compute the value.
      ++numberOfDistinctEvaluations_;

      const U& result = objectiveValueScaling_ * getObjectiveValueImplementation(getDiversifiedParameter(parameter)) + objectiveValueTranslation_;

      cachedObjectiveValues_.insert({parameter, result});
      return result;
    } else {
      return index->second;
    }
#else
    // Without caching, all function evaluations must be computed.
    ++numberOfDistinctEvaluations_;

    return objectiveValueScaling_ * getObjectiveValueImplementation(getDiversifiedParameter(parameter)) + objectiveValueTranslation_;
#endif
  }

  template <typename T, typename U>
  unsigned long long OptimisationProblem<T, U>::getNumberOfEvaluations() const noexcept {
    return numberOfEvaluations_;
  }

  template <typename T, typename U>
  unsigned long long OptimisationProblem<T, U>::getNumberOfDistinctEvaluations() const noexcept {
    return numberOfDistinctEvaluations_;
  }

  template <typename T, typename U>
  void OptimisationProblem<T, U>::reset() noexcept {
    numberOfEvaluations_ = 0llu;
    numberOfDistinctEvaluations_ = 0llu;

    cachedObjectiveValues_.clear();
  }

  template <typename T, typename U>
  std::unordered_map<arma::Col<T>, U, Hash<T>, IsEqual<T>> OptimisationProblem<T, U>::getCachedObjectiveValues() const noexcept {
    return cachedObjectiveValues_;
  }

  template <typename T, typename U>
  arma::Col<T> OptimisationProblem<T, U>::getDiversifiedParameter(
      const arma::Col<T>& parameter) const noexcept {
    assert(parameter.n_elem == numberOfDimensions_);

    if (std::is_floating_point<T>::value) {
      // For continuous problems, parameter is firstly permuted, than scaled, translated and lastly rotated.
      return parameterRotation_ * (parameterScaling_ % parameter.elem(parameterPermutation_) - parameterTranslation_);
    } else {
      // For discrete problems, the parameter is only permuted.
      return parameter.elem(parameterPermutation_);
    }
  }

  template <typename T, typename U>
  U OptimisationProblem<T, U>::getSoftConstraintsValueImplementation(
      const arma::Col<T>& parameter) const noexcept {
    assert(parameter.n_elem == numberOfDimensions_);

    return 0.0;
  }

#if defined(MANTELLA_USE_PARALLEL_ALGORITHMS)
  template <typename T, typename U>
  std::vector<double> OptimisationProblem<T, U>::serialise() const noexcept {
    std::vector<double> serialisedOptimisationProblem;

    for(std::size_t n = 0; n < lowerBounds_.n_elem; ++n) {
      serialisedOptimisationProblem.push_back(lowerBounds_(n));
    }

    for(std::size_t n = 0; n < upperBounds_.n_elem; ++n) {
      serialisedOptimisationProblem.push_back(upperBounds_(n));
    }

    for(std::size_t n = 0; n < parameterPermutation_.n_elem; ++n) {
      serialisedOptimisationProblem.push_back(parameterPermutation_(n));
    }

    if (std::is_floating_point<T>::value) {
      for(std::size_t n = 0; n < parameterScaling_.n_elem; ++n) {
        serialisedOptimisationProblem.push_back(parameterScaling_(n));
      }

      for(std::size_t n = 0; n < parameterTranslation_.n_elem; ++n) {
        serialisedOptimisationProblem.push_back(parameterTranslation_(n));
      }

      for(std::size_t n = 0; n < parameterRotation_.n_elem; ++n) {
        serialisedOptimisationProblem.push_back(parameterRotation_(n));
      }
    }

    serialisedOptimisationProblem.push_back(objectiveValueScaling_);
    serialisedOptimisationProblem.push_back(objectiveValueTranslation_);

    serialisedOptimisationProblem.push_back(acceptableObjectiveValue_);

    return serialisedOptimisationProblem;
  }

  template <typename T, typename U>
  void OptimisationProblem<T, U>::deserialise(
      const std::vector<double>& serialisedOptimisationProblem) {
    lowerBounds_.set_size(this->numberOfDimensions_);
    for(std::size_t n = 0; n < lowerBounds_.n_elem; ++n) {
      lowerBounds_(n) = serialisedOptimisationProblem.pop_back();
    }

    upperBounds_.set_size(this->numberOfDimensions_);
    for(std::size_t n = 0; n < upperBounds_.n_elem; ++n) {
      upperBounds_(n) = serialisedOptimisationProblem.pop_back();
    }

    parameterPermutation_.set_size(this->numberOfDimensions_);
    for(std::size_t n = 0; n < parameterPermutation_.n_elem; ++n) {
      parameterPermutation_(n) = serialisedOptimisationProblem.pop_back();
    }

    if (std::is_floating_point<T>::value) {
      parameterScaling_.set_size(this->numberOfDimensions_);
      for(std::size_t n = 0; n < parameterScaling_.n_elem; ++n) {
        parameterScaling_(n) = serialisedOptimisationProblem.pop_back();
      }

      parameterTranslation_.set_size(this->numberOfDimensions_);
      for(std::size_t n = 0; n < parameterTranslation_.n_elem; ++n) {
        parameterTranslation_(n) = serialisedOptimisationProblem.pop_back();
      }

      parameterRotation_.set_size(this->numberOfDimensions_);
      for(std::size_t n = 0; n < parameterRotation_.n_elem; ++n) {
        parameterRotation_(n) = serialisedOptimisationProblem.pop_back();
      }
    }

    objectiveValueScaling_ = serialisedOptimisationProblem.pop_back();
    objectiveValueTranslation_ = serialisedOptimisationProblem.pop_back();

    acceptableObjectiveValue_ = serialisedOptimisationProblem.pop_back();
  }
#endif
}
<commit_msg>Remove (unnecessary) references for primitive types<commit_after>namespace mant {
  template <typename T, typename U = double>
  class OptimisationProblem : public Printable {
    static_assert(arma::is_supported_elem_type<T>::value, "The parameter type T must be supported by Armadillo C++, i.e. an arithmetic types, except bool.");
    static_assert(std::is_floating_point<U>::value, "The codomain type U must be a floating point type.");

    public:
      const std::size_t numberOfDimensions_;

      explicit OptimisationProblem(
        const std::size_t numberOfDimensions) noexcept;

      void setLowerBounds(
        const arma::Col<T>& lowerBounds);

      void setUpperBounds(
        const arma::Col<T>& upperBounds);

      arma::Col<T> getLowerBounds() const noexcept;

      arma::Col<T> getUpperBounds() const noexcept;

      U getSoftConstraintsValue(
        const arma::Col<T>& parameter);

      arma::Col<unsigned int> isWithinLowerBounds(
        const arma::Col<T>& parameter);

      arma::Col<unsigned int> isWithinUpperBounds(
        const arma::Col<T>& parameter);

      bool isSatisfyingSoftConstraints(
        const arma::Col<T>& parameter);

      bool isSatisfyingConstraints(
        const arma::Col<T>& parameter);

      void setParameterPermutation(
          const arma::Col<unsigned int>& parameterPermutation);

      void setParameterScaling(
        const arma::Col<T>& parameterScaling);

      void setParameterTranslation(
          const arma::Col<T>& parameterTranslation);

      void setParameterRotation(
        const arma::Mat<T>& parameterRotation);

      void setObjectiveValueScaling(
        const U objectiveValueScaling) noexcept;

      void setObjectiveValueTranslation(
        const U objectiveValueTranslation) noexcept;

      void setAcceptableObjectiveValue(
          const U acceptableObjectiveValue) noexcept;

      U getAcceptableObjectiveValue() const noexcept;

      U getObjectiveValue(
        const arma::Col<T>& parameter);

      unsigned long long getNumberOfEvaluations() const noexcept;

      unsigned long long getNumberOfDistinctEvaluations() const noexcept;

      void reset() noexcept;

      std::unordered_map<arma::Col<T>, U, Hash<T>, IsEqual<T>> getCachedObjectiveValues() const noexcept;

      virtual ~OptimisationProblem() = default;

    protected:
      arma::Col<T> lowerBounds_;
      arma::Col<T> upperBounds_;

      arma::Col<unsigned int> parameterPermutation_;
      arma::Col<T> parameterScaling_;
      arma::Col<T> parameterTranslation_;
      arma::Mat<T> parameterRotation_;

      U objectiveValueScaling_;
      U objectiveValueTranslation_;

      U acceptableObjectiveValue_;

      unsigned long long numberOfEvaluations_;
      unsigned long long numberOfDistinctEvaluations_;

      arma::Col<T> getDiversifiedParameter(
        const arma::Col<T>& parameter) const noexcept;

      virtual U getSoftConstraintsValueImplementation(
        const arma::Col<T>& parameter) const noexcept;

      virtual U getObjectiveValueImplementation(
        const arma::Col<T>& parameter) const noexcept = 0;

      std::unordered_map<arma::Col<T>, U, Hash<T>, IsEqual<T>> cachedObjectiveValues_;

#if defined(MANTELLA_USE_PARALLEL_ALGORITHMS)
      // Grants direct access to the otherwise hidden .serialise() and .deserialise(...) methods.
      friend class OptimisationAlgorithm;

      // The type is intentionally fixed to ease usage with MPI_DOUBLE.
      std::vector<double> serialise() const noexcept;

      // The type is intentionally fixed to ease usage with MPI_DOUBLE.
      void deserialise(
          const std::vector<double>& serialisedOptimisationProblem);
#endif
  };

  //
  // Implementation
  //

  template <typename T, typename U>
  OptimisationProblem<T, U>::OptimisationProblem(
      const std::size_t numberOfDimensions) noexcept
    : numberOfDimensions_(numberOfDimensions) {
    reset();

    // A vector with all elements set to the lowest representable value.
    setLowerBounds(arma::zeros<arma::Col<T>>(numberOfDimensions_) - std::numeric_limits<T>::max());
    // A vector with all elements set to the largest representable value.
    setUpperBounds(arma::zeros<arma::Col<T>>(numberOfDimensions_) + std::numeric_limits<T>::max());

    // (0, ..., numberOfDimensions - 1)
    setParameterPermutation(arma::linspace<arma::Col<unsigned int>>(0u, numberOfDimensions_ - 1u, numberOfDimensions));

    if (std::is_floating_point<T>::value) {
      setParameterScaling(arma::ones<arma::Col<T>>(numberOfDimensions_));
      setParameterTranslation(arma::zeros<arma::Col<T>>(numberOfDimensions_));
      setParameterRotation(arma::eye<arma::Mat<T>>(numberOfDimensions_, numberOfDimensions_));
    }

    setObjectiveValueScaling(static_cast<U>(1.0L));
    setObjectiveValueTranslation(static_cast<U>(0.0L));
    setAcceptableObjectiveValue(std::numeric_limits<U>::lowest());
  }

  template <typename T, typename U>
  void OptimisationProblem<T, U>::setLowerBounds(
      const arma::Col<T>& lowerBounds) {
    verify(lowerBounds.n_elem == numberOfDimensions_, "The number of elements must be equal to the number of dimensions.");

    lowerBounds_ = lowerBounds;
  }

  template <typename T, typename U>
  void OptimisationProblem<T, U>::setUpperBounds(
      const arma::Col<T>& upperBounds) {
    verify(upperBounds.n_elem == numberOfDimensions_, "The number of elements must be equal to the number of dimensions.");

    upperBounds_ = upperBounds;
  }

  template <typename T, typename U>
  arma::Col<T> OptimisationProblem<T, U>::getLowerBounds() const noexcept {
    return lowerBounds_;
  }

  template <typename T, typename U>
  arma::Col<T> OptimisationProblem<T, U>::getUpperBounds() const noexcept {
    return upperBounds_;
  }

  template <typename T, typename U>
  U OptimisationProblem<T, U>::getSoftConstraintsValue(
      const arma::Col<T>& parameter) {
    verify(parameter.n_elem == numberOfDimensions_, "The number of elements must be equal to the number of dimensions.");

    const U softConstraintValue = getSoftConstraintsValueImplementation(parameter);

    // All soft-constraint values must be greater than or equal to 0.
    assert(softConstraintValue >= static_cast<U>(0.0L));

    return objectiveValueScaling_ * softConstraintValue;
  }

  template <typename T, typename U>
  arma::Col<unsigned int> OptimisationProblem<T, U>::isWithinLowerBounds(
      const arma::Col<T>& parameter) {
    verify(parameter.n_elem == numberOfDimensions_, "The number of elements must be equal to the number of dimensions.");

    return parameter < lowerBounds_;
  }

  template <typename T, typename U>
  arma::Col<unsigned int> OptimisationProblem<T, U>::isWithinUpperBounds(
      const arma::Col<T>& parameter) {
    verify(parameter.n_elem == numberOfDimensions_, "The number of elements must be equal to the number of dimensions.");

    return  parameter > upperBounds_;
  }

  template <typename T, typename U>
  bool OptimisationProblem<T, U>::isSatisfyingSoftConstraints(
      const arma::Col<T>& parameter) {
    verify(parameter.n_elem == numberOfDimensions_, "The number of elements must be equal to the number of dimensions.");

    return (getSoftConstraintsValue(parameter) == static_cast<U>(0.0L));
  }

  template <typename T, typename U>
  bool OptimisationProblem<T, U>::isSatisfyingConstraints(
      const arma::Col<T>& parameter) {
    verify(parameter.n_elem == numberOfDimensions_, "The number of elements must be equal to the number of dimensions.");

    return (!arma::any(isWithinLowerBounds(parameter)) && !arma::any(isWithinUpperBounds(parameter)) && isSatisfyingSoftConstraints(parameter));
  }

  template <typename T, typename U>
  void OptimisationProblem<T, U>::setParameterPermutation(
      const arma::Col<unsigned int>& parameterPermutation) {
    verify(parameterPermutation.n_elem == numberOfDimensions_, "The number of elements must be equal to the number of dimensions");
    verify(isPermutation(parameterPermutation, 0u, numberOfDimensions_ - 1u), "The parameter must be a permutation.");

    parameterPermutation_ = parameterPermutation;

    // Resets all counters and caches, as the problem could be changed.
    reset();
  }

  template <typename T, typename U>
  void OptimisationProblem<T, U>::setParameterScaling(
      const arma::Col<T>& parameterScaling) {
    verify(parameterScaling.n_elem == numberOfDimensions_, "The number of elements must be equal to the number of dimensions.");

    parameterScaling_ = parameterScaling;

    // Resets all counters and caches, as the problem could be changed.
    reset();
  }

  template <typename T, typename U>
  void OptimisationProblem<T, U>::setParameterTranslation(
      const arma::Col<T>& parameterTranslation) {
    verify(parameterTranslation.n_elem == numberOfDimensions_, "The number of elements must be equal to the number of dimensions.");

    parameterTranslation_ = parameterTranslation;

    // Resets all counters and caches, as the problem could be changed.
    reset();
  }

  template <typename T, typename U>
  void OptimisationProblem<T, U>::setParameterRotation(
      const arma::Mat<T>& parameterRotation) {
    verify(parameterRotation.n_rows == numberOfDimensions_, "The number of rows must be equal to the number of dimensions.");
    verify(isRotationMatrix(parameterRotation), "The parameter must be a rotation matrix.");

    parameterRotation_ = parameterRotation;

    // Resets all counters and caches, as the problem could be changed.
    reset();
  }

  template <typename T, typename U>
  void OptimisationProblem<T, U>::OptimisationProblem::setObjectiveValueScaling(
      const U objectiveValueScaling) noexcept {
    objectiveValueScaling_ = objectiveValueScaling;

    // Resets all counters and caches, as the problem could be changed.
    reset();
  }

  template <typename T, typename U>
  void OptimisationProblem<T, U>::setObjectiveValueTranslation(
      const U objectiveValueTranslation) noexcept {
    objectiveValueTranslation_ = objectiveValueTranslation;

    // Resets all counters and caches, as the problem could be changed.
    reset();
  }

  template <typename T, typename U>
  void OptimisationProblem<T, U>::setAcceptableObjectiveValue(
      const U acceptableObjectiveValue) noexcept {
    acceptableObjectiveValue_ = acceptableObjectiveValue;
  }

  template <typename T, typename U>
  U OptimisationProblem<T, U>::getAcceptableObjectiveValue() const noexcept {
    return acceptableObjectiveValue_;
  }

  template <typename T, typename U>
  U OptimisationProblem<T, U>::getObjectiveValue(
      const arma::Col<T>& parameter)
  {
    verify(parameter.n_elem == numberOfDimensions_, "The number of elements must be equal to the number of dimensions.");

    // Always increase the number of evaluations.
    ++numberOfEvaluations_;

#if defined(MANTELLA_USE_CACHES)
    // Check if the result is already cached.
    const auto& index = cachedObjectiveValues_.find(parameter);
    if (index == cachedObjectiveValues_.cend()) {
      // Increase the number of distinct evaluations only if we actually compute the value.
      ++numberOfDistinctEvaluations_;

      const U result = objectiveValueScaling_ * getObjectiveValueImplementation(getDiversifiedParameter(parameter)) + objectiveValueTranslation_;

      cachedObjectiveValues_.insert({parameter, result});
      return result;
    } else {
      return index->second;
    }
#else
    // Without caching, all function evaluations must be computed.
    ++numberOfDistinctEvaluations_;

    return objectiveValueScaling_ * getObjectiveValueImplementation(getDiversifiedParameter(parameter)) + objectiveValueTranslation_;
#endif
  }

  template <typename T, typename U>
  unsigned long long OptimisationProblem<T, U>::getNumberOfEvaluations() const noexcept {
    return numberOfEvaluations_;
  }

  template <typename T, typename U>
  unsigned long long OptimisationProblem<T, U>::getNumberOfDistinctEvaluations() const noexcept {
    return numberOfDistinctEvaluations_;
  }

  template <typename T, typename U>
  void OptimisationProblem<T, U>::reset() noexcept {
    numberOfEvaluations_ = 0llu;
    numberOfDistinctEvaluations_ = 0llu;

    cachedObjectiveValues_.clear();
  }

  template <typename T, typename U>
  std::unordered_map<arma::Col<T>, U, Hash<T>, IsEqual<T>> OptimisationProblem<T, U>::getCachedObjectiveValues() const noexcept {
    return cachedObjectiveValues_;
  }

  template <typename T, typename U>
  arma::Col<T> OptimisationProblem<T, U>::getDiversifiedParameter(
      const arma::Col<T>& parameter) const noexcept {
    assert(parameter.n_elem == numberOfDimensions_);

    if (std::is_floating_point<T>::value) {
      // For continuous problems, parameter is firstly permuted, than scaled, translated and lastly rotated.
      return parameterRotation_ * (parameterScaling_ % parameter.elem(parameterPermutation_) - parameterTranslation_);
    } else {
      // For discrete problems, the parameter is only permuted.
      return parameter.elem(parameterPermutation_);
    }
  }

  template <typename T, typename U>
  U OptimisationProblem<T, U>::getSoftConstraintsValueImplementation(
      const arma::Col<T>& parameter) const noexcept {
    assert(parameter.n_elem == numberOfDimensions_);

    return 0.0;
  }

#if defined(MANTELLA_USE_PARALLEL_ALGORITHMS)
  template <typename T, typename U>
  std::vector<double> OptimisationProblem<T, U>::serialise() const noexcept {
    std::vector<double> serialisedOptimisationProblem;

    for(std::size_t n = 0; n < lowerBounds_.n_elem; ++n) {
      serialisedOptimisationProblem.push_back(lowerBounds_(n));
    }

    for(std::size_t n = 0; n < upperBounds_.n_elem; ++n) {
      serialisedOptimisationProblem.push_back(upperBounds_(n));
    }

    for(std::size_t n = 0; n < parameterPermutation_.n_elem; ++n) {
      serialisedOptimisationProblem.push_back(parameterPermutation_(n));
    }

    if (std::is_floating_point<T>::value) {
      for(std::size_t n = 0; n < parameterScaling_.n_elem; ++n) {
        serialisedOptimisationProblem.push_back(parameterScaling_(n));
      }

      for(std::size_t n = 0; n < parameterTranslation_.n_elem; ++n) {
        serialisedOptimisationProblem.push_back(parameterTranslation_(n));
      }

      for(std::size_t n = 0; n < parameterRotation_.n_elem; ++n) {
        serialisedOptimisationProblem.push_back(parameterRotation_(n));
      }
    }

    serialisedOptimisationProblem.push_back(objectiveValueScaling_);
    serialisedOptimisationProblem.push_back(objectiveValueTranslation_);

    serialisedOptimisationProblem.push_back(acceptableObjectiveValue_);

    return serialisedOptimisationProblem;
  }

  template <typename T, typename U>
  void OptimisationProblem<T, U>::deserialise(
      const std::vector<double>& serialisedOptimisationProblem) {
    lowerBounds_.set_size(this->numberOfDimensions_);
    for(std::size_t n = 0; n < lowerBounds_.n_elem; ++n) {
      lowerBounds_(n) = serialisedOptimisationProblem.pop_back();
    }

    upperBounds_.set_size(this->numberOfDimensions_);
    for(std::size_t n = 0; n < upperBounds_.n_elem; ++n) {
      upperBounds_(n) = serialisedOptimisationProblem.pop_back();
    }

    parameterPermutation_.set_size(this->numberOfDimensions_);
    for(std::size_t n = 0; n < parameterPermutation_.n_elem; ++n) {
      parameterPermutation_(n) = serialisedOptimisationProblem.pop_back();
    }

    if (std::is_floating_point<T>::value) {
      parameterScaling_.set_size(this->numberOfDimensions_);
      for(std::size_t n = 0; n < parameterScaling_.n_elem; ++n) {
        parameterScaling_(n) = serialisedOptimisationProblem.pop_back();
      }

      parameterTranslation_.set_size(this->numberOfDimensions_);
      for(std::size_t n = 0; n < parameterTranslation_.n_elem; ++n) {
        parameterTranslation_(n) = serialisedOptimisationProblem.pop_back();
      }

      parameterRotation_.set_size(this->numberOfDimensions_);
      for(std::size_t n = 0; n < parameterRotation_.n_elem; ++n) {
        parameterRotation_(n) = serialisedOptimisationProblem.pop_back();
      }
    }

    objectiveValueScaling_ = serialisedOptimisationProblem.pop_back();
    objectiveValueTranslation_ = serialisedOptimisationProblem.pop_back();

    acceptableObjectiveValue_ = serialisedOptimisationProblem.pop_back();
  }
#endif
}
<|endoftext|>


<commit_before>//===- seec/Trace/GetCurrentRuntimeValue.hpp ------------------------ C++ -===//
//
//                                    SeeC
//
// This file is distributed under The MIT License (MIT). See LICENSE.TXT for
// details.
//
//===----------------------------------------------------------------------===//
///
/// \file
///
//===----------------------------------------------------------------------===//

#ifndef SEEC_TRACE_GETCURRENTRUNTIMEVALUE_HPP
#define SEEC_TRACE_GETCURRENTRUNTIMEVALUE_HPP

#include "seec/DSA/MemoryArea.hpp"
#include "seec/Trace/RuntimeValue.hpp"
#include "seec/Util/Maybe.hpp"

#include "llvm/IR/Argument.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"

#include <cstdint>

namespace seec {

namespace trace {

/// \brief Implementation class for getCurrentRuntimeValueAs.
///
/// This class is specialized for various types of T. If no specialization
/// exists then getCurrentRuntimeValueAs will always return an unassigned Maybe.
/// \tparam T Type to try and extract the value as.
template<typename T, typename Enable = void>
struct GetCurrentRuntimeValueAsImpl;

/// \brief Specialization of getCurrentRuntimeValueAs to extract uintptr_t.
///
/// Because we store all pointers as uintptr_t, this specialization also
/// requires the additional requirements of pointer types, namely that the
/// following member functions are present in the source type SrcTy:
///
///   uintptr_t getRuntimeAddress(Function const *);
///   uintptr_t getRuntimeAddress(GlobalVariable const *);
///   llvm::DataLayout const &getDataLayout();
///
/// Which return the run-time addresses of the objects passed to them, or 0 if
/// the run-time addresses cannot be found.
///
/// To retrieve the value of byval Argument pointers, the following member
/// function must also be present in the source type SrcTy:
///
///   seec::Maybe<seec::MemoryArea>
///   getParamByValArea(llvm::Argument const *Arg) const;
///
/// This function returns the area occupied by the byval parameter. The start
/// of this area will be used as the value of the Argument.
///
/// \tparam SrcTy The type of object to get raw GenericValue values from.
template<>
struct GetCurrentRuntimeValueAsImpl<uintptr_t, void> {
  template<typename SrcTy>
  static seec::Maybe<uintptr_t>
  getCurrentRuntimeValueAs(SrcTy &Source, llvm::Value const *V) {
    auto Ty = V->getType();

    if (Ty->isIntegerTy()) {
      if (auto Instruction = llvm::dyn_cast<llvm::Instruction>(V)) {
        if (auto RTValue = Source.getCurrentRuntimeValue(Instruction)) {
          return RTValue->getUIntPtr();
        }

        return seec::Maybe<uintptr_t>();
      }
      else if (auto ConstantInt = llvm::dyn_cast<llvm::ConstantInt>(V)) {
        return static_cast<uintptr_t>(ConstantInt->getZExtValue());
      }

      llvm_unreachable("Don't know how to extract integer.");
    }
    else if (Ty->isPointerTy()) {
      // If the Value is an Instruction, get its recorded runtime value
      if (auto I = llvm::dyn_cast<llvm::Instruction>(V)) {
        if (auto RTValue = Source.getCurrentRuntimeValue(I)) {
          return RTValue->getUIntPtr();
        }

        return seec::Maybe<uintptr_t>();
      }

      // Get constant pointer values
      auto StrippedValue = V->stripPointerCasts();

      if (auto Global = llvm::dyn_cast<llvm::GlobalValue>(StrippedValue)) {
        if (auto Function = llvm::dyn_cast<llvm::Function>(Global)) {
          auto Addr = Source.getRuntimeAddress(Function);
          return Addr ? seec::Maybe<uintptr_t>(Addr)
                      : seec::Maybe<uintptr_t>();
        }
        else if (auto GV = llvm::dyn_cast<llvm::GlobalVariable>(StrippedValue)){
          auto Addr = Source.getRuntimeAddress(GV);
          return Addr ? seec::Maybe<uintptr_t>(Addr)
                      : seec::Maybe<uintptr_t>();
        }

        llvm::errs() << "Value = " << *V << "\n";
        llvm_unreachable("Don't know how to get pointer from global value.");
      }
      else if (llvm::isa<llvm::ConstantPointerNull>(StrippedValue)) {
        return seec::Maybe<uintptr_t>(static_cast<uintptr_t>(0));
      }

      // Get byval argument values
      if (auto const Arg = llvm::dyn_cast<llvm::Argument>(V)) {
        if (Arg->hasByValAttr()) {
          auto const MaybeArea = Source.getParamByValArea(Arg);
          if (MaybeArea.template assigned<seec::MemoryArea>())
            return MaybeArea.template get<seec::MemoryArea>().start();
          return seec::Maybe<uintptr_t>();
        }

        llvm::errs() << "Value = " << *V << "\n";
        llvm_unreachable("Don't know how to get pointer from argument.");
      }

      // Handle some ConstantExpr operations. A better way to do this, if we
      // can, would be to replace the used values that are runtime constants
      // (e.g. global variable addresses) with simple constants and get LLVM
      // to deduce the value.
      if (auto const CE = llvm::dyn_cast<llvm::ConstantExpr>(V)) {
        switch (CE->getOpcode()) {
          case llvm::Instruction::MemoryOps::GetElementPtr:
          {
            llvm::DataLayout const &DL = Source.getDataLayout();
            auto const Base = CE->getOperand(0);

            auto ElemAddress = getCurrentRuntimeValueAs(Source, Base)
                               .template get<uintptr_t>();
            llvm::Type *ElemType = llvm::dyn_cast<llvm::SequentialType>
                                                 (Base->getType());

            auto const NumOperands = CE->getNumOperands();

            for (unsigned i = 1; i < NumOperands; ++i) {
              ElemType = llvm::dyn_cast<llvm::SequentialType>(ElemType)
                         ->getElementType();

              auto const MaybeValue =
                getCurrentRuntimeValueAs(Source, CE->getOperand(i));

              if (!MaybeValue.template assigned<uintptr_t>()) {
                llvm::errs() << "GetElementPtr const expr couldn't value of: "
                             << *(CE->getOperand(i)) << "\n";
                return Maybe<uintptr_t>();
              }

              ElemAddress += (MaybeValue.template get<uintptr_t>()
                              * DL.getTypeAllocSize(ElemType));
            }

            return ElemAddress;
          }

          default:
            llvm::errs() << "can't get runtime value of const expr pointer: "
                         << *CE << "\n";
            return Maybe<uintptr_t>();
        }
      }

      llvm::errs() << "don't know how to get runtime value of pointer: "
                   << *V << "\n";
    }

    return Maybe<uintptr_t>();
  }
};

/// \brief Specialization of getCurrentRuntimeValueAs to extract pointer types.
///
/// Pointer types additionally require that the following member functions are
/// present in the source type SrcTy:
///
///   uintptr_t getRuntimeAddress(Function const *);
///   uintptr_t getRuntimeAddress(GlobalVariable const *);
///
/// Which return the run-time addresses of the objects passed to them, or 0 if
/// the run-time addresses cannot be found.
///
/// \tparam SrcTy The type of object to get raw GenericValue values from.
/// \tparam T The base type to try and extract the value as a pointer to.
template<typename T>
struct GetCurrentRuntimeValueAsImpl<T *, void> {
  template<typename SrcTy>
  static seec::Maybe<T *>
  getCurrentRuntimeValueAs(SrcTy &Source, llvm::Value const *V) {
    auto Addr = GetCurrentRuntimeValueAsImpl<uintptr_t>::
                  getCurrentRuntimeValueAs(Source, V);

    if (Addr.assigned())
      return reinterpret_cast<T *>(Addr.template get<0>());

    return seec::Maybe<T *>();
  }
};

/// \brief Specialization of getCurrentRuntimeValueAs to extract signed
///        integral types.
template<typename T>
struct GetCurrentRuntimeValueAsImpl
  <T,
   typename std::enable_if<std::is_integral<T>::value
                           && std::is_signed<T>::value
                          >::type>
{
  template<typename SrcTy>
  static seec::Maybe<T>
  getCurrentRuntimeValueAs(SrcTy &Source, llvm::Value const *V) {
    if (!V->getType()->isIntegerTy())
      return seec::Maybe<T>();

    if (auto Instruction = llvm::dyn_cast<llvm::Instruction>(V)) {
      if (auto RTValue = Source.getCurrentRuntimeValue(Instruction))
        return getAs<T>(*RTValue, Instruction->getType());
      return seec::Maybe<T>();
    }
    else if (auto ConstantInt = llvm::dyn_cast<llvm::ConstantInt>(V)) {
      // TODO: Assert that the constant isn't too large.
      return static_cast<T>(ConstantInt->getSExtValue());
    }

    llvm_unreachable("Don't know how to extract signed integral type.");
    return seec::Maybe<T>();
  }
};

/// \brief Specialization of getCurrentRuntimeValueAs to extract unsigned
///        integral types.
template<typename T>
struct GetCurrentRuntimeValueAsImpl
  <T,
   typename std::enable_if<std::is_integral<T>::value
                           && std::is_unsigned<T>::value
                          >::type>
{
  template<typename SrcTy>
  static seec::Maybe<T>
  getCurrentRuntimeValueAs(SrcTy &Source, llvm::Value const *V) {
    if (!V->getType()->isIntegerTy())
      return seec::Maybe<T>();

    if (auto Instruction = llvm::dyn_cast<llvm::Instruction>(V)) {
      if (auto RTValue = Source.getCurrentRuntimeValue(Instruction))
        return getAs<T>(*RTValue, Instruction->getType());
      return seec::Maybe<T>();
    }
    else if (auto ConstantInt = llvm::dyn_cast<llvm::ConstantInt>(V)) {
      // TODO: Assert that the constant isn't too large.
      return static_cast<T>(ConstantInt->getZExtValue());
    }

    llvm_unreachable("Don't know how to extract unsigned integral type.");
    return seec::Maybe<T>();
  }
};

// Overload for float types.
template<>
struct GetCurrentRuntimeValueAsImpl<float, void> {
  template<typename SrcTy>
  static seec::Maybe<float>
  getCurrentRuntimeValueAs(SrcTy &Source, llvm::Value const *V) {
    if (!V->getType()->isFloatTy())
      return seec::Maybe<float>();

    if (auto Instruction = llvm::dyn_cast<llvm::Instruction>(V)) {
      if (auto RTValue = Source.getCurrentRuntimeValue(Instruction))
        return RTValue->getFloat();
      return seec::Maybe<float>();
    }
    else if (auto ConstantFloat = llvm::dyn_cast<llvm::ConstantFP>(V)) {
      return ConstantFloat->getValueAPF().convertToFloat();
    }

    llvm_unreachable("Don't know how to extract float!");
    return seec::Maybe<float>();
  }
};

// Overload for double types.
template<>
struct GetCurrentRuntimeValueAsImpl<double, void> {
  template<typename SrcTy>
  static seec::Maybe<double>
  getCurrentRuntimeValueAs(SrcTy &Source, llvm::Value const *V) {
    if (!V->getType()->isDoubleTy())
      return seec::Maybe<double>();

    if (auto Instruction = llvm::dyn_cast<llvm::Instruction>(V)) {
      if (auto RTValue = Source.getCurrentRuntimeValue(Instruction))
        return RTValue->getDouble();
      return seec::Maybe<double>();
    }
    else if (auto ConstantFloat = llvm::dyn_cast<llvm::ConstantFP>(V)) {
      return ConstantFloat->getValueAPF().convertToDouble();
    }

    llvm_unreachable("Don't know how to extract double!");
    return seec::Maybe<double>();
  }
};

// Overload for long double types.
template<>
struct GetCurrentRuntimeValueAsImpl<long double, void> {
  template<typename SrcTy>
  static seec::Maybe<long double>
  getCurrentRuntimeValueAs(SrcTy &Source, llvm::Value const *V) {
    // Ensure that V's type matches one of the "long double" types.
    auto const VTy = V->getType();
    if (!VTy->isX86_FP80Ty() && !VTy->isPPC_FP128Ty())
      return seec::Maybe<long double>();

    if (auto Instruction = llvm::dyn_cast<llvm::Instruction>(V)) {
      if (auto RTValue = Source.getCurrentRuntimeValue(Instruction))
        return static_cast<long double>(RTValue->getDouble());
      return seec::Maybe<long double>();
    }
    else if (auto ConstantFloat = llvm::dyn_cast<llvm::ConstantFP>(V)) {
      auto const DoubleVal = ConstantFloat->getValueAPF().convertToDouble();
      return static_cast<long double>(DoubleVal);
    }

    llvm_unreachable("Don't know how to extract long double!");
    return seec::Maybe<long double>();
  }
};

// Overload to extract the raw RuntimeValue
template<>
struct GetCurrentRuntimeValueAsImpl<RuntimeValue const *, void> {
  template<typename SrcTy>
  static seec::Maybe<RuntimeValue const *>
  getCurrentRuntimeValueAs(SrcTy &Source, llvm::Value const *V) {
    if (auto Instruction = llvm::dyn_cast<llvm::Instruction>(V)) {
      if (auto RTValue = Source.getCurrentRuntimeValue(Instruction))
        return RTValue;
      return seec::Maybe<RuntimeValue const *>();
    }

    llvm_unreachable("Don't know how to extract RuntimeValue.");
    return seec::Maybe<RuntimeValue const *>();
  }
};

/// \brief Find the current value of a Value.
///
/// This requires the source object to implement the function:
///
///   RuntimeValue const *getCurrentRuntimeValue(llvm::Instruction const *I)
///
/// \tparam T The type to extract the value as.
/// \tparam SrcTy The type of source object to get raw RuntimeValues from.
/// \param Source The source object to get raw RuntimeValues from.
/// \param V The Value that we will try to find the run-time value for.
template<typename T, typename SrcTy>
seec::Maybe<T>
getCurrentRuntimeValueAs(SrcTy &Source, llvm::Value const *Value) {
  return GetCurrentRuntimeValueAsImpl<T>
          ::getCurrentRuntimeValueAs(Source, Value);
}

}

}

#endif // SEEC_TRACE_GETCURRENTRUNTIMEVALUE_HPP
<commit_msg>Improve GetCurrentRuntimeValueAsImpl<long double>.<commit_after>//===- seec/Trace/GetCurrentRuntimeValue.hpp ------------------------ C++ -===//
//
//                                    SeeC
//
// This file is distributed under The MIT License (MIT). See LICENSE.TXT for
// details.
//
//===----------------------------------------------------------------------===//
///
/// \file
///
//===----------------------------------------------------------------------===//

#ifndef SEEC_TRACE_GETCURRENTRUNTIMEVALUE_HPP
#define SEEC_TRACE_GETCURRENTRUNTIMEVALUE_HPP

#include "seec/DSA/MemoryArea.hpp"
#include "seec/Trace/RuntimeValue.hpp"
#include "seec/Util/Maybe.hpp"

#include "llvm/IR/Argument.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"

#include <cstdint>
#include <cfloat>

namespace seec {

namespace trace {

/// \brief Implementation class for getCurrentRuntimeValueAs.
///
/// This class is specialized for various types of T. If no specialization
/// exists then getCurrentRuntimeValueAs will always return an unassigned Maybe.
/// \tparam T Type to try and extract the value as.
template<typename T, typename Enable = void>
struct GetCurrentRuntimeValueAsImpl;

/// \brief Specialization of getCurrentRuntimeValueAs to extract uintptr_t.
///
/// Because we store all pointers as uintptr_t, this specialization also
/// requires the additional requirements of pointer types, namely that the
/// following member functions are present in the source type SrcTy:
///
///   uintptr_t getRuntimeAddress(Function const *);
///   uintptr_t getRuntimeAddress(GlobalVariable const *);
///   llvm::DataLayout const &getDataLayout();
///
/// Which return the run-time addresses of the objects passed to them, or 0 if
/// the run-time addresses cannot be found.
///
/// To retrieve the value of byval Argument pointers, the following member
/// function must also be present in the source type SrcTy:
///
///   seec::Maybe<seec::MemoryArea>
///   getParamByValArea(llvm::Argument const *Arg) const;
///
/// This function returns the area occupied by the byval parameter. The start
/// of this area will be used as the value of the Argument.
///
/// \tparam SrcTy The type of object to get raw GenericValue values from.
template<>
struct GetCurrentRuntimeValueAsImpl<uintptr_t, void> {
  template<typename SrcTy>
  static seec::Maybe<uintptr_t>
  getCurrentRuntimeValueAs(SrcTy &Source, llvm::Value const *V) {
    auto Ty = V->getType();

    if (Ty->isIntegerTy()) {
      if (auto Instruction = llvm::dyn_cast<llvm::Instruction>(V)) {
        if (auto RTValue = Source.getCurrentRuntimeValue(Instruction)) {
          return RTValue->getUIntPtr();
        }

        return seec::Maybe<uintptr_t>();
      }
      else if (auto ConstantInt = llvm::dyn_cast<llvm::ConstantInt>(V)) {
        return static_cast<uintptr_t>(ConstantInt->getZExtValue());
      }

      llvm_unreachable("Don't know how to extract integer.");
    }
    else if (Ty->isPointerTy()) {
      // If the Value is an Instruction, get its recorded runtime value
      if (auto I = llvm::dyn_cast<llvm::Instruction>(V)) {
        if (auto RTValue = Source.getCurrentRuntimeValue(I)) {
          return RTValue->getUIntPtr();
        }

        return seec::Maybe<uintptr_t>();
      }

      // Get constant pointer values
      auto StrippedValue = V->stripPointerCasts();

      if (auto Global = llvm::dyn_cast<llvm::GlobalValue>(StrippedValue)) {
        if (auto Function = llvm::dyn_cast<llvm::Function>(Global)) {
          auto Addr = Source.getRuntimeAddress(Function);
          return Addr ? seec::Maybe<uintptr_t>(Addr)
                      : seec::Maybe<uintptr_t>();
        }
        else if (auto GV = llvm::dyn_cast<llvm::GlobalVariable>(StrippedValue)){
          auto Addr = Source.getRuntimeAddress(GV);
          return Addr ? seec::Maybe<uintptr_t>(Addr)
                      : seec::Maybe<uintptr_t>();
        }

        llvm::errs() << "Value = " << *V << "\n";
        llvm_unreachable("Don't know how to get pointer from global value.");
      }
      else if (llvm::isa<llvm::ConstantPointerNull>(StrippedValue)) {
        return seec::Maybe<uintptr_t>(static_cast<uintptr_t>(0));
      }

      // Get byval argument values
      if (auto const Arg = llvm::dyn_cast<llvm::Argument>(V)) {
        if (Arg->hasByValAttr()) {
          auto const MaybeArea = Source.getParamByValArea(Arg);
          if (MaybeArea.template assigned<seec::MemoryArea>())
            return MaybeArea.template get<seec::MemoryArea>().start();
          return seec::Maybe<uintptr_t>();
        }

        llvm::errs() << "Value = " << *V << "\n";
        llvm_unreachable("Don't know how to get pointer from argument.");
      }

      // Handle some ConstantExpr operations. A better way to do this, if we
      // can, would be to replace the used values that are runtime constants
      // (e.g. global variable addresses) with simple constants and get LLVM
      // to deduce the value.
      if (auto const CE = llvm::dyn_cast<llvm::ConstantExpr>(V)) {
        switch (CE->getOpcode()) {
          case llvm::Instruction::MemoryOps::GetElementPtr:
          {
            llvm::DataLayout const &DL = Source.getDataLayout();
            auto const Base = CE->getOperand(0);

            auto ElemAddress = getCurrentRuntimeValueAs(Source, Base)
                               .template get<uintptr_t>();
            llvm::Type *ElemType = llvm::dyn_cast<llvm::SequentialType>
                                                 (Base->getType());

            auto const NumOperands = CE->getNumOperands();

            for (unsigned i = 1; i < NumOperands; ++i) {
              ElemType = llvm::dyn_cast<llvm::SequentialType>(ElemType)
                         ->getElementType();

              auto const MaybeValue =
                getCurrentRuntimeValueAs(Source, CE->getOperand(i));

              if (!MaybeValue.template assigned<uintptr_t>()) {
                llvm::errs() << "GetElementPtr const expr couldn't value of: "
                             << *(CE->getOperand(i)) << "\n";
                return Maybe<uintptr_t>();
              }

              ElemAddress += (MaybeValue.template get<uintptr_t>()
                              * DL.getTypeAllocSize(ElemType));
            }

            return ElemAddress;
          }

          default:
            llvm::errs() << "can't get runtime value of const expr pointer: "
                         << *CE << "\n";
            return Maybe<uintptr_t>();
        }
      }

      llvm::errs() << "don't know how to get runtime value of pointer: "
                   << *V << "\n";
    }

    return Maybe<uintptr_t>();
  }
};

/// \brief Specialization of getCurrentRuntimeValueAs to extract pointer types.
///
/// Pointer types additionally require that the following member functions are
/// present in the source type SrcTy:
///
///   uintptr_t getRuntimeAddress(Function const *);
///   uintptr_t getRuntimeAddress(GlobalVariable const *);
///
/// Which return the run-time addresses of the objects passed to them, or 0 if
/// the run-time addresses cannot be found.
///
/// \tparam SrcTy The type of object to get raw GenericValue values from.
/// \tparam T The base type to try and extract the value as a pointer to.
template<typename T>
struct GetCurrentRuntimeValueAsImpl<T *, void> {
  template<typename SrcTy>
  static seec::Maybe<T *>
  getCurrentRuntimeValueAs(SrcTy &Source, llvm::Value const *V) {
    auto Addr = GetCurrentRuntimeValueAsImpl<uintptr_t>::
                  getCurrentRuntimeValueAs(Source, V);

    if (Addr.assigned())
      return reinterpret_cast<T *>(Addr.template get<0>());

    return seec::Maybe<T *>();
  }
};

/// \brief Specialization of getCurrentRuntimeValueAs to extract signed
///        integral types.
template<typename T>
struct GetCurrentRuntimeValueAsImpl
  <T,
   typename std::enable_if<std::is_integral<T>::value
                           && std::is_signed<T>::value
                          >::type>
{
  template<typename SrcTy>
  static seec::Maybe<T>
  getCurrentRuntimeValueAs(SrcTy &Source, llvm::Value const *V) {
    if (!V->getType()->isIntegerTy())
      return seec::Maybe<T>();

    if (auto Instruction = llvm::dyn_cast<llvm::Instruction>(V)) {
      if (auto RTValue = Source.getCurrentRuntimeValue(Instruction))
        return getAs<T>(*RTValue, Instruction->getType());
      return seec::Maybe<T>();
    }
    else if (auto ConstantInt = llvm::dyn_cast<llvm::ConstantInt>(V)) {
      // TODO: Assert that the constant isn't too large.
      return static_cast<T>(ConstantInt->getSExtValue());
    }

    llvm_unreachable("Don't know how to extract signed integral type.");
    return seec::Maybe<T>();
  }
};

/// \brief Specialization of getCurrentRuntimeValueAs to extract unsigned
///        integral types.
template<typename T>
struct GetCurrentRuntimeValueAsImpl
  <T,
   typename std::enable_if<std::is_integral<T>::value
                           && std::is_unsigned<T>::value
                          >::type>
{
  template<typename SrcTy>
  static seec::Maybe<T>
  getCurrentRuntimeValueAs(SrcTy &Source, llvm::Value const *V) {
    if (!V->getType()->isIntegerTy())
      return seec::Maybe<T>();

    if (auto Instruction = llvm::dyn_cast<llvm::Instruction>(V)) {
      if (auto RTValue = Source.getCurrentRuntimeValue(Instruction))
        return getAs<T>(*RTValue, Instruction->getType());
      return seec::Maybe<T>();
    }
    else if (auto ConstantInt = llvm::dyn_cast<llvm::ConstantInt>(V)) {
      // TODO: Assert that the constant isn't too large.
      return static_cast<T>(ConstantInt->getZExtValue());
    }

    llvm_unreachable("Don't know how to extract unsigned integral type.");
    return seec::Maybe<T>();
  }
};

// Overload for float types.
template<>
struct GetCurrentRuntimeValueAsImpl<float, void> {
  template<typename SrcTy>
  static seec::Maybe<float>
  getCurrentRuntimeValueAs(SrcTy &Source, llvm::Value const *V) {
    if (!V->getType()->isFloatTy())
      return seec::Maybe<float>();

    if (auto Instruction = llvm::dyn_cast<llvm::Instruction>(V)) {
      if (auto RTValue = Source.getCurrentRuntimeValue(Instruction))
        return RTValue->getFloat();
      return seec::Maybe<float>();
    }
    else if (auto ConstantFloat = llvm::dyn_cast<llvm::ConstantFP>(V)) {
      return ConstantFloat->getValueAPF().convertToFloat();
    }

    llvm_unreachable("Don't know how to extract float!");
    return seec::Maybe<float>();
  }
};

// Overload for double types.
template<>
struct GetCurrentRuntimeValueAsImpl<double, void> {
  template<typename SrcTy>
  static seec::Maybe<double>
  getCurrentRuntimeValueAs(SrcTy &Source, llvm::Value const *V) {
    if (!V->getType()->isDoubleTy())
      return seec::Maybe<double>();

    if (auto Instruction = llvm::dyn_cast<llvm::Instruction>(V)) {
      if (auto RTValue = Source.getCurrentRuntimeValue(Instruction))
        return RTValue->getDouble();
      return seec::Maybe<double>();
    }
    else if (auto ConstantFloat = llvm::dyn_cast<llvm::ConstantFP>(V)) {
      return ConstantFloat->getValueAPF().convertToDouble();
    }

    llvm_unreachable("Don't know how to extract double!");
    return seec::Maybe<double>();
  }
};

// Overload for long double types.
template<>
struct GetCurrentRuntimeValueAsImpl<long double, void> {
  template<typename SrcTy>
  static seec::Maybe<long double>
  getCurrentRuntimeValueAs(SrcTy &Source, llvm::Value const *V) {
    // Ensure that V's type matches one of the "long double" types.
    auto const VTy = V->getType();
    if (!VTy->isX86_FP80Ty() && !VTy->isPPC_FP128Ty())
      return seec::Maybe<long double>();

    if (auto Instruction = llvm::dyn_cast<llvm::Instruction>(V)) {
      if (auto RTValue = Source.getCurrentRuntimeValue(Instruction))
        return static_cast<long double>(RTValue->getLongDouble());
      return seec::Maybe<long double>();
    }
    else if (auto ConstantFloat = llvm::dyn_cast<llvm::ConstantFP>(V)) {
      auto const APF = ConstantFloat->getValueAPF();
      auto const SemanticsPtr = &(APF.getSemantics());

      if (SemanticsPtr == &llvm::APFloat::IEEEsingle) {
        return static_cast<long double>(APF.convertToFloat());
      }
      else if (SemanticsPtr == &llvm::APFloat::IEEEdouble) {
        return static_cast<long double>(APF.convertToDouble());
      }
      else if (SemanticsPtr == &llvm::APFloat::x87DoubleExtended) {
        assert(LDBL_MANT_DIG == 64);
        long double Result = 0;
        auto const API = APF.bitcastToAPInt();
        memcpy(reinterpret_cast<char *>(&Result),
               reinterpret_cast<char const *>(API.getRawData()),
               10);
        return Result;
      }
      else {
        llvm_unreachable("Float semantics not yet supported!");
      }
    }

    llvm_unreachable("Don't know how to extract long double!");
    return seec::Maybe<long double>();
  }
};

// Overload to extract the raw RuntimeValue
template<>
struct GetCurrentRuntimeValueAsImpl<RuntimeValue const *, void> {
  template<typename SrcTy>
  static seec::Maybe<RuntimeValue const *>
  getCurrentRuntimeValueAs(SrcTy &Source, llvm::Value const *V) {
    if (auto Instruction = llvm::dyn_cast<llvm::Instruction>(V)) {
      if (auto RTValue = Source.getCurrentRuntimeValue(Instruction))
        return RTValue;
      return seec::Maybe<RuntimeValue const *>();
    }

    llvm_unreachable("Don't know how to extract RuntimeValue.");
    return seec::Maybe<RuntimeValue const *>();
  }
};

/// \brief Find the current value of a Value.
///
/// This requires the source object to implement the function:
///
///   RuntimeValue const *getCurrentRuntimeValue(llvm::Instruction const *I)
///
/// \tparam T The type to extract the value as.
/// \tparam SrcTy The type of source object to get raw RuntimeValues from.
/// \param Source The source object to get raw RuntimeValues from.
/// \param V The Value that we will try to find the run-time value for.
template<typename T, typename SrcTy>
seec::Maybe<T>
getCurrentRuntimeValueAs(SrcTy &Source, llvm::Value const *Value) {
  return GetCurrentRuntimeValueAsImpl<T>
          ::getCurrentRuntimeValueAs(Source, Value);
}

}

}

#endif // SEEC_TRACE_GETCURRENTRUNTIMEVALUE_HPP
<|endoftext|>


<commit_before>#pragma once

#include<algorithm>
#include<vector>
#include<universal/blas/operators.hpp>
#include<universal/blas/solvers.hpp>
const double EPS = 1E-9;
const double k = 0.0000001;
namespace sw {
    namespace universal {
        namespace blas {

            template<typename Scalar>
            size_t find_rank(const matrix<Scalar>& A) {
                size_t n = num_rows(A);
                size_t m = num_cols(A);

                size_t rank = 0;
                vector<bool> row(n, false);
                for (size_t i = 0; i < m; ++i) {
                    for (size_t j = 0; j < n; ++j) {
                        if (abs(A[j][i]) > EPS && !row[j]) break;
                    }

                    if (j != n) {
                        ++rank;
                        row[j] = true;
                        for (size_t p = i + 1; p < m; ++p) A[j][p] /= A[j][i];
                        for (size_t k = 0; k < n; ++k) {
                            if (abs(A[k][i]) > EPS && k != j) {
                                for (size_t p = i + 1; p < m; ++p)
                                    A[k][p] -= A[j][p] * A[k][i];
                            }
                        }
                    }
                }
                return rank;
            }
            template<typename Matrix, typename MatrixQ, typename MatrixR, typename Scalar>
            void qr(const Matrix& A, MatrixQ& Q, MatrixR& R) {
                typedef typename matrix<Scalar>::value_type     value_type;//use Scalar
                typedef typename matrix<Scalar>::size_type      size_type;//use size_type directly
                typedef typename Magnitude<value_type>::type    magnitude_type;

                size_type ncols = num_cols(A), nrows = num_cols(A);
                mini = ncols == nrows ? ncols - 1 : (nrows >= ncols ? ncols : nrows);
                magnitude_type  factor = magnitude_type(2);

                Q = 1;
                for (size_type i = 0; i < mini; ++i) {
                    //have to compute Q && R Here
                }

            }

            template<typename Scalar>
            std::pair<matrix<Scalar>, matrix<Scalar>>
                inline qr(const matrix<Scalar>& A) {
                //R is the upper triangular matrix
                //Q is the orthogonal matrix
                matrix<Scalar> Q(num_rows(A), num_cols(A)), R(A);
                qr(A, Q, R);
                return std::make_pair(Q, R);
            }
            template<typename Scalar>
            inline void svd(const matrix<Scalar>& A, matrix<Scalar>& S, matrix<Scalar>& V, matrix<Scalar>& D, double tol = 10e-10) {
                typedef typename matrix<Scalar>::value_type   value_type;
                typedef typename matrix<Scalar>::size_type    size_type;
                size_type        ncols = num_cols(A), nrows = num_rows(A);
                value_type       ref, zero = math::zero(ref), one = math::one(ref);
                double 	     err(std::numeric_limits<double>::max()), e, f;
                if (nrows != ncols) std::swap(row, col);
                matrix<Scalar> Q(nrows, nrows), R(nrows, ncols), VT(nrows, ncols), E(nrows, ncols),QT(ncols, ncols), RT(ncols, nrows);
                size_type l = 100 * std::max(nrows, ncols);
                S = one; D = one; E = zero;
                for (size_type i = 0; err > tol && i < l; ++i) {
                    std::tie(QT, RT) = qr(V);
                    S *= QT;
                    VT = RT.transpose();
                    std::tie(Q, R) = qr(VT);
                    D *= Q;
                    E = triu(R, 1);
                    V = trans(R);
                    //have to implement when upper(R)=0
                }
            }
            template<typename Scalar>
            std::tuple<matrix<Scalar>, matrix<Scalar>, matrix<Scalar>>
            inline svd(const matrix<Scalar>& A, double tol= 10e-10) {
                typedef typename Collection<Matrix>::size_type    size_type;
                size_type    ncols = num_cols(A), nrows = num_rows(A);
                if (nrows != ncols) std::swap(row, col);
                matrix<Scalar> ST(ncols, ncols), V(A), D(nrows, nrows);
                svd(A, ST, V, D, tol);
                return std::make_tuple(ST, V, D);

            }
            template<typename Scalar>
            std::tuple<matrix<Scalar>,matrix<Scalar>, matrix<Scalar>>
                inline randsvd(const matrix<Scalar>& A) {
                size_t k = min(num_cols(A), num_rows(A));
                size_t n = num_cols(A), m = num_row(A);
                //generate a gaussian random matrix of size n x k omega here
                matrix<Scalar> omega(n,k),Y, B;
                //omega(n x k) x A(m x n) == Y(m x k)
                Y = A * omega;
                tie(Q, R) = qr(Y);
                //implement qr decomposition & svd here
                Q.transpose();
                B = Q * A;
                std::tie(S, V, D) = svd(B,k);
                return std::make_tuple(S, V, D);
            }
        }
    }
}<commit_msg>update<commit_after>#pragma once

#include<algorithm>
#include<vector>
#include<universal/blas/operators.hpp>
#include<universal/blas/solvers.hpp>
const double EPS = 1E-9;
const double k = 0.0000001;
namespace sw {
    namespace universal {
        namespace blas {

            template<typename Scalar>
            size_t find_rank(const matrix<Scalar>& A) {
                size_t n = num_rows(A);
                size_t m = num_cols(A);

                size_t rank = 0;
                vector<bool> row(n, false);
                for (size_t i = 0; i < m; ++i) {
                    for (size_t j = 0; j < n; ++j) {
                        if (abs(A[j][i]) > EPS && row[j]!=Scalar(0)) break;
                    }

                    if (j != n) {
                        ++rank;
                        row[j] = true;
                        for (size_t p = i + 1; p < m; ++p) A[j][p] /= A[j][i];
                        for (size_t k = 0; k < n; ++k) {
                            if (abs(A[k][i]) > EPS && k != j) {
                                for (size_t p = i + 1; p < m; ++p)
                                    A[k][p] -= A[j][p] * A[k][i];
                            }
                        }
                    }
                }
                return rank;
            }
            template<typename Matrix, typename MatrixQ, typename MatrixR, typename Scalar>
            void qr(const Matrix& A, MatrixQ& Q, MatrixR& R) {
                using value_type = typename matrix::value_type;
                using size_type = typename matrix::size_type;
                using Magnitude<value_type>::type = typename matrix::magnitude_type;

                size_type ncols = num_cols(A), nrows = num_cols(A);
                mini = ncols == nrows ? ncols - 1 : (nrows >= ncols ? ncols : nrows);
                magnitude_type  factor = magnitude_type(2);

                Q = 1;
                for (size_type i = 0; i < mini; ++i) {
                    //have to compute Q && R Here
                }

            }

            template<typename Scalar>
            std::pair<matrix<Scalar>, matrix<Scalar>>
                inline qr(const matrix<Scalar>& A) {
                //R is the upper triangular matrix
                //Q is the orthogonal matrix
                matrix<Scalar> Q(num_rows(A), num_cols(A)), R(A);
                qr(A, Q, R);
                return std::make_pair(Q, R);
            }
            template<typename Scalar>
            inline void svd(const matrix<Scalar>& A, matrix<Scalar>& S, matrix<Scalar>& V, matrix<Scalar>& D, double tol = 10e-10) {
                using value_type = typename matrix::value_type;
                using size_type = typename matrix::size_type;
                size_type        ncols = num_cols(A), nrows = num_rows(A);
                value_type       ref, zero = math::zero(ref), one = math::one(ref);
                double 	     err(std::numeric_limits<double>::max()), e, f;
                if (nrows != ncols) std::swap(row, col);
                matrix<Scalar> Q(nrows, nrows), R(nrows, ncols), VT(nrows, ncols), E(nrows, ncols),QT(ncols, ncols), RT(ncols, nrows);
                size_type l = 100 * std::max(nrows, ncols);
                S = one; D = one; E = zero;
                for (size_type i = 0; err > tol && i < l; ++i) {
                    std::tie(QT, RT) = qr(V);
                    S *= QT;
                    VT = RT.transpose();
                    std::tie(Q, R) = qr(VT);
                    D *= Q;
                    E = triu(R, 1);
                    V = trans(R);
                    //have to implement when upper(R)=0
                }
            }
            template<typename Scalar, typename Tolerance>
            std::tuple<matrix<Scalar>, matrix<Scalar>, matrix<Scalar>>
            inline svd(const matrix<Scalar>& A, Tolerance tol= 10e-10) {
                typedef typename Collection<Matrix>::size_type    size_type;
                size_type    ncols = num_cols(A), nrows = num_rows(A);
                if (nrows != ncols) std::swap(row, col);
                matrix<Scalar> ST(ncols, ncols), V(A), D(nrows, nrows);
                svd(A, ST, V, D, tol);
                return std::make_tuple(ST, V, D);

            }
            template<typename Scalar>
            std::tuple<matrix<Scalar>,matrix<Scalar>, matrix<Scalar>>
                inline randsvd(const matrix<Scalar>& A) {
                size_t k = min(num_cols(A), num_rows(A));
                size_t n = num_cols(A), m = num_row(A);
                //generate a gaussian random matrix of size n x k omega here
                matrix<Scalar> omega(n,k),Y, B;
                //omega(n x k) x A(m x n) == Y(m x k)
                Y = A * omega;
                tie(Q, R) = qr(Y);
                //implement qr decomposition & svd here
                Q.transpose();
                B = Q * A;
                std::tie(S, V, D) = svd(B,k);
                return std::make_tuple(S, V, D);
            }
        }
    }
}<|endoftext|>


<commit_before>#pragma once
// trigonometric.hpp: trigonometric functions for posits
//
// Copyright (C) 2017-2019 Stillwater Supercomputing, Inc.
//
// This file is part of the universal numbers project, which is released under an MIT Open Source license.

namespace sw {
	namespace unum {

		// the current shims are NON-COMPLIANT with the posit standard, which says that every function must be
		// correctly rounded for every input value. Anything less sacrifices bitwise reproducibility of results.

		// value representing an angle expressed in radians
		// One radian is equivalent to 180/PI degrees

		// sine of an angle of x radians
		template<size_t nbits, size_t es>
		posit<nbits,es> sin(posit<nbits,es> x) {
			return posit<nbits,es>(std::sin(double(x)));
		}

		// cosine of an angle of x radians
		template<size_t nbits, size_t es>
		posit<nbits,es> cos(posit<nbits,es> x) {
			return posit<nbits,es>(std::cos(double(x)));
		}

		// tangent of an angle of x radians
		template<size_t nbits, size_t es>
		posit<nbits,es> tan(posit<nbits,es> x) {
			return posit<nbits,es>(std::tan(double(x)));
		}

		// cotangent of an angle of x radians
		template<size_t nbits, size_t es>
		posit<nbits,es> atan(posit<nbits,es> x) {
			return posit<nbits,es>(std::atan(double(x)));
		}

		// Arc tangent with two parameters
		template<size_t nbits, size_t es>
		posit<nbits,es> atan2(posit<nbits,es> y, posit<nbits,es> x) {
			return posit<nbits,es>(std::atan2(double(y),double(x)));
		}

		// cosecant of an angle of x radians
		template<size_t nbits, size_t es>
		posit<nbits,es> acos(posit<nbits,es> x) {
			return posit<nbits,es>(std::acos(double(x)));
		}

		// secant of an angle of x radians
		template<size_t nbits, size_t es>
		posit<nbits,es> asin(posit<nbits,es> x) {
			return posit<nbits,es>(std::asin(double(x)));
		}

		// cotangent an angle of x radians
		template<size_t nbits, size_t es>
		posit<nbits,es> cot(posit<nbits,es> x) {
			return posit<nbits,es>(std::tan(sw::unum::m_pi_2-double(x)));
		}

		// secant of an angle of x radians
		template<size_t nbits, size_t es>
		posit<nbits,es> sec(posit<nbits,es> x) {
			return posit<nbits,es>(1.0/std::cos(double(x)));
		}

		// cosecant of an angle of x radians
		template<size_t nbits, size_t es>
		posit<nbits,es> csc(posit<nbits,es> x) {
			return posit<nbits,es>(1.0/std::sin(double(x)));
		}

	}  // namespace unum

}  // namespace sw
<commit_msg>tracing trig functions<commit_after>#pragma once
// trigonometric.hpp: trigonometric functions for posits
//
// Copyright (C) 2017-2020 Stillwater Supercomputing, Inc.
//
// This file is part of the universal numbers project, which is released under an MIT Open Source license.

namespace sw {
	namespace unum {

		// the current shims are NON-COMPLIANT with the posit standard, which says that every function must be
		// correctly rounded for every input value. Anything less sacrifices bitwise reproducibility of results.

		// value representing an angle expressed in radians
		// One radian is equivalent to 180/PI degrees

		// sine of an angle of x radians
		template<size_t nbits, size_t es>
		posit<nbits,es> sin(posit<nbits,es> x) {
			//std::cerr << "sw::unum::sin(posit<" << nbits << "," << es << ")";
			return posit<nbits,es>(std::sin(double(x)));
		}

		// cosine of an angle of x radians
		template<size_t nbits, size_t es>
		posit<nbits,es> cos(posit<nbits,es> x) {
			//std::cerr << "sw::unum::cos(posit<" << nbits << "," << es << ")";
			return posit<nbits,es>(std::cos(double(x)));
		}

		// tangent of an angle of x radians
		template<size_t nbits, size_t es>
		posit<nbits,es> tan(posit<nbits,es> x) {
			//std::cerr << "sw::unum::tan(posit<" << nbits << "," << es << ")";
			return posit<nbits,es>(std::tan(double(x)));
		}

		// cotangent of an angle of x radians
		template<size_t nbits, size_t es>
		posit<nbits,es> atan(posit<nbits,es> x) {
			//std::cerr << "sw::unum::atan(posit<" << nbits << "," << es << ")";
			return posit<nbits,es>(std::atan(double(x)));
		}

		// Arc tangent with two parameters
		template<size_t nbits, size_t es>
		posit<nbits,es> atan2(posit<nbits,es> y, posit<nbits,es> x) {
			return posit<nbits,es>(std::atan2(double(y),double(x)));
		}

		// cosecant of an angle of x radians
		template<size_t nbits, size_t es>
		posit<nbits,es> acos(posit<nbits,es> x) {
			return posit<nbits,es>(std::acos(double(x)));
		}

		// secant of an angle of x radians
		template<size_t nbits, size_t es>
		posit<nbits,es> asin(posit<nbits,es> x) {
			return posit<nbits,es>(std::asin(double(x)));
		}

		// cotangent an angle of x radians
		template<size_t nbits, size_t es>
		posit<nbits,es> cot(posit<nbits,es> x) {
			return posit<nbits,es>(std::tan(sw::unum::m_pi_2-double(x)));
		}

		// secant of an angle of x radians
		template<size_t nbits, size_t es>
		posit<nbits,es> sec(posit<nbits,es> x) {
			return posit<nbits,es>(1.0/std::cos(double(x)));
		}

		// cosecant of an angle of x radians
		template<size_t nbits, size_t es>
		posit<nbits,es> csc(posit<nbits,es> x) {
			return posit<nbits,es>(1.0/std::sin(double(x)));
		}

	}  // namespace unum

}  // namespace sw
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: ShapeFilterBase.hxx,v $
 * $Revision: 1.6 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef OOX_SHAPE_SHAPEFILTERBASE_HXX
#define OOX_SHAPE_SHAPEFILTERBASE_HXX

#include <boost/shared_ptr.hpp>
#include <rtl/ref.hxx>
#include "oox/vml/drawing.hxx"
#include "oox/drawingml/table/tablestylelist.hxx"
#include "oox/core/xmlfilterbase.hxx"

namespace oox {
namespace shape {

// ============================================================================

class ShapeFilterBase : public core::XmlFilterBase
{
public:
    typedef boost::shared_ptr<ShapeFilterBase> Pointer_t;

    explicit            ShapeFilterBase(
                            const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory );

    virtual             ~ShapeFilterBase();

    /** Has to be implemented by each filter to resolve scheme colors. */
    virtual sal_Int32   getSchemeClr( sal_Int32 nColorSchemeToken ) const;

    /** Has to be implemented by each filter to return drawings collection. */
    virtual const ::oox::vml::DrawingPtr getDrawings();

    /** Has to be implemented by each filter to return TableStyles. */
    virtual const ::oox::drawingml::table::TableStyleListPtr getTableStyles();

    virtual ::oox::drawingml::chart::ChartConverter& getChartConverter();

    virtual rtl::OUString implGetImplementationName() const;

    virtual bool importDocument() { return true; }
    virtual bool exportDocument() { return true; }

private:
    ::boost::shared_ptr< ::oox::drawingml::chart::ChartConverter > mxChartConv;
};

// ============================================================================

} // namespace shape
} // namespace oox

#endif

<commit_msg>INTEGRATION: CWS xmlfilter06 (1.5.6); FILE MERGED 2008/06/30 09:57:35 dr 1.5.6.3: RESYNC: (1.5-1.6); FILE MERGED 2008/06/06 16:27:54 dr 1.5.6.2: chart formatting: builtin line/fill/effect styles, manual line formatting 2008/05/27 10:40:43 dr 1.5.6.1: joined changes from CWS xmlfilter05<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: ShapeFilterBase.hxx,v $
 * $Revision: 1.7 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef OOX_SHAPE_SHAPEFILTERBASE_HXX
#define OOX_SHAPE_SHAPEFILTERBASE_HXX

#include <boost/shared_ptr.hpp>
#include <rtl/ref.hxx>
#include "oox/vml/drawing.hxx"
#include "oox/drawingml/table/tablestylelist.hxx"
#include "oox/core/xmlfilterbase.hxx"

namespace oox {
namespace shape {

// ============================================================================

class ShapeFilterBase : public core::XmlFilterBase
{
public:
    typedef boost::shared_ptr<ShapeFilterBase> Pointer_t;

    explicit            ShapeFilterBase(
                            const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory );

    virtual             ~ShapeFilterBase();

    /** Has to be implemented by each filter, returns the current theme. */
    virtual const ::oox::drawingml::Theme* getCurrentTheme() const;

    /** Has to be implemented by each filter to resolve scheme colors. */
    virtual sal_Int32   getSchemeClr( sal_Int32 nColorSchemeToken ) const;

    /** Has to be implemented by each filter to return drawings collection. */
    virtual const ::oox::vml::DrawingPtr getDrawings();

    /** Has to be implemented by each filter to return TableStyles. */
    virtual const ::oox::drawingml::table::TableStyleListPtr getTableStyles();

    virtual ::oox::drawingml::chart::ChartConverter& getChartConverter();

    virtual rtl::OUString implGetImplementationName() const;

    virtual bool importDocument() { return true; }
    virtual bool exportDocument() { return true; }

private:
    ::boost::shared_ptr< ::oox::drawingml::chart::ChartConverter > mxChartConv;
};

// ============================================================================

} // namespace shape
} // namespace oox

#endif

<|endoftext|>