A tourist wants to visit country Zeydabad for Zbazi (a local game in Zeydabad).

The country Zeydabad is a rectangular table consisting of n rows and m columns. Each cell on the country is either 'z' or '.'.

The tourist knows this country is named Zeydabad because there are lots of ''Z-pattern"s in the country. A ''Z-pattern" is a square which anti-diagonal is completely filled with 'z' and its upper and lower rows are also completely filled with 'z'. All other cells of a square can be arbitrary.

<image>

Note that a ''Z-pattern" can consist of only one cell (see the examples).

So he wants to count the number of ''Z-pattern"s in the country (a necessary skill for Zbazi).

Now your task is to help tourist with counting number of ''Z-pattern"s.

As input/output can reach huge size it is recommended to use fast input/output methods: for example, prefer to use gets/scanf/printf instead of getline/cin/cout in C++, prefer to use BufferedReader/PrintWriter instead of Scanner/System.out in Java.

Input

The first line contains two integers n, m (1 ≤ n, m ≤ 3000) — the number of rows and columns respectively.

Each of the next n lines contains m characters 'z' or '.' — the description of Zeydabad.

Output

Print the only integer a — the number of ''Z-pattern"s in Zeydabad.

Examples

Input

4 4
zzzz
zzz.
.z..
zzzz


Output

16


Input

1 4
z.z.


Output

2


Input

2 2
zz
zz


Output

5
#include <bits/stdc++.h>
class Segtree {
  int32_t** segtree;
  int32_t size_;
  void build(int32_t node, int32_t left, int32_t right,
             std::vector<int32_t>& data) {
    segtree[node] = new int32_t[right - left];
    if (right - left == 1) {
      segtree[node][0] = data[left];
      return;
    }
    int32_t m = (left + right) / 2;
    build(node * 2 + 1, left, m, data);
    build(node * 2 + 2, m, right, data);
    std::merge(segtree[node * 2 + 1], segtree[node * 2 + 1] + m - left,
               segtree[node * 2 + 2], segtree[node * 2 + 2] + right - m,
               segtree[node]);
  }

 public:
  void fill(std::vector<int32_t>& data) {
    segtree = new int32_t*[4 * data.size()];
    for (int32_t i = 0; i < 4 * data.size(); i++) segtree[i] = nullptr;
    build(0, 0, data.size(), data);
    size_ = data.size();
  }
  int32_t query(int32_t node, int32_t left, int32_t right, int32_t query_left,
                int32_t query_right, int32_t val) {
    if (left >= query_right || right <= query_left) return 0;
    if (left >= query_left && right <= query_right)
      return std::lower_bound(segtree[node], segtree[node] + right - left,
                              val) -
             segtree[node];
    int32_t m = (left + right) / 2;
    return query(node * 2 + 1, left, m, query_left, query_right, val) +
           query(node * 2 + 2, m, right, query_left, query_right, val);
  }
  void destroy() {
    for (int32_t i = 0; i < 4 * size_; i++) delete[] segtree[i];
    delete[] segtree;
  }
};
int main() {
  int32_t n, m;
  std::cin >> n >> m;
  std::string* field = new std::string[n];
  for (int32_t i = 0; i < n; i++) {
    std::cin >> field[i];
    for (int32_t j = 0; j < m; j++)
      field[i].push_back(rand() % 2 == 1 ? 'z' : '.');
  }
  int32_t** available_left = new int32_t*[n];
  for (int32_t i = 0; i < n; i++) {
    available_left[i] = new int32_t[m];
    int32_t begin = -1;
    int32_t left_passed = 0;
    for (int32_t j = 0; j <= m; j++) {
      if (j < m && field[i][j] == 'z') {
        left_passed++;
        if (begin == -1) begin = j;
      } else {
        if (begin != -1)
          for (int32_t k = begin; k < j; k++)
            available_left[i][k] = k - begin + 1;
        begin = -1;
      }
    }
  }
  int32_t** available_diag = new int32_t*[n];
  for (int32_t i = 0; i < n; i++) {
    available_diag[i] = new int32_t[m];
  }
  for (int32_t i = 0; i < n; i++) {
    std::pair<int32_t, int32_t> begin = {-1, -1};
    std::pair<int32_t, int32_t> cur = {i, 0};
    for (int32_t j = 0; cur.first >= 0 && cur.second < m; j++) {
      if (field[cur.first][cur.second] == 'z') {
        if (begin.first == -1) begin = cur;
      } else {
        if (begin.first != -1)
          for (std::pair<int32_t, int32_t> k = begin; k != cur;) {
            available_diag[k.first][k.second] = begin.first - k.first + 1;
            k.first--;
            k.second++;
          }
        begin = {-1, -1};
      }
      cur.first--;
      cur.second++;
    }
    if (begin.first != -1) {
      for (std::pair<int32_t, int32_t> k = begin; k != cur;) {
        available_diag[k.first][k.second] = begin.first - k.first + 1;
        k.first--;
        k.second++;
      }
    }
  }
  for (int32_t i = 1; i < m; i++) {
    std::pair<int32_t, int32_t> begin = {-1, -1};
    std::pair<int32_t, int32_t> cur = {n - 1, i};
    for (int32_t j = 0; cur.first >= 0 && cur.second < m; j++) {
      if (field[cur.first][cur.second] == 'z') {
        if (begin.first == -1) begin = cur;
      } else {
        if (begin.first != -1)
          for (std::pair<int32_t, int32_t> k = begin; k != cur;) {
            available_diag[k.first][k.second] = begin.first - k.first + 1;
            k.first--;
            k.second++;
          }
        begin = {-1, -1};
      }
      cur.first--;
      cur.second++;
    }
    if (begin.first != -1) {
      for (std::pair<int32_t, int32_t> k = begin; k != cur;) {
        available_diag[k.first][k.second] = begin.first - k.first + 1;
        k.first--;
        k.second++;
      }
    }
  }
  int32_t** ends_right = new int32_t*[n];
  for (int32_t i = 0; i < n; i++) {
    ends_right[i] = new int32_t[m];
    int32_t begin = -1;
    for (int32_t j = m - 1; j >= -1; j--) {
      if (j >= 0 && field[i][j] == 'z') {
        if (begin == -1) begin = j;
      } else {
        for (int32_t k = begin; k > j; k--) ends_right[i][k] = begin;
        begin = -1;
      }
    }
  }
  std::vector<int32_t>* ens_per_diag = new std::vector<int32_t>[n + m - 1];
  int32_t** index_in_diag = new int32_t*[n + m - 1];
  for (int32_t i = 0; i < n; i++) {
    index_in_diag[i] = new int32_t[m];
    for (int32_t j = 0; j < m; j++) {
      index_in_diag[i][j] = ens_per_diag[i + j].size();
      ens_per_diag[i + j].push_back(ends_right[i][j]);
    }
  }
  Segtree* trees = new Segtree[n + m - 1];
  int64_t answer = 0;
  std::vector<std::pair<int32_t, int32_t> > all_cells;
  for (int32_t i = 0; i < n; i++)
    for (int32_t j = 0; j < m; j++) {
      if (field[i][j] == 'z') all_cells.emplace_back(i, j);
    }
  std::sort(all_cells.begin(), all_cells.end(),
            [](std::pair<int32_t, int32_t> p1, std::pair<int32_t, int32_t> p2) {
              return p1.first + p1.second < p2.first + p2.second;
            });
  for (int32_t i = 0; i < all_cells.size(); i++) {
    if (i > 0 && all_cells[i - 1].first + all_cells[i - 1].second <
                     all_cells[i].first + all_cells[i].second)
      trees[all_cells[i - 1].first + all_cells[i - 1].second].destroy();
    if (i == 0 || all_cells[i - 1].first + all_cells[i - 1].second <
                      all_cells[i].first + all_cells[i].second)
      trees[all_cells[i].first + all_cells[i].second].fill(
          ens_per_diag[all_cells[i].first + all_cells[i].second]);
    int32_t go_down =
        std::min(available_left[all_cells[i].first][all_cells[i].second],
                 available_diag[all_cells[i].first][all_cells[i].second]);
    answer += index_in_diag[all_cells[i].first + go_down - 1]
                           [all_cells[i].second - go_down + 1] -
              index_in_diag[all_cells[i].first][all_cells[i].second] + 1;
    answer -= trees[all_cells[i].first + all_cells[i].second].query(
        0, 0, ens_per_diag[all_cells[i].first + all_cells[i].second].size(),
        index_in_diag[all_cells[i].first][all_cells[i].second],
        index_in_diag[all_cells[i].first + go_down - 1]
                     [all_cells[i].second - go_down + 1] +
            1,
        all_cells[i].second);
  }
  std::cout << answer;
  return 0;
}
