Problem: Snuke has a grid with H rows and W columns. The square at the i-th row and j-th column contains a character S_{i,j}.

He can perform the following two kinds of operation on the grid:

* Row-reverse: Reverse the order of the squares in a selected row.
* Column-reverse: Reverse the order of the squares in a selected column.



For example, reversing the 2-nd row followed by reversing the 4-th column will result as follows:

<image>

By performing these operations any number of times in any order, how many placements of characters on the grid can be obtained?

Constraints

* 1≦H,W≦200
* S_{i,j} is a lowercase English letter (`a`-`z`).

Input

The input is given from Standard Input in the following format:


H W
S_{1,1}S_{1,2}...S_{1,W}
S_{2,1}S_{2,2}...S_{2,W}
:
S_{H,1}S_{H,2}...S_{H,W}


Output

Print the number of placements of characters on the grid that can be obtained, modulo 1000000007 (=10^9+7).

Examples

Input

2 2
cf
cf


Output

6


Input

1 12
codefestival


Output

2

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
#define rep(i, n) for (rint i = 1; i <= (n); i ++)
#define re0(i, n) for (rint i = 0; i < (int) n; i ++)
#define travel(i, u) for (rint i = head[u]; i; i = e[i].nxt)
#define rint register int
using namespace std;
   
typedef long long lo;

template<typename tp> inline void read(tp &x) {
    x = 0; char c = getchar(); int f = 0;
    for (; c < '0' || c > '9'; f |= c == '-', c = getchar());
    for (; c >= '0' && c <= '9'; x = (x << 3) + (x << 1) + c - '0', c = getchar());
    if (f) x = -x;
}

namespace {
    const int mo = 1e9 + 7;
    inline int add(int x) {return x >= mo ? x - mo : x;}
    inline int sub(int x) {return x < 0 ? x + mo : x;}
    inline int mul(int x, int y) {return (long long) x * y % mo;}
    inline int power(int a, int k = mo - 2) {
	int ans = 1;
	for (; k; k >>= 1, a = mul(a, a))
	    if (k & 1) ans = mul(ans, a);
	return ans;
    }
}

namespace G {
    vector <int> pre;
    int n;
    inline void init(int _n) {
	n = _n;
	pre.resize(n + 1);
	rep (i, n) pre[i] = i;
    }
    inline int find(int x) {
	return pre[x] == x ? x : pre[x] = find(pre[x]);
    }
    inline void make(int x, int y) {
	assert(x <= n); assert(y <= n);
	pre[find(x)] = find(y);
    }
}
const int N = 233;
int n, m;
char s[N][N];

int main(void) {
    read(n); read(m);
    G::init(n / 2 + m / 2);
    rep (i, n) scanf("%s", s[i] + 1);
    int ans = 1;
    if (n & 1) {
	for (int j = 1; j <= m / 2; j++)
	    if (s[n / 2 + 1][j] != s[n / 2 + 1][m + 1 - j]) {
		ans = mul(ans, 2);
		break;
	    }
    }
    if (m & 1) {
	for (int i = 1; i <= n / 2; i++)
	    if (s[i][m / 2 + 1] != s[n + 1 - i][m / 2 + 1]) {
		ans = mul(ans, 2);
		break;
	    }
    }
    for (int i = 1; i <= n / 2; i++)
	for (int j = 1; j <= m / 2; j++) {
	    int a[] = {s[i][j], s[n - i + 1][j], s[n - i + 1][m - j + 1], s[i][m - j + 1]};
	    sort(a, a + 4);
	    int cnt = 0;
	    do {
		++cnt;
	    } while (next_permutation(a, a + 4));
	    cnt == 24 ? G::make(i, j + n / 2), ans = mul(ans, 12) : ans = mul(ans, cnt);
	}
    int o = n / 2 + m / 2;
    rep (i, n / 2 + m / 2) o -= G::find(i) == i;
    ans = mul(ans, power(2, o));
    cout << ans << "\n";
}