#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <math.h>
#include <assert.h>
#include <queue>
#include <map>
#include <set>
#include <string>
#include <algorithm>
#include <iostream>
#include <functional>
#include <unordered_map>
#include <unordered_set>
#include <list>
#include <bitset>

using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
#define Fi first
#define Se second
#define pb(x) push_back(x)
#define sz(x) ((int)(x).size())
#define rep(i, n) for(int i=0;i<n;i++)
#define all(x) (x).begin(), (x).end()
typedef tuple<int, int, int> t3;
typedef pair<ll, ll> pll;
typedef long double ldouble;
typedef pair<double, double> pdd;

int chk[110][110][110];

struct str{
	str(){}
	str(pii a, int f, int v) : a(a), f(f), v(v) {}
	pii a;
	int f, v;
	bool operator<(const str &rhs) const{
		return (ll)a.Fi * rhs.a.Se < (ll)a.Se * rhs.a.Fi;
	}
};

int A, B, C, D;

ll Get(pii s, pii t, int X) {
	ll u = ((ll) t.Fi * X - 1) / t.Se;
	ll l = ((ll) s.Fi * X) / s.Se + 1;
	u = min(u, (ll)X - D - 1);
	return max(0LL, u - l + 1);
}

void solve() {
	/*
	int a, b, c, d; cin >> a >> b >> c >> d;
	rep(i, a) rep(j, b) rep(k, c) {
		double px = (double) k / c * a;
		double py = (double) k / c * b;
		if(i <= px && px <= i+1 && j <= py && py <= j+1) chk[i][j][k] = 1;
		px = (double)(k + 1) / c * a;
		py = (double)(k + 1) / c * b;
		if(i <= px && px <= i+1 && j <= py && py <= j+1) chk[i][j][k] = 1;
		py = (double) i / a * b;
		double pz = (double) i / a * c;
		if(j <= py && py <= j+1 && k <= pz && pz <= k+1) chk[i][j][k] = 1;
		py = (double)(i + 1) / a * b;
		pz = (double)(i + 1) / a * c;
		if(j <= py && py <= j+1 && k <= pz && pz <= k+1) chk[i][j][k] = 1;
		px = (double) j / b * a;
		pz = (double) j / b * c;
		if(i <= px && px <= i+1 && k <= pz && pz <= k+1) chk[i][j][k] = 1;
		px = (double)(j + 1) / b * a;
		pz = (double)(j + 1) / b * c;
		if(i <= px && px <= i+1 && k <= pz && pz <= k+1) chk[i][j][k] = 1;
	}
	set <t3> S;
	rep(i, a) rep(j, b) rep(k, c) if(chk[i][j][k]) rep(x, 2*d+1) rep(y, 2*d+1) rep(z, 2*d+1) {
		int px = i + x - d;
		int py = j + y - d;
		int pz = k + z - d;
		S.insert(t3(px, py, pz));
	}
	printf("%d\n", sz(S));
	int t = 2 * d + 1;
	printf("%d\n", t * t * t + (a + b + c - 3) * t * t);
	 */
	const int MOD = 1e9 + 7;
	cin >> A >> B >> C >> D;
	vector <str> V;
	for(int i=1;i<=min(D, A-D-1);i++) V.emplace_back(pii(i, A), 0, 1);
	for(int i=max(D+1, A-D);i<A;i++) V.emplace_back(pii(i, A), 0, -1);
	for(int i=1;i<=min(D, B-D-1);i++) V.emplace_back(pii(i, B), 1, 1);
	for(int i=max(D+1, B-D);i<B;i++) V.emplace_back(pii(i, B), 1, -1);
	for(int i=1;i<=min(D, C-D-1);i++) V.emplace_back(pii(i, C), 2, 1);
	for(int i=max(D+1, C-D);i<C;i++) V.emplace_back(pii(i, C), 2, -1);
	V.emplace_back(pii(1, 1), 0, -1);
	sort(all(V));
	ll ans = (ll) min(A,D+1) * min(B,D+1) * min(C,D+1) % MOD;
	pii now = pii(0, A);
	int p[3] = {min(A,D+1), min(B,D+1), min(C,D+1)};
	for(int i=0;i<sz(V);i++) {
		str X = V[i];
		ll q[3] = {Get(now, X.a, A), Get(now, X.a, B), Get(now, X.a, C) };
		if(X.v == 1) ++q[X.f];
		ans += (ll) q[0] % MOD * p[1] % MOD * p[2] % MOD;
		ans += (ll) q[1] % MOD * p[0] % MOD * p[2] % MOD;
		ans += (ll) q[2] % MOD * p[0] % MOD * p[1] % MOD;
		ans %= MOD;
		p[X.f] += X.v;
		
		now = X.a;
	}
	printf("%lld\n", ans);
}

int main(){
	int Tc = 1; // scanf("%d\n", &Tc);
	for(int tc=1;tc<=Tc;tc++){
		// printf("Case #%d: ", tc);
		solve();
	}
	return 0;
}

Measured memory_bytes: 10476