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.List;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.Locale;
import java.util.ArrayList;
import java.util.Comparator;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.math.BigInteger;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author AlexFetisov
 */
public class Main {
	public static void main(String[] args) {
		Locale.setDefault(Locale.US);
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		TaskD_LittleElAndTriangle solver = new TaskD_LittleElAndTriangle();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskD_LittleElAndTriangle {
    public static final int MOD = (int) 1e9 + 7;

    public void solve(int testNumber, InputReader in, PrintWriter out) {
        int n = in.nextInt();
        int m = in.nextInt();

        int res = 0;
        int amY0 = getAm(false, 0, m);
        int amY1 = m + 1 - amY0;
        int amX0 = getAm(false, 0, n);
        int amX1 = n + 1 - amX0;

        for (int x = 0; x <= 1; ++x) {
            int B1 = BitUtils.checkBit(1 - x, 0) ? amX1 : amX0;
            int B3 = BitUtils.checkBit(x, 0) ? amX1 : amX0;
            int amX = (x == 0 ? (n/2) + 1 : (n +1) / 2);


            for (int y = 0; y <= 1; ++y) {
                int amY = (y == 0 ? (m/2) + 1 : (m +1) / 2);
                int B2 = BitUtils.checkBit(y, 0) ? amY1 : amY0;
                int B4 = BitUtils.checkBit(1 - y, 0) ? amY1 : amY0;
                for (int xx2 = 0; xx2 <= 1; ++xx2) {
                    int A1 = BitUtils.checkBit(xx2, 0) ? amX1 : amX0;
                    for (int yy1 = 0; yy1 <= 1; ++yy1) {
                        if (odd(xx2 - x) * odd(yy1 - y) == 0) {
                            int A2 = BitUtils.checkBit(yy1, 0) ? amY1 : amY0;
                            long cur2 = (B1 * B2 + B3 * (m+1));
                            cur2 = cur2 * A1 * A2;
                            cur2 %= MOD;
                            cur2 *= amX;
                            cur2 %= MOD;
                            cur2 *= amY;
                            cur2 %= MOD;
                            res += cur2;
                            if (res >= MOD) res -= MOD;
                        } else {
                            int A2 = BitUtils.checkBit(yy1, 0) ? amY1 : amY0;
                            long cur = A1 * A2;
                            cur = cur * B1 * B4;
                            cur %= MOD;
                            cur *= amX;
                            cur %= MOD;
                            cur *= amY;
                            cur %= MOD;
                            res += cur;
                            if (res >= MOD) res -= MOD;
                        }
                    }
                }
            }
        }

        for (int dx = 0; dx <= n; ++dx) {
            for (int dy = 0; dy <= m; ++dy) {
                if (dx == 0 && dy == 0) continue;
                int amX = n - dx + 1;
                int amY = m - dy + 1;
                int amPoints = IntegerUtils.gcd(dx, dy);
                if (dx == 0 || dy == 0) {
                    res -= (amPoints * 6L * amX * amY) % MOD;
                } else {
                    res -= (amPoints * 12L * amX * amY) % MOD;
                }
                res += MOD;
                if (res >= MOD) {
                    res -= MOD;
                }
            }
        }

        res -= (n + 1) * (m + 1);
        res += MOD;
        if (res >= MOD) {
            res -= MOD;
        }

        out.println(res);
    }

    private int odd(int x) {
        return BitUtils.checkBit(x, 0) ? 1 : 0;
    }

    private int getAm(boolean odd, int begin, int end) {
        if (BitUtils.checkBit(begin, 0) != odd) {
            ++begin;
        }
        if (BitUtils.checkBit(end, 0) != odd) {
            --end;
        }
        if (begin <= end) {
            return (end - begin) / 2 + 1;
        }
        return 0;
    }
}

class InputReader {
    private BufferedReader reader;
    private StringTokenizer stt;

    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream));
    }

    public String nextLine() {
        try {
            return reader.readLine();
        } catch (IOException e) {
            return null;
        }
    }

    public String nextString() {
        while (stt == null || !stt.hasMoreTokens()) {
            stt = new StringTokenizer(nextLine());
        }
        return stt.nextToken();
    }

    public int nextInt() {
        return Integer.parseInt(nextString());
    }

}

class BitUtils {
    public static boolean checkBit(int mask, int bit) {
        return (mask & (1 << bit)) > 0;
    }

}

class IntegerUtils {

    public static int gcd(int x, int y) {
        return y == 0 ? x : gcd(y, x % y);
    }

}