# Global Metrics

path: .metrics.halstead.vocabulary
old: 14.0
new: 60.0
path: .metrics.halstead.bugs
old: 0.012868305242730796
new: 2.1169058953641136
path: .metrics.halstead.volume
old: 68.53238859703687
new: 4382.912821941521
path: .metrics.halstead.difficulty
old: 3.5
new: 115.47058823529412
path: .metrics.halstead.effort
old: 239.86336008962903
new: 506097.5217336003
path: .metrics.halstead.n2
old: 7.0
new: 34.0
path: .metrics.halstead.purity_ratio
old: 2.1834982727114696
new: 0.39782367826708886
path: .metrics.halstead.time
old: 13.325742227201614
new: 28116.528985200017
path: .metrics.halstead.length
old: 18.0
new: 742.0
path: .metrics.halstead.n1
old: 7.0
new: 26.0
path: .metrics.halstead.level
old: 0.2857142857142857
new: 0.008660213958227204
path: .metrics.halstead.N1
old: 11.0
new: 440.0
path: .metrics.halstead.estimated_program_length
old: 39.302968908806456
new: 295.18516927417994
path: .metrics.halstead.N2
old: 7.0
new: 302.0
path: .metrics.nexits.sum
old: 1.0
new: 29.0
path: .metrics.nexits.average
old: 1.0
new: 1.5263157894736843
path: .metrics.cognitive.average
old: 0.0
new: 2.0526315789473686
path: .metrics.cognitive.sum
old: 0.0
new: 39.0
path: .metrics.nom.functions
old: 1.0
new: 19.0
path: .metrics.nom.total
old: 1.0
new: 19.0
path: .metrics.cyclomatic.sum
old: 3.0
new: 70.0
path: .metrics.cyclomatic.average
old: 1.0
new: 3.1818181818181817
path: .metrics.nargs.average
old: 0.0
new: 1.7894736842105263
path: .metrics.nargs.sum
old: 0.0
new: 34.0
path: .metrics.mi.mi_visual_studio
old: 58.36090267701658
new: 13.242559809120772
path: .metrics.mi.mi_sei
old: 111.68217310214428
new: 0.510097211429624
path: .metrics.mi.mi_original
old: 99.79714357769836
new: 22.644777273596517
path: .metrics.loc.blank
old: 4.0
new: 32.0
path: .metrics.loc.cloc
old: 9.0
new: 66.0
path: .metrics.loc.lloc
old: 1.0
new: 49.0
path: .metrics.loc.ploc
old: 7.0
new: 140.0
path: .metrics.loc.sloc
old: 20.0
new: 238.0

# Spaces Data

## Minimal test - lines (13, 236)

path: .spaces[0].metrics.nom.functions
old: 1.0
new: 19.0
path: .spaces[0].metrics.nom.total
old: 1.0
new: 19.0
path: .spaces[0].metrics.halstead.difficulty
old: 3.5
new: 124.96774193548389
path: .spaces[0].metrics.halstead.n2
old: 5.0
new: 31.0
path: .spaces[0].metrics.halstead.purity_ratio
old: 1.9538203080525025
new: 0.37370124430035434
path: .spaces[0].metrics.halstead.volume
old: 57.3594000115385
new: 4304.672830453579
path: .spaces[0].metrics.halstead.level
old: 0.2857142857142857
new: 0.008002065049044915
path: .spaces[0].metrics.halstead.time
old: 11.153216668910265
new: 29885.846855156207
path: .spaces[0].metrics.halstead.estimated_program_length
old: 31.26112492884004
new: 275.7915182936615
path: .spaces[0].metrics.halstead.bugs
old: 0.011428621282029669
new: 2.2048080867107913
path: .spaces[0].metrics.halstead.n1
old: 7.0
new: 26.0
path: .spaces[0].metrics.halstead.N1
old: 11.0
new: 440.0
path: .spaces[0].metrics.halstead.N2
old: 5.0
new: 298.0
path: .spaces[0].metrics.halstead.effort
old: 200.75790004038475
new: 537945.2433928117
path: .spaces[0].metrics.halstead.vocabulary
old: 12.0
new: 57.0
path: .spaces[0].metrics.halstead.length
old: 16.0
new: 738.0
path: .spaces[0].metrics.cyclomatic.sum
old: 2.0
new: 69.0
path: .spaces[0].metrics.cyclomatic.average
old: 1.0
new: 3.2857142857142856
path: .spaces[0].metrics.mi.mi_original
old: 112.18157046532524
new: 23.95056059465739
path: .spaces[0].metrics.mi.mi_sei
old: 123.86199247718932
new: 1.57384872606017
path: .spaces[0].metrics.mi.mi_visual_studio
old: 65.60325758206154
new: 14.00617578634935
path: .spaces[0].metrics.nexits.average
old: 1.0
new: 1.5263157894736843
path: .spaces[0].metrics.nexits.sum
old: 1.0
new: 29.0
path: .spaces[0].metrics.nargs.average
old: 0.0
new: 1.7894736842105263
path: .spaces[0].metrics.nargs.sum
old: 0.0
new: 34.0
path: .spaces[0].metrics.cognitive.average
old: 0.0
new: 2.0526315789473686
path: .spaces[0].metrics.cognitive.sum
old: 0.0
new: 39.0
path: .spaces[0].metrics.loc.sloc
old: 10.0
new: 224.0
path: .spaces[0].metrics.loc.cloc
old: 3.0
new: 59.0
path: .spaces[0].metrics.loc.lloc
old: 1.0
new: 49.0
path: .spaces[0].metrics.loc.ploc
old: 5.0
new: 135.0
path: .spaces[0].metrics.loc.blank
old: 2.0
new: 30.0

### Code

    namespace mozilla {

    /**
     * A ValueCalculator class that performs additional checks before performing
     * arithmetic operations such that if either operand is Forever (or the
     * negative equivalent) the result remains Forever (or the negative equivalent
     * as appropriate).
     *
     * Currently this only checks if either argument to each operation is
     * Forever/-Forever. However, it is possible that, for example,
     * aA + aB > INT64_MAX (or < INT64_MIN).
     *
     * We currently don't check for that case since we don't expect that to
     * happen often except under test conditions in which case the wrapping
     * behavior is probably acceptable.
     */
    class StickyTimeDurationValueCalculator {
     public:
      static int64_t Add(int64_t aA, int64_t aB) {
        MOZ_ASSERT((aA != INT64_MAX || aB != INT64_MIN) &&
                       (aA != INT64_MIN || aB != INT64_MAX),
                   "'Infinity + -Infinity' and '-Infinity + Infinity'"
                   " are undefined");

        // Forever + x = Forever
        // x + Forever = Forever
        if (aA == INT64_MAX || aB == INT64_MAX) {
          return INT64_MAX;
        }
        // -Forever + x = -Forever
        // x + -Forever = -Forever
        if (aA == INT64_MIN || aB == INT64_MIN) {
          return INT64_MIN;
        }

        return aA + aB;
      }

      // Note that we can't just define Add and have BaseTimeDuration call Add with
      // negative arguments since INT64_MAX != -INT64_MIN so the saturating logic
      // won't work.
      static int64_t Subtract(int64_t aA, int64_t aB) {
        MOZ_ASSERT((aA != INT64_MAX && aA != INT64_MIN) || aA != aB,
                   "'Infinity - Infinity' and '-Infinity - -Infinity'"
                   " are undefined");

        // Forever - x  = Forever
        // x - -Forever = Forever
        if (aA == INT64_MAX || aB == INT64_MIN) {
          return INT64_MAX;
        }
        // -Forever - x = -Forever
        // x - Forever  = -Forever
        if (aA == INT64_MIN || aB == INT64_MAX) {
          return INT64_MIN;
        }

        return aA - aB;
      }

      template
      static int64_t Multiply(int64_t aA, T aB) {
        // Specializations for double, float, and int64_t are provided following.
        return Multiply(aA, static_cast(aB));
      }

      static int64_t Divide(int64_t aA, int64_t aB) {
        MOZ_ASSERT(aB != 0, "Division by zero");
        MOZ_ASSERT((aA != INT64_MAX && aA != INT64_MIN) ||
                       (aB != INT64_MAX && aB != INT64_MIN),
                   "Dividing +/-Infinity by +/-Infinity is undefined");

        // Forever / +x = Forever
        // Forever / -x = -Forever
        // -Forever / +x = -Forever
        // -Forever / -x = Forever
        if (aA == INT64_MAX || aA == INT64_MIN) {
          return (aA >= 0) ^ (aB >= 0) ? INT64_MIN : INT64_MAX;
        }
        // x /  Forever = 0
        // x / -Forever = 0
        if (aB == INT64_MAX || aB == INT64_MIN) {
          return 0;
        }

        return aA / aB;
      }

      static double DivideDouble(int64_t aA, int64_t aB) {
        MOZ_ASSERT(aB != 0, "Division by zero");
        MOZ_ASSERT((aA != INT64_MAX && aA != INT64_MIN) ||
                       (aB != INT64_MAX && aB != INT64_MIN),
                   "Dividing +/-Infinity by +/-Infinity is undefined");

        // Forever / +x = Forever
        // Forever / -x = -Forever
        // -Forever / +x = -Forever
        // -Forever / -x = Forever
        if (aA == INT64_MAX || aA == INT64_MIN) {
          return (aA >= 0) ^ (aB >= 0) ? NegativeInfinity()
                                       : PositiveInfinity();
        }
        // x /  Forever = 0
        // x / -Forever = 0
        if (aB == INT64_MAX || aB == INT64_MIN) {
          return 0.0;
        }

        return static_cast(aA) / aB;
      }

      static int64_t Modulo(int64_t aA, int64_t aB) {
        MOZ_ASSERT(aA != INT64_MAX && aA != INT64_MIN,
                   "Infinity modulo x is undefined");

        return aA % aB;
      }
    };

    template <>
    inline int64_t StickyTimeDurationValueCalculator::Multiply(
        int64_t aA, int64_t aB) {
      MOZ_ASSERT((aA != 0 || (aB != INT64_MIN && aB != INT64_MAX)) &&
                     ((aA != INT64_MIN && aA != INT64_MAX) || aB != 0),
                 "Multiplication of infinity by zero");

      // Forever  * +x = Forever
      // Forever  * -x = -Forever
      // -Forever * +x = -Forever
      // -Forever * -x = Forever
      //
      // i.e. If one or more of the arguments is +/-Forever, then
      // return -Forever if the signs differ, or +Forever otherwise.
      if (aA == INT64_MAX || aA == INT64_MIN || aB == INT64_MAX ||
          aB == INT64_MIN) {
        return (aA >= 0) ^ (aB >= 0) ? INT64_MIN : INT64_MAX;
      }

      return aA * aB;
    }

    template <>
    inline int64_t StickyTimeDurationValueCalculator::Multiply(int64_t aA,
                                                                       double aB) {
      MOZ_ASSERT((aA != 0 || (!IsInfinite(aB))) &&
                     ((aA != INT64_MIN && aA != INT64_MAX) || aB != 0.0),
                 "Multiplication of infinity by zero");

      // As with Multiply, if one or more of the arguments is
      // +/-Forever or +/-Infinity, then return -Forever if the signs differ,
      // or +Forever otherwise.
      if (aA == INT64_MAX || aA == INT64_MIN || IsInfinite(aB)) {
        return (aA >= 0) ^ (aB >= 0.0) ? INT64_MIN : INT64_MAX;
      }

      return aA * aB;
    }

    template <>
    inline int64_t StickyTimeDurationValueCalculator::Multiply(int64_t aA,
                                                                      float aB) {
      MOZ_ASSERT(IsInfinite(aB) == IsInfinite(static_cast(aB)),
                 "Casting to float loses infinite-ness");

      return Multiply(aA, static_cast(aB));
    }

    /**
     * Specialization of BaseTimeDuration that uses
     * StickyTimeDurationValueCalculator for arithmetic on the mValue member.
     *
     * Use this class when you need a time duration that is expected to hold values
     * of Forever (or the negative equivalent) *and* when you expect that
     * time duration to be used in arithmetic operations (and not just value
     * comparisons).
     */
    typedef BaseTimeDuration StickyTimeDuration;

    // Template specializations to allow arithmetic between StickyTimeDuration
    // and TimeDuration objects by falling back to the safe behavior.
    inline StickyTimeDuration operator+(const TimeDuration& aA,
                                        const StickyTimeDuration& aB) {
      return StickyTimeDuration(aA) + aB;
    }
    inline StickyTimeDuration operator+(const StickyTimeDuration& aA,
                                        const TimeDuration& aB) {
      return aA + StickyTimeDuration(aB);
    }

    inline StickyTimeDuration operator-(const TimeDuration& aA,
                                        const StickyTimeDuration& aB) {
      return StickyTimeDuration(aA) - aB;
    }
    inline StickyTimeDuration operator-(const StickyTimeDuration& aA,
                                        const TimeDuration& aB) {
      return aA - StickyTimeDuration(aB);
    }

    inline StickyTimeDuration& operator+=(StickyTimeDuration& aA,
                                          const TimeDuration& aB) {
      return aA += StickyTimeDuration(aB);
    }
    inline StickyTimeDuration& operator-=(StickyTimeDuration& aA,
                                          const TimeDuration& aB) {
      return aA -= StickyTimeDuration(aB);
    }

    inline double operator/(const TimeDuration& aA, const StickyTimeDuration& aB) {
      return StickyTimeDuration(aA) / aB;
    }
    inline double operator/(const StickyTimeDuration& aA, const TimeDuration& aB) {
      return aA / StickyTimeDuration(aB);
    }

    inline StickyTimeDuration operator%(const TimeDuration& aA,
                                        const StickyTimeDuration& aB) {
      return StickyTimeDuration(aA) % aB;
    }
    inline StickyTimeDuration operator%(const StickyTimeDuration& aA,
                                        const TimeDuration& aB) {
      return aA % StickyTimeDuration(aB);
    }

    }  // namespace mozilla

## Minimal test - lines (29, 130)

path: .spaces[0].spaces[0].metrics.mi.mi_sei
old: 145.70189629357947
new: 31.78673334368015
path: .spaces[0].spaces[0].metrics.mi.mi_visual_studio
old: 71.68371117970403
new: 28.206064456481215
path: .spaces[0].spaces[0].metrics.mi.mi_original
old: 122.5791461172939
new: 48.23237022058288
path: .spaces[0].spaces[0].metrics.cyclomatic.average
old: 1.0
new: 5.285714285714286
path: .spaces[0].spaces[0].metrics.cyclomatic.sum
old: 1.0
new: 37.0
path: .spaces[0].spaces[0].metrics.loc.blank
old: 0.0
new: 14.0
path: .spaces[0].spaces[0].metrics.loc.cloc
old: 3.0
new: 24.0
path: .spaces[0].spaces[0].metrics.loc.sloc
old: 6.0
new: 102.0
path: .spaces[0].spaces[0].metrics.loc.lloc
old: 1.0
new: 29.0
path: .spaces[0].spaces[0].metrics.loc.ploc
old: 3.0
new: 64.0
path: .spaces[0].spaces[0].metrics.nom.functions
old: 1.0
new: 6.0
path: .spaces[0].spaces[0].metrics.nom.total
old: 1.0
new: 6.0
path: .spaces[0].spaces[0].metrics.nargs.sum
old: 0.0
new: 12.0
path: .spaces[0].spaces[0].metrics.nargs.average
old: 0.0
new: 2.0
path: .spaces[0].spaces[0].metrics.nexits.sum
old: 1.0
new: 14.0
path: .spaces[0].spaces[0].metrics.nexits.average
old: 1.0
new: 2.3333333333333335
path: .spaces[0].spaces[0].metrics.cognitive.sum
old: 0.0
new: 28.0
path: .spaces[0].spaces[0].metrics.cognitive.average
old: 0.0
new: 4.666666666666667
path: .spaces[0].spaces[0].metrics.halstead.time
old: 7.751165554737178
new: 6559.332041928755
path: .spaces[0].spaces[0].metrics.halstead.bugs
old: 0.00896681942530452
new: 0.802232328652098
path: .spaces[0].spaces[0].metrics.halstead.n1
old: 7.0
new: 21.0
path: .spaces[0].spaces[0].metrics.halstead.effort
old: 139.5209799852692
new: 118067.9767547176
path: .spaces[0].spaces[0].metrics.halstead.difficulty
old: 3.5
new: 61.25
path: .spaces[0].spaces[0].metrics.halstead.volume
old: 39.86313713864835
new: 1927.6404368117155
path: .spaces[0].spaces[0].metrics.halstead.N1
old: 9.0
new: 211.0
path: .spaces[0].spaces[0].metrics.halstead.N2
old: 3.0
new: 140.0
path: .spaces[0].spaces[0].metrics.halstead.estimated_program_length
old: 24.406371956566694
new: 202.27776589566173
path: .spaces[0].spaces[0].metrics.halstead.vocabulary
old: 10.0
new: 45.0
path: .spaces[0].spaces[0].metrics.halstead.length
old: 12.0
new: 351.0
path: .spaces[0].spaces[0].metrics.halstead.level
old: 0.2857142857142857
new: 0.0163265306122449
path: .spaces[0].spaces[0].metrics.halstead.purity_ratio
old: 2.033864329713891
new: 0.5762899313266716
path: .spaces[0].spaces[0].metrics.halstead.n2
old: 3.0
new: 24.0

### Code

    class StickyTimeDurationValueCalculator {
     public:
      static int64_t Add(int64_t aA, int64_t aB) {
        MOZ_ASSERT((aA != INT64_MAX || aB != INT64_MIN) &&
                       (aA != INT64_MIN || aB != INT64_MAX),
                   "'Infinity + -Infinity' and '-Infinity + Infinity'"
                   " are undefined");

        // Forever + x = Forever
        // x + Forever = Forever
        if (aA == INT64_MAX || aB == INT64_MAX) {
          return INT64_MAX;
        }
        // -Forever + x = -Forever
        // x + -Forever = -Forever
        if (aA == INT64_MIN || aB == INT64_MIN) {
          return INT64_MIN;
        }

        return aA + aB;
      }

      // Note that we can't just define Add and have BaseTimeDuration call Add with
      // negative arguments since INT64_MAX != -INT64_MIN so the saturating logic
      // won't work.
      static int64_t Subtract(int64_t aA, int64_t aB) {
        MOZ_ASSERT((aA != INT64_MAX && aA != INT64_MIN) || aA != aB,
                   "'Infinity - Infinity' and '-Infinity - -Infinity'"
                   " are undefined");

        // Forever - x  = Forever
        // x - -Forever = Forever
        if (aA == INT64_MAX || aB == INT64_MIN) {
          return INT64_MAX;
        }
        // -Forever - x = -Forever
        // x - Forever  = -Forever
        if (aA == INT64_MIN || aB == INT64_MAX) {
          return INT64_MIN;
        }

        return aA - aB;
      }

      template
      static int64_t Multiply(int64_t aA, T aB) {
        // Specializations for double, float, and int64_t are provided following.
        return Multiply(aA, static_cast(aB));
      }

      static int64_t Divide(int64_t aA, int64_t aB) {
        MOZ_ASSERT(aB != 0, "Division by zero");
        MOZ_ASSERT((aA != INT64_MAX && aA != INT64_MIN) ||
                       (aB != INT64_MAX && aB != INT64_MIN),
                   "Dividing +/-Infinity by +/-Infinity is undefined");

        // Forever / +x = Forever
        // Forever / -x = -Forever
        // -Forever / +x = -Forever
        // -Forever / -x = Forever
        if (aA == INT64_MAX || aA == INT64_MIN) {
          return (aA >= 0) ^ (aB >= 0) ? INT64_MIN : INT64_MAX;
        }
        // x /  Forever = 0
        // x / -Forever = 0
        if (aB == INT64_MAX || aB == INT64_MIN) {
          return 0;
        }

        return aA / aB;
      }

      static double DivideDouble(int64_t aA, int64_t aB) {
        MOZ_ASSERT(aB != 0, "Division by zero");
        MOZ_ASSERT((aA != INT64_MAX && aA != INT64_MIN) ||
                       (aB != INT64_MAX && aB != INT64_MIN),
                   "Dividing +/-Infinity by +/-Infinity is undefined");

        // Forever / +x = Forever
        // Forever / -x = -Forever
        // -Forever / +x = -Forever
        // -Forever / -x = Forever
        if (aA == INT64_MAX || aA == INT64_MIN) {
          return (aA >= 0) ^ (aB >= 0) ? NegativeInfinity()
                                       : PositiveInfinity();
        }
        // x /  Forever = 0
        // x / -Forever = 0
        if (aB == INT64_MAX || aB == INT64_MIN) {
          return 0.0;
        }

        return static_cast(aA) / aB;
      }

      static int64_t Modulo(int64_t aA, int64_t aB) {
        MOZ_ASSERT(aA != INT64_MAX && aA != INT64_MIN,
                   "Infinity modulo x is undefined");

        return aA % aB;
      }
    };