SyDEVS  v0.6.7
Multiscale Simulation and Systems Modeling Library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
quantity.h
Go to the documentation of this file.
1 #pragma once
2 #ifndef SYDEVS_QUANTITY_H_
3 #define SYDEVS_QUANTITY_H_
4 
5 #include <sydevs/core/units.h>
6 #include <cmath>
7 #include <ostream>
8 
9 namespace sydevs {
10 
11 
12 constexpr int64 quantity_limit = int64(1)*1000*1000*1000*1000*1000;
13 
14 
20 {
21 public:
22  constexpr bool valid() const;
23  constexpr bool finite() const;
24  constexpr int64 multiplier() const;
25  constexpr scale precision() const;
26  constexpr bool fixed() const;
27 
28 protected:
29  constexpr quantity_base();
30  explicit constexpr quantity_base(int64 multiplier);
31  constexpr quantity_base(int64 multiplier, scale precision);
32  constexpr quantity_base(int64 multiplier, scale precision, bool fixed);
33  constexpr quantity_base(scale precision, float64 multiplier, int8 fixed);
34 
35  constexpr quantity_base(const quantity_base&) = default;
36  quantity_base& operator=(const quantity_base&) = default;
37  quantity_base(quantity_base&&) = default;
38  quantity_base& operator=(quantity_base&&) = default;
39  ~quantity_base() = default;
40 
41  static constexpr float64 inf_float64 = std::numeric_limits<float64>::infinity();
42  static constexpr float64 nan_float64 = std::numeric_limits<float64>::quiet_NaN();
43  static constexpr int64 inf_int64 = std::numeric_limits<int64>::max();
44  static constexpr int64 nan_int64 = std::numeric_limits<int64>::min();
45 
46  static constexpr int64 constexpr_abs(int64 n);
47  static constexpr float64 constexpr_abs(float64 x);
48  static constexpr float64 convert_multiplier(int64 multiplier);
49  static constexpr int64 convert_level(int64 multiplier, int64 level);
50  static constexpr float64 offset_multiplier(float64 multiplier);
51  static constexpr int64 truncate_multiplier(float64 multiplier);
52  static constexpr int64 round_multiplier(float64 multiplier);
53  static constexpr int64 scale_multiplier(float64 multiplier, float64 factor);
54 
58 };
59 
60 
233 template<typename U>
234 class quantity : public quantity_base
235 {
236 template<typename U_> friend class quantity;
237 public:
241  constexpr quantity();
242 
255  explicit constexpr quantity(int64 multiplier);
256 
271 
272  constexpr quantity(const quantity&) = default;
273  quantity& operator=(const quantity&) = default;
274  quantity(quantity&&) = default;
275  quantity& operator=(quantity&&) = default;
276  ~quantity() = default;
277 
278  static constexpr quantity inf();
279  static constexpr quantity max(scale precision);
280 
281  constexpr const quantity fixed_at(scale precision) const;
282  constexpr const quantity rescaled(scale precision) const;
283  constexpr const quantity refined() const;
284  constexpr const quantity coarsened() const;
285  constexpr const quantity unfixed() const;
286 
289  quantity& operator*=(float64 rhs);
290  quantity& operator/=(float64 rhs);
291 
292  constexpr const quantity operator+() const;
293  constexpr const quantity operator-() const;
294 
295  constexpr const quantity operator+(quantity rhs) const;
296  constexpr const quantity operator-(quantity rhs) const;
297 
298  constexpr const quantity operator*(float64 rhs) const;
299  constexpr const quantity operator/(float64 rhs) const;
300 
301  template<typename U_>
303 
304  template<typename U_>
305  constexpr quantity<decltype(U()/U_())> operator/(quantity<U_> rhs) const;
306 
307  template<typename U_>
308  constexpr quantity<decltype(U()*U_())> operator*(U_ rhs) const;
309 
310  template<typename U_>
311  constexpr quantity<decltype(U()/U_())> operator/(U_ rhs) const;
312 
313  constexpr bool operator==(quantity rhs) const;
314  constexpr bool operator!=(quantity rhs) const;
315  constexpr bool operator<(quantity rhs) const;
316  constexpr bool operator>(quantity rhs) const;
317  constexpr bool operator<=(quantity rhs) const;
318  constexpr bool operator>=(quantity rhs) const;
319 
320 private:
321  constexpr quantity(int64 multiplier, scale precision, bool fixed);
323 
324  constexpr quantity autoscaled() const;
325  constexpr quantity autorounded() const;
326 };
327 
328 
333 template<>
335 {
336 template<typename U_> friend class quantity;
337 public:
338  constexpr quantity();
339  explicit constexpr quantity(int64 multiplier);
341 
342  constexpr quantity(const quantity&) = default;
343  quantity& operator=(const quantity&) = default;
344  quantity(quantity&&) = default;
345  quantity& operator=(quantity&&) = default;
346  ~quantity() = default;
347 
348  static constexpr quantity inf();
349  static constexpr quantity max(scale precision);
350 
351  constexpr const quantity fixed_at(scale precision) const;
352  constexpr const quantity rescaled(scale precision) const;
353  constexpr const quantity refined() const;
354  constexpr const quantity coarsened() const;
355  constexpr const quantity unfixed() const;
356 
357  constexpr const quantity operator+() const;
358  constexpr const quantity operator-() const;
359 
360  constexpr const quantity operator+(quantity rhs) const;
361  constexpr const quantity operator-(quantity rhs) const;
362 
363  constexpr const quantity operator*(float64 rhs) const;
364  constexpr const quantity operator/(float64 rhs) const;
365 
366  template<typename U_>
367  constexpr quantity<U_> operator*(quantity<U_> rhs) const;
368 
369  template<typename U_>
370  constexpr quantity<decltype(_1/U_())> operator/(quantity<U_> rhs) const;
371 
372  template<typename U_>
373  constexpr quantity<U_> operator*(U_ rhs) const;
374 
375  template<typename U_>
376  constexpr quantity<decltype(_1/U_())> operator/(U_ rhs) const;
377 
378  constexpr operator float64() const;
379 
380 private:
381  constexpr quantity(int64 multiplier, scale precision, bool fixed);
383 
384  constexpr quantity autoscaled() const;
385  constexpr quantity autorounded() const;
386 };
387 
388 
389 constexpr bool quantity_base::valid() const
390 {
391  return multiplier_ == multiplier_;
392 }
393 
394 
395 constexpr bool quantity_base::finite() const
396 {
397  return multiplier_ < inf_float64 && multiplier_ > -inf_float64;
398 }
399 
400 
402 {
403  return !valid() ? nan_int64 :
407 }
408 
409 
411 {
412  return precision_;
413 }
414 
415 
416 constexpr bool quantity_base::fixed() const
417 {
418  return fixed_ == 1;
419 }
420 
421 
423  : multiplier_(nan_float64)
424  , precision_(unit)
425  , fixed_(0)
426 {
427 }
428 
429 
430 constexpr quantity_base::quantity_base(int64 multiplier)
431  : multiplier_(convert_multiplier(multiplier))
432  , precision_(unit)
433  , fixed_(0)
434 {
435 }
436 
437 
438 constexpr quantity_base::quantity_base(int64 multiplier, scale precision)
439  : multiplier_(convert_multiplier(multiplier))
440  , precision_(convert_level(multiplier, precision.level()))
441  , fixed_(0)
442 {
443 }
444 
445 
446 constexpr quantity_base::quantity_base(int64 multiplier, scale precision, bool fixed)
447  : multiplier_(convert_multiplier(multiplier))
448  , precision_(convert_level(multiplier, precision.level()))
449  , fixed_(fixed)
450 {
451 }
452 
453 
454 constexpr quantity_base::quantity_base(scale precision, float64 multiplier, int8 fixed)
455  : multiplier_(multiplier)
456  , precision_(precision)
457  , fixed_(fixed)
458 {
459 }
460 
461 
463 {
464  return n < 0 ? -n : n;
465 }
466 
467 
469 {
470  return x < 0 ? -x : x;
471 }
472 
473 
475 {
476  return multiplier == nan_int64 ? nan_float64 :
477  multiplier >= quantity_limit ? inf_float64 :
478  multiplier <= -quantity_limit ? -inf_float64 :
479  float64(multiplier);
480 }
481 
482 
483 constexpr int64 quantity_base::convert_level(int64 multiplier, int64 level)
484 {
485  return multiplier == nan_int64 || constexpr_abs(multiplier) >= quantity_limit ? 0 :
486  level;
487 }
488 
489 
491 {
492  return multiplier >= 0 ? multiplier + 0.5 :
493  multiplier - 0.5;
494 }
495 
496 
498 {
499  return multiplier >= quantity_limit ? inf_int64 :
500  multiplier <= -quantity_limit ? -inf_int64 :
501  int64(multiplier);
502 }
503 
504 
506 {
507  return truncate_multiplier(offset_multiplier(multiplier));
508 }
509 
510 
512 {
513  return factor >= 1 ? truncate_multiplier(offset_multiplier(factor*multiplier)) :
514  truncate_multiplier(factor*offset_multiplier(multiplier));
515 }
516 
517 
518 template<typename U>
520  : quantity_base()
521 {
522 }
523 
524 
526  : quantity_base()
527 {
528 }
529 
530 
531 template<typename U>
532 constexpr quantity<U>::quantity(int64 multiplier)
533  : quantity_base(multiplier)
534 {
535 }
536 
537 
538 constexpr quantity<no_units>::quantity(int64 multiplier)
539  : quantity_base(multiplier)
540 {
541 }
542 
543 
544 template<typename U>
545 constexpr quantity<U>::quantity(int64 multiplier, scale precision)
546  : quantity_base(multiplier, precision)
547 {
548 }
549 
550 
551 constexpr quantity<no_units>::quantity(int64 multiplier, scale precision)
552  : quantity_base(multiplier, precision)
553 {
554 }
555 
556 
557 template<typename U>
558 constexpr quantity<U>::quantity(int64 multiplier, scale precision, bool fixed)
559  : quantity_base(multiplier, precision, fixed)
560 {
561 }
562 
563 
564 constexpr quantity<no_units>::quantity(int64 multiplier, scale precision, bool fixed)
565  : quantity_base(multiplier, precision, fixed)
566 {
567 }
568 
569 
570 template<typename U>
571 constexpr quantity<U>::quantity(scale precision, float64 multiplier, int8 fixed)
572  : quantity_base(precision, multiplier, fixed)
573 {
574 }
575 
576 
577 constexpr quantity<no_units>::quantity(scale precision, float64 multiplier, int8 fixed)
578  : quantity_base(precision, multiplier, fixed)
579 {
580 }
581 
582 
583 template<typename U>
585 {
586  return quantity<U>(quantity_limit);
587 }
588 
589 
591 {
593 }
594 
595 
596 template<typename U>
597 constexpr quantity<U> quantity<U>::max(scale precision)
598 {
599  return quantity<U>(quantity_limit - 1, precision);
600 }
601 
602 
604 {
606 }
607 
608 
609 template<typename U>
610 constexpr const quantity<U> quantity<U>::fixed_at(scale precision) const
611 {
612  return !valid() ? quantity<U>() :
613  quantity<U>(scale_multiplier(multiplier_, precision_/precision), precision, int8(1));
614 }
615 
616 
617 constexpr const quantity<no_units> quantity<no_units>::fixed_at(scale precision) const
618 {
619  return !valid() ? quantity<no_units>() :
621 }
622 
623 
624 template<typename U>
625 constexpr const quantity<U> quantity<U>::rescaled(scale precision) const
626 {
627  return !valid() ? quantity<U>() :
628  quantity<U>(scale_multiplier(multiplier_, precision_/precision), precision, fixed_ == 1);
629 }
630 
631 
632 constexpr const quantity<no_units> quantity<no_units>::rescaled(scale precision) const
633 {
634  return !valid() ? quantity<no_units>() :
636 }
637 
638 
639 template<typename U>
640 constexpr const quantity<U> quantity<U>::refined() const
641 {
642  return !valid() ? quantity<U>() :
643  !finite() ? *this :
644  multiplier_ == 0 ? quantity<U>(0) :
645  constexpr_abs(round_multiplier(1000.0*multiplier_)) >= quantity_limit ? *this :
646  quantity<U>(precision_ - 1, 1000.0*multiplier_, int8(0)).autorounded().refined();
647 }
648 
649 
651 {
652  return !valid() ? quantity<no_units>() :
653  !finite() ? *this :
654  multiplier_ == 0 ? quantity<no_units>(0) :
656  quantity<no_units>(precision_ - 1, 1000.0*multiplier_, int8(0)).autorounded().refined();
657 }
658 
659 
660 template<typename U>
661 constexpr const quantity<U> quantity<U>::coarsened() const
662 {
663  return !valid() ? quantity<U>() :
664  !finite() ? *this :
665  multiplier_ == 0 ? quantity<U>(0) :
666  multiplier_ != 1000.0*round_multiplier(0.001*multiplier_) ? *this :
667  quantity<U>(precision_ + 1, float64(round_multiplier(0.001*multiplier_)), int8(0)).coarsened();
668 }
669 
670 
672 {
673  return !valid() ? quantity<no_units>() :
674  !finite() ? *this :
675  multiplier_ == 0 ? quantity<no_units>(0) :
676  multiplier_ != 1000.0*round_multiplier(0.001*multiplier_) ? *this :
678 }
679 
680 
681 template<typename U>
682 constexpr const quantity<U> quantity<U>::unfixed() const
683 {
684  return quantity<U>(precision_, multiplier_, int8(0));
685 }
686 
687 
689 {
691 }
692 
693 
694 template<typename U>
696 {
697  *this = *this + rhs;
698  return *this;
699 }
700 
701 
702 template<typename U>
704 {
705  *this = *this - rhs;
706  return *this;
707 }
708 
709 
710 template<typename U>
712 {
713  *this = *this*rhs;
714  return *this;
715 }
716 
717 
718 template<typename U>
720 {
721  *this = *this/rhs;
722  return *this;
723 }
724 
725 
726 template<typename U>
727 constexpr const quantity<U> quantity<U>::operator+() const
728 {
729  return quantity<U>(precision_, multiplier_, fixed_);
730 }
731 
732 
734 {
736 }
737 
738 
739 template<typename U>
740 constexpr const quantity<U> quantity<U>::operator-() const
741 {
742  return quantity<U>(precision_, -multiplier_, fixed_);
743 }
744 
745 
747 {
749 }
750 
751 
752 template<typename U>
753 constexpr const quantity<U> quantity<U>::operator+(quantity rhs) const
754 {
755  return fixed_ && rhs.fixed_ ? precision_ == rhs.precision_ ? quantity<U>(precision_, multiplier_ + rhs.multiplier_, int8(1)).autorounded() :
756  quantity<U>() :
757  fixed_ ? quantity<U>(precision_, multiplier_ + (rhs.precision_/precision_)*rhs.multiplier_, int8(1)).autorounded() :
758  rhs.fixed_ ? quantity<U>(rhs.precision_, (precision_/rhs.precision_)*multiplier_ + rhs.multiplier_, int8(1)).autorounded() :
759  precision_ <= rhs.precision_ ? quantity<U>(precision_, multiplier_ + (rhs.precision_/precision_)*rhs.multiplier_, int8(0)).autoscaled() :
760  quantity<U>(rhs.precision_, (precision_/rhs.precision_)*multiplier_ + rhs.multiplier_, int8(0)).autoscaled();
761 }
762 
763 
765 {
766  return fixed_ && rhs.fixed_ ? precision_ == rhs.precision_ ? quantity<no_units>(precision_, multiplier_ + rhs.multiplier_, int8(1)).autorounded() :
768  fixed_ ? quantity<no_units>(precision_, multiplier_ + (rhs.precision_/precision_)*rhs.multiplier_, int8(1)).autorounded() :
769  rhs.fixed_ ? quantity<no_units>(rhs.precision_, (precision_/rhs.precision_)*multiplier_ + rhs.multiplier_, int8(1)).autorounded() :
770  precision_ <= rhs.precision_ ? quantity<no_units>(precision_, multiplier_ + (rhs.precision_/precision_)*rhs.multiplier_, int8(0)).autoscaled() :
771  quantity<no_units>(rhs.precision_, (precision_/rhs.precision_)*multiplier_ + rhs.multiplier_, int8(0)).autoscaled();
772 }
773 
774 
775 template<typename U>
776 constexpr const quantity<U> quantity<U>::operator-(quantity rhs) const
777 {
778  return fixed_ && rhs.fixed_ ? precision_ == rhs.precision_ ? quantity<U>(precision_, multiplier_ - rhs.multiplier_, int8(1)).autorounded() :
779  quantity<U>() :
780  fixed_ ? quantity<U>(precision_, multiplier_ - (rhs.precision_/precision_)*rhs.multiplier_, int8(1)).autorounded() :
781  rhs.fixed_ ? quantity<U>(rhs.precision_, (precision_/rhs.precision_)*multiplier_ - rhs.multiplier_, int8(1)).autorounded() :
782  precision_ <= rhs.precision_ ? quantity<U>(precision_, multiplier_ - (rhs.precision_/precision_)*rhs.multiplier_, int8(0)).autoscaled() :
783  quantity<U>(rhs.precision_, (precision_/rhs.precision_)*multiplier_ - rhs.multiplier_, int8(0)).autoscaled();
784 }
785 
786 
788 {
789  return fixed_ && rhs.fixed_ ? precision_ == rhs.precision_ ? quantity<no_units>(precision_, multiplier_ - rhs.multiplier_, int8(1)).autorounded() :
791  fixed_ ? quantity<no_units>(precision_, multiplier_ - (rhs.precision_/precision_)*rhs.multiplier_, int8(1)).autorounded() :
792  rhs.fixed_ ? quantity<no_units>(rhs.precision_, (precision_/rhs.precision_)*multiplier_ - rhs.multiplier_, int8(1)).autorounded() :
793  precision_ <= rhs.precision_ ? quantity<no_units>(precision_, multiplier_ - (rhs.precision_/precision_)*rhs.multiplier_, int8(0)).autoscaled() :
794  quantity<no_units>(rhs.precision_, (precision_/rhs.precision_)*multiplier_ - rhs.multiplier_, int8(0)).autoscaled();
795 }
796 
797 
798 template<typename U>
799 constexpr const quantity<U> quantity<U>::operator*(float64 rhs) const
800 {
801  return fixed_ ? quantity<U>(precision_, multiplier_*rhs, int8(1)).autorounded() :
802  quantity<U>(precision_, multiplier_*rhs, int8(0)).autoscaled();
803 }
804 
805 
807 {
808  return fixed_ ? quantity<no_units>(precision_, multiplier_*rhs, int8(1)).autorounded() :
809  quantity<no_units>(precision_, multiplier_*rhs, int8(0)).autoscaled();
810 }
811 
812 
813 template<typename U>
814 constexpr const quantity<U> quantity<U>::operator/(float64 rhs) const
815 {
816  return fixed_ ? quantity<U>(precision_, multiplier_/rhs, int8(1)).autorounded() :
817  quantity<U>(precision_, multiplier_/rhs, int8(0)).autoscaled();
818 }
819 
820 
822 {
823  return fixed_ ? quantity<no_units>(precision_, multiplier_/rhs, int8(1)).autorounded() :
824  quantity<no_units>(precision_, multiplier_/rhs, int8(0)).autoscaled();
825 }
826 
827 
828 template<typename U>
829 template<typename U_>
831 {
832  return quantity<decltype(U()*U_())>(precision_ + rhs.precision().level(), multiplier_*rhs.multiplier(), int8(0)).autoscaled();
833 }
834 
835 
836 template<typename U_>
838 {
839  return quantity<U_>(precision_ + rhs.precision().level(), multiplier_*rhs.multiplier(), int8(0)).autoscaled();
840 }
841 
842 
843 template<typename U>
844 template<typename U_>
845 constexpr quantity<decltype(U()/U_())> quantity<U>::operator/(quantity<U_> rhs) const
846 {
847  return !rhs.valid() ? quantity<decltype(U()/U_())>() :
848  quantity<decltype(U()/U_())>(precision_ - rhs.precision().level(), multiplier_/rhs.multiplier(), int8(0)).autoscaled();
849 }
850 
851 
852 template<typename U_>
853 constexpr quantity<decltype(_1/U_())> quantity<no_units>::operator/(quantity<U_> rhs) const
854 {
855  return !rhs.valid() ? quantity<decltype(_1/U_())>() :
856  quantity<decltype(_1/U_())>(precision_ - rhs.precision().level(), multiplier_/rhs.multiplier(), int8(0)).autoscaled();
857 }
858 
859 
860 template<typename U>
861 template<typename U_>
863 {
864  return quantity<decltype(U()*U_())>(precision_, multiplier_, int8(0));
865 }
866 
867 
868 template<typename U_>
870 {
872 }
873 
874 
875 template<typename U>
876 template<typename U_>
877 constexpr quantity<decltype(U()/U_())> quantity<U>::operator/(U_ rhs) const
878 {
879  return quantity<decltype(U()/U_())>(precision_, multiplier_, int8(0));
880 }
881 
882 
883 template<typename U_>
884 constexpr quantity<decltype(_1/U_())> quantity<no_units>::operator/(U_ rhs) const
885 {
886  return quantity<decltype(_1/U_())>(precision_, multiplier_, int8(0));
887 }
888 
889 
890 template<typename U>
891 constexpr bool quantity<U>::operator==(quantity<U> rhs) const
892 {
893  return precision_ <= rhs.precision_ ? multiplier_ == (rhs.precision_/precision_)*rhs.multiplier_ :
894  (precision_/rhs.precision_)*multiplier_ == rhs.multiplier_;
895 }
896 
897 
898 template<typename U>
899 constexpr bool quantity<U>::operator!=(quantity<U> rhs) const
900 {
901  return precision_ <= rhs.precision_ ? multiplier_ != (rhs.precision_/precision_)*rhs.multiplier_ :
902  (precision_/rhs.precision_)*multiplier_ != rhs.multiplier_;
903 }
904 
905 
906 template<typename U>
907 constexpr bool quantity<U>::operator<(quantity<U> rhs) const
908 {
909  return precision_ <= rhs.precision_ ? multiplier_ < (rhs.precision_/precision_)*rhs.multiplier_ :
910  (precision_/rhs.precision_)*multiplier_ < rhs.multiplier_;
911 }
912 
913 
914 template<typename U>
915 constexpr bool quantity<U>::operator>(quantity<U> rhs) const
916 {
917  return precision_ <= rhs.precision_ ? multiplier_ > (rhs.precision_/precision_)*rhs.multiplier_ :
918  (precision_/rhs.precision_)*multiplier_ > rhs.multiplier_;
919 }
920 
921 
922 template<typename U>
923 constexpr bool quantity<U>::operator<=(quantity<U> rhs) const
924 {
925  return precision_ <= rhs.precision_ ? multiplier_ <= (rhs.precision_/precision_)*rhs.multiplier_ :
926  (precision_/rhs.precision_)*multiplier_ <= rhs.multiplier_;
927 }
928 
929 
930 template<typename U>
931 constexpr bool quantity<U>::operator>=(quantity<U> rhs) const
932 {
933  return precision_ <= rhs.precision_ ? multiplier_ >= (rhs.precision_/precision_)*rhs.multiplier_ :
934  (precision_/rhs.precision_)*multiplier_ >= rhs.multiplier_;
935 }
936 
937 
938 template<typename U>
939 constexpr quantity<U> quantity<U>::autoscaled() const
940 {
941  return !valid() ? quantity<U>() :
942  multiplier_ == inf_float64 ? quantity<U>::inf() :
943  multiplier_ == -inf_float64 ? -quantity<U>::inf() :
944  constexpr_abs(multiplier_) + 0.5 >= quantity_limit ? quantity<U>(precision_ + 1, 0.001*multiplier_, int8(0)).autoscaled() :
945  1000.0*constexpr_abs(multiplier_) + 0.5 >= quantity_limit ? autorounded() :
946  multiplier_ == int64(multiplier_) ? autorounded() :
947  quantity<U>(precision_ - 1, 1000.0*multiplier_, int8(0)).autoscaled();
948 }
949 
950 
951 constexpr quantity<no_units> quantity<no_units>::autoscaled() const
952 {
953  return !valid() ? quantity<no_units>() :
956  constexpr_abs(multiplier_) + 0.5 >= quantity_limit ? quantity<no_units>(precision_ + 1, 0.001*multiplier_, int8(0)).autoscaled() :
957  1000.0*constexpr_abs(multiplier_) + 0.5 >= quantity_limit ? autorounded() :
958  multiplier_ == int64(multiplier_) ? autorounded() :
959  quantity<no_units>(precision_ - 1, 1000.0*multiplier_, int8(0)).autoscaled();
960 }
961 
962 
963 template<typename U>
964 constexpr quantity<U> quantity<U>::autorounded() const
965 {
966  return !valid() ? quantity<U>() :
967  multiplier_ + 0.5 >= quantity_limit ? quantity<U>::inf() :
968  multiplier_ - 0.5 <= -quantity_limit ? -quantity<U>::inf() :
969  quantity(int64(offset_multiplier(multiplier_)), precision_, fixed_ == 1);
970 }
971 
972 
973 constexpr quantity<no_units> quantity<no_units>::autorounded() const
974 {
975  return !valid() ? quantity<no_units>() :
977  multiplier_ - 0.5 <= -quantity_limit ? -quantity<no_units>::inf() :
979 }
980 
981 
983 {
984  return precision_ == unit ? multiplier_ :
985  precision_ < unit ? 0.001*float64(quantity<no_units>(precision_ + 1, multiplier_, int8(0))) :
986  1000.0*float64(quantity<no_units>(precision_ - 1, multiplier_, int8(0)));
987 }
988 
989 
990 template<typename U>
991 constexpr const quantity<U> operator*(float64 lhs, quantity<U> rhs)
992 {
993  return rhs*lhs;
994 }
995 
996 
997 template<typename U>
998 constexpr const quantity<decltype(_1/U())> operator/(float64 lhs, quantity<U> rhs)
999 {
1000  return (quantity<no_units>(1)*lhs)/rhs;
1001 }
1002 
1003 
1011 
1012 
1013 constexpr mass operator"" _yg(unsigned long long multiplier) { return mass(int64(multiplier), yocto); }
1014 constexpr mass operator"" _zg(unsigned long long multiplier) { return mass(int64(multiplier), zepto); }
1015 constexpr mass operator"" _ag(unsigned long long multiplier) { return mass(int64(multiplier), atto); }
1016 constexpr mass operator"" _fg(unsigned long long multiplier) { return mass(int64(multiplier), femto); }
1017 constexpr mass operator"" _pg(unsigned long long multiplier) { return mass(int64(multiplier), pico); }
1018 constexpr mass operator"" _ng(unsigned long long multiplier) { return mass(int64(multiplier), nano); }
1019 constexpr mass operator"" _ug(unsigned long long multiplier) { return mass(int64(multiplier), micro); }
1020 constexpr mass operator"" _mg(unsigned long long multiplier) { return mass(int64(multiplier), milli); }
1021 constexpr mass operator"" _g(unsigned long long multiplier) { return mass(int64(multiplier)); }
1022 constexpr mass operator"" _kg(unsigned long long multiplier) { return mass(int64(multiplier), kilo); }
1023 constexpr mass operator"" _Mg(unsigned long long multiplier) { return mass(int64(multiplier), mega); }
1024 constexpr mass operator"" _Gg(unsigned long long multiplier) { return mass(int64(multiplier), giga); }
1025 constexpr mass operator"" _Tg(unsigned long long multiplier) { return mass(int64(multiplier), tera); }
1026 constexpr mass operator"" _Pg(unsigned long long multiplier) { return mass(int64(multiplier), peta); }
1027 constexpr mass operator"" _Eg(unsigned long long multiplier) { return mass(int64(multiplier), exa); }
1028 constexpr mass operator"" _Zg(unsigned long long multiplier) { return mass(int64(multiplier), zetta); }
1029 constexpr mass operator"" _Yg(unsigned long long multiplier) { return mass(int64(multiplier), yotta); }
1030 
1031 
1032 constexpr distance operator"" _ym(unsigned long long multiplier) { return distance(int64(multiplier), yocto); }
1033 constexpr distance operator"" _zm(unsigned long long multiplier) { return distance(int64(multiplier), zepto); }
1034 constexpr distance operator"" _am(unsigned long long multiplier) { return distance(int64(multiplier), atto); }
1035 constexpr distance operator"" _fm(unsigned long long multiplier) { return distance(int64(multiplier), femto); }
1036 constexpr distance operator"" _pm(unsigned long long multiplier) { return distance(int64(multiplier), pico); }
1037 constexpr distance operator"" _nm(unsigned long long multiplier) { return distance(int64(multiplier), nano); }
1038 constexpr distance operator"" _um(unsigned long long multiplier) { return distance(int64(multiplier), micro); }
1039 constexpr distance operator"" _mm(unsigned long long multiplier) { return distance(int64(multiplier), milli); }
1040 constexpr distance operator"" _m(unsigned long long multiplier) { return distance(int64(multiplier)); }
1041 constexpr distance operator"" _km(unsigned long long multiplier) { return distance(int64(multiplier), kilo); }
1042 constexpr distance operator"" _Mm(unsigned long long multiplier) { return distance(int64(multiplier), mega); }
1043 constexpr distance operator"" _Gm(unsigned long long multiplier) { return distance(int64(multiplier), giga); }
1044 constexpr distance operator"" _Tm(unsigned long long multiplier) { return distance(int64(multiplier), tera); }
1045 constexpr distance operator"" _Pm(unsigned long long multiplier) { return distance(int64(multiplier), peta); }
1046 constexpr distance operator"" _Em(unsigned long long multiplier) { return distance(int64(multiplier), exa); }
1047 constexpr distance operator"" _Zm(unsigned long long multiplier) { return distance(int64(multiplier), zetta); }
1048 constexpr distance operator"" _Ym(unsigned long long multiplier) { return distance(int64(multiplier), yotta); }
1049 
1050 
1051 constexpr duration operator"" _ys(unsigned long long multiplier) { return duration(int64(multiplier), yocto); }
1052 constexpr duration operator"" _zs(unsigned long long multiplier) { return duration(int64(multiplier), zepto); }
1053 constexpr duration operator"" _as(unsigned long long multiplier) { return duration(int64(multiplier), atto); }
1054 constexpr duration operator"" _fs(unsigned long long multiplier) { return duration(int64(multiplier), femto); }
1055 constexpr duration operator"" _ps(unsigned long long multiplier) { return duration(int64(multiplier), pico); }
1056 constexpr duration operator"" _ns(unsigned long long multiplier) { return duration(int64(multiplier), nano); }
1057 constexpr duration operator"" _us(unsigned long long multiplier) { return duration(int64(multiplier), micro); }
1058 constexpr duration operator"" _ms(unsigned long long multiplier) { return duration(int64(multiplier), milli); }
1059 constexpr duration operator"" _s(unsigned long long multiplier) { return duration(int64(multiplier)); }
1060 constexpr duration operator"" _ks(unsigned long long multiplier) { return duration(int64(multiplier), kilo); }
1061 constexpr duration operator"" _Ms(unsigned long long multiplier) { return duration(int64(multiplier), mega); }
1062 constexpr duration operator"" _Gs(unsigned long long multiplier) { return duration(int64(multiplier), giga); }
1063 constexpr duration operator"" _Ts(unsigned long long multiplier) { return duration(int64(multiplier), tera); }
1064 constexpr duration operator"" _Ps(unsigned long long multiplier) { return duration(int64(multiplier), peta); }
1065 constexpr duration operator"" _Es(unsigned long long multiplier) { return duration(int64(multiplier), exa); }
1066 constexpr duration operator"" _Zs(unsigned long long multiplier) { return duration(int64(multiplier), zetta); }
1067 constexpr duration operator"" _Ys(unsigned long long multiplier) { return duration(int64(multiplier), yotta); }
1068 
1069 constexpr duration operator"" _min(unsigned long long multiplier) { return duration(int64(60*multiplier)); }
1070 constexpr duration operator"" _hr(unsigned long long multiplier) { return duration(int64((60*60)*multiplier)); }
1071 constexpr duration operator"" _day(unsigned long long multiplier) { return duration(int64((60*60*24)*multiplier)); }
1072 constexpr duration operator"" _yr(unsigned long long multiplier) { return duration(int64((60*60*24*365)*multiplier)); }
1073 
1074 
1075 constexpr electric_current operator"" _yA(unsigned long long multiplier) { return electric_current(int64(multiplier), yocto); }
1076 constexpr electric_current operator"" _zA(unsigned long long multiplier) { return electric_current(int64(multiplier), zepto); }
1077 constexpr electric_current operator"" _aA(unsigned long long multiplier) { return electric_current(int64(multiplier), atto); }
1078 constexpr electric_current operator"" _fA(unsigned long long multiplier) { return electric_current(int64(multiplier), femto); }
1079 constexpr electric_current operator"" _pA(unsigned long long multiplier) { return electric_current(int64(multiplier), pico); }
1080 constexpr electric_current operator"" _nA(unsigned long long multiplier) { return electric_current(int64(multiplier), nano); }
1081 constexpr electric_current operator"" _uA(unsigned long long multiplier) { return electric_current(int64(multiplier), micro); }
1082 constexpr electric_current operator"" _mA(unsigned long long multiplier) { return electric_current(int64(multiplier), milli); }
1083 constexpr electric_current operator"" _A(unsigned long long multiplier) { return electric_current(int64(multiplier)); }
1084 constexpr electric_current operator"" _kA(unsigned long long multiplier) { return electric_current(int64(multiplier), kilo); }
1085 constexpr electric_current operator"" _MA(unsigned long long multiplier) { return electric_current(int64(multiplier), mega); }
1086 constexpr electric_current operator"" _GA(unsigned long long multiplier) { return electric_current(int64(multiplier), giga); }
1087 constexpr electric_current operator"" _TA(unsigned long long multiplier) { return electric_current(int64(multiplier), tera); }
1088 constexpr electric_current operator"" _PA(unsigned long long multiplier) { return electric_current(int64(multiplier), peta); }
1089 constexpr electric_current operator"" _EA(unsigned long long multiplier) { return electric_current(int64(multiplier), exa); }
1090 constexpr electric_current operator"" _ZA(unsigned long long multiplier) { return electric_current(int64(multiplier), zetta); }
1091 constexpr electric_current operator"" _YA(unsigned long long multiplier) { return electric_current(int64(multiplier), yotta); }
1092 
1093 
1094 constexpr thermodynamic_temperature operator"" _yK(unsigned long long multiplier) { return thermodynamic_temperature(int64(multiplier), yocto); }
1095 constexpr thermodynamic_temperature operator"" _zK(unsigned long long multiplier) { return thermodynamic_temperature(int64(multiplier), zepto); }
1096 constexpr thermodynamic_temperature operator"" _aK(unsigned long long multiplier) { return thermodynamic_temperature(int64(multiplier), atto); }
1097 constexpr thermodynamic_temperature operator"" _fK(unsigned long long multiplier) { return thermodynamic_temperature(int64(multiplier), femto); }
1098 constexpr thermodynamic_temperature operator"" _pK(unsigned long long multiplier) { return thermodynamic_temperature(int64(multiplier), pico); }
1099 constexpr thermodynamic_temperature operator"" _nK(unsigned long long multiplier) { return thermodynamic_temperature(int64(multiplier), nano); }
1100 constexpr thermodynamic_temperature operator"" _uK(unsigned long long multiplier) { return thermodynamic_temperature(int64(multiplier), micro); }
1101 constexpr thermodynamic_temperature operator"" _mK(unsigned long long multiplier) { return thermodynamic_temperature(int64(multiplier), milli); }
1102 constexpr thermodynamic_temperature operator"" _K(unsigned long long multiplier) { return thermodynamic_temperature(int64(multiplier)); }
1103 constexpr thermodynamic_temperature operator"" _kK(unsigned long long multiplier) { return thermodynamic_temperature(int64(multiplier), kilo); }
1104 constexpr thermodynamic_temperature operator"" _MK(unsigned long long multiplier) { return thermodynamic_temperature(int64(multiplier), mega); }
1105 constexpr thermodynamic_temperature operator"" _GK(unsigned long long multiplier) { return thermodynamic_temperature(int64(multiplier), giga); }
1106 constexpr thermodynamic_temperature operator"" _TK(unsigned long long multiplier) { return thermodynamic_temperature(int64(multiplier), tera); }
1107 constexpr thermodynamic_temperature operator"" _PK(unsigned long long multiplier) { return thermodynamic_temperature(int64(multiplier), peta); }
1108 constexpr thermodynamic_temperature operator"" _EK(unsigned long long multiplier) { return thermodynamic_temperature(int64(multiplier), exa); }
1109 constexpr thermodynamic_temperature operator"" _ZK(unsigned long long multiplier) { return thermodynamic_temperature(int64(multiplier), zetta); }
1110 constexpr thermodynamic_temperature operator"" _YK(unsigned long long multiplier) { return thermodynamic_temperature(int64(multiplier), yotta); }
1111 
1112 
1113 constexpr amount_of_substance operator"" _ymol(unsigned long long multiplier) { return amount_of_substance(int64(multiplier), yocto); }
1114 constexpr amount_of_substance operator"" _zmol(unsigned long long multiplier) { return amount_of_substance(int64(multiplier), zepto); }
1115 constexpr amount_of_substance operator"" _amol(unsigned long long multiplier) { return amount_of_substance(int64(multiplier), atto); }
1116 constexpr amount_of_substance operator"" _fmol(unsigned long long multiplier) { return amount_of_substance(int64(multiplier), femto); }
1117 constexpr amount_of_substance operator"" _pmol(unsigned long long multiplier) { return amount_of_substance(int64(multiplier), pico); }
1118 constexpr amount_of_substance operator"" _nmol(unsigned long long multiplier) { return amount_of_substance(int64(multiplier), nano); }
1119 constexpr amount_of_substance operator"" _umol(unsigned long long multiplier) { return amount_of_substance(int64(multiplier), micro); }
1120 constexpr amount_of_substance operator"" _mmol(unsigned long long multiplier) { return amount_of_substance(int64(multiplier), milli); }
1121 constexpr amount_of_substance operator"" _mol(unsigned long long multiplier) { return amount_of_substance(int64(multiplier)); }
1122 constexpr amount_of_substance operator"" _kmol(unsigned long long multiplier) { return amount_of_substance(int64(multiplier), kilo); }
1123 constexpr amount_of_substance operator"" _Mmol(unsigned long long multiplier) { return amount_of_substance(int64(multiplier), mega); }
1124 constexpr amount_of_substance operator"" _Gmol(unsigned long long multiplier) { return amount_of_substance(int64(multiplier), giga); }
1125 constexpr amount_of_substance operator"" _Tmol(unsigned long long multiplier) { return amount_of_substance(int64(multiplier), tera); }
1126 constexpr amount_of_substance operator"" _Pmol(unsigned long long multiplier) { return amount_of_substance(int64(multiplier), peta); }
1127 constexpr amount_of_substance operator"" _Emol(unsigned long long multiplier) { return amount_of_substance(int64(multiplier), exa); }
1128 constexpr amount_of_substance operator"" _Zmol(unsigned long long multiplier) { return amount_of_substance(int64(multiplier), zetta); }
1129 constexpr amount_of_substance operator"" _Ymol(unsigned long long multiplier) { return amount_of_substance(int64(multiplier), yotta); }
1130 
1131 
1132 constexpr luminous_intensity operator"" _ycd(unsigned long long multiplier) { return luminous_intensity(int64(multiplier), yocto); }
1133 constexpr luminous_intensity operator"" _zcd(unsigned long long multiplier) { return luminous_intensity(int64(multiplier), zepto); }
1134 constexpr luminous_intensity operator"" _acd(unsigned long long multiplier) { return luminous_intensity(int64(multiplier), atto); }
1135 constexpr luminous_intensity operator"" _fcd(unsigned long long multiplier) { return luminous_intensity(int64(multiplier), femto); }
1136 constexpr luminous_intensity operator"" _pcd(unsigned long long multiplier) { return luminous_intensity(int64(multiplier), pico); }
1137 constexpr luminous_intensity operator"" _ncd(unsigned long long multiplier) { return luminous_intensity(int64(multiplier), nano); }
1138 constexpr luminous_intensity operator"" _ucd(unsigned long long multiplier) { return luminous_intensity(int64(multiplier), micro); }
1139 constexpr luminous_intensity operator"" _mcd(unsigned long long multiplier) { return luminous_intensity(int64(multiplier), milli); }
1140 constexpr luminous_intensity operator"" _cd(unsigned long long multiplier) { return luminous_intensity(int64(multiplier)); }
1141 constexpr luminous_intensity operator"" _kcd(unsigned long long multiplier) { return luminous_intensity(int64(multiplier), kilo); }
1142 constexpr luminous_intensity operator"" _Mcd(unsigned long long multiplier) { return luminous_intensity(int64(multiplier), mega); }
1143 constexpr luminous_intensity operator"" _Gcd(unsigned long long multiplier) { return luminous_intensity(int64(multiplier), giga); }
1144 constexpr luminous_intensity operator"" _Tcd(unsigned long long multiplier) { return luminous_intensity(int64(multiplier), tera); }
1145 constexpr luminous_intensity operator"" _Pcd(unsigned long long multiplier) { return luminous_intensity(int64(multiplier), peta); }
1146 constexpr luminous_intensity operator"" _Ecd(unsigned long long multiplier) { return luminous_intensity(int64(multiplier), exa); }
1147 constexpr luminous_intensity operator"" _Zcd(unsigned long long multiplier) { return luminous_intensity(int64(multiplier), zetta); }
1148 constexpr luminous_intensity operator"" _Ycd(unsigned long long multiplier) { return luminous_intensity(int64(multiplier), yotta); }
1149 
1150 
1151 inline std::ostream& operator<<(std::ostream& os, const mass& rhs)
1152 {
1153  if (!rhs.valid()) {
1154  os << "mass()";
1155  }
1156  else {
1157  if (!rhs.finite()) {
1158  os << (rhs < 0_g ? "-" : "") << "mass::inf()";
1159  }
1160  else {
1161  if (rhs.precision() == unit) {
1162  os << rhs.multiplier() << "_g";
1163  }
1164  else if (rhs.precision() >= yocto && rhs.precision() <= yotta) {
1165  os << rhs.multiplier() << "_" << rhs.precision().symbol() << "g";
1166  }
1167  else {
1168  os << "mass(" << rhs.multiplier() << ", " << rhs.precision() << ")";
1169  }
1170  }
1171  }
1172  return os;
1173 }
1174 
1175 
1176 inline std::ostream& operator<<(std::ostream& os, const distance& rhs)
1177 {
1178  if (!rhs.valid()) {
1179  os << "distance()";
1180  }
1181  else {
1182  if (!rhs.finite()) {
1183  os << (rhs < 0_m ? "-" : "") << "distance::inf()";
1184  }
1185  else {
1186  if (rhs.precision() == unit) {
1187  os << rhs.multiplier() << "_m";
1188  }
1189  else if (rhs.precision() >= yocto && rhs.precision() <= yotta) {
1190  os << rhs.multiplier() << "_" << rhs.precision().symbol() << "m";
1191  }
1192  else {
1193  os << "distance(" << rhs.multiplier() << ", " << rhs.precision() << ")";
1194  }
1195  }
1196  }
1197  return os;
1198 }
1199 
1200 
1201 inline std::ostream& operator<<(std::ostream& os, const duration& rhs)
1202 {
1203  if (!rhs.valid()) {
1204  os << "duration()";
1205  }
1206  else {
1207  if (!rhs.finite()) {
1208  os << (rhs < 0_s ? "-" : "") << "duration::inf()";
1209  }
1210  else {
1211  if (rhs.precision() == unit) {
1212  os << rhs.multiplier() << "_s";
1213  }
1214  else if (rhs.precision() >= yocto && rhs.precision() <= yotta) {
1215  os << rhs.multiplier() << "_" << rhs.precision().symbol() << "s";
1216  }
1217  else {
1218  os << "duration(" << rhs.multiplier() << ", " << rhs.precision() << ")";
1219  }
1220  }
1221  }
1222  return os;
1223 }
1224 
1225 
1226 inline std::ostream& operator<<(std::ostream& os, const electric_current& rhs)
1227 {
1228  if (!rhs.valid()) {
1229  os << "electric_current()";
1230  }
1231  else {
1232  if (!rhs.finite()) {
1233  os << (rhs < 0_A ? "-" : "") << "electric_current::inf()";
1234  }
1235  else {
1236  if (rhs.precision() == unit) {
1237  os << rhs.multiplier() << "_A";
1238  }
1239  else if (rhs.precision() >= yocto && rhs.precision() <= yotta) {
1240  os << rhs.multiplier() << "_" << rhs.precision().symbol() << "A";
1241  }
1242  else {
1243  os << "electric_current(" << rhs.multiplier() << ", " << rhs.precision() << ")";
1244  }
1245  }
1246  }
1247  return os;
1248 }
1249 
1250 
1251 inline std::ostream& operator<<(std::ostream& os, const thermodynamic_temperature& rhs)
1252 {
1253  if (!rhs.valid()) {
1254  os << "thermodynamic_temperature()";
1255  }
1256  else {
1257  if (!rhs.finite()) {
1258  os << (rhs < 0_K ? "-" : "") << "thermodynamic_temperature::inf()";
1259  }
1260  else {
1261  if (rhs.precision() == unit) {
1262  os << rhs.multiplier() << "_K";
1263  }
1264  else if (rhs.precision() >= yocto && rhs.precision() <= yotta) {
1265  os << rhs.multiplier() << "_" << rhs.precision().symbol() << "K";
1266  }
1267  else {
1268  os << "thermodynamic_temperature(" << rhs.multiplier() << ", " << rhs.precision() << ")";
1269  }
1270  }
1271  }
1272  return os;
1273 }
1274 
1275 
1276 inline std::ostream& operator<<(std::ostream& os, const amount_of_substance& rhs)
1277 {
1278  if (!rhs.valid()) {
1279  os << "amount_of_substance()";
1280  }
1281  else {
1282  if (!rhs.finite()) {
1283  os << (rhs < 0_mol ? "-" : "") << "amount_of_substance::inf()";
1284  }
1285  else {
1286  if (rhs.precision() == unit) {
1287  os << rhs.multiplier() << "_mol";
1288  }
1289  else if (rhs.precision() >= yocto && rhs.precision() <= yotta) {
1290  os << rhs.multiplier() << "_" << rhs.precision().symbol() << "mol";
1291  }
1292  else {
1293  os << "amount_of_substance(" << rhs.multiplier() << ", " << rhs.precision() << ")";
1294  }
1295  }
1296  }
1297  return os;
1298 }
1299 
1300 
1301 inline std::ostream& operator<<(std::ostream& os, const luminous_intensity& rhs)
1302 {
1303  if (!rhs.valid()) {
1304  os << "luminous_intensity()";
1305  }
1306  else {
1307  if (!rhs.finite()) {
1308  os << (rhs < 0_cd ? "-" : "") << "luminous_intensity::inf()";
1309  }
1310  else {
1311  if (rhs.precision() == unit) {
1312  os << rhs.multiplier() << "_cd";
1313  }
1314  else if (rhs.precision() >= yocto && rhs.precision() <= yotta) {
1315  os << rhs.multiplier() << "_" << rhs.precision().symbol() << "cd";
1316  }
1317  else {
1318  os << "luminous_intensity(" << rhs.multiplier() << ", " << rhs.precision() << ")";
1319  }
1320  }
1321  }
1322  return os;
1323 }
1324 
1325 
1326 inline std::ostream& operator<<(std::ostream& os, const quantity<no_units>& rhs)
1327 {
1328  if (rhs.valid() && rhs < quantity<no_units>(0)) {
1329  os << "-";
1330  }
1331  os << "quantity<no_units>";
1332  if (!rhs.valid()) {
1333  os << "()";
1334  }
1335  else if (!rhs.finite()) {
1336  os << "::inf()";
1337  }
1338  else {
1339  os << "(" << (rhs.multiplier() < 0 ? -rhs.multiplier() : rhs.multiplier()) << ", " << rhs.precision() << ")";
1340  }
1341  return os;
1342 }
1343 
1344 
1345 template<typename U>
1346 inline std::ostream& operator<<(std::ostream& os, const quantity<U>& rhs)
1347 {
1348  if (rhs.valid() && rhs < quantity<U>(0)) {
1349  os << "-";
1350  }
1351  os << "quantity<decltype(";
1352  bool starting = true;
1353  for (int64 i = 0; i != U::g_; i += (U::g_ > 0 ? 1 : -1)) {
1354  if (U::g_ != 0) {
1355  os << (starting ? (U::g_ > 0 ? "" : "_1/") :
1356  (U::g_ > 0 ? "*" : "/"));
1357  }
1358  os << "_g";
1359  starting = false;
1360  }
1361  for (int64 i = 0; i != U::m_; i += (U::m_ > 0 ? 1 : -1)) {
1362  if (U::m_ != 0) {
1363  os << (starting ? (U::m_ > 0 ? "" : "_1/") :
1364  (U::m_ > 0 ? "*" : "/"));
1365  }
1366  os << "_m";
1367  starting = false;
1368  }
1369  for (int64 i = 0; i != U::s_; i += (U::s_ > 0 ? 1 : -1)) {
1370  if (U::s_ != 0) {
1371  os << (starting ? (U::s_ > 0 ? "" : "_1/") :
1372  (U::s_ > 0 ? "*" : "/"));
1373  }
1374  os << "_s";
1375  starting = false;
1376  }
1377  for (int64 i = 0; i != U::A_; i += (U::A_ > 0 ? 1 : -1)) {
1378  if (U::A_ != 0) {
1379  os << (starting ? (U::A_ > 0 ? "" : "_1/") :
1380  (U::A_ > 0 ? "*" : "/"));
1381  }
1382  os << "_A";
1383  starting = false;
1384  }
1385  for (int64 i = 0; i != U::K_; i += (U::K_ > 0 ? 1 : -1)) {
1386  if (U::K_ != 0) {
1387  os << (starting ? (U::K_ > 0 ? "" : "_1/") :
1388  (U::K_ > 0 ? "*" : "/"));
1389  }
1390  os << "_K";
1391  starting = false;
1392  }
1393  for (int64 i = 0; i != U::mol_; i += (U::mol_ > 0 ? 1 : -1)) {
1394  if (U::mol_ != 0) {
1395  os << (starting ? (U::mol_ > 0 ? "" : "_1/") :
1396  (U::mol_ > 0 ? "*" : "/"));
1397  }
1398  os << "_mol";
1399  starting = false;
1400  }
1401  for (int64 i = 0; i != U::cd_; i += (U::cd_ > 0 ? 1 : -1)) {
1402  if (U::cd_ != 0) {
1403  os << (starting ? (U::cd_ > 0 ? "" : "_1/") :
1404  (U::cd_ > 0 ? "*" : "/"));
1405  }
1406  os << "_cd";
1407  starting = false;
1408  }
1409  os << ")>";
1410  if (!rhs.valid()) {
1411  os << "()";
1412  }
1413  else if (!rhs.finite()) {
1414  os << "::inf()";
1415  }
1416  else {
1417  os << "(" << (rhs.multiplier() < 0 ? -rhs.multiplier() : rhs.multiplier()) << ", " << rhs.precision() << ")";
1418  }
1419  return os;
1420 }
1421 
1422 
1423 } // namespace
1424 
1425 #endif
quantity< amperes > electric_current
Definition: quantity.h:1007
static constexpr int64 round_multiplier(float64 multiplier)
Definition: quantity.h:505
~quantity_base()=default
Destructor.
constexpr scale pico
Definition: scale.h:159
constexpr scale exa
Definition: scale.h:169
quantity< candelas > luminous_intensity
Definition: quantity.h:1010
constexpr scale yotta
Definition: scale.h:171
constexpr const quantity operator-() const
Returns the negation of the quantity value.
Definition: quantity.h:740
units< 0, 0, 0, 0, 0, 0, 0 > no_units
Definition: units.h:115
constexpr auto _cd
Definition: units.h:132
constexpr quantity_base()
Definition: quantity.h:422
quantity< meters > distance
Definition: quantity.h:1005
std::ostream & operator<<(std::ostream &os, const arraynd< T, ndims > &rhs)
Definition: arraynd.h:1156
constexpr scale atto
Definition: scale.h:157
constexpr const quantity coarsened() const
Returns a new quantity value with the length precision maximized without losing precision.
Definition: quantity.h:661
constexpr int64 quantity_limit
The maximum precision multiplier, plus 1.
Definition: quantity.h:12
constexpr const quantity fixed_at(scale precision) const
Returns a new quantity value with the length precision changed and fixed.
Definition: quantity.h:610
constexpr scale nano
Definition: scale.h:160
static constexpr int64 scale_multiplier(float64 multiplier, float64 factor)
Definition: quantity.h:511
constexpr scale yocto
Definition: scale.h:155
float64 multiplier_
Definition: quantity.h:55
constexpr quantity()
Constructs an invalid quantity value.
Definition: quantity.h:519
A base class for quantities, defining operations that do not depend on the dimension.
Definition: quantity.h:19
constexpr auto _mol
Definition: units.h:131
quantity_base & operator=(const quantity_base &)=default
Copy assignment.
constexpr scale zetta
Definition: scale.h:170
constexpr auto _g
Definition: units.h:126
constexpr bool operator>(quantity rhs) const
Returns true if the quantity value is greater than rhs.
Definition: quantity.h:915
quantity< moles > amount_of_substance
Definition: quantity.h:1009
constexpr const quantity operator+() const
Returns a copy of the quantity value.
Definition: quantity.h:727
constexpr bool operator<(quantity rhs) const
Returns true if the quantity value is less than rhs.
Definition: quantity.h:907
constexpr bool fixed() const
Returns true if the quantity value has a fixed length precision.
Definition: quantity.h:416
constexpr auto _s
Definition: units.h:128
constexpr scale milli
Definition: scale.h:162
constexpr scale peta
Definition: scale.h:168
constexpr bool operator<=(quantity rhs) const
Returns true if the quantity value is at most rhs.
Definition: quantity.h:923
constexpr auto _K
Definition: units.h:130
constexpr bool finite() const
Returns true if the quantity value is finite.
Definition: quantity.h:395
constexpr scale micro
Definition: scale.h:161
scale precision_
Definition: quantity.h:56
constexpr bool operator!=(quantity rhs) const
Returns true if the quantity value does not equal rhs.
Definition: quantity.h:899
constexpr bool operator==(quantity rhs) const
Returns true if the quantity value equals rhs.
Definition: quantity.h:891
A data type which represents the general concept of scale as a dimensionless power of 1000...
Definition: scale.h:70
static constexpr int64 convert_level(int64 multiplier, int64 level)
Definition: quantity.h:483
static constexpr quantity inf()
Definition: quantity.h:584
static constexpr int64 inf_int64
Definition: quantity.h:43
quantity & operator*=(float64 rhs)
Multiplies the quantity value by rhs.
Definition: quantity.h:711
static constexpr quantity max(scale precision)
Definition: quantity.h:597
constexpr int64 level() const
Returns the level integer.
Definition: scale.h:174
constexpr auto _A
Definition: units.h:129
A speciaulization to facilitate the conversion of dimensionless quantities into floats.
Definition: quantity.h:334
constexpr scale precision() const
Returns the length precision.
Definition: quantity.h:410
static constexpr quantity inf()
Definition: quantity.h:590
~quantity()=default
Destructor.
char symbol() const
Provdes the metric prefix symbol.
Definition: scale.cpp:53
int8 fixed_
Definition: quantity.h:57
quantity & operator+=(quantity rhs)
Adds rhs to the quantity value.
Definition: quantity.h:695
static constexpr int64 truncate_multiplier(float64 multiplier)
Definition: quantity.h:497
constexpr scale tera
Definition: scale.h:167
quantity< seconds > duration
Definition: quantity.h:1006
constexpr scale zepto
Definition: scale.h:156
static constexpr int64 nan_int64
Definition: quantity.h:44
static constexpr float64 offset_multiplier(float64 multiplier)
Definition: quantity.h:490
constexpr scale giga
Definition: scale.h:166
quantity & operator=(const quantity &)=default
Copy assignment.
A template which represents Standard International (SI) units inclusing the base units such as grams...
Definition: units.h:79
constexpr scale kilo
Definition: scale.h:164
constexpr const quantity operator/(float64 rhs) const
Returns a new quantity value divided by rhs.
Definition: quantity.h:814
constexpr const quantity unfixed() const
Returns a new quantity value with the length precision unfixed.
Definition: quantity.h:682
static constexpr float64 convert_multiplier(int64 multiplier)
Definition: quantity.h:474
constexpr bool operator>=(quantity rhs) const
Returns true if the quantity value is at least rhs.
Definition: quantity.h:931
constexpr bool valid() const
Returns true if the quantity value is valid.
Definition: quantity.h:389
quantity & operator-=(quantity rhs)
Subtracts rhs from the quantity value.
Definition: quantity.h:703
arraynd< T, ndims > operator*(const arraynd< T, ndims > &lhs, const arraynd< T, ndims > &rhs)
Definition: arraynd.h:796
constexpr scale unit
Definition: scale.h:163
quantity< grams > mass
Definition: quantity.h:1004
int64_t int64
Definition: number_types.h:14
constexpr auto _m
Definition: units.h:127
constexpr const quantity operator*(float64 rhs) const
Returns a new quantity value multiplied by rhs.
Definition: quantity.h:799
int8_t int8
Definition: number_types.h:11
static constexpr int64 constexpr_abs(int64 n)
Definition: quantity.h:462
constexpr const quantity rescaled(scale precision) const
Returns a new quantity value with the length precision changed but neither fixed nor unfixed...
Definition: quantity.h:625
quantity & operator/=(float64 rhs)
Divides the quantity value by rhs.
Definition: quantity.h:719
constexpr const quantity refined() const
Returns a new quantity value with the length precision minimized without losing precision.
Definition: quantity.h:640
quantity< kelvins > thermodynamic_temperature
Definition: quantity.h:1008
double float64
Definition: number_types.h:22
constexpr auto _1
Definition: units.h:125
constexpr scale femto
Definition: scale.h:158
constexpr int64 multiplier() const
Returns the number that multiples the length precision.
Definition: quantity.h:401
static constexpr float64 inf_float64
Definition: quantity.h:41
A data type template which represents a dimensioned quantity as a multiple of a precision level...
Definition: quantity.h:234
constexpr scale mega
Definition: scale.h:165
arraynd< T, ndims > operator/(const arraynd< T, ndims > &lhs, const arraynd< T, ndims > &rhs)
Definition: arraynd.h:824
static constexpr float64 nan_float64
Definition: quantity.h:42