Program Listing for File degrees.hpp

Return to documentation for file (rcppsw/math/degrees.hpp)

#pragma once

/*******************************************************************************
 * Includes
 ******************************************************************************/
#include <cmath>
#include <limits>
#include <string>

#include "rcppsw/math/range.hpp"
#include "rcppsw/rcppsw.hpp"
#include "rcppsw/math/math.hpp"

/*******************************************************************************
 * Namespaces/Decls
 ******************************************************************************/
namespace rcppsw::math {

class radians;

/*******************************************************************************
 * Class Definitions
 ******************************************************************************/
class degrees final : public er::stringizable {
 public:
  /*
   * These are MATHEMATICAL constants, so they get UPPER_CASE naming convention
   * to emphasize that fact.
   */
  static const double kDEGREES_TO_RADIANS; // NOLINT

  degrees(void) = default;

  explicit degrees(double value) : m_value(value) {}

  explicit degrees(const radians& r);

  double v(void) const { return m_value; }

  double operator()(void) const { return v(); }

  void set(double value) { m_value = value; }

  degrees& signed_normalize(void) {
    return *this = kSignedRange.wrap_value(*this);
  }

  degrees& unsigned_normalize(void) {
    return *this = kUnsignedRange.wrap_value(*this);
  }

  std::string to_str(void) const override;

  degrees& operator+(void) { return *this; }

  degrees operator-(void) const { return degrees(-m_value); }

  degrees& operator+=(const degrees& other) {
    m_value += other.m_value;
    return *this;
  }

  degrees& operator+=(double value) {
    m_value += value;
    return *this;
  }

  degrees& operator-=(const degrees& other) {
    m_value -= other.m_value;
    return *this;
  }
  degrees& operator-=(double value) {
    m_value -= value;
    return *this;
  }
  degrees& operator*=(double value) {
    m_value *= value;
    return *this;
  }

  degrees& operator/=(double value) {
    m_value /= value;
    return *this;
  }

  degrees operator+(const degrees& other) const {
    degrees res(*this);
    res += other;
    return res;
  }

  degrees operator-(const degrees& other) const {
    degrees res(*this);
    res -= other;
    return res;
  }

  degrees operator*(double value) const {
    degrees res(*this);
    res *= value;
    return res;
  }

  double operator/(const degrees& other) const { return m_value / other.m_value; }

  degrees operator/(double value) const {
    degrees res(*this);
    res /= value;
    return res;
  }

  bool operator<(const degrees& other) const { return m_value < other.m_value; }

  bool operator<=(const degrees& other) const { return m_value <= other.m_value; }

  bool operator>(const degrees& other) const { return m_value > other.m_value; }

  bool operator>=(const degrees& other) const { return m_value >= other.m_value; }

  bool operator==(const degrees& other) const {
    return std::fabs(m_value - other.m_value) <= kDOUBLE_EPSILON;
  }

  bool operator!=(const degrees& other) const { return !(*this == other); }

  friend std::istream& operator>>(std::istream& is, degrees& d) {
    is >> d.m_value;
    return is;
  }

 private:
  static const range<degrees> kSignedRange;

  static const range<degrees> kUnsignedRange;

  double m_value{ 0.0 };
};

/*******************************************************************************
 * Operators
 ******************************************************************************/
std::ostream& operator<<(std::ostream& stream, const degrees& d);

} /* namespace rcppsw::math */