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;
int n, m, tot, sum;
int f[2][2][2][2], g[2][2];
long long gcd(int a, int b) { return !b ? a : gcd(b, a % b); }
int main() {
  scanf("%d%d", &n, &m);
  long long tmp = (n + 1) * (m + 1);
  tmp = tmp * (tmp - 1) % 1000000007 * (tmp - 2) % 1000000007;
  int t = (int)tmp;
  tmp = n + 1;
  tmp = tmp * (tmp - 1) * (tmp - 2) % 1000000007 * (m + 1);
  t = (t - tmp + 1000000007) % 1000000007;
  tmp = m + 1;
  tmp = tmp * (tmp - 1) * (tmp - 2) % 1000000007 * (n + 1);
  t = (t - tmp + 1000000007) % 1000000007;
  for (int i = 1; i <= n; ++i)
    for (int j = 1; j <= m; ++j)
      t = (t - (gcd(i, j) - 1) * (n - i + 1) * (m - j + 1) % 1000000007 * 12 +
           1000000007) %
          1000000007;
  for (int i = 0; i <= n; ++i)
    for (int j = 0; j <= m; ++j)
      (g[i & 1][j & 1] = (g[i & 1][j & 1] + 1) % 1000000007);
  for (int i = 0; i <= n; ++i)
    for (int j = 0; j <= m; ++j) {
      (f[0][0][i & 1][j & 1] = (f[0][0][i & 1][j & 1] + g[0][0]) % 1000000007);
      (f[0][1][i & 1][j & 1 ^ 1] =
           (f[0][1][i & 1][j & 1 ^ 1] + g[0][1]) % 1000000007);
      (f[1][0][i & 1 ^ 1][j & 1] =
           (f[1][0][i & 1 ^ 1][j & 1] + g[1][0]) % 1000000007);
      (f[1][1][i & 1 ^ 1][j & 1 ^ 1] =
           (f[1][1][i & 1 ^ 1][j & 1 ^ 1] + g[1][1]) % 1000000007);
    }
  for (int i = 0; i <= n; ++i)
    for (int j = 0; j <= m; ++j) {
      if (i % 2 == 0) {
        if (j % 2 == 0) {
          (sum = (sum + f[1][0][0][1]) % 1000000007);
          (sum = (sum + f[1][0][1][1]) % 1000000007);
          (sum = (sum + f[0][1][1][0]) % 1000000007);
          (sum = (sum + f[0][1][1][1]) % 1000000007);
          (sum = (sum + f[1][1][1][0]) % 1000000007);
          (sum = (sum + f[1][1][0][1]) % 1000000007);
        } else {
          (sum = (sum + f[1][0][1][0]) % 1000000007);
          (sum = (sum + f[1][0][0][1]) % 1000000007);
          (sum = (sum + f[1][1][0][1]) % 1000000007);
          (sum = (sum + f[1][1][1][1]) % 1000000007);
          (sum = (sum + f[0][0][1][0]) % 1000000007);
          (sum = (sum + f[0][0][1][1]) % 1000000007);
        }
      } else {
        if (j % 2 == 0) {
          (sum = (sum + f[1][1][1][0]) % 1000000007);
          (sum = (sum + f[1][1][1][1]) % 1000000007);
          (sum = (sum + f[0][0][0][1]) % 1000000007);
          (sum = (sum + f[0][0][1][1]) % 1000000007);
          (sum = (sum + f[0][1][1][0]) % 1000000007);
          (sum = (sum + f[0][1][0][1]) % 1000000007);
        } else {
          (sum = (sum + f[1][0][1][0]) % 1000000007);
          (sum = (sum + f[1][0][1][1]) % 1000000007);
          (sum = (sum + f[0][0][1][0]) % 1000000007);
          (sum = (sum + f[0][0][0][1]) % 1000000007);
          (sum = (sum + f[0][1][0][1]) % 1000000007);
          (sum = (sum + f[0][1][1][1]) % 1000000007);
        }
      }
    }
  t = (t - sum + 1000000007) % 1000000007;
  cout << t << endl;
  return 0;
}