#include<iostream>
#include<algorithm>
#include<cmath>
#include<map>
#include<stdio.h>
#include<vector>
#include<queue>
using namespace std;
#define int long long
#define double long double
#define rep(s,i,n) for(int i=s;i<n;i++)
#define c(n) cout<<n<<endl;
#define ic(n) int n;cin>>n;
#define sc(s) string s;cin>>s;
#define mod 1000000007
#define inf 1000000000000000007
#define f first
#define s second
#define mini(c,a,b) *min_element(c+a,c+b)
#define maxi(c,a,b) *max_element(c+a,c+b)
#define P pair<int,int>
//printf("%.12Lf\n",);
int keta(int x){
	rep(0,i,30){
		if(x<10){
			return i+1;
		}
		x=x/10;
	}
}	
int gcd(int x,int y){
	int aa=x,bb=y;
	rep(0,i,1000){
		aa=aa%bb;
		if(aa==0){
			return bb;
		}	
		bb=bb%aa;
		if(bb==0){
			return aa;
		}
	}
}	
int lcm(int x,int y){
	int aa=x,bb=y;
	rep(0,i,1000){
		aa=aa%bb;
		if(aa==0){
			return x/bb*y;
		}	
		bb=bb%aa;
		if(bb==0){
			return x/aa*y;
		}
	}
}
bool p(int x){
	if(x==1)return false;
	rep(2,i,sqrt(x)+1){
		if(x%i==0&&x!=i){
			return false;
		}
	}	
	return true;
}
int max(int a,int b){
	if(a>=b)return a;
	else return b;
}
int min(int a,int b){
	if(a>=b)return b;
	else return a;
}	
int n2[41];		
int nis[41]; 
int nia[41];
int mody[41];
int nn;
int com(int n,int y){
	int ni=1;
	for(int i=0;i<41;i++){
		n2[i]=ni;
		ni*=2;
	}
	int bunsi=1,bunbo=1;
	rep(0,i,y)bunsi=(bunsi*(n-i))%mod;
	rep(0,i,y)bunbo=(bunbo*(i+1))%mod;
	mody[0]=bunbo;
	rep(1,i,41){
		bunbo=(bunbo*bunbo)%mod;
		mody[i]=bunbo;
	}
	rep(0,i,41)nis[i]=0;
	nn=mod-2;
	for(int i=40;i>=0;i-=1){
		if(nn>n2[i]){
			nis[i]++;
			nn-=n2[i];
		}
	}
	nis[0]++;
	rep(0,i,41){
		if(nis[i]==1){
			bunsi=(bunsi*mody[i])%mod;
		}
	}
	return bunsi;
}
int gyakugen(int n,int y){
	int ni=1;
	for(int i=0;i<41;i++){
		n2[i]=ni;
		ni*=2;
	}
	mody[0]=y;
	rep(1,i,41){
		y=(y*y)%mod;
		mody[i]=y;
	}
	rep(0,i,41)nis[i]=0;
	nn=mod-2;
	for(int i=40;i>=0;i-=1){
		if(nn>n2[i]){
			nis[i]++;
			nn-=n2[i];
		}
	}
	nis[0]++;
	rep(0,i,41){
		if(nis[i]==1){
			n=(n*mody[i])%mod;
		}
	}
	return n;	
}	
int yakuwa(int n){
	int sum=0;
	rep(1,i,sqrt(n+1)){
		if(n%i==0)sum+=i+n/i;
		if(i*i==n)sum-=i;
	}
	return sum;
}	
bool integer(double n){
	if(n==long(n))return true;
	else return false;	
}
int pow(int b,int a){	
	int aa=1;
	rep(0,i,a)aa*=b;	
	return aa;
}
int ketawa(int x,int sinsuu){
	int sum=0;
	rep(0,i,20)sum+=(x%pow(sinsuu,i+1))/(pow(sinsuu,i));
	return sum;
}	
int sankaku(int a){
	return a*(a+1)/2;
} 
bool search(int x){
	int n;
	int a[n];
	int l=0,r=n;
	while(r-l>=1){
		int i=(l+r)/2;
		if(a[i]==x)return true;
		else if(a[i]<x)l=i+1;
		else r=i;
	}
	return false;
}
using Graph=vector<vector<int>>;
/*int oya[114514];
int depth[114514];
void dfs(const Graph &G, int v, int p, int d) {
    depth[v] = d;
    oya[v]=p;
    for (auto nv : G[v]) {
       if (nv == p) continue; // nv が親 p だったらダメ
       dfs(G, nv, v, d+1); // d を 1 増やして子ノードへ
    }
}*/
/*int H=10,W=10;
char field[10][10];
char memo[10][10];
void dfs(int h, int w) {
    memo[h][w] = 'x';

    // 八方向を探索
    for (int dh = -1; dh <= 1; ++dh) {
        for (int dw = -1; dw <= 1; ++dw) {
        	if(abs(0-dh)+abs(0-dw)==2)continue;
            int nh = h + dh, nw = w + dw;

            // 場外アウトしたり、0 だったりはスルー
            if (nh < 0 || nh >= H || nw < 0 || nw >= W) continue;
            if (memo[nh][nw] == 'x') continue;

            // 再帰的に探索
            dfs(nh, nw);
        }
    }
}*/
int comd[2214514];
int comb[2214514];
signed main(){
	ic(a) ic(b) ic(c) ic(d)
	long long ans=0;
	comd[0]=1;
	rep(1,i,c+d+1){
		comd[i]=gyakugen(comd[i-1],i);
		comd[i]=((comd[i]*i)%mod+(comd[i]*c)%mod)%mod;
	}
	comb[0]=1;
	rep(1,i,d+a+1){
		comb[i]=gyakugen(comb[i-1],i);
		comb[i]=((comb[i]*i)%mod+(comb[i]*a)%mod-comb[i])%mod;
	}	
	rep(b,i,d+1){
		ans+=mod+comd[i+1]-comb[i+1];
		ans=ans%mod;
	}	
	c(ans)
}


Measured memory_bytes: 33152