#include <bits/stdc++.h>
using namespace std;
const int OO = 1e9;
const double EPS = 1e-9;
struct hsh {
  int h0, h1, h2;
  hsh() { h0 = h1 = h2 = 0; }
  int& operator[](int I) { return !I ? h0 : (I == 1 ? h1 : h2); }
  bool operator==(hsh oth) const {
    return h0 == oth.h0 && h1 == oth.h1 && h2 == oth.h2;
  }
};
struct Hash {
  size_t operator()(hsh p) const {
    return hash<long long>()(((1LL * p[0]) << 32) ^ p[1]);
  }
};
const int MX = 1e6 + 5, HASH_CNT = 3;
int p[] = {1299709, 1299721, 1299841}, pPw[MX][HASH_CNT];
int M[] = {1000000009, 1000000007, 998244353};
vector<vector<hsh>> prefHash(MX);
int n, m, u, v, inv[3];
vector<vector<int>> adj(MX);
vector<unordered_map<int, int>> pos(MX);
vector<hsh> computePrefHash(const vector<int>& s) {
  vector<hsh> prefHash(int(s.size()) + 1);
  for (int i = 1; i <= int(s.size()); ++i)
    for (int I = 0; I < HASH_CNT; ++I)
      prefHash[i][I] =
          (prefHash[i - 1][I] + (s[i - 1]) * 1LL * pPw[i - 1][I]) % M[I];
  return prefHash;
}
hsh remove(vector<hsh>& prefHash, int pos) {
  hsh ret;
  for (int I = 0; I < HASH_CNT; ++I) {
    ret[I] = (prefHash[pos - 1][I] +
              (prefHash.back()[I] - prefHash[pos][I]) * 1LL * inv[I]) %
             M[I];
    while (ret[I] < 0) ret[I] += M[I];
  }
  return ret;
}
long long inverse(long long a, long long b) {
  return 1 < a ? b - inverse(b % a, a) * b / a : 1;
}
int main() {
  ios::sync_with_stdio(false);
  cout.precision(10);
  cin.tie(0);
  for (int I = 0; I < HASH_CNT; ++I) inv[I] = inverse(p[I], M[I]);
  for (int I = 0; I < HASH_CNT; ++I) pPw[0][I] = 1;
  for (int i = 1; i < MX; ++i)
    for (int I = 0; I < HASH_CNT; ++I)
      pPw[i][I] = (p[I] * 1LL * pPw[i - 1][I]) % M[I];
  cin >> n >> m;
  for (int i = 0; i < m; ++i) {
    cin >> u >> v;
    adj[u].push_back(v);
    adj[v].push_back(u);
  }
  unordered_map<hsh, int, Hash> hashes;
  vector<vector<hsh>> prefHashes(n + 1);
  for (int i = 1; i <= n; ++i) {
    sort(adj[i].begin(), adj[i].end());
    for (int j = 0; j < int(adj[i].size()); ++j) {
      pos[i][adj[i][j]] = j;
    }
    prefHashes[i] = computePrefHash(adj[i]);
    ++hashes[prefHashes[i].back()];
  }
  long long ans = 0;
  for (auto& pr : hashes) {
    ans += pr.second * 1LL * (pr.second - 1) / 2;
  }
  int add = 0;
  for (int i = 1; i <= n; ++i) {
    for (auto& j : adj[i]) {
      int posJ = pos[i][j] + 1;
      int posI = pos[j][i] + 1;
      add += (remove(prefHashes[i], posJ) == remove(prefHashes[j], posI));
    }
  }
  cout << ans + add / 2 << '\n';
  return 0;
}
