#include <bits/stdc++.h>
#pragma optimize("-O3")
using namespace std;
const long long mod = 998244353;
int n, m, u, v;
pair<vector<int>, int> adj[1000006];
int alr[1000006];
long long ans = 0, cr = 0;
bool check(int i, int j) {
  if ((int)adj[i].first.size() != (int)adj[j].first.size()) return false;
  int x = (int)adj[i].first.size();
  int in1 = 0, in2 = 0;
  while (in1 < x && in2 < x) {
    if (adj[i].first[in1] == adj[j].second) {
      in1++;
      continue;
    }
    if (adj[j].first[in2] == adj[i].second) {
      in2++;
      continue;
    }
    if (adj[i].first[in1] != adj[j].first[in2]) return false;
    in1++;
    in2++;
  }
  return true;
}
bool check2(int i, int j) {
  if ((int)adj[i].first.size() != (int)adj[j].first.size()) return false;
  int x = (int)adj[i].first.size();
  int in1 = 0;
  while (in1 < x) {
    if (adj[i].first[in1] != adj[j].first[in1]) return false;
    in1++;
  }
  return true;
}
void dfs(int i) {
  for (auto &x : adj[i].first) {
    if (x < i) continue;
    if (check(i, x)) ans++;
  }
}
void solve() {
  cin >> n >> m;
  for (long long i = (long long)0; i != (long long)m; i = i + 1) {
    cin >> u >> v;
    u--;
    v--;
    adj[u].first.push_back(v);
    adj[v].first.push_back(u);
  }
  for (long long i = (long long)0; i != (long long)n; i = i + 1) {
    adj[i].second = i;
    sort(adj[i].first.begin(), adj[i].first.end());
  }
  for (long long i = (long long)0; i != (long long)n; i = i + 1) {
    dfs(i);
  };
  sort(adj, adj + n);
  for (long long i = (long long)0; i != (long long)n; i = i + 1)
    ;
  for (long long i = (long long)1; i != (long long)n; i = i + 1) {
    if (check2(i, i - 1)) {
      cr++;
      ;
      ans += 1ll * cr;
    } else {
      cr = 0;
    }
  }
  cout << ans << '\n';
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  long long t;
  t = 1;
  while (t--) {
    solve();
  }
}
