Problem:
Dungeon Creation
The king demon is waiting in his dungeon to defeat a brave man.
His dungeon consists of
H \times W
grids.
Each cell is connected to four (i.e. north, south, east and west) neighboring cells and some cells are occupied by obstacles.
To attack the brave man, the king demon created and sent a servant  that walks around in the dungeon.
However, soon the king demon found that the servant does not work as he wants.
The servant  is too dumb. If the dungeon had  cyclic path, it might keep walking along the cycle forever.
In order to make sure that the servant eventually find the brave man, the king demon decided to  eliminate all cycles by building walls between cells.
At the same time, he must be careful so that there  is at least one path between any two cells  not occupied by obstacles.
Your task is to write a program that computes in how many ways the kind demon can build walls.
Input
The first line of each test case has two integers
H
and
W
(
1 \leq H \leq 500
,
1 \leq W \leq 15
), which  are the height and the width of the dungeon.
Following
H
lines consist of exactly
W
letters each of which is '.' (there is no obstacle on the cell) or '#' (there is an obstacle).
You may assume that there is at least one cell that does not have an obstacle.
The input terminates when
H = 0
and
W = 0
. Your program must not output for this case.
Output
For each test case, print its case number and the number of ways that walls can be built in one line. Since the answer can be very big, output in modulo 1,000,000,007.
Sample Input
2 2
..
..
3 3
...
...
..#
0 0
Output for the Sample Input
Case 1: 4
Case 2: 56

Submitted solutions:

code_snippet: #include <iostream>
#include <algorithm>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>

using namespace std;

typedef long long LL;
const int dir[4][2] = {-1, 0, 1, 0, 0, -1, 0, 1};
const int maxn = 512;
const int mod = 1000000007;
char s[maxn][maxn];
int idx[maxn][maxn];
vector<vector<int> > g;

LL exgcd(LL a, LL b, LL& x, LL& y) {
    LL g = a; x = 1; y = 0;
    if (b != 0) {
        g = exgcd(b, a % b, y, x), y -= (a / b) * x;
    }
    return g;
}

LL inv(LL a, LL mod) {
    LL x, y;
    if (exgcd(a, mod, x, y) == 1) {
        return (x % mod + mod) % mod;
    }
    return 0;
}
int H, W, cas = 0;
bool invalid(int x, int y) {
    return x >= 0 && y >= 0 && x < H && y < W;
}

void guass(vector<vector<int> >& mat) {
    int h = mat.size();
    if (h == 0) return;
    int w = mat[0].size() / 2;
    for (int i = 0; i < h; ++i) {
        if (mat[i][w] == 0) return;
        for (int j = i + 1; j < min(h, i + w + 1); ++j) {
            LL r = (mod - mat[j][w - (j - i)]) * inv(mat[i][w], mod) % mod;
            for (int dx = 0; dx < w + 1; ++dx) {
                int fx = w + dx;
                int tx = w - (j - i) + dx;
                g[j][tx] = (g[j][tx] + g[i][fx] * r) % mod;
            }
        }
    }
}

void print(vector<vector<int> >& g) {
    for (int i = 0; i < g.size(); ++i) {
        for (int j = 0; j < g[i].size(); ++j) {
            cout << g[i][j] << ' ';
        }
        cout << endl;
    }
}

int main() {
    
    while (scanf("%d %d", &H, &W), H + W) {
        for (int i = 0; i < H; ++i) {
            scanf("%s", s[i]);
        }
        //printf("Case %d: ", ++cas);
        memset(idx, -1, sizeof(idx));
        int cid = 0;
        for (int i = 0; i < H; ++i) {
            for (int j = 0; j < W; ++j) {
                if (s[i][j] == '#' && cid == 0) continue;
                idx[i][j] = cid++;
            }
        }
        g = vector<vector<int> >(cid, vector<int>(2 * W + 1, 0));
        for (int i = 0; i < H; ++i) {
            for (int j = 0; j < W; ++j) {
                if (idx[i][j] == -1) continue;
                if (s[i][j] == '#') {
                    g[idx[i][j]][W] = 1; continue;
                }
                for (int k = 0; k < 4; ++k) {
                    int tx = i + dir[k][0];
                    int ty = j + dir[k][1];
                    if (!invalid(tx, ty) || s[tx][ty] == '#') continue;
                    ++g[idx[i][j]][W];
                    int offset = tx * W + ty - i * W - j;
                    g[idx[i][j]][W + offset] = mod - 1;
                }
            }
        }
        g.erase(g.begin());
        for (int dx = 0; dx < min(W, (int)g.size()); ++dx) {
            g[dx][W - dx - 1] = 0;
        }
        //print(g);
        guass(g);
        //print(g);
        for (int i = 0; i < g.size() / 2; ++i) {
            for (int j = 0; j < W * 2 + 1; ++j) {
                swap(g[i][j], g[g.size() - i - 1][j]);
            }
        }
        for (int i = 0; i < g.size(); ++i) {
            for (int j = 0; j < W; ++j) {
                swap(g[i][j], g[i][2 * W - j]);
            }
        }
        //print(g);
        guass(g);
        //print(g);
        LL ans = 1;
        for (int i = 0; i < g.size(); ++i) {
            ans = (ans * g[i][W]) % mod;
        }
        printf("Case %d: ", ++cas);
        cout << ans << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 600
memory_kb: 7132
final_rank: 2

code_snippet: #line 1 "a.cpp"
// cSpell:disable
/*	author:  Kite_kuma
	created: 2022.11.22 08:22:44 */

#line 2 "SPJ-Library/template/kuma.hpp"

#line 2 "SPJ-Library/template/basic_func.hpp"

#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>

#line 1 "SPJ-Library/template/header.hpp"
#include <bits/stdc++.h>
#line 2 "SPJ-Library/template/io.hpp"

#line 4 "SPJ-Library/template/io.hpp"

#line 8 "SPJ-Library/template/debug.hpp"

#line 3 "SPJ-Library/template/constants.hpp"

constexpr int inf = 1000'000'000;
constexpr long long INF = 1'000'000'000'000'000'000LL;
constexpr int mod_1000000007 = 1000000007;
constexpr int mod_998244353 = 998244353;
const long double pi = acosl(-1.);
constexpr int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
constexpr int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
#line 10 "SPJ-Library/template/debug.hpp"

namespace viewer {

template <typename T, typename U>
void view(const std::pair<T, U> &p);

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p);

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p);

void view(const long long &e);

void view(const int &e);

template <typename T>
void view(const T &e);

template <typename T>
void view(const std::set<T> &s);

template <typename T>
void view(const std::unordered_set<T> &s);

template <typename T>
void view(const std::multiset<T> &s);

template <typename T>
void view(const std::unordered_multiset<T> &s);

template <typename T>
void view(const std::vector<T> &v);

template <typename T, std::size_t ary_size>
void view(const std::array<T, ary_size> &v);

template <typename T>
void view(const std::vector<std::vector<T>> &vv);

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v);

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v);

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v);

template <typename map_type>
void view_map_container(const map_type &m);

template <typename T, typename U>
void view(const std::map<T, U> &m);

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m);

template <typename container_type>
void view_container(const container_type &c, bool vertically = false) {
	typename container_type::const_iterator begin = c.begin();
	const typename container_type::const_iterator end = c.end();
	if(vertically) {
		std::cerr << "{\n";
		while(begin != end) {
			std::cerr << '\t';
			view(*(begin++));
			if(begin != end) std::cerr << ',';
			std::cerr << '\n';
		}
		std::cerr << '}';
		return;
	}
	std::cerr << "{ ";
	while(begin != end) {
		view(*(begin++));
		if(begin != end) std::cerr << ',';
		std::cerr << ' ';
	}
	std::cerr << '}';
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << '(';
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ')';
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << '(';
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ')';
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << '(';
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ')';
}

void view(const long long &e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int &e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T &e) {
	std::cerr << e;
}

template <typename T>
void view(const std::set<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::multiset<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::unordered_multiset<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::vector<T> &v) {
	view_container(v);
}

template <typename T, std::size_t ary_size>
void view(const std::array<T, ary_size> &v) {
	view_container(v);
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	view_container(vv, true);
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	view_container(v, true);
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	view_container(v, true);
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	view_container(v, true);
}

template <typename map_type>
void view_map_container(const map_type &m) {
	std::cerr << "{\n";
	for(typename map_type::const_iterator it = m.begin(); it != m.end(); it++) {
		std::cerr << "\t[";
		view(it->first);
		std::cerr << "] : ";
		view(it->second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	view_map_container(m);
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	view_map_container(m);
}

}  // namespace viewer

// when compiling : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename T>
void debug_out(const T &x) {
	viewer::view(x);
}
template <typename Head, typename... Tail>
void debug_out(const Head &H, const Tail &... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "]\n";                                       \
	} while(0)
#else
#define debug(...) (void(0))
#endif
#line 2 "SPJ-Library/template/scanner.hpp"

#line 6 "SPJ-Library/template/scanner.hpp"

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner
#line 7 "SPJ-Library/template/io.hpp"

#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}

template <typename T1, typename T2>
std::ostream &operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << ' ' << p.second;
	return os;
}

struct fast_io {
	fast_io() {
		std::ios::sync_with_stdio(false);
		std::cin.tie(nullptr);
		std::cout << std::fixed << std::setprecision(15);
		srand((unsigned)time(NULL));
	}
} fast_io_;
#line 2 "SPJ-Library/template/macros.hpp"

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define pcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))
#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;
#line 7 "SPJ-Library/template/kuma.hpp"

using namespace std;
#line 1 "atcoder/modint.hpp"



#line 6 "atcoder/modint.hpp"
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif

#line 1 "atcoder/internal_math.hpp"



#line 5 "atcoder/internal_math.hpp"

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

// @param m `1 <= m`
// @return x mod m
constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

// Fast modular multiplication by barrett reduction
// Reference: https://en.wikipedia.org/wiki/Barrett_reduction
// NOTE: reconsider after Ice Lake
struct barrett {
    unsigned int _m;
    unsigned long long im;

    // @param m `1 <= m < 2^31`
    explicit barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    // @return m
    unsigned int umod() const { return _m; }

    // @param a `0 <= a < m`
    // @param b `0 <= b < m`
    // @return `a * b % m`
    unsigned int mul(unsigned int a, unsigned int b) const {
        // [1] m = 1
        // a = b = im = 0, so okay

        // [2] m >= 2
        // im = ceil(2^64 / m)
        // -> im * m = 2^64 + r (0 <= r < m)
        // let z = a*b = c*m + d (0 <= c, d < m)
        // a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im
        // c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2
        // ((ab * im) >> 64) == c or c + 1
        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned int v = (unsigned int)(z - x * _m);
        if (_m <= v) v += _m;
        return v;
    }
};

// @param n `0 <= n`
// @param m `1 <= m`
// @return `(x ** n) % m`
constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

// Reference:
// M. Forisek and J. Jancina,
// Fast Primality Testing for Integers That Fit into a Machine Word
// @param n `0 <= n`
constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    constexpr long long bases[3] = {2, 7, 61};
    for (long long a : bases) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n> constexpr bool is_prime = is_prime_constexpr(n);

// @param b `1 <= b`
// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    // Contracts:
    // [1] s - m0 * a = 0 (mod b)
    // [2] t - m1 * a = 0 (mod b)
    // [3] s * |m1| + t * |m0| <= b
    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b

        // [3]:
        // (s - t * u) * |m1| + t * |m0 - m1 * u|
        // <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)
        // = s * |m1| + t * |m0| <= b

        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    // by [3]: |m0| <= b/g
    // by g != b: |m0| < b/g
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

// Compile time primitive root
// @param m must be prime
// @return primitive root (and minimum in now)
constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

// @param n `n < 2^32`
// @param m `1 <= m < 2^32`
// @return sum_{i=0}^{n-1} floor((ai + b) / m) (mod 2^64)
unsigned long long floor_sum_unsigned(unsigned long long n,
                                      unsigned long long m,
                                      unsigned long long a,
                                      unsigned long long b) {
    unsigned long long ans = 0;
    while (true) {
        if (a >= m) {
            ans += n * (n - 1) / 2 * (a / m);
            a %= m;
        }
        if (b >= m) {
            ans += n * (b / m);
            b %= m;
        }

        unsigned long long y_max = a * n + b;
        if (y_max < m) break;
        // y_max < m * (n + 1)
        // floor(y_max / m) <= n
        n = (unsigned long long)(y_max / m);
        b = (unsigned long long)(y_max % m);
        std::swap(m, a);
    }
    return ans;
}

}  // namespace internal

}  // namespace atcoder


#line 1 "atcoder/internal_type_traits.hpp"



#line 7 "atcoder/internal_type_traits.hpp"

namespace atcoder {

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value,
                              __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                  is_signed_int128<T>::value ||
                                                  is_unsigned_int128<T>::value,
                                              std::true_type,
                                              std::false_type>::type;

template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                 std::is_signed<T>::value) ||
                                                    is_signed_int128<T>::value,
                                                std::true_type,
                                                std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value,
    make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value,
                              std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T> using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
                                              std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T> using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder


#line 14 "atcoder/modint.hpp"

namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
    using mint = static_modint;

  public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = internal::inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = internal::is_prime<m>;
};

template <int id> struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

  public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = internal::inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt(998244353);

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class> struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder


#line 7 "a.cpp"
using mint = atcoder::modint1000000007;
std::ostream &operator<<(std::ostream &os, const mint &p) {
	os << p.val();
	return os;
}
// vector<vector<mint>> lap(1500, vector<mint>(1500, 0));
vector<vector<int>> ids(502, vi(15, -1));
mint solve(int h, int w) {
	int vertex_id = 0;
	vector<vector<int>> walls(h, vi(w));
	rep(i, h) rep(j, w) {
		int &cell = ids[i][j];
		char c;
		cin >> c;
		if(c == '#') {
			cell = -1;
		} else {
			cell = vertex_id++;
		}
	}
	assert(vertex_id > 0);
	if(vertex_id == 1) return 1;
	const int sz = vertex_id - 1;
	// vector<vector<mint>> lap(sz, vector<mint>(sz));
	vector<map<int, mint>> lap(sz);
	// rep(i, sz) rep(j, sz) lap[i][j] = 0;

	auto add_map = [&](int row, int key, mint value) -> void {
		if(lap[row].count(key))
			lap[row][key] += value;
		else
			lap[row][key] = value;
		return;
	};

	auto add_wall = [&](int x, int y) -> void {
		debug(x, y);
		if(x > y) swap(x, y);
		// x < y
		if(x == -1 || y == -1) return;
		debug(lap);
		add_map(x, x, 1);
		debug(lap);
		// exit(0);
		if(y == sz) return;
		add_map(y, y, 1);
		add_map(x, y, -1);
		add_map(y, x, -1);
		return;
	};
	debug(lap);
	rep(i, h) rep(j, w) {
		if(i < h - 1) add_wall(ids[i][j], ids[i + 1][j]);
		if(j < w - 1) add_wall(ids[i][j], ids[i][j + 1]);
	}
	debug(lap);
	constexpr int band = 100;
	mint ans = 1;

	rep(col, sz) {
		debug(lap);
		int nonzero_row = -1;
		rep(row, col, sz) {
			if(lap[row].count(col) && lap[row][col] != 0) {
				nonzero_row = row;
				break;
			}
		}
		if(nonzero_row == -1) return mint(0);
		if(nonzero_row > col) {
			ans *= -1;
			swap(lap[nonzero_row], lap[col]);
		}
		debug(lap);
		const mint diag = lap[col][col];
		ans *= diag;
		debug(diag);
		rep(i, col, sz) {
			if(lap[col].count(i)) lap[col][i] /= diag;
		}
		debug(lap);
		rep(row, col + 1, min(sz, col + band)) {
			if(lap[row].count(col) && lap[row][col] != 0) {
				const mint mult = lap[row][col];
				rep(j, col, min(sz, col + band)) {
					if(lap[col].count(j)) add_map(row, j, -mult * lap[col][j]);
				}
			}
		}
	}
	return ans;
}
int main() {
	int h, w;
	int case_id = 0;
	while(cin >> h >> w && h + w) {
		case_id++;
		cout << "Case " << case_id << ": " << solve(h, w) << '\n';
	}
	return 0;
}
accuracy: 1
time_ms: 1990
memory_kb: 14276
final_rank: 10

code_snippet: #pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
#include<chrono>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
//constexpr ll mod = 998244353;
constexpr ll mod = 1000000007;
const ll INF = mod * mod;
typedef pair<int, int>P;

#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;

template<typename T>
void chmin(T& a, T b) {
	a = min(a, b);
}
template<typename T>
void chmax(T& a, T b) {
	a = max(a, b);
}
template<typename T>
void cinarray(vector<T>& v) {
	rep(i, v.size())cin >> v[i];
}
template<typename T>
void coutarray(vector<T>& v) {
	rep(i, v.size()) {
		if (i > 0)cout << " "; cout << v[i];
	}
	cout << "\n";
}
ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	//if (x == 0)return 0;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	int n;
	modint() :n(0) { ; }
	modint(ll m) {
		if (m < 0 || mod <= m) {
			m %= mod; if (m < 0)m += mod;
		}
		n = m;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
bool operator<(modint a, modint b) { return a.n < b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 20;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}

ll gcd(ll a, ll b) {
	a = abs(a); b = abs(b);
	if (a < b)swap(a, b);
	while (b) {
		ll r = a % b; a = b; b = r;
	}
	return a;
}
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;
const ld pi = acosl(-1.0);
template<typename T>
void addv(vector<T>& v, int loc, T val) {
	if (loc >= v.size())v.resize(loc + 1, 0);
	v[loc] += val;
}
/*const int mn = 100005;
bool isp[mn];
vector<int> ps;
void init() {
	fill(isp + 2, isp + mn, true);
	for (int i = 2; i < mn; i++) {
		if (!isp[i])continue;
		ps.push_back(i);
		for (int j = 2 * i; j < mn; j += i) {
			isp[j] = false;
		}
	}
}*/

//[,val)
template<typename T>
auto prev_itr(set<T>& st, T val) {
	auto res = st.lower_bound(val);
	if (res == st.begin())return st.end();
	res--; return res;
}

//[val,)
template<typename T>
auto next_itr(set<T>& st, T val) {
	auto res = st.lower_bound(val);
	return res;
}
using mP = pair<modint, modint>;


int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };
//-----------------------------------------
using Data = modint;
using pD = pair<int, Data>;
void refl(vector<pD>& p) {
	auto cop = p; p.clear();
	sort(all(cop));
	rep(i, cop.size()) {
		Data num = cop[i].second;
		while (i + 1 < cop.size() && cop[i].first == cop[i + 1].first) {
			i++;
			num += cop[i].second;
		}
		if (num != (Data)0)p.push_back({ cop[i].first,num });
	}
}
void merge(vector<pD>& p, vector<pD>& q) {
	vector<pD> res;
	int idp = 0, idq = 0;
	while (idp < p.size() && idq < q.size()) {
		if (p[idp].first < q[idq].first) {
			res.push_back(p[idp]); idp++;
		}
		else if (p[idp].first > q[idq].first) {
			res.push_back(q[idq]); idq++;
		}
		else {
			Data val = p[idp].second + q[idq].second;
			if (val != (Data)0) {
				res.push_back({ p[idp].first,val });
			}
			idp++; idq++;
		}
	}
	while (idp < p.size()) {
		res.push_back(p[idp]); idp++;
	}
	while (idq < q.size()) {
		res.push_back(q[idq]); idq++;
	}
	swap(p, res);
}
Data det(vector<vector<pD>> A) {
	rep(i, A.size())refl(A[i]);
	int n = A.size();
	Data ans = 1;
	rep(i, n) {
		Rep(j, i, A.size()) {
			if (A[j].size() && A[j][0].first == i) {
				if (i != j)ans *= -1;
				swap(A[i], A[j]);
				break;
			}
		}
		if (A[i].empty() || A[i][0].first != i) {
			ans = 0; break;
		}
		ans *= A[i][0].second;
		Data coef = (Data)1 / A[i][0].second;
		Rep(j, i + 1, A.size()) {
			if (A[j].size() && A[j][0].first == i) {
				Data cc = coef * A[j][0].second;
				vector<pD> nw(A[i].size());
				rep(k, A[i].size())nw[k] = { A[i][k].first,A[i][k].second * (modint)-cc };
				merge(A[j], nw);
			}
		}
	}
	return ans;
}

int tmp = 0;

int h, w;
void solve() {
	vector<string> s(h);
	rep(i, h)cin >> s[i];
	tmp++;
	cout << "Case " << tmp << ": ";
	rep(_, h * w) {
		int i = _ / w;
		int j = _ % w;
		if (s[i][j] == '.') {
			vector<vector<bool>> used(h, vector<bool>(w));
			used[i][j] = true;
			queue<P> q;
			q.push({ i,j });
			while (!q.empty()) {
				P p = q.front(); q.pop();
				rep(d, 4) {
					int nx = p.first + dx[d];
					int ny = p.second + dy[d];
					if (nx < 0 || nx >= h || ny < 0 || ny >= w)continue;
					if (s[nx][ny] == '.') {
						if (!used[nx][ny]) {
							used[nx][ny] = true;
							q.push({ nx,ny });
						}
					}
				}
			}
			rep(x, h)rep(y, w) {
				if (s[x][y] == '.') {
					if (!used[x][y]) {
						cout << 0 << "\n"; return;
					}
				}
			}
			break;
		}
	}
	while (true) {
		bool exi = false;
		rep(j, w)if (s[h - 1][j] == '.')exi = true;
		if (!exi) {
			h--;
		}
		else break;
	}
	vector<vector<int>> trans(h, vector<int>(w));
	int c = 0;
	rep(i, h)rep(j, w) {
		if (s[i][j] == '.') {
			trans[i][j] = c; c++;
		}
	}
	using speP = pair<int, modint>;
	vector<vector<speP>> A(c - 1);
	rep(i, h)rep(j, w)if (s[i][j] == '.') {
		rep(d, 4) {
			int nx = i + dx[d];
			int ny = j + dy[d];
			if (nx < 0 || nx >= h || ny < 0 || ny >= w)continue;
			if (s[nx][ny] == '.') {
				int fr = trans[i][j];
				int to = trans[nx][ny];
				if (fr != c - 1) {
					A[fr].push_back({ fr,1 });
				}
				if (fr != c - 1 && to != c - 1) {
					A[fr].push_back({ to,-1 });
				}
			}
		}
	}
	auto refl = [&](vector<speP>& p) {
		auto cop = p; p.clear();
		sort(all(cop));
		rep(i, cop.size()) {
			modint num = cop[i].second;
			while (i + 1 < cop.size() && cop[i].first == cop[i + 1].first) {
				i++;
				num += cop[i].second;
			}
			if (num != (modint)0)p.push_back({ cop[i].first,num });
		}
	};
	if (c == 1) {
		cout << 1 << "\n"; return;
	}
	else {
		modint ans = det(A);
		cout << ans << "\n";
	}
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << fixed << setprecision(10);
	//init_f();
	//init();
	//while(true)
	//expr();
	//int t; cin >> t; rep(i, t)
	while (cin >> h >> w, h)
		solve();
	return 0;
}
accuracy: 1
time_ms: 400
memory_kb: 13428
final_rank: 5

code_snippet: #pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
#include<chrono>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
//constexpr ll mod = 998244353;
constexpr ll mod = 1000000007;
const ll INF = mod * mod;
typedef pair<int, int>P;

#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;

template<typename T>
void chmin(T& a, T b) {
	a = min(a, b);
}
template<typename T>
void chmax(T& a, T b) {
	a = max(a, b);
}
template<typename T>
void cinarray(vector<T>& v) {
	rep(i, v.size())cin >> v[i];
}
template<typename T>
void coutarray(vector<T>& v) {
	rep(i, v.size()) {
		if (i > 0)cout << " "; cout << v[i];
	}
	cout << "\n";
}
ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	//if (x == 0)return 0;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	int n;
	modint() :n(0) { ; }
	modint(ll m) {
		if (m < 0 || mod <= m) {
			m %= mod; if (m < 0)m += mod;
		}
		n = m;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
bool operator<(modint a, modint b) { return a.n < b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 20;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}

ll gcd(ll a, ll b) {
	a = abs(a); b = abs(b);
	if (a < b)swap(a, b);
	while (b) {
		ll r = a % b; a = b; b = r;
	}
	return a;
}
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;
const ld pi = acosl(-1.0);
template<typename T>
void addv(vector<T>& v, int loc, T val) {
	if (loc >= v.size())v.resize(loc + 1, 0);
	v[loc] += val;
}
/*const int mn = 100005;
bool isp[mn];
vector<int> ps;
void init() {
	fill(isp + 2, isp + mn, true);
	for (int i = 2; i < mn; i++) {
		if (!isp[i])continue;
		ps.push_back(i);
		for (int j = 2 * i; j < mn; j += i) {
			isp[j] = false;
		}
	}
}*/

//[,val)
template<typename T>
auto prev_itr(set<T>& st, T val) {
	auto res = st.lower_bound(val);
	if (res == st.begin())return st.end();
	res--; return res;
}

//[val,)
template<typename T>
auto next_itr(set<T>& st, T val) {
	auto res = st.lower_bound(val);
	return res;
}
using mP = pair<modint, modint>;


int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };
//-----------------------------------------

using Data = modint;
using pD = pair<int, Data>;
void refl(vector<pD>& p) {
	auto cop = p; p.clear();
	sort(all(cop));
	rep(i, cop.size()) {
		Data num = cop[i].second;
		while (i + 1 < cop.size() && cop[i].first == cop[i + 1].first) {
			i++;
			num += cop[i].second;
		}
		if (num != (Data)0)p.push_back({ cop[i].first,num });
	}
}
Data det(vector<vector<pD>> A) {
	rep(i, A.size())refl(A[i]);
	int n = A.size();
	Data ans = 1;
	rep(i, n) {
		Rep(j, i, A.size()) {
			if (A[j].size() && A[j][0].first == i) {
				if (i != j)ans *= -1;
				swap(A[i], A[j]);
				break;
			}
		}
		if (A[i].empty() || A[i][0].first != i) {
			ans = 0; break;
		}
		ans *= A[i][0].second;
		Data coef = (Data)1 / A[i][0].second;
		Rep(j, i + 1, A.size()) {
			if (A[j].size() && A[j][0].first == i) {
				Data cc = coef * A[j][0].second;
				for (auto p : A[i]) {
					A[j].push_back({ p.first,(Data)-cc * p.second });
				}
				refl(A[j]);
			}
		}
	}
	return ans;
}

int tmp = 0;

int h, w;
void solve() {
	vector<string> s(h);
	rep(i, h)cin >> s[i];
	tmp++;
	cout << "Case " << tmp << ": ";
	rep(_,h*w) {
		int i = _ / w;
		int j = _ % w;
		if (s[i][j] == '.') {
			vector<vector<bool>> used(h, vector<bool>(w));
			used[i][j] = true;
			queue<P> q;
			q.push({ i,j });
			while (!q.empty()) {
				P p = q.front(); q.pop();
				rep(d, 4) {
					int nx = p.first + dx[d];
					int ny = p.second + dy[d];
					if (nx < 0 || nx >= h || ny < 0 || ny >= w)continue;
					if (s[nx][ny] == '.') {
						if (!used[nx][ny]) {
							used[nx][ny] = true;
							q.push({ nx,ny });
						}
					}
				}
			}
			rep(x, h)rep(y, w) {
				if (s[x][y] == '.') {
					if (!used[x][y]) {
						cout << 0 << "\n"; return;
					}
				}
			}
			break;
		}
	}
	while (true) {
		bool exi = false;
		rep(j, w)if (s[h - 1][j] == '.')exi = true;
		if (!exi) {
			h--;
		}
		else break;
	}
	vector<vector<int>> trans(h, vector<int>(w));
	int c = 0;
	rep(i, h)rep(j, w) {
		if (s[i][j] == '.') {
			trans[i][j] = c; c++;
		}
	}
	using speP = pair<int, modint>;
	vector<vector<speP>> A(c-1);
	rep(i, h)rep(j, w)if (s[i][j] == '.') {
		rep(d, 4) {
			int nx = i + dx[d];
			int ny = j + dy[d];
			if (nx < 0 || nx >= h || ny < 0 || ny >= w)continue;
			if (s[nx][ny] == '.') {
				int fr = trans[i][j];
				int to = trans[nx][ny];
				if (fr != c - 1) {
					A[fr].push_back({ fr,1 });
				}
				if (fr!=c-1&&to != c - 1) {
					A[fr].push_back({ to,-1 });
				}
			}
		}
	}
	auto refl = [&](vector<speP>& p) {
		auto cop = p; p.clear();
		sort(all(cop));
		rep(i, cop.size()) {
			modint num = cop[i].second;
			while (i + 1 < cop.size() && cop[i].first == cop[i + 1].first) {
				i++;
				num += cop[i].second;
			}
			if (num != (modint)0)p.push_back({ cop[i].first,num });
		}
	};
	if (c == 1) {
		cout << 1 << "\n"; return;
	}
	else {
		modint ans = det(A);
		cout << ans << "\n";
	}
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << fixed << setprecision(10);
	//init_f();
	//init();
	//while(true)
	//expr();
	//int t; cin >> t; rep(i, t)
	while(cin>>h>>w,h)
	solve();
	return 0;
}
accuracy: 1
time_ms: 530
memory_kb: 15916
final_rank: 8

code_snippet: #pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
#include<chrono>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
//constexpr ll mod = 998244353;
constexpr ll mod = 1000000007;
const ll INF = mod * mod;
typedef pair<int, int>P;

#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;

template<typename T>
void chmin(T& a, T b) {
	a = min(a, b);
}
template<typename T>
void chmax(T& a, T b) {
	a = max(a, b);
}
template<typename T>
void cinarray(vector<T>& v) {
	rep(i, v.size())cin >> v[i];
}
template<typename T>
void coutarray(vector<T>& v) {
	rep(i, v.size()) {
		if (i > 0)cout << " "; cout << v[i];
	}
	cout << "\n";
}
ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	//if (x == 0)return 0;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	int n;
	modint() :n(0) { ; }
	modint(ll m) {
		if (m < 0 || mod <= m) {
			m %= mod; if (m < 0)m += mod;
		}
		n = m;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
bool operator<(modint a, modint b) { return a.n < b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 20;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}

ll gcd(ll a, ll b) {
	a = abs(a); b = abs(b);
	if (a < b)swap(a, b);
	while (b) {
		ll r = a % b; a = b; b = r;
	}
	return a;
}
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;
const ld pi = acosl(-1.0);
template<typename T>
void addv(vector<T>& v, int loc, T val) {
	if (loc >= v.size())v.resize(loc + 1, 0);
	v[loc] += val;
}
/*const int mn = 100005;
bool isp[mn];
vector<int> ps;
void init() {
	fill(isp + 2, isp + mn, true);
	for (int i = 2; i < mn; i++) {
		if (!isp[i])continue;
		ps.push_back(i);
		for (int j = 2 * i; j < mn; j += i) {
			isp[j] = false;
		}
	}
}*/

//[,val)
template<typename T>
auto prev_itr(set<T>& st, T val) {
	auto res = st.lower_bound(val);
	if (res == st.begin())return st.end();
	res--; return res;
}

//[val,)
template<typename T>
auto next_itr(set<T>& st, T val) {
	auto res = st.lower_bound(val);
	return res;
}
using mP = pair<modint, modint>;


int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };
//-----------------------------------------

typedef modint Data;
typedef vector<Data> Array;
typedef vector<Array> mat;

bool is_zero(Data dat) { return abs(dat) < eps; }
mat operator-(mat a) {
	rep(i, a.size())rep(j, a[0].size())a[i][j] = -a[i][j];
	return a;
}
mat operator+(mat lhs, mat& rhs) {
	rep(i, lhs.size())rep(j, lhs[0].size())lhs[i][j] += rhs[i][j];
	return lhs;
}
mat operator-(mat lhs, mat& rhs) {
	rep(i, lhs.size())rep(j, lhs[0].size())lhs[i][j] -= rhs[i][j];
	return lhs;
}
mat operator*(const mat& lhs, const mat& rhs) {
	mat ret(lhs.size(), Array(rhs[0].size(), 0));
	rep(i, lhs.size())rep(j, rhs[0].size())rep(k, rhs.size()) {
		ret[i][j] += lhs[i][k] * rhs[k][j];
	}
	return ret;
}


Data det(mat a) {
	const int n = a.size();
	Data D = Data(1);
	for (int i = 0; i < n; ++i) {
		int pivot = i;
		for (int j = i + 1; j < n; ++j) {
			if (abs(a[j][i]) > abs(a[pivot][i]))pivot = j;
		}
		swap(a[pivot], a[i]);
		D = D * a[i][i] * Data(i != pivot ? -1 : 1);
		if (is_zero(a[i][i]))break;
		Data coef = (Data)1 / a[i][i];
		for (int j = i + 1; j < n; ++j) {
			if (a[j][i] == (Data)0)continue;
			for (int k = n - 1; k >= i; --k) {
				a[j][k] = a[j][k] - a[i][k] * a[j][i] * coef;
			}
		}
	}
	return D;
}

int tmp = 0;

int h, w;
void solve() {
	vector<string> s(h);
	rep(i, h)cin >> s[i];
	tmp++;
	cout << "Case " << tmp << ": ";
	rep(_,h*w) {
		int i = _ / w;
		int j = _ % w;
		if (s[i][j] == '.') {
			vector<vector<bool>> used(h, vector<bool>(w));
			used[i][j] = true;
			queue<P> q;
			q.push({ i,j });
			while (!q.empty()) {
				P p = q.front(); q.pop();
				rep(d, 4) {
					int nx = p.first + dx[d];
					int ny = p.second + dy[d];
					if (nx < 0 || nx >= h || ny < 0 || ny >= w)continue;
					if (s[nx][ny] == '.') {
						if (!used[nx][ny]) {
							used[nx][ny] = true;
							q.push({ nx,ny });
						}
					}
				}
			}
			rep(x, h)rep(y, w) {
				if (s[x][y] == '.') {
					if (!used[x][y]) {
						cout << 0 << "\n"; return;
					}
				}
			}
			break;
		}
	}
	while (true) {
		bool exi = false;
		rep(j, w)if (s[h - 1][j] == '.')exi = true;
		if (!exi) {
			h--;
		}
		else break;
	}
	vector<vector<int>> trans(h, vector<int>(w));
	int c = 0;
	rep(i, h)rep(j, w) {
		if (s[i][j] == '.') {
			trans[i][j] = c; c++;
		}
	}
	using speP = pair<int, modint>;
	vector<vector<speP>> A(c-1);
	rep(i, h)rep(j, w)if (s[i][j] == '.') {
		rep(d, 4) {
			int nx = i + dx[d];
			int ny = j + dy[d];
			if (nx < 0 || nx >= h || ny < 0 || ny >= w)continue;
			if (s[nx][ny] == '.') {
				int fr = trans[i][j];
				int to = trans[nx][ny];
				if (fr != c - 1) {
					A[fr].push_back({ fr,1 });
				}
				if (fr!=c-1&&to != c - 1) {
					A[fr].push_back({ to,-1 });
				}
			}
		}
	}
	auto refl = [&](vector<speP>& p) {
		auto cop = p; p.clear();
		sort(all(cop));
		rep(i, cop.size()) {
			modint num = cop[i].second;
			while (i + 1 < cop.size() && cop[i].first == cop[i + 1].first) {
				i++;
				num += cop[i].second;
			}
			if (num != (modint)0)p.push_back({ cop[i].first,num });
		}
	};
	if (c == 1) {
		cout << 1 << "\n"; return;
	}
	else {
		modint ans = 1;
		rep(i, A.size())refl(A[i]);
		rep(i, c-1) {
			Rep(j, i, A.size()) {
				if (A[j].size() && A[j][0].first == i) {
					if(i!=j)ans *= -1;
					swap(A[i], A[j]);
					break;
				}
			}
			if (A[i].empty() || A[i][0].first != i) {
				ans = 0; break;
			}
			ans *= A[i][0].second;
			modint coef = (modint)1 / A[i][0].second;
			Rep(j, i + 1, A.size()) {
				if (A[j].size() && A[j][0].first == i) {
					modint cc = coef * A[j][0].second;
					for (auto p : A[i]) {
						A[j].push_back({ p.first,(modint)-cc * p.second });
					}
					refl(A[j]);
				}
			}
		}
		cout << ans << "\n";
	}
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << fixed << setprecision(10);
	//init_f();
	//init();
	//while(true)
	//expr();
	//int t; cin >> t; rep(i, t)
	while(cin>>h>>w,h)
	solve();
	return 0;
}
accuracy: 1
time_ms: 570
memory_kb: 15128
final_rank: 7

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



typedef vector<ll> V;
typedef vector<V> MATRIX;


int H,W;
int height,width;
int num_case;
int diff_row[4] = {-1,0,0,1},diff_col[4] = {0,-1,1,0};
ll table[505][20];
char base_map[505][20];


bool rangeCheck(int row,int col){

	return row >= 0 && row <= H-1 && col >= 0 && col <= W-1;
}

ll gcd(ll x,ll y){

	x = abs(x);
	y = abs(y);

	if(x < y){
		swap(x,y);
	}
	if(y == 0){
		return x;
	}else{
		return gcd(y,x%y);
	}
}

ll lcm(ll x,ll y){

	return (x*y)/gcd(x,y);
}

ll extgcd(ll a,ll b,ll &x,ll &y){
	ll d = a;
	if(b != 0){
		d = extgcd(b,a%b,y,x);
		y -= (a/b)*x;
	}else{
		x = 1;
		y = 0;
	}
	return d;
}

ll mod_inverse(ll a,ll m){
    ll x,y;
    extgcd(a,m,x,y);
    return (m+x%m)%m;
}

ll determinant(MATRIX A){

	MATRIX C(height,V(width));

	for(int row = 0; row < height; row++){
		for(int col = 0; col < width; col++){
			C[row][col] = A[row][col];
		}
	}

	int RANGE = W;

	ll mult = 1;

	for(int base = 0; base < height-1; base++){

		int row = -1;

		if(C[base][W] != 0){

			row = base;
		}else{

			for(int k = 1; k <= RANGE && base+k < height; k++){

				if(C[base+k][W-k] != 0){

					row = base+k;

					for(int a = 0; a < 2*W+1; a++){

						swap(C[base+k][W-k+a],C[base][W+a]);
					}

					mult *= (-1+MOD);
					mult %= MOD;
					break;
				}
			}

			if(row == -1)return 0;
		}

		for(int k = 1; k <= RANGE && base+k < height; k++){

			if(C[base+k][W-k] == 0)continue;

			ll LCM = lcm(C[base][W],C[base+k][W-k]);

			ll mult_base = LCM/C[base][W];
			ll mult_k = LCM/C[base+k][W-k];

			mult *= mult_k;
			mult %= MOD;

			for(int a = 0; a < 2*W+1; a++){

				C[base+k][W-k+a] *= mult_k;
				C[base+k][W-k+a] %= MOD;
			}

			for(int a = 0; a < 2*W+1; a++){

				C[base+k][W-k+a] -= C[base][W+a]*mult_base;

				if(C[base+k][W-k+a] < 0){
					C[base+k][W-k+a] = abs(C[base+k][W-k+a])%MOD;
					C[base+k][W-k+a] *= -1;
					C[base+k][W-k+a] += MOD;
				}
			}
		}
	}

	ll ret = 1;
	for(int i = 0; i < height; i++){

		ret *= C[i][W];
		ret %= MOD;
	}

	ret *= mod_inverse(mult,MOD);

	return ret%MOD;
}


void func(){

	for(int row = 0; row < H; row++){

		scanf("%s",base_map[row]);
	}

	int index = 0;

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){

			if(base_map[row][col] == '#')continue;

			table[row][col] = index++;
		}
	}

	height = index-1;
	width = 3*W+1;

	MATRIX A(height,V(width));

	for(int row = 0; row < height; row++){
		for(int col = 0; col < width; col++){

			A[row][col] = 0;
		}
	}

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){

			if(base_map[row][col] == '#' || table[row][col] == index-1)continue;

			for(int i = 0; i < 4; i++){

				int adj_row = row+diff_row[i];
				int adj_col = col+diff_col[i];

				if(rangeCheck(adj_row,adj_col) == false || base_map[adj_row][adj_col] == '#')continue;

				if(table[adj_row][adj_col] != index-1){

					A[table[row][col]][table[adj_row][adj_col]-table[row][col]+W] = -1+MOD;
				}

				A[table[row][col]][W]++;
			}
		}
	}

	printf("Case %d: %lld\n",num_case++,abs(determinant(A)));
}


int main(){

	num_case = 1;

	while(true){

		scanf("%d %d",&H,&W);
		if(H == 0 && W == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 390
memory_kb: 11868
final_rank: 4

code_snippet: #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 500 + 5;
const int M = 20;
const int V = 500 * 15 + 5;
const int MOD = (int)1e9 + 7;

struct Matrix
{
	long long a[V][M * 3];
	long long& getEntry(int x, int y) {
		return a[x][y - x + M];
	}
	bool haveEntry(int x, int y) {
		return 0 <= y - x + M && y - x + M < M * 3;
	}
	void clear() {
		memset(a, 0, sizeof a);
	}
} a;

int n, m;
char c[N][M];
int id[N][M];

#define getId(x,y) (id[x][y])

long long modPow(long long a, long long p, long long MOD)
{
	long long ret = 1;
	for( ; p; p >>= 1, a = a * a % MOD) {
		if (p & 1) {
			ret = ret * a % MOD;
		}
	}
	return ret;
}


void solve()
{
	a.clear();
	int v = 0;
	for(int i = 0; i < n; ++ i) {
		scanf("%s", c[i]);
		for(int j = 0; j < m; ++ j) {
			if (c[i][j] == '.') {
				id[i][j] = v ++;
			}
		}
	}
	for(int i = 0; i < n; ++ i) {
		for(int j = 0; j < m; ++ j) {
			if (c[i][j] == '.') {
				if (i + 1 < n && c[i + 1][j] == '.') {
					a.getEntry(getId(i, j), getId(i, j)) ++;
					a.getEntry(getId(i + 1, j), getId(i + 1, j)) ++;
					a.getEntry(getId(i, j), getId(i + 1, j)) --;
					a.getEntry(getId(i + 1, j), getId(i, j)) --;
				}
				if (j + 1 < m && c[i][j + 1] == '.') {
					a.getEntry(getId(i, j), getId(i, j)) ++;
					a.getEntry(getId(i, j + 1), getId(i, j + 1)) ++;
					a.getEntry(getId(i, j), getId(i, j + 1)) --;
					a.getEntry(getId(i, j + 1), getId(i, j)) --;
				}
			}
		}
	}
	--v;
	long long ret = 1;
	for(int col = 0; col < v; ++ col) {
		if (a.getEntry(col, col) == 0) {
			for(int i = col + 1; a.haveEntry(i, col) && i < v; ++ i) {
				if (a.getEntry(i, col)) {
					for(int j = col; a.haveEntry(col, j) && a.haveEntry(i, j) && j < v; ++ j) {
						swap(a.getEntry(col, j), a.getEntry(i, j));
					}
					ret = -ret;
					break;
				}
			}
		}
		if (a.getEntry(col, col)) {
			ret = ret * a.getEntry(col, col) % MOD;
			long long inv = modPow(a.getEntry(col, col), MOD - 2, MOD);
			for(int i = col + 1; a.haveEntry(i, col) && i < v; ++ i) {
				if (a.getEntry(i, col)) {
					long long by = -a.getEntry(i, col) * inv % MOD;
					for(int j = col; a.haveEntry(col, j) && a.haveEntry(i, j) && j < v; ++ j) {
						(a.getEntry(i, j) += a.getEntry(col, j) * by) %= MOD;
					}
				}
			}
		} else {
			ret = 0;
			break;
		}
	}
	cout << (ret + MOD) % MOD << endl;
}

int main()
{
	int t = 0;
	for( ; scanf("%d%d", &n, &m) == 2 && (n || m); ) {
		printf("Case %d: ", ++ t);
		solve();
	}
	return 0;
}
accuracy: 1
time_ms: 160
memory_kb: 4820
final_rank: 1

code_snippet: #include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <unordered_map>
#include <iterator>
#include <functional>
#include <cassert>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;

#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define REPS(i,x) for(int i=1;i<=(int)(x);i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RREPS(i,x) for(int i=((int)(x));i>0;i--)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) (container).begin(), (container).end()
#define RALL(container) (container).rbegin(), (container).rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define pb push_back
#define eb emplace_back
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );

template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const map<S, T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
template<class S, class T> pair<S,T> operator+(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first+t.first, s.second+t.second);}
template<class S, class T> pair<S,T> operator-(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first-t.first, s.second-t.second);}

const int INF = 1<<28;
const double EPS = 1e-8;
const int MOD = 1000000007;

typedef unordered_map<int, int> Array;
typedef vector<Array> Matrix;
ostream& operator<<(ostream &os, const Array &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
ostream& operator<<(ostream &os, const Matrix &t) {
FOR(it,t)os<<*it<<endl;return os;
}

int T, n, m;

inline ll mod_inv(ll a, ll m){
  ll b = m, u = 1, v = 0;
  while (b) {
    ll t = a / b;
    swap(a -= t * b, b);
    swap(u -= t * v, v);
  }
  return (u % m + m) % m;
}


int det(Matrix mat){
	int n = mat.size();
	ll ans = 1;
	REP(i, n){
		ans = ans * mat[i][i] % MOD;
		if(!ans) return ans;
		ll inv = mod_inv(mat[i][i], MOD);
		for(int j=i+1;j<n;j++)if(mat[j].count(i)){
			ll coef = (MOD - mat[j][i] * inv % MOD) % MOD;
			for(auto it : mat[i]){
				auto &jt = mat[j][it.first];
				jt = (jt + coef*it.second) % MOD;
				if(jt == 0) mat[j].erase(it.first);
			}
		}
	}
	return ans;
}

int main(int argc, char *argv[]){
	ios::sync_with_stdio(false);
	int T = 1;
	while(cin >> n >> m, n){
		vector<string> s(n);
		REP(i, n) cin >> s[i];
		vi to(n*m);
		int c = 0;
		Matrix mat;
		REP(i, n*m){
			int x = i%m;
			int y = i/m;
			if(s[y][x] == '#') continue;
			mat.eb();
			if(x && s[y][x-1] != '#'){
				mat[c][c] ++; mat[c-1][c-1] ++;
				mat[c][c-1] = mat[c-1][c] = MOD-1;
			}
			if(y && s[y-1][x] != '#'){
				mat[c][c] ++; mat[to[i-m]][to[i-m]] ++;
				mat[c][to[i-m]] = mat[to[i-m]][c] = MOD-1;
			}
			to[i] = c++;
		}
		REP(i, c-1) mat[i].erase(c-1);
		mat.pop_back();
		cout << "Case " << T++ << ": " << det(mat) << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 2830
memory_kb: 9312
final_rank: 9

code_snippet: #include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define rep1(i,n) for(int i=1;i<=(int)(n);i++)
#define all(c) c.begin(),c.end()
#define pb push_back
#define fs first
#define sc second
#define show(x) cout << #x << " = " << x << endl
#define chmin(x,y) x=min(x,y)
#define chmax(x,y) x=max(x,y)
using namespace std;
/*
use under a[i][j]!=0 -> abs(i-j)<=B
(??????+-B?????????????????????????????????)
??????????????????swap?????±?????§,-B~+2B?????§???3B+1??????vi??????????????£??????
?????????0????????????B-th value(0-indexed) ???a[i][i]??????????????????????????????
time O(NB^2)
space O(NB)
*/
typedef long long ll;
ll mod=1e9+7;
typedef vector<ll> vi;
typedef vector<vi> bmat;
ll ex(ll x,ll p){
	ll a=1;
	while(p){
		if(p%2) a=a*x%mod;
		x=x*x%mod;
		p/=2;
	}
	return a;
}
ll inv(ll a){
	return ex(a,mod-2);
}
ll det(bmat a){
	int N=a.size();
	if(N==0) return 1;
	int B=a[0].size()/3;
	ll ans=1;
	rep(i,N){
		if(a[i][B]==0){
			for(int j=i+1;j<N;j++){
				if(B-(j-i)<0) break;
				if(a[j][B-(j-i)]!=0){
					int d=j-i;
					for(int k=d;k<=2*B+d;k++){
						swap(a[i][k],a[j][k-d]);
					}
					ans*=-1;
					break;
				}
			}
			if(a[i][B]==0) return 0;
		}
		for(int j=i+1;j<N;j++){
			if(B-(j-i)<0) break;
			int d=j-i;
			ll c=a[j][B-d]*inv(a[i][B])%mod;
			for(int k=B;k<=3*B;k++){
				a[j][k-d]=(a[j][k-d]-c*a[i][k])%mod;
			}
		}
		ans=ans*a[i][B]%mod;
	}
	if(ans<0) ans+=mod;
	return ans;
}
int H,W;
int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
string s[500];
bool is(int x,int y){
	return 0<=x&&x<H&&0<=y&&y<W&&s[x][y]=='.';
}
int n[500][15];
int main(){
	int tt=0;
	while(true){
		tt++;
		cin>>H>>W;
		if(H==0) break;
		rep(i,H) cin>>s[i];
		int N=0;
		rep(i,H) rep(j,W){
			if(s[i][j]=='#') n[i][j]=-1;
			else n[i][j]=N++;
		}
		bmat a(N-1,vi(3*W+1,0));
		rep(i,H) rep(j,W){
			if(!is(i,j)) continue;
			if(n[i][j]==N-1) break;
			rep(d,4){
				int x=i+dx[d],y=j+dy[d];
				if(!is(x,y)) continue;
				if(n[x][y]!=N-1) a[n[i][j]][n[x][y]-n[i][j]+W]++;
				a[n[i][j]][W]++;
			}
		}
		cout<<"Case "<<tt<<": "<<det(a)<<endl;
	}
}
accuracy: 1
time_ms: 900
memory_kb: 7084
final_rank: 3

code_snippet: #include<stdio.h>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
char str[600][20];
int dx[]={1,0,-1,0};
int dy[]={0,1,0,-1};
int num[600][20];
long long mod=1000000007;
long long pow(long long a,long long b){
	long long ret=1;
	while(b){
		if(b%2)ret=ret*a%mod;
		a=a*a%mod;
		b/=2;
	}
	return ret;
}
typedef map<int,long long> vec;
typedef vector<vec> mat;
long long det(mat A){
	int n=A.size();
	long long val=1;
	for(int i=0;i<n;i++){
		int at=-1;
		for(int j=i;j<n;j++){
			if(A[j].count(i)&&A[j][i]){
				at=j;break;
			}
		}
		if(!~at)return 0;
		if(at!=i){
			swap(A[at],A[i]);
			val=(mod-val);
		}
		val=val*A[i][i]%mod;
		long long t=pow(A[i][i],mod-2);
		for(map<int,long long>::iterator it=A[i].begin();it!=A[i].end();it++){
			A[i][(*it).first]=(*it).second*t%mod;
		}
		for(int j=i+1;j<n;j++){
			if(A[j].count(i)&&A[j][i]){
				long long div=mod-A[j][i];
				for(map<int,long long>::iterator it=A[i].begin();it!=A[i].end();it++){
					if((*it).second==0){continue;}
					if(!A[j].count((*it).first))A[j][(*it).first]=(*it).second*div%mod;
					else A[j][(*it).first]=(A[j][(*it).first]+(*it).second*div)%mod;
				}
			}
		}
	}
	for(int i=0;i<n;i++)val=val*A[i][i]%mod;
	return val;
}
int main(){
	int a,b;
	int T=0;
	while(scanf("%d%d",&a,&b),a){
		T++;
		for(int i=0;i<a;i++)scanf("%s",str[i]);
		int at=0;
		for(int i=0;i<a;i++)for(int j=0;j<b;j++){
			num[i][j]=-1;
		}
		for(int i=0;i<a;i++)for(int j=0;j<b;j++){
			if(str[i][j]!='#')num[i][j]=at++;
		}
		mat A(at-1);
		for(int i=0;i<a;i++)for(int j=0;j<b;j++){
			if(str[i][j]!='#'){
				int deg=0;
				for(int k=0;k<4;k++){
					if(0<=i+dx[k]&&i+dx[k]<a&&0<=j+dy[k]&&j+dy[k]<b&&~num[i+dx[k]][j+dy[k]]){
						deg++;
						if(num[i][j]<at-1&&num[i+dx[k]][j+dy[k]]<at-1){
							A[num[i][j]][num[i+dx[k]][j+dy[k]]]=mod-1;
						}
					}
				}
				if(num[i][j]<at-1)A[num[i][j]][num[i][j]]=deg;
			}
		}
	//	for(int i=0;i<at-1;i++,printf("\n"))for(int j=0;j<at-1;j++)printf("%lld ",A[i][j]);
		printf("Case %d: %lld\n",T,det(A));
	}
}
accuracy: 1
time_ms: 2950
memory_kb: 18356
final_rank: 11

code_snippet: #include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
#include <assert.h>
#include <vector>
#include <queue>
#include <string>
#include <map>
#include <set>
#include <deque>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c) for (__typeof((c).begin())it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

typedef vector<int> Array;
typedef vector<Array> Matrix;
const ll MOD = 1e+9 + 7;

void PrintMatrix(const Matrix &mat) {
  REP(y, mat.size()) {
    REP(x, mat[0].size()) {
      printf("%d ", mat[y][x]);
    }
    puts("");
  }
  puts("");
}

//a x + b y = gcd(a, b)
long long extgcd(long long a, long long b, long long &x, long long &y) {
  long long g = a; x = 1; y = 0;
  if (b != 0) g = extgcd(b, a % b, y, x), y -= (a / b) * x;
  return g;
}

long long InvMod(long long a, long long mod) {
  long long x, y;
  if (extgcd(a, mod, x, y) == 1) { return (x + mod) % mod; }
  return 0;
}


void BandGaussElimination(Matrix &mat) {
  int h = mat.size();
  if (h == 0) { return; }
  int w = mat[0].size() / 2;
  REP(fy, h) {
    if (mat[fy][w] == 0) { return; }
    FOR(ty, fy + 1, min(h, fy + w + 1)) {
      ll ratio = (MOD - mat[ty][w - (ty - fy)]) * InvMod(mat[fy][w], MOD) % MOD;
      FOR(dx, 0, w + 1) {
        int fx = w + dx;
        int tx = w - (ty - fy) + dx;
        mat[ty][tx] = (mat[ty][tx] + mat[fy][fx] * ratio) % MOD;
      }
    }
  }
}

char field[600][600];
int indexes[600][20];
int main() {
  int w, h;
  int test_case = 0;
  while (scanf("%d %d", &h, &w), h|w) {
    MEMSET(indexes, -1);
    test_case++;
    REP(y, h) {
      scanf("%s", field[y]);
    }
    int m = 0;
    REP(y, h) {
      REP(x, w) {
        if (field[y][x] == '#' && m == 0) { continue; }
        indexes[y][x] = m++;
      }
    }
    Matrix mat(m, Array(2 * w + 1, 0));
    REP(y, h) {
      REP(x, w) {
        if (indexes[y][x] == -1) { continue; }
        if (field[y][x] == '#') {
          mat[indexes[y][x]][w] = 1;
          continue;
        }
        REP(dir, 4) {
          const int dx[4] = { 1, 0, -1, 0 };
          const int dy[4] = { 0, 1, 0, -1 };
          int nx = x + dx[dir];
          int ny = y + dy[dir];
          if (nx < 0 || nx >= w || ny < 0 || ny >= h) { continue; }
          if (field[ny][nx] == '#') { continue; }
          mat[indexes[y][x]][w]++;
          int offset = ny *  w + nx - y * w - x;
          mat[indexes[y][x]][w + offset] = MOD - 1;
          assert(abs(offset) <= w);
        }
      }
    }
    mat.erase(mat.begin());
    REP(dx, min(w, (int)mat.size())) {
      mat[dx][w - dx - 1] = 0;
    }
    BandGaussElimination(mat);
    REP(y, mat.size() / 2) REP(x, w * 2 + 1) { swap(mat[y][x], mat[mat.size() - y - 1][x]); }
    REP(y, mat.size()) REP(x, w) { swap(mat[y][x], mat[y][2 * w - x]); }
    BandGaussElimination(mat);
    ll ans = 1;
    REP(i, mat.size()) { ans = (ans * mat[i][w]) % MOD; }
    printf("Case %d: %lld\n", test_case, ans);
  }
}
accuracy: 1
time_ms: 2410
memory_kb: 2304
final_rank: 6