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>

#ifdef _PRINTDEBUG
  #include "lib/printdebug.hpp"
#else
  #define printdebug(...) 1
#endif
#define I1000000007 (1000000007)
#define I998244353   (998244353)
#define IINF             (1<<28)
#define LINF           (1LL<<60)
#define ALL(a)         (a).begin(), (a).end()
#define rep(i, n)      REP(i, 0, (n))
#define repc(i, n)     REPC(i, 0, (n))
#define REP(i, n, m)   for (int i = (int)(n); i <  (int)(m); i++)
#define REPC(i, n, m)  for (int i = (int)(n); i <= (int)(m); i++)
#define REPCM(i, n, m) for (int i = (int)(n); i >= (int)(m); i--)
#define yesno(cond)       YESNO((cond), "Yes", "No")
#define YESNO(cond, a, b) cout << ((cond) ? (a) : (b)) << "\n"
template<class T> inline bool chmin(T& a, const T& b) {
  if (a > b) { a = b; return true; } else return false;
}
template<class T> inline bool chmax(T& a, const T& b) {
  if (a < b) { a = b; return true; } else return false;
}
namespace combinatorics {
  const int limit = 2000020;
  const int mod = 1000000007;

  bool initialized = false;
  long long fac_table[limit], inv_table[limit], finv_table[limit];

  void initialize() {
    fac_table[0] = fac_table[1] = 1;
    inv_table[1] = 1;
    finv_table[0] = finv_table[1] = 1;
    for (int i = 2; i < limit; i++) {
      fac_table[i] = fac_table[i - 1] * i % mod;
      inv_table[i] = mod - inv_table[mod % i] * (mod / i) % mod;
      finv_table[i] = finv_table[i - 1] * inv_table[i] % mod;
    }
    initialized = true;
  }

  long long com(int n, int k) {
    if (!initialized) initialize();
    if (n < k || n < 0 || k < 0) return 0;
    else return fac_table[n] * (finv_table[k] * finv_table[n - k] % mod) % mod;
  }
}
template<std::int_fast64_t divisor> struct modint {
  using i64 = std::int_fast64_t;

  i64 val;

  constexpr modint(i64 v = 0) noexcept : val(v % divisor) {
    if (val < 0) val += divisor;
  }

  constexpr modint operator + (const modint& rhs) const noexcept {
    return modint(*this) += rhs;
  }

  constexpr modint operator - (const modint& rhs) const noexcept {
    return modint(*this) -= rhs;
  }

  constexpr modint operator * (const modint& rhs) const noexcept {
    return modint(*this) *= rhs;
  }

  constexpr modint operator / (const modint& rhs) const noexcept {
    return modint(*this) /= rhs;
  }

  constexpr modint operator ~ () const noexcept {
    i64 a = this->val, b = divisor, u = 1, v = 0;
    while (b > 0) {
      i64 t = a / b;
      a -= t * b;
      u -= t * v;
      i64 c = a; a = b; b = c;
      i64 w = u; u = v; v = w;
    }
    if (u < 0) u += divisor;
    u %= divisor;
    return u;
  }

  constexpr modint& operator += (const modint& rhs) noexcept {
    val += rhs.val;
    if (val >= divisor) val -= divisor;
    return *this;
  }

  constexpr modint& operator -= (const modint& rhs) noexcept {
    if (val < rhs.val) val += divisor;
    val -= rhs.val;
    return *this;
  }

  constexpr modint& operator *= (const modint& rhs) noexcept {
    val = val * rhs.val % divisor;
    return *this;
  }

  constexpr modint& operator /= (const modint& rhs) noexcept {
    val = val * (~(modint(rhs))).val % divisor;
    return *this;
  }

  friend modint<divisor> modpow (modint<divisor> a, i64 n) noexcept {
    auto res = modint<divisor>(1);
    while(n > 0) {
      if(n&1) res *= a;
      a *= a;
      n >>= 1;
    }
    return res;
  }

  friend std::ostream& operator << (std::ostream& os, const modint<divisor>& a) noexcept {
    return os << a.val;
  }
};

namespace solver {
  using namespace std;
  using ll = long long;
  using mint = modint<I1000000007>;

  int r1, c1, r2, c2;

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

  void solve() {
    mint ans = 0;
    REPC(r, r1, r2) {
      ans += combinatorics::com(r+1+c2, r+1);
      ans -= combinatorics::com(r+1+c1-1, r+1);
    }
    cout << ans << "\n";
  }
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(0);
  solver::init();
  solver::solve();
  return 0;
}