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.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Locale;
import java.util.Queue;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;

public class Solution implements Runnable {

	BufferedReader in;
	PrintWriter out;
	StringTokenizer st;

	String nextToken() throws Exception {
		while (st == null || !st.hasMoreTokens()) {
			st = new StringTokenizer(in.readLine());
		}
		return st.nextToken();
	}

	int nextInt() throws Exception {
		return Integer.parseInt(nextToken());
	}

	long nextLong() throws Exception {
		return Long.parseLong(nextToken());
	}

	double nextDouble() throws Exception {
		return Double.parseDouble(nextToken());
	}
	
	long modd = 1000000007;
	
	long gcd(long a, long b) {
		while (b != 0) {
			long t = a % b;
			a = b;
			b = t;
		}
		return a;
	}
	
	long f(int a, int b) {
		long res = 0;
		boolean evens = a * b % 2 == 0;
		if (evens) {
			res = 2 * a + 2 * b;
		}
		long all = (a - 1) * (b - 1);
		long odd = a / 2 * (b / 2);
		if (evens) {
			res = (res + 4 * (all - odd)) % modd;
		} else {
			res = (res + 4 * odd) % modd;
		}
		long aeven = 0;
		if (a % 2 == 0) aeven = b + 1; else {
			aeven = (b + 2) / 2;
		}
		long aodd = b + 1 - aeven;
		long beven = 0;
		if (b % 2 == 0) beven = a + 1; else {
			beven = (a + 2) / 2;
		}
		long bodd = a + 1 - beven;
		long tmp = aeven * beven % modd + aodd * bodd % modd;
		if (evens) tmp = (tmp + modd - 2) % modd;
		tmp = (tmp + modd - gcd(a, b) - 1) % modd;
		return (res + 2 * tmp) % modd;
	}
	
	int ans(int w, int h) {
		long ans = 0;
		if (w < h) { int t = w; w = h; h = t; }
		for (int i = 1; i <= h; i++) {
			for (int j = i + 1; j <= h; j++) {
				long t = f(i, j);
				ans = (ans + t * (w - i + 1) * (h - j + 1)) % modd;
				ans = (ans + t * (h - i + 1) * (w - j + 1)) % modd;
			}
		}
		for (int i = 1; i <= h; i++) {
			long t = f(i, i);
			ans = (ans + t * (w - i + 1) * (h - i + 1)) % modd;
		}
		for (int i = h + 1; i <= w; i++) {
			for (int j = 1; j <= h; j++) {
				long t = f(i, j);
				ans = (ans + t * (w - i + 1) * (h - j + 1)) % modd;
			}
		}
		return (int)(ans * 6 % modd);
	}
	
	void solve() throws Exception {
		int w = nextInt(), h = nextInt();
		out.println(ans(w, h));
	}

	public void run() {
		try {
			Locale.setDefault(Locale.UK);
			in = new BufferedReader(new InputStreamReader(System.in));
			// in = new BufferedReader(new FileReader("input.txt"));
			out = new PrintWriter(System.out);
			// out = new PrintWriter("output.txt");
			solve();
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		} finally {
			out.close();
		}
	}

	public static void main(String[] args) {
		// new Thread(null, new Solution(), "1", 1 << 28).start();
		(new Solution()).run();
	}

}