#pragma GCC target ("avx2")
#pragma GCC optimize ("unroll-loops")
#pragma GCC optimize ("O3")
#include "bits/stdc++.h"
#include <unordered_set>
#include <unordered_map>
#include <random>
using namespace std;
typedef long long ll;
const ll MOD = 1'000'000'007LL; /*998'244'353LL;*/
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(), (x).end()
#define rep(i, n) for(int (i)=0; (i)<(n); (i)++)
const int dx[4]={ 1,0,-1,0 };
const int dy[4]={ 0,1,0,-1 };

template<long long Mod>
struct mint{
    long long x;
    mint(long long x=0) :x((x% Mod+Mod)%Mod){}

    mint operator-() const { return mint(-x); }

    mint& operator+=(const mint a) {
        if((x += a.x) >= Mod) x -= Mod;
        return *this;
    }
    mint& operator-=(const mint a) {
        if((x += Mod-a.x) >= Mod) x -= Mod;
        return *this;
    }
    mint& operator*=(const mint a) {
        (x *= a.x) %= Mod;
        return *this;
    }

    mint operator^(long long t) const {
        mint ret(1);
        mint a = *this;
        while(t){
            if(t&1){
                ret *= a;
            }
            a *= a;
            t >>= 1;
        }
        return ret;
    }
    mint inv() const { return *this ^ (Mod-2); }
    mint& operator/=(const mint a) { return *this *= a.inv(); }

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

    friend istream& operator>>(istream& is, mint& a) { return is >> a.x; }
    friend ostream& operator<<(ostream& os, const mint& a) { return os << a.x; }
};

int H, W, K;
string S[2000];

int g[2000][2000];

signed main(){
    cin >> H >> W;
    rep(i, H) cin >> S[i];

    rep(i, H){
        rep(j, W){
            if(S[i][j] == '.') K++;
        }
    }

    rep(i, H){
        int k;
        for(k=0; k<W; k++){
            if(S[i][k] == '#') break;
        }
        for(int l=0; l<k; l++){
            g[i][l] += k;
        }
        rep(j, W){
            if(S[i][j] == '#'){
                int k;
                for(k=j+1; k<W; k++){
                    if(S[i][k] == '#') break;
                }
                for(int l=j+1; l<k; l++){
                    g[i][l] += k-j-1;
                }
            }
        }
    }
    rep(j, W){
        int k;
        for(k=0; k<H; k++){
            if(S[k][j] == '#') break;
        }
        for(int l=0; l<k; l++){
            g[l][j] += k;
        }
        rep(i, H){
            if(S[i][j] == '#'){
                int k;
                for(k=i+1; k<H; k++){
                    if(S[k][j] == '#') break;
                }
                for(int l=i+1; l<k; l++){
                    g[l][j] += k-i-1;
                }
            }
        }
    }

    mint<MOD> ans = 0;
    rep(i, H){
        rep(j, W){
            if(S[i][j] == '#'){
                continue;
            }
            ans += mint<MOD>(2)^K;
            ans -= mint<MOD>(2)^(K-g[i][j]+1);
        }
    }
    cout << ans << endl;
}
#include <bits/stdc++.h>

using namespace std;

int main()
{
    // Input from input.txt
    ifstream in("input.txt");
    cin.rdbuf(in.rdbuf());

    // Speeding up cin
    cin.tie(0);
    ios::sync_with_stdio(false);

    // Main code
    int N, M;
    cin >> N >> M;
    vector<string> S(N);
    for (int i = 0; i < N; i++) {
        cin >> S[i];
    }
    
    int64_t even = 0, odd = 0;
    for (int i = 0; i < N; i++) {
        bitset<20> bs(S[i]);
        if (bs.count() % 2 == 0) {
            even++;
        } else {
            odd++;
        }
    }
    cout << even * odd << endl;
    
    return 0;
}
