Problem: There are some coins in the xy-plane. The positions of the coins are represented by a grid of characters with H rows and W columns. If the character at the i-th row and j-th column, s_{ij}, is `#`, there is one coin at point (i,j); if that character is `.`, there is no coin at point (i,j). There are no other coins in the xy-plane.

There is no coin at point (x,y) where 1\leq i\leq H,1\leq j\leq W does not hold. There is also no coin at point (x,y) where x or y (or both) is not an integer. Additionally, two or more coins never exist at the same point.

Find the number of triples of different coins that satisfy the following condition:

* Choosing any two of the three coins would result in the same Manhattan distance between the points where they exist.



Here, the Manhattan distance between points (x,y) and (x',y') is |x-x'|+|y-y'|. Two triples are considered the same if the only difference between them is the order of the coins.

Constraints

* 1 \leq H,W \leq 300
* s_{ij} is `#` or `.`.

Input

Input is given from Standard Input in the following format:


H W
s_{11}...s_{1W}
:
s_{H1}...s_{HW}


Output

Print the number of triples that satisfy the condition.

Examples

Input

5 4
#.##
.##.
#...
..##
...#


Output

3


Input

5 4
.##
.##.
...
..##
...#


Output

3


Input

13 27
......#.........#.......#..
...#.....###..
..............#####...##...
...#######......#...#######
...#.....#.....###...#...#.
...#######....#.#.#.#.###.#
..............#.#.#...#.#..
.#.#.#...###..
...........#...#...#######
..#######..#...#...#.....#
..#.....#..#...#...#.###.#
..#######..#...#...#.#.#.#
..........##...#...#.#####


Output

870

Solution (in CPP):

Solution:
#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<math.h>
#include<iomanip>
#include<set>
#include<numeric>
#include<cstring>
#include<cstdio>
#include<functional>
#include<bitset>
#include<limits.h>
#include<cassert>
#include <fstream>
#include <time.h>
#include <iterator>


#define REP(i, n) for(int i = 0;i < n;i++)
#define REPR(i, n) for(int i = n;i >= 0;i--)
#define FOR(i, m, n) for(int i = m;i < n;i++)
#define FORR(i, m, n) for(int i = m;i >= n;i--)
#define SORT(v, n) sort(v, v+n);
#define VSORT(v) sort(v.begin(), v.end());
#define REVERSE(v,n) reverse(v,v+n);
#define VREVERSE(v) reverse(v.begin(), v.end());
#define ll long long
#define pb(a) push_back(a)
#define m0(x) memset(x,0,sizeof(x))
#define print(x) cout<<x<<endl;
#define pe(x) cout<<x<<" ";
#define lb(v,n) lower_bound(v.begin(), v.end(), n);
#define ub(v,n) upper_bound(v.begin(), v.end(), n);
#define int long long
#define all(x) (x).begin(), (x).end()

using namespace std;

int MOD = (ll)1000000000 + 7;
const ll INF = 1e17;
const double pi = acos(-1);
const double EPS = 1e-10;
typedef pair<int, int>P;
const int MAX = 200020;

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


int A[620][620],cum[620][620];
string S[303];
int H, W,N,ret;
void solve() {
	//横方向に累積和をとる
	REP(i, N) {
		cum[i][0] = 0;
		REP(j, N) {
			cum[i][j + 1] = cum[i][j] + A[i][j];
		}
	}

	//横方向で二点を固定する
	REP(x, N) {
		REP(y, N) {
			if (A[x][y] == 0)continue;
			FOR(y2, y + 1, N) {
				if (A[x][y2] == 0)continue;
				int d = y2 - y;
				if (x + d < N) {
					ret += cum[x+d][y2] - cum[x+d][y];
				}
			}
		}
	}
}
int A2[620][620];
//90度回転
void rot() {
	REP(i, N) {
		REP(j, N) {
			A2[i][j] = A[j][N - 1 - i];
		}
	}
	REP(i, N) {
		REP(j, N) {
			A[i][j] = A2[i][j];
		}
	}
}

signed main() {
	cin.tie(0);
	ios::sync_with_stdio(false);
	cin >> H >> W;
	REP(i, H) {
		cin >> S[i];
	}
	REP(i, H) {
		REP(j, W) {
			if (S[i][j] == '#') {
				int x = i + j;
				int y = i - j - 1 + W;
				A[x][y] = 1;
			}
		}
	}
	N = H + W;
	/*REP(i, N) {
		REP(j, N) {
			pe(A[i][j]);
		}cout << endl;
	}*/

	ret = 0;
	solve(); rot();
	solve(); rot();
	solve(); rot();
	solve();
	print(ret);
}