/*{{{*/
#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <cassert>
using namespace std;
typedef pair<int, int> PP;
typedef long long LL;
#define pb push_back
#define fr first
#define sc second
#define bitcnt __builtin_popcount
#define all(x) x.begin(), x.end()
inline LL ri() {LL x; scanf("%lld", &x); return x;}
#define rep2(i, n, ...) for (int i = 0; i < (n); i ++) 
#define rep3(i, a, b, ...) for (int i = (a); i < (b); i ++)
#define GET_MACRO(_1, _2, _3, NAME, ...) NAME
#define rep(...) GET_MACRO(__VA_ARGS__, rep3, rep2)(__VA_ARGS__)
#define drep2(i, n, ...) for (int i = (n) - 1; i >= 0; i --)
#define drep3(i, a, b) for (int i = (a) - 1; i >= (b); i --)
#define drep(...) GET_MACRO(__VA_ARGS__, drep3, drep2)(__VA_ARGS__)
template<typename T>inline bool smax(T&a, T b){if(a<b){a=b;return true;}return false;} 
template<typename T>inline bool smin(T&a, T b){if(a>b){a=b;return true;}return false;} 
/*}}}*/


int n, m;
char s[400][400];
char _s[400][400];

#define get gett
//unordered_set<tuple<int, int, int>> vis;

inline int get(int x, int y) {
  return x >= 0 && x < n && y >= 0 && y < m && s[x][y] == '#';
}

inline int get(const PP& a) {
  return get(a.fr, a.sc);
}

LL res = 0;

void rotate() {
  rep(i, n) {
    rep(j, m) {
      _s[j][i] = s[n - 1 - i][j];
    }
  }
  swap(n, m);
  rep(i, n) {
    rep(j, m) {
      s[i][j] = _s[i][j]; 
    }
  }
}
inline int sign(int x) {
  return x == 0 ? 0 : (x > 0 ? 1 : -1);
}

inline PP diff(PP& a, PP & b) {
  return PP(sign(b.fr - a.fr), sign(b.sc - a.sc));
}

inline void add(PP& a, PP &b) {
  a.fr += b.fr;
  a.sc += b.sc;
}

void solve() {
  for (int s = 0; s < n + m - 1; s ++) {
    int max_d = min(s, n - 1) - max(s - m + 1, 0);
    for (int d = 1; d <= max_d; d ++) {
      PP last_1, last_2;
      int cnt = 0;
      bool init = false;
      for (int i = max(s - m + 1, 0); i + d <= s && i + d < n; i ++) {
        PP new_1 = {i, s - i - d - d},new_2 = {i - d, s - i - d};
        if (init) {
          if (get(last_2)) cnt --;
          if (get(new_1)) cnt ++;
        } 
        else {
          for (PP p = new_1, df = diff(new_1, new_2); ; add(p, df)) {
            if (get(p)) cnt ++;
            if (p == new_2) {
              break;
            }
          }
        }

        if (get(PP({i, s - i})) && get(PP({i + d, s - i - d}))) {
          //if (cnt) {
          //cout << i << ' ' << s - i << ' '  << i + d << ' ' << s - i - d << ' ' << cnt <<  endl;
          //}
          res += cnt * 2;
          if (get(new_1)) res --;
          if (get(new_2)) res --;
        }
        last_1 = new_1;
        last_2 = new_2;
        init = true;
      }
    }

    // 

    //for (int i = max(s - m - 1, 0); i <= s && i < n; i ++) {
    //for (int j = max(s - m - 1, 0); j < i; j ++) {
    ////
    //}
    //}
  }
}

int main() {
  cin >> n >> m;
  rep(i, n) cin >> s[i];

  rep(i, 4) {
    solve();
     rotate();
  }

  //int res = 0;
  //for (int i = 1; i < 300; i ++) {
    //for (int x = -300 + n; x < 300 + n; x ++) {
      //for (int y = -300 + m; y < 300 + m; y ++) {
        //int d[4] = {get(x, y), get(x - i, y + i), get(x, y + 2 * i), get(x + i, y + i)};
        //if (d[0] && d[1] && d[2]) res ++;
        //if (d[1] && d[2] && d[3]) res ++;
        //if (d[2] && d[3] && d[0]) res ++;
        //if (d[3] && d[0] && d[1]) res ++;
      //}
    //}
  //}
  cout << res / 2 << endl;

  //for (int i = 0; i < n + m - 1; i ++)  {
    //for (int j = max(i - m - 1, 0); j < n && j <= i; j ++) {
      ////for (int k = max(i - m - 1, 0); k < j; k ++) {
        ////int dis = 2 * (j - k);

      ////}
      //for (int d = min(n - 1))
    //}
  //}
  

  return 0;
}


Measured memory_bytes: 512