#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
using pll = pair<long long, long long>;
#define rep(i, n) for(int i = 0; i < (n); ++i)
#define all(x) (x).begin(),(x).end()
constexpr char ln = '\n';
constexpr long long MOD = 1000000007;
//constexpr long long MOD = 998244353;
template<class T1, class T2> inline bool chmax(T1 &a, T2 b) { if (a < b) { a = b; return true;} return false; }
template<class T1, class T2> inline bool chmin(T1 &a, T2 b) { if (a > b) { a = b; return true;} return false; }
inline int popcount(int x) {return __builtin_popcount(x);}
inline int popcount(long long x) {return __builtin_popcountll(x);}
void print() { cout << "\n"; }
template<class T, class... Args>
void print(const T &x, const Args &... args) {
    cout << x << " ";
    print(args...);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////

template<typename T>
struct CumlativeSum2D {
    int N,M;
    vector<vector<T>> arr;

    CumlativeSum2D (vector<vector<T>> &A) {
        N = A.size();
        A.emplace_back();
        M = A[0].size();
        A.pop_back();
        arr.assign(N+1, vector<T>(M+1,0));
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                arr[i+1][j+1] = A[i][j];
            }
        }
        for (int i = 0; i <= N; i++) {
            for (int j = 0; j < M; j++) {
                arr[i][j+1] += arr[i][j];
            }
        }
        for (int j = 0; j <= M; j++) {
            for (int i = 0; i < N; i++) {
                arr[i+1][j] += arr[i][j];
            }
        }
    }

    //[h1,h2],[w1,w2]
    T get(int h1, int h2, int w1, int w2) {
        if (h1 > h2 || w1 > w2) return 0;
        return arr[h2+1][w2+1] - arr[h2+1][w1] - arr[h1][w2+1] + arr[h1][w1];
    }

    inline const vector<T> &operator[](int k) const {return arr[k+1];}
  	inline vector<T> &operator[](int k) {return arr[k+1];}
};

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

int main() {
    ios::sync_with_stdio(false); cin.tie(nullptr);
    int H,W; cin >> H >> W;
    vector<string> S(H);
    rep(i,H) cin >> S[i];

    vector<vector<int>> T(H+W, vector<int>(H+W));
    rep(i,H) rep(j,W) {
        if (S[i][j]=='#') T[i+j][i-j+W] = 1;
    }
    CumlativeSum2D<int> C(T);

    ll ans = 0;
    auto check =[&](int pos) {
        return pos < 0 or pos >= H+W;
    };
    rep(x,H+W) rep(y,H+W) {
        if (abs(x+y-W)&1) continue;
        int D = H+W;
        chmin(D,min(x,H+W-1-x));
        chmin(D,min(y,H+W-1-y));
        for (int k = 1; k <= D; k++) {
            rep(l,4) {
                int px = x+k*dx[l];
                int py = y+k*dy[l];
                int qx = x+k*dx[(l+1)%4];
                int qy = y+k*dy[(l+1)%4];
                int rx = x+k*dx[(l+2)%4];
                int ry = y+k*dy[(l+2)%4];
                if (check(px) or check(py) or check(qx) or check(qy) or check(rx) or check(ry)) continue;
                if (T[px][py] and T[qx][qy]) {
                    if (px==qx) {
                        ans += C.get(rx,rx,min(py,qy)+1,max(py,qy)-1);
                    } else {
                        ans += C.get(min(px,qx)+1,max(px,qx)-1,ry,ry);
                    }
                }
                if (T[px][py] and T[qx][qy] and T[rx][ry]) ans++;
            }
        }
    }

    cout << ans << ln;
}


Measured memory_bytes: 6084