// Errichto - hard
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstring>
#include<assert.h>
using namespace std;
#define FOR(i,a,n) for(int i = (a); i <= (n); ++i)
#define FORD(i,a,n) for(int i = (a); i >= (n); --i)
#define REP(i,n) FOR(i,0,(n)-1)
#define RI(i,n) FOR(i,1,(n))
#define pb push_back
#define mp make_pair
#define st first
#define nd second
#define mini(a,b) a=min(a,(b))
#define maxi(a,b) a=max(a,(b))
#define sz(w) (int)w.size()
typedef vector< int > vi;
typedef long long ll;
typedef long double ld;
typedef pair< int ,int > pii;
const int inf = 1e9 + 5 ;
const int nax = 1e6 + 5 ;
const int mod = 1e9 + 7 ;
int mul( int a, int b) { return ( ll) a * b % mod; }
int add( int a, int b) { return ( a + b) % mod; }
int X, Y;
class SubRectangles
{
int power( int a, int b) {
int r = 1 ;
while ( b) {
if ( b % 2 ) r = mul( r, a) ;
a = mul( a, a) ;
b / = 2 ;
}
return r;
}
public : int countWays( int H, int W, int h, int w) {
int bin[ 5 ] [ 5 ] ;
REP( i, 5 ) {
REP( j, 5 ) bin[ i] [ j] = 0 ;
bin[ i] [ 0 ] = 1 ;
RI( j, i) bin[ i] [ j] = bin[ i- 1 ] [ j- 1 ] + bin[ i- 1 ] [ j] ;
}
int n = h * w;
int total = 0 ;
REP( mask, 1 << n) {
int row[ 4 ] , col[ 4 ] ;
REP( i, 4 ) row[ i] = col[ i] = 0 ;
REP( i, n) if ( mask & ( 1 << i) ) {
row[ i/ w] ++ ;
col[ i% w] ++ ;
}
REP( i, 4 ) assert ( row[ i] <= w) ;
REP( i, 4 ) assert ( col[ i] <= h) ;
int one = 1 ;
REP( i, w) {
int Z = ( W- i+ w- 1 ) / w;
int x = 0 ;
FOR( j, 0 , col[ i] )
x = add( x, power( bin[ col[ i] ] [ j] , Z) ) ;
one = mul( one, x) ;
}
int two = 1 ;
REP( i, h) row[ i] = w- row[ i] ;
REP( i, h) {
int Z = ( H- i+ h- 1 ) / h;
ll x = 0 ;
if ( row[ i] == 0 ) x = 1 ;
else if ( row[ i] == 1 ) x = 0 ;
else if ( row[ i] == 2 ) x = power( 2 , Z) - 2 ;
else if ( row[ i] == 3 ) x = 2LL * power( 3 , Z) - 6LL * power( 2 , Z) + 6 ;
else if ( row[ i] == 4 ) x = power( 6 , Z) + 2LL * power( 4 , Z) - 16LL * power( 3 , Z) + 24LL * power( 2 , Z) - 14LL;
else assert ( false ) ;
while ( x < 0 ) x + = mod;
//printf("%d - %lld\n", row[i], x);
two = mul( two, x % mod) ;
}
total = add( total, mul( one, two) ) ;
}
return total;
}
} ;
Ly8gRXJyaWNodG8gLSBoYXJkCiNpbmNsdWRlPGNzdGRpbz4KI2luY2x1ZGU8YWxnb3JpdGhtPgojaW5jbHVkZTx2ZWN0b3I+CiNpbmNsdWRlPGNzdHJpbmc+CiNpbmNsdWRlPGFzc2VydC5oPgp1c2luZyBuYW1lc3BhY2Ugc3RkOwojZGVmaW5lIEZPUihpLGEsbikgZm9yKGludCBpID0gKGEpOyBpIDw9IChuKTsgKytpKQojZGVmaW5lIEZPUkQoaSxhLG4pIGZvcihpbnQgaSA9IChhKTsgaSA+PSAobik7IC0taSkKI2RlZmluZSBSRVAoaSxuKSBGT1IoaSwwLChuKS0xKQojZGVmaW5lIFJJKGksbikgRk9SKGksMSwobikpCiNkZWZpbmUgcGIgcHVzaF9iYWNrCiNkZWZpbmUgbXAgbWFrZV9wYWlyCiNkZWZpbmUgc3QgZmlyc3QKI2RlZmluZSBuZCBzZWNvbmQKI2RlZmluZSBtaW5pKGEsYikgYT1taW4oYSwoYikpCiNkZWZpbmUgbWF4aShhLGIpIGE9bWF4KGEsKGIpKQojZGVmaW5lIHN6KHcpIChpbnQpdy5zaXplKCkKdHlwZWRlZiB2ZWN0b3I8aW50PiB2aTsKdHlwZWRlZiBsb25nIGxvbmcgbGw7CnR5cGVkZWYgbG9uZyBkb3VibGUgbGQ7CnR5cGVkZWYgcGFpcjxpbnQsaW50PiBwaWk7CmNvbnN0IGludCBpbmYgPSAxZTkgKyA1Owpjb25zdCBpbnQgbmF4ID0gMWU2ICsgNTsKY29uc3QgaW50IG1vZCA9IDFlOSArIDc7CgppbnQgbXVsKGludCBhLCBpbnQgYikgeyByZXR1cm4gKGxsKSBhICogYiAlIG1vZDsgfQppbnQgYWRkKGludCBhLCBpbnQgYikgeyByZXR1cm4gKGEgKyBiKSAlIG1vZDsgfQoKaW50IFgsIFk7CgpjbGFzcyBTdWJSZWN0YW5nbGVzCnsKCWludCBwb3dlcihpbnQgYSwgaW50IGIpIHsKCQlpbnQgciA9IDE7CgkJd2hpbGUoYikgewoJCQlpZihiICUgMikgciA9IG11bChyLCBhKTsKCQkJYSA9IG11bChhLCBhKTsKCQkJYiAvPSAyOwoJCX0KCQlyZXR1cm4gcjsKCX0KCXB1YmxpYyA6IGludCBjb3VudFdheXMoaW50IEgsIGludCBXLCBpbnQgaCwgaW50IHcpIHsKCQlpbnQgYmluWzVdWzVdOwoJCVJFUChpLCA1KSB7CgkJCVJFUChqLCA1KSBiaW5baV1bal0gPSAwOwoJCQliaW5baV1bMF0gPSAxOwoJCQlSSShqLCBpKSBiaW5baV1bal0gPSBiaW5baS0xXVtqLTFdICsgYmluW2ktMV1bal07CgkJfQoJCWludCBuID0gaCAqIHc7CgkJaW50IHRvdGFsID0gMDsKCQlSRVAobWFzaywgMSA8PCBuKSB7CgkJCWludCByb3dbNF0sIGNvbFs0XTsKCQkJUkVQKGksIDQpIHJvd1tpXSA9IGNvbFtpXSA9IDA7CgkJCVJFUChpLCBuKSBpZihtYXNrICYgKDEgPDwgaSkpIHsKCQkJCXJvd1tpL3ddKys7CgkJCQljb2xbaSV3XSsrOwoJCQl9CgkJCVJFUChpLCA0KSBhc3NlcnQocm93W2ldIDw9IHcpOwoJCQlSRVAoaSwgNCkgYXNzZXJ0KGNvbFtpXSA8PSBoKTsKCQkJCgkJCWludCBvbmUgPSAxOwoJCQlSRVAoaSwgdykgewoJCQkJaW50IFogPSAoVy1pK3ctMSkgLyB3OwoJCQkJaW50IHggPSAwOwoJCQkJRk9SKGosIDAsIGNvbFtpXSkKCQkJCQl4ID0gYWRkKHgsIHBvd2VyKGJpbltjb2xbaV1dW2pdLCBaKSk7CgkJCQlvbmUgPSBtdWwob25lLCB4KTsKCQkJfQoJCQlpbnQgdHdvID0gMTsKCQkJUkVQKGksIGgpIHJvd1tpXSA9IHctcm93W2ldOwoJCQlSRVAoaSwgaCkgewoJCQkJaW50IFogPSAoSC1pK2gtMSkgLyBoOwoJCQkJbGwgeCA9IDA7CgkJCQlpZihyb3dbaV0gPT0gMCkgeCA9IDE7CgkJCQllbHNlIGlmKHJvd1tpXSA9PSAxKSB4ID0gMDsKCQkJCWVsc2UgaWYocm93W2ldID09IDIpIHggPSBwb3dlcigyLCBaKSAtIDI7CgkJCQllbHNlIGlmKHJvd1tpXSA9PSAzKSB4ID0gMkxMICogcG93ZXIoMywgWikgLSA2TEwgKiBwb3dlcigyLCBaKSArIDY7CgkJCQllbHNlIGlmKHJvd1tpXSA9PSA0KSB4ID0gcG93ZXIoNiwgWikgKyAyTEwgKiBwb3dlcig0LCBaKSAtIDE2TEwgKiBwb3dlcigzLCBaKSArIDI0TEwgKiBwb3dlcigyLCBaKSAtIDE0TEw7CgkJCQllbHNlIGFzc2VydChmYWxzZSk7CgkJCQl3aGlsZSh4IDwgMCkgeCArPSBtb2Q7CgkJCQkvL3ByaW50ZigiJWQgLSAlbGxkXG4iLCByb3dbaV0sIHgpOwoJCQkJdHdvID0gbXVsKHR3bywgeCAlIG1vZCk7CgkJCX0KCQkJdG90YWwgPSBhZGQodG90YWwsIG11bChvbmUsIHR3bykpOwoJCX0KCQlyZXR1cm4gdG90YWw7Cgl9Cn07