use std::collections::{BTreeMap, BTreeSet};

fn main() {
    let s = std::io::stdin();
    let mut sc = Scanner { stdin: s.lock() };
    let h: usize = sc.read();
    let w: usize = sc.read();
    let map: Vec<Vec<char>> = (0..h).map(|_| sc.chars()).collect();

    let mut left: BTreeMap<i64, Vec<(i64, i64)>> = BTreeMap::new();
    let mut right: BTreeMap<i64, Vec<(i64, i64)>> = BTreeMap::new();
    for x in 0..h {
        for y in 0..w {
            if map[x][y] == '#' {
                let x = x as i64;
                let y = y as i64;
                let k = y - x;
                let l = y + x;
                left.entry(k).or_insert(Vec::new()).push((x, y));
                right.entry(l).or_insert(Vec::new()).push((x, y));
            }
        }
    }

    for v in left.values_mut() {
        v.sort();
    }
    for v in right.values_mut() {
        v.sort();
    }

    let insert = |ans: &mut BTreeSet<[(i64, i64); 3]>, left: &BTreeMap<i64, Vec<(i64, i64)>>| {
        for (&key, value) in left.iter() {
            let n = value.len();
            for i in 0..n {
                for j in (i + 1)..n {
                    let (x1, y1) = value[i];
                    let (x2, y2) = value[j];
                    let d = (x1 - x2).abs() + (y1 - y2).abs();
                    if let Some(v) = left.get(&(key + d)) {
                        for &(x3, y3) in v.iter() {
                            let d1 = (x1 - x3).abs() + (y1 - y3).abs();
                            let d2 = (x2 - x3).abs() + (y2 - y3).abs();
                            if d1 == d && d2 == d {
                                ans.insert(tuple((x1, y1), (x2, y2), (x3, y3)));
                            }
                        }
                    }
                    if let Some(v) = left.get(&(key - d)) {
                        for &(x3, y3) in v.iter() {
                            let d1 = (x1 - x3).abs() + (y1 - y3).abs();
                            let d2 = (x2 - x3).abs() + (y2 - y3).abs();
                            if d1 == d && d2 == d {
                                ans.insert(tuple((x1, y1), (x2, y2), (x3, y3)));
                            }
                        }
                    }
                }
            }
        }
    };

    let mut ans = BTreeSet::new();
    insert(&mut ans, &left);
    insert(&mut ans, &right);
    println!("{}", ans.len());
}

fn tuple(p1: (i64, i64), p2: (i64, i64), p3: (i64, i64)) -> [(i64, i64); 3] {
    let mut v = [p1, p2, p3];
    v.sort();
    [v[0], v[1], v[2]]
}

pub struct Scanner<R> {
    stdin: R,
}

impl<R: std::io::Read> Scanner<R> {
    pub fn read<T: std::str::FromStr>(&mut self) -> T {
        use std::io::Read;
        let buf = self
            .stdin
            .by_ref()
            .bytes()
            .map(|b| b.unwrap())
            .skip_while(|&b| b == b' ' || b == b'\n')
            .take_while(|&b| b != b' ' && b != b'\n')
            .collect::<Vec<_>>();
        unsafe { std::str::from_utf8_unchecked(&buf) }
            .parse()
            .ok()
            .expect("Parse error.")
    }
    pub fn vec<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.read()).collect()
    }
    pub fn chars(&mut self) -> Vec<char> {
        self.read::<String>().chars().collect()
    }
}
