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 JAVA):

Solution:
import java.io.*;

import java.awt.geom.Point2D;
import java.text.*;
import java.math.*;
import java.util.*;

public class Main implements Runnable {

	final String filename = "";

	final int MOD = 1000000007;

	public void solve() throws Exception {
		int w = iread(), h = iread();
		long[][] count = new long[2][2];
		for (int i = 0; i <= w; i++)
			for (int j = 0; j <= h; j++) {
				count[i % 2][j % 2]++;
			}
		long ans = 0;
		for (int dx = 0; dx < 2; dx++)
			for (int dy = 0; dy < 2; dy++)
				for (int dx2 = 0; dx2 < 2; dx2++)
					for (int dy2 = 0; dy2 < 2; dy2++)
						for (int dx3 = 0; dx3 < 2; dx3++)
							for (int dy3 = 0; dy3 < 2; dy3++) {
								int t = (dx + dx2 + dx3) * (dy + dy2 + dy3) + dx * dy + dx2 * dy2 + dx3 * dy3;
								if (t % 2 == 0) {
									ans = ans + (count[dx][dy] * count[dx2][dy2]) % MOD * count[dx3][dy3];
									ans %= MOD;
								}
							}
		int w1 = w + 1, h1 = h + 1;
		ans -= w1 * (h1 * (long) (w1 * h1 - 1)) % MOD * 3;
		ans %= MOD;
		ans -= w1 * h1;
		ans %= MOD;
		for (int i = 0; i <= w; i++)
			for (int j = 0; j <= h; j++)
				if ((i > 0 || j > 0)) {
					int d = gcd(i, j) - 1;
					long s = (w - i + 1) * (long) (h - j + 1);
					if (i != 0 && j != 0)
						s *= 2;
					if (d > 0)
						ans -= d * s * 6;
				}
		ans %= MOD;
		if (ans < 0)
			ans += MOD;
		out.write(ans + "\n");
	}

	int gcd(int x, int y) {
		while (x > 0 && y > 0) {
			if (x >= y)
				x %= y;
			else
				y %= x;
		}
		return x + y;
	}

	public void run() {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new BufferedWriter(new OutputStreamWriter(System.out));
			// in = new BufferedReader(new FileReader(filename+".in"));
			// out = new BufferedWriter(new FileWriter(filename+".out"));
			solve();
			out.flush();
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
	}

	public int iread() throws Exception {
		return Integer.parseInt(readword());
	}

	public double dread() throws Exception {
		return Double.parseDouble(readword());
	}

	public long lread() throws Exception {
		return Long.parseLong(readword());
	}

	BufferedReader in;

	BufferedWriter out;

	public String readword() throws IOException {
		StringBuilder b = new StringBuilder();
		int c;
		c = in.read();
		while (c >= 0 && c <= ' ')
			c = in.read();
		if (c < 0)
			return "";
		while (c > ' ') {
			b.append((char) c);
			c = in.read();
		}
		return b.toString();
	}

	public static void main(String[] args) {
		try {
			Locale.setDefault(Locale.US);
		} catch (Exception e) {

		}
		// new Thread(new Main()).start();
		new Thread(null, new Main(), "1", 1 << 25).start();
	}
}