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.util.*;
import java.io.*;

public class A {
	public static void main(String[] args) throws IOException {
		st = new StringTokenizer(rd.readLine());
		M = Integer.parseInt(st.nextToken());
		N = Integer.parseInt(st.nextToken());
		F[0] = 1;
	//	for(int i=0; i<=4000; i++) for(int j=0; j<=4000; j++) g[i][j] = gcd(i, j);
		for(int i=1; i<F.length; i++) F[i] = (F[i-1]*i)%Q;
		for(int i=0; i<IF.length; i++) IF[i] = pow(F[i], Q-2);
		long[] X = new long[4];
		long numEven1 = N/2+1, numOdd1 = N+1-numEven1, numEven2 = M/2+1, numOdd2 = M+1-numEven2;
		X[0] = numEven1*numEven2;
		X[1] = numEven1*numOdd2;
		X[2] = numOdd1*numEven2;
		X[3] = numOdd1*numOdd2;
	//	System.out.println(Arrays.toString(X));
		P = new Point[4];
		P[0] = new Point(0, 0);
		P[1] = new Point(0, 1);
		P[2] = new Point(1, 0);
		P[3] = new Point(1, 1);
		long res = 0;
		for(int i=0; i<4; i++){
			for(int j=0; j<4; j++){
				for(int k=0; k<4; k++){
					if(isOk(i, j, k)){
						if(i!=j && j!=k && i!=k){
							res = (res + ((X[i]*X[j])%Q)*X[k])%Q;
						}
						else if(i!=j && j!=k && i==k){
							res = (res + (X[i]>0? ((X[i]*X[j])%Q)*(X[i]-1): 0))%Q;
						}
						else if(i!=j && j==k && i!=k){
							res = (res + (X[j]>0? ((X[i]*X[j])%Q)*(X[j]-1): 0))%Q;
						}
						else if(i!=j && j==k && i==k){
							//
						}
						else if(i==j && j!=k && i!=k){
							res = (res + (X[i]>0? ((X[i]*(X[i]-1))%Q)*X[k]: 0))%Q;
						}
						else if(i==j && j!=k && i==k){
							//							
						}
						else if(i==j && j==k && i!=k){
							//
						}
						else if(i==j && j==k && i==k){
							res = (res + (X[i]>1? ((X[i]*(X[i]-1))%Q)*(X[i]-2): 0))%Q;
						}
					}
				}
			}
		}
		pw.println((res-numOnLine()+Q)%Q);
		int r = 0;
		pw.flush();
		if(r==0) return;
		for(int x1=0; x1<=M; x1++){
			for(int x2=0; x2<=M; x2++){
				for(int x3=0; x3<=M; x3++){
					for(int y1=0; y1<=N; y1++){
						for(int y2=0; y2<=N; y2++){
							for(int y3=0; y3<=N; y3++){
								int s = Math.abs(x1*(y2-y3)+x2*(y3-y1)+x3*(y1-y2));
								if(s!=0 && s%2==0) r++;
							}
						}
					}
				}
			}
		}
//		System.out.println(r);
	}
	
	static int numOnLine(){
		long res = 0;
		for(int m=0; m<=M; m++){
			for(int n=0; n<=N; n++){
				long mult = (M-m+1)*(N-n+1);
				if(m==0 || n==0){
					int s = m+n;
					if(s>=2){
						res = (res + mult*(s-1)*6)%Q;
		//				System.out.println("XAZI");
					}
				}
				else{
					int d = gcd1(m, n);
					int t = n/d;
					int num = n/t+1;
					if(num>=3){
				//		if(m<2 && n<2) System.out.println("TY");
		//				System.out.println("diagonali");
						res = (res + mult*(num-2)*12)%Q;
					}
				}
			}
		}
		return (int) res;
	}
	
	static int gcd1(int x, int y){
		if(x==0 || y==0) return x+y;
		if(x==1 || y==1) return 1;
		if(x>y) return gcd1(x%y, y);
		return gcd1(x, y%x);
	}
	
	static long getA(int x, int y){
		return F[x]*IF[x-y];
	}
	
	static long[] F = new long[4001], IF = new long[4001];
	
	static long pow(long x, long y){
		if(y==0) return 1;
		if(y==1) return x%Q;
		long sq = pow(x, y>>1);
		return y%2==0? (sq*sq)%Q: (((sq*sq)%Q)*x)%Q;
	}
	
	static int gcd(int x, int y){
		if(x>y) return gcd(y, x);
		if(x==0 || y==0) return x+y;
		if(x==1 || y==1) return 1;
		if((x&1)==0 && (y&1)==0) return 2*gcd(x>>1, y>>1);
		if((x&1)==0) return gcd(x>>1, y);
		if((y&1)==0) return gcd(x, y>>1);
		return gcd(x, (y-x)>>1);
	}
	
	static int[][] g = new int[4001][4001];
	
	static int Q = 1000000007;
	
	static Point[] P;
	
	static boolean isOk(int i, int j, int k){
		Point a = new Point(P[i].x, P[i].y), b = new Point(P[j].x, P[j].y), c = new Point(P[k].x, P[k].y);
		int mult = a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y)+1000;
		return mult%2==0;
	}
	
	static int M, N;
	
	static BufferedReader rd = new BufferedReader(new InputStreamReader(System.in));
	static PrintWriter pw = new PrintWriter(System.out);
	static StringTokenizer st;
	
}

class Point{
	public Point(int x, int y){
		this.x = x;
		this.y = y;
	}
	
	public int x, y;
	
	
	
}