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

#include<iostream>
#include<math.h>
#include<algorithm>
#include<stdint.h>
#include<vector>
#include<deque>
#include<stack>
#include<functional>
#include<string>
#include<cstring>
#include<time.h>
#include<array>
#include<iomanip>
#include<list>
#include<set>
#include<map>
#include<random>
#include<unordered_map>
#include<unordered_set>
#include<bitset>
#include <queue>


using namespace std;
using ll = long long;
using ull = unsigned long long;
using uint = unsigned int;
using ldb = long double;


//BDD,ZDD,kdtree, bdtree,bicalc, bolonoy, doloney, tree, chinesemod,segmenttree,daikusutora, saidairyuu, 2bugurahu, heirokenshutu, topologicalsort, kyourenketuseibun

#define REP(i,a,b) for(ll i = a; i < b; ++i)
#define PRI(s) cout << s << endl
#define PRIF(v, n) printf("%."#n"f\n", v)
#define PRIY PRI("Yes")
#define PRIN PRI("No")
#define MINS(a,b) a = min(a,(decltype(a))(b))
#define MAXS(a,b) a = max(a,(decltype(a))(b))

ll mod = 1e9 + 7;

//拡張ユークリッドの互除法。戻り値は最大公約数、x,yはax+by=gcd(a,b)を満たす組の一つ
long long gcdext(long long a, long long b, long long& x, long long& y) {
	if (b == 0) {
		x = 1;
		y = 0;
		return a;
	}
	long long g = gcdext(b, a % b, y, x);
	y -= a / b * x;
	return g;
}

//モジュラ逆数
long long modinv(long long a, long long mod) {
	long long x, y;
	gcdext(a, mod, x, y);
	x = ((x % mod) + mod) % mod;
	return x;
}

class com_table {
public:
	vector<long long> frac;
	vector<long long> finv;
	long long mod;
	com_table() = default;
	void init(long long size, long long mod) {
		this->mod = mod;
		frac.resize(size + 1);
		finv.resize(size + 1);
		frac[0] = 1;
		finv[0] = 1;
		for (int i = 1; i <= size; ++i) frac[i] = frac[i - 1] * i % mod;
		finv[size] = modinv(frac[size], mod);
		for (int i = size; i >= 2; --i) finv[i - 1] = finv[i] * i % mod;
	}
	long long operator()(int a, int b) {
		if (a < b)return 0;
		return ((frac[a] * finv[b] % mod) * finv[a - b]) % mod;
	}
};

com_table tbl;

ll T(ll X, ll Y) {
	ll ans = 0;
	REP(y, 0, Y + 1) {
		ans = (ans + tbl(y + X + 1, X)) % mod;
	}
	return ans;
}

ll Mod(ll  x) { return (x % mod + mod) % mod; }

int main() {
	tbl.init(3000000,mod);

	ll r1, c1, r2, c2;
	cin >> r1 >> c1 >> r2 >> c2;
	--r1; --c1;
	ll ans = T(r2, c2);
	ans = Mod(ans);
	ans -= T(r2, c1);
	ans = Mod(ans);
	ans -= T(r1, c2);
	ans = Mod(ans);
	ans += T(r1, c1);
	ans = Mod(ans);
	PRI(ans);
	return 0;
}