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;
const int maxn = 10008, maxm = 100008;
struct Tedge {
  int tot, start[maxn];
  struct arr {
    int a, next;
  } e[maxm];
  void Clear() {
    tot = 1;
    memset(start, 0, sizeof(start));
  }
  void Add(int x, int y) {
    e[++tot].a = y;
    e[tot].next = start[x];
    start[x] = tot;
    e[++tot].a = x;
    e[tot].next = start[y];
    start[y] = tot;
  }
} E;
const int pp = 1e9 + 7;
int f[4008][4008];
int gcd(int x, int y) {
  if (x < y) swap(x, y);
  return f[x][y] = f[y][x % y];
}
struct Tprogram {
  int n, m;
  long long ans;
  int tx[3], ty[3];
  void Init() {
    scanf("%d%d", &n, &m);
    tx[0] = (n + 1) / 2;
    tx[1] = (n + 1) / 2;
    if (n & 1 ^ 1) tx[0]++;
    ty[0] = (m + 1) / 2;
    ty[1] = (m + 1) / 2;
    if (m & 1 ^ 1) ty[0]++;
    for (int i = 0; i <= n; i++)
      for (int j = 0; j <= m; j++) {
        int x0, x1, y0, y1;
        x0 = tx[0], x1 = tx[1];
        if (i & 1) swap(x0, x1);
        y0 = ty[0], y1 = ty[1];
        if (j & 1) swap(y0, y1);
        ans += (long long)x1 * y1 * x1 * y1 % pp;
        ans += ((long long)x0 * y1 + x1 * y0 + x0 * y0) *
               (x0 * y1 + x1 * y0 + x0 * y0) % pp;
      }
    long long t = ((long long)n + 1) * (m + 1) * (n + 1) * (m + 1) % pp;
    ans -= t * 3;
    ans += 2 * (n + 1) * (m + 1);
    ans %= pp;
    for (int i = 0; i <= 4000; i++) f[i][0] = i;
    for (int i = 1; i <= n; i++)
      for (int j = 1; j <= m; j++) {
        if (i + j)
          ans -= ((long long)gcd(i, j) - 1) * (n - i + 1) * (m - j + 1) * 6 * 2;
        ans %= pp;
      }
    ans -= (long long)(n + 1) * n * (n - 1) * (m + 1) % pp;
    ans -= (long long)(m + 1) * m * (m - 1) * (n + 1) % pp;
    ans %= pp;
    if (ans < 0) ans += pp;
    printf("%d\n", ans);
  }
  void Work() {}
} program;
int main() {
  program.Init();
  program.Work();
  return 0;
}