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>
#pragma GCC optimize(3, "Ofast", "inline")
using namespace std;
long long read() {
  long long x = 0, f = 1;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') {
    x = (x << 3) + (x << 1) + (ch ^ 48);
    ch = getchar();
  }
  return x * f;
}
long long n, m, ans, a[10], G[4005][4005];
long long gcd(long long x, long long y) {
  if (!y) return x;
  if (G[x][y]) return G[x][y];
  return G[x][y] = gcd(y, x % y);
}
long long Get(long long x, long long opt) {
  if (opt == 1) {
    if (n % 2 == 0) {
      if (x)
        return n / 2;
      else
        return n / 2 + 1;
    } else
      return n / 2 + 1;
  } else {
    if (m % 2 == 0) {
      if (x)
        return m / 2;
      else
        return m / 2 + 1;
    } else
      return m / 2 + 1;
  }
}
void calc() {
  if ((a[3] - a[1]) * (a[6] - a[2]) - (a[5] - a[1]) * (a[4] - a[2]) % 2 != 0)
    return;
  long long x = Get(a[1], 1) * Get(a[2], 2), y = Get(a[3], 1) * Get(a[4], 2),
            z = Get(a[5], 1) * Get(a[6], 2);
  if (a[1] == a[3] && a[2] == a[4]) y--;
  if (a[1] == a[5] && a[2] == a[6]) z--;
  if (a[3] == a[5] && a[4] == a[6]) z--;
  ans += x * y % 1000000007 * z % 1000000007;
  ans %= 1000000007;
}
void dfs(long long x) {
  if (x == 7) {
    calc();
    return;
  }
  a[x] = 0;
  dfs(x + 1);
  a[x] = 1;
  dfs(x + 1);
}
signed main() {
  n = read();
  m = read();
  for (long long i = 0; i <= 4000; i++) {
    for (long long j = 0; j <= 4000; j++) {
      G[i][j] = gcd(i, j);
    }
  }
  dfs(1);
  for (long long i = 2; i <= n; i++) {
    for (long long j = 2; j <= m; j++) {
      long long GCD = G[i][j];
      ans -= (n - i + 1) % 1000000007 * (m - j + 1) % 1000000007 * (GCD - 1) %
             1000000007 * 12ll % 1000000007 % 1000000007;
      ans %= 1000000007;
      ans += 1000000007;
      ans %= 1000000007;
    }
  }
  for (long long i = 0; i <= n; i++) {
    if (i >= 2)
      ans -= (m + 1) * (i * (i - 1) / 2) % 1000000007 * 6 % 1000000007;
    ans += 1000000007;
    ans %= 1000000007;
  }
  for (long long i = 0; i <= m; i++) {
    if (i >= 2)
      ans -= (n + 1) * (i * (i - 1) / 2) % 1000000007 * 6 % 1000000007;
    ans += 1000000007;
    ans %= 1000000007;
  }
  ans %= 1000000007;
  ans += 1000000007;
  ans += 1000000007;
  ans %= 1000000007;
  printf("%d\n", ans);
}