@@ -413,22 +413,22 @@ NEW_UNIT(Luminosity, candela, 0, 0, 0, 0, 0, 0, 1, 0);
413413NEW_UNIT (Moles, mol, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 );
414414
415415namespace units {
416- // helper function for Quantity-Double compatibility
417- template <isQuantity Q> constexpr double getInternal ( const Q& lhs) { return lhs. internal (); }
418-
419- constexpr double getInternal ( double lhs) { return lhs; }
416+ constexpr bool isNan ( double lhs) {
417+ // Use the fact that NaN is not equal to itself
418+ return lhs != lhs;
419+ }
420420
421- template <isArithmetic Q> constexpr bool isNan (const Q& lhs) { return lhs != lhs ; }
421+ template <isQuantity Q> constexpr bool isNan (const Q& lhs) { return isNan ( lhs. internal ()) ; }
422422
423- template <isArithmetic Q> constexpr Q abs (const Q& lhs) { return Q (std::abs (getInternal ( lhs))); }
423+ template <isQuantity Q> constexpr Q abs (const Q& lhs) { return Q (std::abs (lhs. internal ( ))); }
424424
425- template <isArithmetic Q, isArithmetic R> constexpr Q max (const Q& lhs, const R& rhs)
425+ template <isQuantity Q, isQuantity R> constexpr Q max (const Q& lhs, const R& rhs)
426426 requires Isomorphic<Q, R>
427427{
428428 return (lhs > rhs ? lhs : rhs);
429429}
430430
431- template <isArithmetic Q, isArithmetic R> constexpr Q min (const Q& lhs, const R& rhs)
431+ template <isQuantity Q, isQuantity R> constexpr Q min (const Q& lhs, const R& rhs)
432432 requires Isomorphic<Q, R>
433433{
434434 return (lhs < rhs ? lhs : rhs);
@@ -440,77 +440,73 @@ constexpr double sgn(double lhs) {
440440 return lhs;
441441}
442442
443- template <isArithmetic Q> constexpr double sgn (const Q& lhs) { return sgn (lhs.internal ()); }
443+ template <isQuantity Q> constexpr double sgn (const Q& lhs) { return sgn (lhs.internal ()); }
444444
445- template <int R, isArithmetic Q, isArithmetic S = Exponentiated<Q, std::ratio<R>>> constexpr S pow (const Q& lhs) {
445+ template <int R, isQuantity Q, isQuantity S = Exponentiated<Q, std::ratio<R>>> constexpr S pow (const Q& lhs) {
446446 return S (std::pow (lhs.internal (), R));
447447}
448448
449- template <isArithmetic Q, isArithmetic S = Exponentiated<Q, std::ratio<2 >>> constexpr S square (const Q& lhs) {
449+ template <isQuantity Q, isQuantity S = Exponentiated<Q, std::ratio<2 >>> constexpr S square (const Q& lhs) {
450450 return pow<2 >(lhs);
451451}
452452
453- template <isArithmetic Q, isArithmetic S = Exponentiated<Q, std::ratio<3 >>> constexpr S cube (const Q& lhs) {
453+ template <isQuantity Q, isQuantity S = Exponentiated<Q, std::ratio<3 >>> constexpr S cube (const Q& lhs) {
454454 return pow<3 >(lhs);
455455}
456456
457- template <int R, isArithmetic Q, isArithmetic S = Rooted<Q, std::ratio<R>>> constexpr S root (const Q& lhs) {
457+ template <int R, isQuantity Q, isQuantity S = Rooted<Q, std::ratio<R>>> constexpr S root (const Q& lhs) {
458458 return S (std::pow (lhs.internal (), 1.0 / R));
459459}
460460
461- template <isArithmetic Q, isArithmetic S = Rooted<Q, std::ratio<2 >>> constexpr S sqrt (const Q& lhs) {
462- return root<2 >(lhs);
463- }
461+ template <isQuantity Q, isQuantity S = Rooted<Q, std::ratio<2 >>> constexpr S sqrt (const Q& lhs) { return root<2 >(lhs); }
464462
465- template <isArithmetic Q, isArithmetic S = Rooted<Q, std::ratio<3 >>> constexpr S cbrt (const Q& lhs) {
466- return root<3 >(lhs);
467- }
463+ template <isQuantity Q, isQuantity S = Rooted<Q, std::ratio<3 >>> constexpr S cbrt (const Q& lhs) { return root<3 >(lhs); }
468464
469- template <isArithmetic Q, isArithmetic R> constexpr Q hypot (const Q& lhs, const R& rhs)
465+ template <isQuantity Q, isQuantity R> constexpr Q hypot (const Q& lhs, const R& rhs)
470466 requires Isomorphic<Q, R>
471467{
472468 return Q (std::hypot (lhs.internal (), rhs.internal ()));
473469}
474470
475- template <isArithmetic Q, isArithmetic R> constexpr Q mod (const Q& lhs, const R& rhs) {
471+ template <isQuantity Q, isQuantity R> constexpr Q mod (const Q& lhs, const R& rhs) {
476472 return Q (std::fmod (lhs.internal (), rhs.internal ()));
477473}
478474
479- template <isArithmetic Q, isArithmetic R> constexpr Q remainder (const Q& lhs, const R& rhs) {
475+ template <isQuantity Q, isQuantity R> constexpr Q remainder (const Q& lhs, const R& rhs) {
480476 return Q (std::remainder (lhs.internal (), rhs.internal ()));
481477}
482478
483- template <isArithmetic Q1, isArithmetic Q2> constexpr Q1 copysign (const Q1& lhs, const Q2& rhs) {
479+ template <isQuantity Q1, isQuantity Q2> constexpr Q1 copysign (const Q1& lhs, const Q2& rhs) {
484480 return Q1 (std::copysign (lhs.internal (), rhs.internal ()));
485481}
486482
487- template <isArithmetic Q> constexpr bool signbit (const Q& lhs) { return std::signbit (lhs.internal ()); }
483+ template <isQuantity Q> constexpr bool signbit (const Q& lhs) { return std::signbit (lhs.internal ()); }
488484
489- template <isArithmetic Q, isArithmetic R, isArithmetic S> constexpr Q clamp (const Q& lhs, const R& lo, const S& hi)
485+ template <isQuantity Q, isQuantity R, isQuantity S> constexpr Q clamp (const Q& lhs, const R& lo, const S& hi)
490486 requires Isomorphic<Q, R, S>
491487{
492488 return Q (std::clamp (lhs.internal (), lo.internal (), hi.internal ()));
493489}
494490
495- template <isArithmetic Q, isArithmetic R> constexpr Q ceil (const Q& lhs, const R& rhs)
491+ template <isQuantity Q, isQuantity R> constexpr Q ceil (const Q& lhs, const R& rhs)
496492 requires Isomorphic<Q, R>
497493{
498494 return Q (std::ceil (lhs.internal () / rhs.internal ()) * rhs.internal ());
499495}
500496
501- template <isArithmetic Q, isArithmetic R> constexpr Q floor (const Q& lhs, const R& rhs)
497+ template <isQuantity Q, isQuantity R> constexpr Q floor (const Q& lhs, const R& rhs)
502498 requires Isomorphic<Q, R>
503499{
504500 return Q (std::floor (lhs.internal () / rhs.internal ()) * rhs.internal ());
505501}
506502
507- template <isArithmetic Q, isArithmetic R> constexpr Q trunc (const Q& lhs, const R& rhs)
503+ template <isQuantity Q, isQuantity R> constexpr Q trunc (const Q& lhs, const R& rhs)
508504 requires Isomorphic<Q, R>
509505{
510506 return Q (std::trunc (lhs.internal () / rhs.internal ()) * rhs.internal ());
511507}
512508
513- template <isArithmetic Q, isArithmetic R> constexpr Q round (const Q& lhs, const R& rhs)
509+ template <isQuantity Q, isQuantity R> constexpr Q round (const Q& lhs, const R& rhs)
514510 requires Isomorphic<Q, R>
515511{
516512 return Q (std::round (lhs.internal () / rhs.internal ()) * rhs.internal ());
0 commit comments