static LongLong multiplication(final LongLong r, final long a, final long b) {
    /*
    final long x0 = a & LOWER_MASK;
    final long x1 = (a & UPPER_MASK) >> MID;

    final long y0 = b & LOWER_MASK;
    final long y1 = (b & UPPER_MASK) >> MID;

    final long t = (x0 + x1)*(y0 + y1);
    final long u = (x0 - x1)*(y0 - y1);
    final long v = x1*y1;

    final long tmp = (t - u)>>>1;
    result.d0 = ((t + u)>>>1) - v + ((tmp << MID) & FULL_MASK);
    result.d1 = v + (tmp >> MID);
    return result;
    */
    final long a_lower = a & LOWER_MASK;
    final long a_upper = (a & UPPER_MASK) >> MID;

    final long b_lower = b & LOWER_MASK;
    final long b_upper = (b & UPPER_MASK) >> MID;

    final long tmp = a_lower*b_upper + a_upper*b_lower;
    r.d0 = a_lower*b_lower + ((tmp << MID) & FULL_MASK);
    r.d1 = a_upper*b_upper + (tmp >> MID);
    return r;
  }
@Test
  void testMultiplication() {
    for (int i = 0; i < 100; i++) {
      final long a = nextPositiveLong();
      final long b = nextPositiveLong();
      verifyMultiplication(a, b);
    }
    final long max = Long.MAX_VALUE & MASK;
    verifyMultiplication(max, max);
  }