Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DM-7913: Implement RFC-240: make Angle's named methods const... #184

Merged
merged 9 commits into from Mar 11, 2017

Conversation

kfindeisen
Copy link
Member

@kfindeisen kfindeisen commented Mar 1, 2017

In addition to the changes requested in DM-7913, this change includes some code cleanup of Angle... which I might have gotten a bit carried away with:

  • clang-format pass
  • splitting declaration/definition of complex methods in Angle
  • added unary - operator (surprising omission in previous API, came up when writing tests for separation)
  • added support for C++11 features
  • reformatted and greatly expanded documentation

@kfindeisen kfindeisen requested review from laurenam and removed request for laurenam March 1, 2017 21:29
@kfindeisen kfindeisen force-pushed the tickets/DM-7913 branch 4 times, most recently from 270471c to a38f3ae Compare March 9, 2017 18:23
Copy link
Contributor

@r-owen r-owen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! A few minor suggestions including removing outdated SWIG macros and comments and fixing a possible edge case bug.

inline constexpr double radToArcsec(double x) noexcept { return x * 3600. * 180. / PI; }
inline constexpr double radToMas(double x) noexcept { return x * 1000. * 3600. * 180. / PI; }
inline constexpr double arcsecToRad(double x) noexcept { return (x / 3600.) * PI / 180.; }
inline constexpr double masToRad(double x) noexcept { return (x / (1000. * 3600.)) * PI / 180.; }

// NOTE, if you add things here, you must also add them to
// python/lsst/afw/geom/__init__.py
// (if you want them to accessible from python)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest deleting this code comment; it is outdated and not very useful

*/
class AngleUnit {
class AngleUnit
#ifndef SWIG
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please delete all SWIG macro commands and all comments that include SWIG. Note that some SWIG comments use "swig" (lowercase).

/************************************************************************************************************/

class Angle;
/**
* \brief A class used to convert scalar POD types such as double to Angle
* A class used to convert scalar POD types such as `double` to Angle.
*
* For example:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a bit more information to make it clear that degrees is an instance of AngleUnit?

inline bool lsst::afw::geom::AngleUnit::operator==(lsst::afw::geom::AngleUnit const &rhs) const {
return (_val == rhs._val);
inline constexpr bool AngleUnit::operator==(AngleUnit const& rhs) const noexcept {
return (_val == rhs._val);
}

// NOTE, if you add things here, remember to also add them to
// python/lsst/afw/geom/__init__.py

// swig likes this way of initialising the constant, so don't mess with it;
// N.b. swig 1.3 doesn't like PI/(60*180)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(SWIG comment to delete; I won't point out any more)

inline bool lsst::afw::geom::AngleUnit::operator==(lsst::afw::geom::AngleUnit const &rhs) const {
return (_val == rhs._val);
inline constexpr bool AngleUnit::operator==(AngleUnit const& rhs) const noexcept {
return (_val == rhs._val);
}

// NOTE, if you add things here, remember to also add them to
// python/lsst/afw/geom/__init__.py
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please delete (or fix) this comment.

@@ -246,73 +299,182 @@ Angle const NullAngle = Angle(-1000000., degrees);
* N.b. We need both int and double versions to avoid ambiguous overloading due to implicit conversion of
* Angle to double
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ANGLE_OP does not appear to do anything with int; I suspect this comment refers to ANGLE_OP_TYPE; if so please move it.

template <typename T>
inline constexpr Angle operator*(T lhs, AngleUnit rhs) noexcept {
static_assert(std::is_arithmetic<T>::value,
"Only numeric types may be converted to Angles using degrees/radians!");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error message could be improved. Perhaps something like "Only numeric types may multiplied by an AngleUnit such as degrees or radians to create an Angle".


inline double Angle::toUnitSphereDistanceSquared() const noexcept {
return 2. * (1. - std::cos(asRadians()));
// == 4.0 * pow(std::sin(0.5 * asRadians()), 2.0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is one preferred over the other in a particular regime? If so, is there any point to a conditional?

In any case it might be worth a brief comment as to why one was chosen and the other not

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There might be, but this is preexisting code, and the initial commit (2b49698) doesn't provide any clues.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... both methods are used only in afw/table/Match.cc. Perhaps they could at least be moved there, since they aren't really operations on angles in the general sense.

}
// maximum relative roundoff error for subtraction is 2 epsilon
if (wrapped - refAngRad < -PI) {
wrapped -= wrapped * 2.0 * std::numeric_limits<double>::epsilon();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be +=?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is equivalent to wrapped *= (1.0 - 2ε), regardless of whether wrapped is positive or negative. So neither += nor -= really make sense (e.g., consider if wrapped = 0 and refAngRad = π + ε).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try as I might, I can't come up with a test case that exposes any problems with the code as-is (although removing this block does cause existing tests to fail). I'm not comfortable trying to fix this if I can't see the effects, so at most I can file DM-9765 to investigate later... 😞

// Without an explicit wrapper, Python lets Angle / Angle -> Angle
clsAngle.def("__truediv__", [](Angle const& self, Angle const& other) {
throw py::type_error("unsupported operand type(s) for /: 'Angle' and 'Angle'");
});

clsAngle.def("__float__", &Angle::operator double);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we get rid of this? I suppose it may require an RFC (though if it passed Jenkins...)

This allows method bodies to use the full Angle API, particularly
operators. Trivial getters have not been moved to minimize code
duplication.
Client code is generally simpler if wrap methods return an altered
Angle instead of modifying the object they are called on.
This change allows Angles to be used in compile-time expressions and
take advantage of noexcept optimizations. It also simplifies some
existing metaprogramming using C++11-only tools.
This commit ensures all API elements are documented, and that
documentation complies with current style guidelines.
These methods were added to Angle as part of
2b49698 to be used in table::Match.
They have not been used anywhere else, their use case is more specific
than other Angle operations, and they do not need any access to
Angle's internals (cf. Effective C++ 3rd. Ed., Item 23). In addition,
making them an implementation detail of Match reduces coupling between
afw::geom and afw::table, which may be useful in the long run.
@kfindeisen kfindeisen merged commit 7f9d117 into master Mar 11, 2017
@kfindeisen kfindeisen deleted the tickets/DM-7913 branch August 22, 2018 19:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants