#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e9 + 7;
int precomp_gcd[4444][4444];
inline void norm(int &x) {
  while (x < 0) x += MOD;
  while (x >= MOD) x -= MOD;
}
inline bool get_bit(int k, int i) { return ((1 << i) & k) != 0; }
int triangles_with_integer_area(int w, int h) {
  int count_points_x[2] = {0, 0};
  int count_points_y[2] = {0, 0};
  const int good[] = {0, 1, 2, 4, 5, 6, 8, 9, 10, 15};
  long long add[2][2];
  for (int i = 0; i < w + 1; i++) count_points_x[i & 1]++;
  for (int i = 0; i < h + 1; i++) count_points_y[i & 1]++;
  int ans = 0;
  for (int i = 0; i < 2; i++)
    for (int j = 0; j < 2; j++) {
      add[i][j] = 0;
      for (const auto &k : good) {
        int t0 = get_bit(k, 0);
        int t1 = get_bit(k, 1);
        int t2 = get_bit(k, 2);
        int t3 = get_bit(k, 3);
        long long ways = count_points_x[t0 ^ (i & 1)];
        ways *= count_points_y[t1 ^ (j & 1)];
        ways *= count_points_x[t2 ^ (i & 1)];
        ways *= count_points_y[t3 ^ (j & 1)];
        add[i][j] += ways;
        add[i][j] %= MOD;
      }
    }
  for (int i = 0; i < w + 1; i++)
    for (int j = 0; j < h + 1; j++) {
      ans += add[i & 1][j & 1];
      norm(ans);
    }
  return ans;
}
int triangles_with_zero_area(int w, int h) {
  int ans = 0;
  for (int dx = -w; dx <= w; dx++) {
    for (int dy = 0; dy <= h; dy++) {
      if (dx < 0 and dy == 0) continue;
      long long number_of_segments = (w - abs(dx) + 1);
      number_of_segments *= h - dy + 1;
      number_of_segments %= MOD;
      ans =
          (ans + number_of_segments *
                     (dx == 0 and dy == 0 ? 1 : 6 * precomp_gcd[abs(dx)][dy])) %
          MOD;
    }
  }
  norm(ans);
  return ans;
}
int main() {
  cin.sync_with_stdio(false);
  int w, h;
  cin >> w >> h;
  for (int i = 0; i <= max(w, h); i++)
    for (int j = 0; j <= i; j++) {
      if (i == 0 or j == 0)
        precomp_gcd[i][j] = max(i, j);
      else
        precomp_gcd[i][j] = precomp_gcd[j][i % j];
      precomp_gcd[j][i] = precomp_gcd[i][j];
    }
  int ans = triangles_with_integer_area(w, h);
  ans -= triangles_with_zero_area(w, h);
  norm(ans);
  cout << ans << endl;
  return 0;
}

### Prompt

Generate a CPP solution to the following 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

### Response

```cpp
#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e9 + 7;
int precomp_gcd[4444][4444];
inline void norm(int &x) {
  while (x < 0) x += MOD;
  while (x >= MOD) x -= MOD;
}
inline bool get_bit(int k, int i) { return ((1 << i) & k) != 0; }
int triangles_with_integer_area(int w, int h) {
  int count_points_x[2] = {0, 0};
  int count_points_y[2] = {0, 0};
  const int good[] = {0, 1, 2, 4, 5, 6, 8, 9, 10, 15};
  long long add[2][2];
  for (int i = 0; i < w + 1; i++) count_points_x[i & 1]++;
  for (int i = 0; i < h + 1; i++) count_points_y[i & 1]++;
  int ans = 0;
  for (int i = 0; i < 2; i++)
    for (int j = 0; j < 2; j++) {
      add[i][j] = 0;
      for (const auto &k : good) {
        int t0 = get_bit(k, 0);
        int t1 = get_bit(k, 1);
        int t2 = get_bit(k, 2);
        int t3 = get_bit(k, 3);
        long long ways = count_points_x[t0 ^ (i & 1)];
        ways *= count_points_y[t1 ^ (j & 1)];
        ways *= count_points_x[t2 ^ (i & 1)];
        ways *= count_points_y[t3 ^ (j & 1)];
        add[i][j] += ways;
        add[i][j] %= MOD;
      }
    }
  for (int i = 0; i < w + 1; i++)
    for (int j = 0; j < h + 1; j++) {
      ans += add[i & 1][j & 1];
      norm(ans);
    }
  return ans;
}
int triangles_with_zero_area(int w, int h) {
  int ans = 0;
  for (int dx = -w; dx <= w; dx++) {
    for (int dy = 0; dy <= h; dy++) {
      if (dx < 0 and dy == 0) continue;
      long long number_of_segments = (w - abs(dx) + 1);
      number_of_segments *= h - dy + 1;
      number_of_segments %= MOD;
      ans =
          (ans + number_of_segments *
                     (dx == 0 and dy == 0 ? 1 : 6 * precomp_gcd[abs(dx)][dy])) %
          MOD;
    }
  }
  norm(ans);
  return ans;
}
int main() {
  cin.sync_with_stdio(false);
  int w, h;
  cin >> w >> h;
  for (int i = 0; i <= max(w, h); i++)
    for (int j = 0; j <= i; j++) {
      if (i == 0 or j == 0)
        precomp_gcd[i][j] = max(i, j);
      else
        precomp_gcd[i][j] = precomp_gcd[j][i % j];
      precomp_gcd[j][i] = precomp_gcd[i][j];
    }
  int ans = triangles_with_integer_area(w, h);
  ans -= triangles_with_zero_area(w, h);
  norm(ans);
  cout << ans << endl;
  return 0;
}

```