@@ -523,5 +523,174 @@ TEST(Constant, OrderingWorksWithScaledConstants) {
523523 EXPECT_THAT (double_c, Gt (half_c));
524524}
525525
526+ TEST (ConstantAddition, SameConstantsDoubleTheValue) {
527+ constexpr auto one_foot = make_constant (feet);
528+ constexpr auto result = one_foot + one_foot;
529+ EXPECT_THAT (result,
530+ AllOf (Eq (make_constant (feet * mag<2 >())), ConstantLabelIs (StrEq (" [2 ft]" ))));
531+ }
532+
533+ TEST (ConstantAddition, ResultTypeIsConstantOfUnitSum) {
534+ using OneFoot = Constant<Feet>;
535+ using OneInch = Constant<Inches>;
536+ using ResultUnit = UnitSum<Feet, Inches>;
537+ StaticAssertTypeEq<decltype (OneFoot{} + OneInch{}), Constant<ResultUnit>>();
538+ }
539+
540+ TEST (ConstantAddition, DifferentUnitsProduceUnitSum) {
541+ constexpr auto one_foot = make_constant (feet);
542+ constexpr auto one_inch = make_constant (inches);
543+ constexpr auto result = one_foot + one_inch;
544+ EXPECT_THAT (
545+ result,
546+ AllOf (Eq (inches (13 )), ConstantLabelIs (AnyOf (StrEq (" (ft + in)" ), StrEq (" (in + ft)" )))));
547+ }
548+
549+ TEST (ConstantAddition, DifferentScalesOfSameUnitCombine) {
550+ constexpr auto two_feet = make_constant (feet * mag<2 >());
551+ constexpr auto three_feet = make_constant (feet * mag<3 >());
552+ constexpr auto result = two_feet + three_feet;
553+ EXPECT_THAT (result,
554+ AllOf (Eq (make_constant (feet * mag<5 >())), ConstantLabelIs (StrEq (" [5 ft]" ))));
555+ }
556+
557+ TEST (ConstantAddition, OppositeConstantsCancelToZero) {
558+ constexpr auto one_foot = make_constant (feet);
559+ constexpr auto neg_foot = -one_foot;
560+ StaticAssertTypeEq<decltype (one_foot + neg_foot), Zero>();
561+ }
562+
563+ TEST (ConstantAddition, PartialCancellationLeavesRemainder) {
564+ constexpr auto three_feet = make_constant (feet * mag<3 >());
565+ constexpr auto neg_two_feet = make_constant (feet * (-mag<2 >()));
566+ constexpr auto result = three_feet + neg_two_feet;
567+ EXPECT_THAT (result, AllOf (Eq (make_constant (feet)), ConstantLabelIs (StrEq (" ft" ))));
568+ }
569+
570+ TEST (ConstantAddition, AddingZeroReturnsOriginal) {
571+ StaticAssertTypeEq<decltype (Constant<Feet>{} + ZERO), Constant<Feet>>();
572+ }
573+
574+ TEST (ConstantAddition, ZeroPlusConstantReturnsConstant) {
575+ StaticAssertTypeEq<decltype (ZERO + Constant<Feet>{}), Constant<Feet>>();
576+ }
577+
578+ TEST (ConstantAddition, MultipleUnitsCollectLikeTerms) {
579+ constexpr auto two_feet = make_constant (feet * mag<2 >());
580+ constexpr auto one_inch = make_constant (inches);
581+ constexpr auto one_foot = make_constant (feet);
582+ constexpr auto result = two_feet + one_inch + one_foot;
583+
584+ EXPECT_THAT (
585+ result,
586+ AllOf (Eq (inches (37 )), ConstantLabelIs (AnyOf (StrEq (" (in + 3 ft)" ), StrEq (" (3 ft + in)" )))));
587+ }
588+
589+ TEST (ConstantSubtraction, SameConstantsYieldZero) {
590+ constexpr auto one_foot = make_constant (feet);
591+ StaticAssertTypeEq<decltype (one_foot - one_foot), Zero>();
592+ }
593+
594+ TEST (ConstantSubtraction, ResultTypeIsConstantOfUnitSum) {
595+ using OneFoot = Constant<Feet>;
596+ using OneInch = Constant<Inches>;
597+ using NegInch = decltype (Inches{} * (-mag<1 >()));
598+ using ResultUnit = UnitSum<Feet, NegInch>;
599+ StaticAssertTypeEq<decltype (OneFoot{} - OneInch{}), Constant<ResultUnit>>();
600+ }
601+
602+ TEST (ConstantSubtraction, DifferentUnitsProduceUnitSum) {
603+ constexpr auto one_foot = make_constant (feet);
604+ constexpr auto one_inch = make_constant (inches);
605+ constexpr auto result = one_foot - one_inch;
606+
607+ EXPECT_THAT (result, AllOf (Eq (inches (11 )), ConstantLabelIs (StrEq (" (ft - in)" ))));
608+ }
609+
610+ TEST (ConstantSubtraction, DifferentScalesOfSameUnitCombine) {
611+ constexpr auto five_feet = make_constant (feet * mag<5 >());
612+ constexpr auto two_feet = make_constant (feet * mag<2 >());
613+ constexpr auto result = five_feet - two_feet;
614+ EXPECT_THAT (result,
615+ AllOf (Eq (make_constant (feet * mag<3 >())), ConstantLabelIs (StrEq (" [3 ft]" ))));
616+ }
617+
618+ TEST (ConstantSubtraction, SubtractingZeroReturnsOriginal) {
619+ StaticAssertTypeEq<decltype (Constant<Feet>{} - ZERO), Constant<Feet>>();
620+ }
621+
622+ TEST (ConstantSubtraction, ZeroMinusConstantReturnsNegative) {
623+ StaticAssertTypeEq<decltype (ZERO - Constant<Feet>{}), decltype (-Constant<Feet>{})>();
624+ }
625+
626+ TEST (ConstantSubtraction, SubtractingNegativeAdds) {
627+ constexpr auto one_foot = make_constant (feet);
628+ constexpr auto neg_foot = -one_foot;
629+ constexpr auto result = one_foot - neg_foot;
630+ EXPECT_THAT (result,
631+ AllOf (Eq (make_constant (feet * mag<2 >())), ConstantLabelIs (StrEq (" [2 ft]" ))));
632+ }
633+
634+ TEST (ConstantSubtraction, ResultCanBeNegative) {
635+ constexpr auto two_feet = make_constant (feet * mag<2 >());
636+ constexpr auto five_feet = make_constant (feet * mag<5 >());
637+ constexpr auto result = two_feet - five_feet;
638+ EXPECT_THAT (result,
639+ AllOf (Eq (make_constant (feet * (-mag<3 >()))), ConstantLabelIs (StrEq (" [-3 ft]" ))));
640+ }
641+
642+ TEST (ConstantAddition, FractionalCoefficientsWork) {
643+ constexpr auto half_foot = make_constant (feet / mag<2 >());
644+ constexpr auto quarter_foot = make_constant (feet / mag<4 >());
645+ constexpr auto result = half_foot + quarter_foot;
646+ EXPECT_THAT (result,
647+ AllOf (Eq (make_constant (feet * mag<3 >() / mag<4 >())),
648+ ConstantLabelIs (StrEq (" [(3 / 4) ft]" ))));
649+ }
650+
651+ TEST (ConstantAddition, CommutativeProperty) {
652+ constexpr auto one_foot = make_constant (feet);
653+ constexpr auto one_meter = make_constant (meters);
654+ EXPECT_THAT (one_foot + one_meter, Eq (one_meter + one_foot));
655+ }
656+
657+ TEST (ConstantSubtraction, AntiCommutativeProperty) {
658+ constexpr auto one_foot = make_constant (feet);
659+ constexpr auto one_meter = make_constant (meters);
660+ EXPECT_THAT (one_foot - one_meter, Eq (-(one_meter - one_foot)));
661+ }
662+
663+ TEST (ConstantAddition, NegativeFirstTermShowsMinusPrefix) {
664+ constexpr auto neg_foot = make_constant (feet * (-mag<1 >()));
665+ constexpr auto one_inch = make_constant (inches);
666+
667+ // Positive coefficients come before negative, so result is (in + (-ft)) = (in - ft).
668+ constexpr auto result = neg_foot + one_inch;
669+ EXPECT_THAT (result, ConstantLabelIs (StrEq (" (in - ft)" )));
670+ }
671+
672+ TEST (ConstantAddition, BothNegativeShowsMinusSigns) {
673+ constexpr auto neg_foot = make_constant (feet * (-mag<1 >()));
674+ constexpr auto neg_inch = make_constant (inches * (-mag<1 >()));
675+
676+ // Both negative, order depends on InOrderFor.
677+ constexpr auto result = neg_foot + neg_inch;
678+ EXPECT_THAT (result, ConstantLabelIs (AnyOf (StrEq (" (-in - ft)" ), StrEq (" (-ft - in)" ))));
679+ }
680+
681+ TEST (ConstantAddition, ScaledUnitsShowScaleInLabel) {
682+ constexpr auto two_feet = make_constant (feet * mag<2 >());
683+ constexpr auto three_inches = make_constant (inches * mag<3 >());
684+ constexpr auto result = two_feet + three_inches;
685+ EXPECT_THAT (result, ConstantLabelIs (AnyOf (StrEq (" (2 ft + 3 in)" ), StrEq (" (3 in + 2 ft)" ))));
686+ }
687+
688+ TEST (ConstantSubtraction, NegativeFractionalScaleShowsCorrectly) {
689+ constexpr auto one_foot = make_constant (feet);
690+ constexpr auto three_quarters_inch = make_constant (inches * mag<3 >() / mag<4 >());
691+ constexpr auto result = one_foot - three_quarters_inch;
692+ EXPECT_THAT (result, ConstantLabelIs (StrEq (" (ft - (3 / 4) in)" )));
693+ }
694+
526695} // namespace
527696} // namespace au
0 commit comments