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# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Linq;

namespace Contest
{
    partial class Program
    {
        static void Main(string[] args)
        {
            ABC154_F();
        }



        static void ABC154_A()
        {
            var st = ReadStrN();
            var ab = ReadIntN();
            var u = ReadStr();
            Console.WriteLine("{0} {1}", ab[0] - (st[0] == u ? 1 : 0), ab[1] - (st[1] == u ? 1 : 0));
        }
        static void ABC154_B()
        {
            Console.WriteLine(String.Join("", Enumerable.Repeat('x', ReadStr().Length)));
        }
        static void ABC154_C()
        {
            var N = ReadInt();
            var A = ReadIntN();
            A = A.OrderBy(x => x).ToArray();
            for (int i = 0; i < N - 1; ++i)
            {
                if (A[i] == A[i + 1])
                {
                    Console.WriteLine("NO");
                    return;
                }
            }
            Console.WriteLine("YES");
        }
        static void ABC154_D()
        {
            var NK = ReadIntN();
            var P = ReadIntN();
            var N = NK[0];
            var K = NK[1];
            int[] sums = new int[N + 1];
            sums[0] = 0;
            for (int i = 1; i < N + 1; ++i)
            {
                sums[i] = sums[i - 1] + P[i - 1];
            }
            var max = Enumerable.Range(0, N - K + 1).Select(i => sums[i + K] - sums[i]).Max();
            Console.WriteLine((max + K) / 2.0);
        }
        static void ABC154_E()
        {
            var NStr = ReadStr();
            var K = ReadInt();
            var N = NStr.Select(c => Convert.ToInt32(c) - 48).Reverse().ToArray();
            var length = N.Length;
            long[,] table1 = new long[length, 3];
            long[,] table2 = new long[length, 3];

            table1[0, 0] = N[0];
            table2[0, 0] = 9;

            for (int i = 1; i < length; ++i)
            {
                table2[i, 0] = table2[i - 1, 0] * 1 + 9;
                table2[i, 1] = table2[i - 1, 1] * 1 + table2[i - 1, 0] * 9;
                table2[i, 2] = table2[i - 1, 2] * 1 + table2[i - 1, 1] * 9;
                var n = N[i];
                if (n == 0)
                {
                    for (int j = 0; j < 3; ++j)
                    {
                        table1[i, j] = table1[i - 1, j];
                    }
                }
                else
                {
                    table1[i, 0] = table2[i - 1, 0] + (n - 1) + 1;
                    table1[i, 1] = table2[i - 1, 1] + (n - 1) * table2[i - 1, 0] + table1[i - 1, 0];
                    table1[i, 2] = table2[i - 1, 2] + (n - 1) * table2[i - 1, 1] + table1[i - 1, 1];
                }
            }
            Console.WriteLine(table1[length - 1, K - 1]);
        }
        static void ABC154_F()
        {
            var P = 1000000007;
            var RC = ReadIntN();
            var r1 = RC[0];
            var c1 = RC[1];
            var r2 = RC[2];
            var c2 = RC[3];
            var facts = Facts(r2 + c2 + 2, P);
            var factInvs = facts.Select(x => Inverse(x, P)).ToArray();

            Func<int, int, long> sumF = (r, c) =>
                  ((facts[r + c + 2] * factInvs[r + 1] % P) * factInvs[c + 1] % P + (P - 1)) % P;
            long ans = (sumF(r2, c2) - sumF(r1 - 1, c2) - sumF(r2, c1 - 1) + sumF(r1 - 1, c1 - 1) + P * 2) % P;
            Console.WriteLine(ans);
        }
        static long Inverse(long a, long p)
        {
            long b = p, c = 1, d = 0, e = 0, f = 0;
            while (b != 0)
            {
                e = a / b;
                f = b; b = a - e * b; a = f;
                f = d; d = c - e * d; c = f;
            }
            c %= p;
            return c + (c < 0 ? p : 0);
        }
        static long[] Facts(int n, long p)
        {
            var facts = new long[n + 1];
            facts[0] = 1;
            for (int i = 1; i <= n; ++i)
            {
                facts[i] = (i * facts[i - 1]) % p;
            }
            return facts;
        }

        static string ReadStr()
        {
            return Console.ReadLine();
        }
        static string[] ReadStrN()
        {
            return Console.ReadLine().Split(' ');
        }
        static int ReadInt()
        {
            return Convert.ToInt32(Console.ReadLine());
        }
        static int[] ReadIntN()
        {
            return Console.ReadLine().Split(' ').Select(s => Convert.ToInt32(s)).ToArray();
        }
    }
}