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 <bits/stdc++.h>

#define rep(i,n) for(int i=0; i<(n); i++)
#define reps(i,x,n) for(int i=x; i<(n); i++)
#define rrep(i,n) for(int i=(n)-1; i>=0; i--)
#define all(X) (X).begin(),(X).end()
#define X first
#define Y second
#define pb push_back
#define eb emplace_back

using namespace std;
typedef long long int ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

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 A, size_t N, class T> void Fill(A (&a)[N], const T &v){ fill( (T*)a, (T*)(a+N), v ); }

template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {os<<"{"; rep(i,t.size()) {os<<t[i]<<",";} os<<"}"; return os;}
template<class T,size_t n> ostream& operator<<(ostream &os, const array<T,n> &t) {os<<"{"; rep(i,n) {os<<t[i]<<",";} os<<"}"; return os;}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}

const ll INF = 1e9+7;


int main(){
	ios_base::sync_with_stdio(false);
	int H, W, ans=0;
	string S[505];

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

	vector<int> vx[2][605];
	int sum[2][605][605] = {};
	bool mp[605][605] = {};
	rep(i,H) rep(j,W) if( S[i][j] == '#' ){
		// 左回り45度
		int x = i+j;
		int y = j-i + 300;
		vx[0][x].push_back(y);
		sum[0][x][y+1]++;
		// 右回り45度
		swap(x, y);
		vx[1][x].push_back(y);
		sum[1][x][y+1]++;
		// bool map
		mp[y][x] = true;
	}
	rep(k,2) rep(i,605) rep(j,601) sum[k][i][j+1] += sum[k][i][j];

	rep(k,2) rep(x,605) rep(i,vx[k][x].size()) rep(j,i){
		int y1 = vx[k][x][i];
		int y2 = vx[k][x][j];
		if( y1 < y2 ) swap(y1, y2);
		int r = y1 - y2;
		//cout << k << ": x=" << x << ": " << y1 << " - " << y2 << " : " << r << endl;
		if( x-r >= 0  ) ans += sum[k][x-r][y1+1] - sum[k][x-r][y2];
		if( x+r < 605 ) ans += sum[k][x+r][y1+1] - sum[k][x+r][y2];
	}

	rep(x,605) rep(i,vx[0][x].size()) rep(j,i){
		int y1 = vx[0][x][i];
		int y2 = vx[0][x][j];
		int r = abs(y1 - y2);
		if( x-r >= 0  && mp[x-r][y1] ) ans -= 1;
		if( x-r >= 0  && mp[x-r][y2] ) ans -= 1;
		if( x+r < 605 && mp[x+r][y1] ) ans -= 1;
		if( x+r < 605 && mp[x+r][y2] ) ans -= 1;
	}

	cout << ans << endl;

	return 0;
}