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 C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include <bits/stdc++.h>
using namespace std;

/*-------------------Define Start-------------------*/
typedef bool BL;                        // 布尔类型
typedef char SB;                        // 有符号1字节,8位
typedef unsigned char UB;                // 无符号1字节,8位
typedef short SW;                        // 有符号短整型,16位
typedef unsigned short UW;                // 无符号短整型,16位
typedef long SDW;                        // 有符号整型,32位
typedef unsigned long UDW;               // 无符号整型,32位
typedef long long SLL;                    // 有符号长整型,64位
typedef unsigned long long ULL;            // 无符号长整型,64位
typedef char CH;                        // 单个字符
typedef float R32;                        // 单精度浮点数
typedef double R64;                        // 双精度浮点数

#define Rep(i, n) for (register SDW i = 0; i < (n); ++i)
#define For(i, s, t) for (register SDW i = (s); i <= (t); ++i)
#define rFor(i, t, s) for (register SDW i = (t); i >= (s); --i)
#define foreach(i, c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
#define ms0(a) memset(a,0,sizeof(a))
#define msI(a) memset(a,0x7f,sizeof(a))
#define LOWBIT(x) ((x)&(-x))

#define MP make_pair
#define PB push_back
#define ft first
#define sd second

#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl

const ULL mod = 1e9 + 7;                //常用模数(可根据题目需要修改)
const ULL inf = 0x7fffffff;                //用来表示无限大
const ULL infLL = 0x7fffffffffffffffLL;    //用来表示无限大
/*-------------------Define End-------------------*/

const UDW maxN = 1e6 + 7;
SLL r1, c1, r2, c2;
SLL ans;

SLL fac[maxN * 2];
void init_fact() {
    fac[0] = 1;
    For(i, 1, 2 * maxN - 1) {
        fac[i] = (i * fac[i - 1]) % mod;
    }
}

void input(){
    cin >> r1 >> c1 >> r2 >> c2;
    init_fact();
}

//ax + by = gcd(a, b) = d
// 扩展欧几里德算法
/**
 *    a*x + b*y = 1
 *    如果ab互质，有解
 *    x就是a关于b的逆元
 *    y就是b关于a的逆元
 *     
 *    证明： 
 *        a*x % b + b*y % b = 1 % b
 *        a*x % b = 1 % b
 *        a*x = 1 (mod b)
 */
inline void ex_gcd(SLL a, SLL b, SLL &x, SLL &y, SLL &d){
    if(!b) {
        d = a, x = 1, y = 0;
    }
    else{
        ex_gcd(b, a % b, y, x, d);
        y -= x * (a / b);
    }
}

// 求a关于p的逆元，如果不存在，返回-1 
// a与p互质，逆元才存在 
inline SLL inv_mod(SLL a, SLL p = mod){
    SLL d, x, y;
    ex_gcd(a, p, x, y, d);
    return d == 1 ? (x % p + p) % p : -1;
}

inline SLL comb_mod(SLL m, SLL n) {
    SLL ret;

    if(m > n) {
        swap(m, n);
    } 
    
    ret = (fac[n] * inv_mod(fac[m], mod)) % mod;
    ret = (ret * inv_mod(fac[n - m], mod)) % mod;
    
    return ret;
}

void solve(){
    For(i, r1, r2) {
        ans = (ans + comb_mod(i + 1, c2 + i + 1) - comb_mod(i + 1, c1 + i) + mod) % mod;
    }
}

void output(){
    cout << ans << endl;
}

int main() {
    input();
    solve();
    output();
    return 0;
}