Problem:
Score : 600 points

Problem Statement

Snuke is standing on a two-dimensional plane. In one operation, he can move by 1 in the positive x-direction, or move by 1 in the positive y-direction.

Let us define a function f(r, c) as follows:

f(r,c) := (The number of paths from the point (0, 0) to the point (r, c) that Snuke can trace by repeating the operation above)

Given are integers r_1, r_2, c_1, and c_2.
Find the sum of f(i, j) over all pair of integers (i, j) such that r_1 ≤ i ≤ r_2 and c_1 ≤ j ≤ c_2, and compute this value modulo (10^9+7).

Constraints

1 ≤ r_1 ≤ r_2 ≤ 10^6

1 ≤ c_1 ≤ c_2 ≤ 10^6

All values in input are integers.

Input

Input is given from Standard Input in the following format:

r_1 c_1 r_2 c_2

Output

Print the sum of f(i, j) modulo (10^9+7).

Sample Input 1

1 1 2 2

Sample Output 1

14

For example, there are two paths from the point (0, 0) to the point (1, 1): (0,0) → (0,1) → (1,1) and (0,0) → (1,0) → (1,1), so f(1,1)=2.

Similarly, f(1,2)=3, f(2,1)=3, and f(2,2)=6. Thus, the sum is 14.

Sample Input 2

314 159 2653 589

Sample Output 2

602215194

Solution in Java8 (OpenJDK 1.8.0) (judge verdict: Wrong Answer)

import java.io.*;
import java.util.*;

class Main  {
    static int mod = 1000000007;
    static int mx = 2000007;
    static int[] fact, ifact;
    
    public static void main(String args[]) throws IOException {
        fact = new int[mx];
        ifact = new int[mx];
        fact[1] = 1;
        ifact[1] = 1;
        
        for(int i = 2; i < mx; ++i){
            fact[i] = modMul(fact[i-1], i);
            ifact[i] = modMul(ifact[i-1], modExp(i, mod-2));
        }
        
        Scan sc = new Scan();
        int tr1 = sc.scanInt();
        int tc1 = sc.scanInt();
        int tr2 = sc.scanInt();
        int tc2 = sc.scanInt();
        
        int r1 = Math.min(tr1, tr2);
        int c1 = Math.min(tc1, tc2);
        
        int r2 = tr1+tr2-r1;
        int c2 = tc1+tc2-c1;
            
        int part1 = modAdd(comb(r1 + c1, c1), comb(r2 + c2 + 2, c2 + 1), true);
        int part2 = modAdd(comb(r1 + c2 + 1, c2 + 1), comb(r2 + c1 + 1, c1), true);
        System.out.println(modAdd(part1, part2, false));
        
    }
    
    static int comb(int n, int r){
        return modMul(fact[n], modMul(ifact[r], ifact[n-r]));
    }
    
    static int modAdd(int a, int b, boolean add){
        return add ? (int)((long)a + b) : (int)((long)a - b);    
    }
    
    static int modMul(int a, int b){
        return (int)(((long)a*b)%mod);
    }
    
    static int modExp(int a, int b){
        int res = 1;
        while(b > 0){
            if(b%2==1){
                res = modMul(res, a);
            }
            a = modMul(a, a);
            b>>=1;
        }
        return res;
    }
}

class Scan {
    private byte[] buf=new byte[1024];
    private int index;
    private InputStream in;
    private int total;
    public Scan()
    {
        in=System.in;
    }
    public int scan()throws IOException
    {
        if(total<0)
        throw new InputMismatchException();
        if(index>=total)
        {
            index=0;
            total=in.read(buf);
            if(total<=0)
            return -1;
        }
        return buf[index++];
    }
    public int scanInt()throws IOException
    {
        int integer=0;
        int n=scan();
        while(isWhiteSpace(n))
        n=scan();
        int neg=1;
        if(n=='-')
        {
            neg=-1;
            n=scan();
        }
        while(!isWhiteSpace(n))
        {
            if(n>='0'&&n<='9')
            {
                integer*=10;
                integer+=n-'0';
                n=scan();
            }
            else throw new InputMismatchException();
        }
        return neg*integer;
    }
    public double scanDouble()throws IOException
    {
        double doub=0;
        int n=scan();
        while(isWhiteSpace(n))
        n=scan();
        int neg=1;
        if(n=='-')
        {
            neg=-1;
            n=scan();
        }
        while(!isWhiteSpace(n)&&n!='.')
        {
            if(n>='0'&&n<='9')
            {
                doub*=10;
                doub+=n-'0';
                n=scan();
            }
            else throw new InputMismatchException();
        }
        if(n=='.')
        {
            n=scan();
            double temp=1;
            while(!isWhiteSpace(n))
            {
                if(n>='0'&&n<='9')
                {
                    temp/=10;
                    doub+=(n-'0')*temp;
                    n=scan();
                }
                else throw new InputMismatchException();
            }
        }
        return doub*neg;
    }
    public String scanString()throws IOException
    {
        StringBuilder sb=new StringBuilder();
        int n=scan();
        while(isWhiteSpace(n))
        n=scan();
        while(!isWhiteSpace(n))
        {
            sb.append((char)n);
            n=scan();
        }
        return sb.toString();
    }
    private boolean isWhiteSpace(int n)
    {
        if(n==' '||n=='\n'||n=='\r'||n=='\t'||n==-1)
        return true;
        return false;
    }
}