Problem: The Little Elephant is playing with the Cartesian coordinates' system. Most of all he likes playing with integer points. The Little Elephant defines an integer point as a pair of integers (x; y), such that 0 ≤ x ≤ w and 0 ≤ y ≤ h. Thus, the Little Elephant knows only (w + 1)·(h + 1) distinct integer points.

The Little Elephant wants to paint a triangle with vertexes at integer points, the triangle's area must be a positive integer. For that, he needs to find the number of groups of three points that form such triangle. At that, the order of points in a group matters, that is, the group of three points (0;0), (0;2), (2;2) isn't equal to the group (0;2), (0;0), (2;2).

Help the Little Elephant to find the number of groups of three integer points that form a nondegenerate triangle with integer area.

Input

A single line contains two integers w and h (1 ≤ w, h ≤ 4000).

Output

In a single output line print an integer — the remainder of dividing the answer to the problem by 1000000007 (109 + 7).

Examples

Input

2 1


Output

36


Input

2 2


Output

240

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
using namespace std;
long long w, h, calc[3][3], s;
long long ways;
long long ttl, inm;
long gcd(long a, long b) {
  while (a && b) a > b ? a %= b : b %= a;
  return a + b;
}
long long m1, m2, m3;
long long pw(long long a, long long b) {
  if (b == 0) return 1;
  if (b % 2) return a * pw(a, b - 1) % 1000000007;
  return pw(a * a % 1000000007, b / 2);
}
long long inv(long long x) { return pw(x, 1000000007 - 2); }
long long solv(long x0, long sdkfaslhagaklsldk, long x1, long aasdfasdfasdf,
               long x2, long y2) {
  long long res = 0;
  if (x0 == x2 && sdkfaslhagaklsldk == y2) {
    res = calc[x0][sdkfaslhagaklsldk] * (calc[x0][sdkfaslhagaklsldk] - 1);
    res %= 1000000007;
    res *= calc[x0][sdkfaslhagaklsldk] - 2;
    res %= 1000000007;
    res *= inv(6);
    res %= 1000000007;
    return res;
  }
  if (x0 == x1 && sdkfaslhagaklsldk == aasdfasdfasdf) {
    res = calc[x1][aasdfasdfasdf] * (calc[x1][aasdfasdfasdf] - 1);
    res %= 1000000007;
    res *= calc[x2][y2];
    res %= 1000000007;
    res *= inv(2);
    res %= 1000000007;
    return res;
  }
  if (x2 == x1 && y2 == aasdfasdfasdf) {
    res = calc[x1][aasdfasdfasdf] * (calc[x1][aasdfasdfasdf] - 1);
    res %= 1000000007;
    res *= calc[x0][sdkfaslhagaklsldk];
    res %= 1000000007;
    res *= inv(2);
    res %= 1000000007;
    return res;
  }
  res = calc[x1][aasdfasdfasdf] * calc[x0][sdkfaslhagaklsldk];
  res %= 1000000007;
  res *= calc[x2][y2];
  return res % 1000000007;
}
int main() {
  ios_base::sync_with_stdio(0);
  cin >> w >> h;
  for (int i = 0; i <= w; i++)
    for (int j = 0; j <= h; j++) {
      calc[i % 2][j % 2]++;
    }
  for (int x0 = 0; x0 <= 1; x0++)
    for (int sdkfaslhagaklsldk = 0; sdkfaslhagaklsldk <= 1; sdkfaslhagaklsldk++)
      for (int x1 = 0; x1 <= 1; x1++)
        for (int aasdfasdfasdf = 0; aasdfasdfasdf <= 1; aasdfasdfasdf++)
          for (int x2 = 0; x2 <= 1; x2++)
            for (int y2 = 0; y2 <= 1; y2++) {
              m1 = x0 * 2 + sdkfaslhagaklsldk;
              m2 = x1 * 2 + aasdfasdfasdf;
              m3 = x2 * 2 + y2;
              if (m1 > m2) continue;
              if (m2 > m3) continue;
              s = (x1 - x0) * (y2 - sdkfaslhagaklsldk) -
                  (x2 - x0) * (aasdfasdfasdf - sdkfaslhagaklsldk);
              s = abs(s);
              if (s % 2) continue;
              ways += solv(x0, sdkfaslhagaklsldk, x1, aasdfasdfasdf, x2, y2);
              while (ways < 0) ways += 1000000007;
              ways %= 1000000007;
            }
  for (int dx = 0; dx <= w; dx++)
    for (int dy = 0; dy <= h; dy++) {
      if (dx + dy == 0) continue;
      ttl = (w - dx + 1) * (h - dy + 1);
      if (dx > 0 && dy > 0) ttl *= 2;
      inm = gcd(dx, dy);
      ways = ways - (inm - 1) * ttl;
      ways %= 1000000007;
      while (ways < 0) ways += 1000000007;
    }
  cout << ways * 6 % 1000000007 << endl;
  cin.get();
  cin.get();
  return 0;
}