#include <bits/stdc++.h>
using namespace std;
const int MAXBUF = 1 << 23;
char B[MAXBUF], *Si = B, *Ti = B;
inline char getc() {
  if (Si == Ti) Ti = (Si = B) + fread(B, 1, MAXBUF, stdin);
  if (Si == Ti)
    return 0;
  else
    return *Si++;
}
template <class T>
inline void read(T &a) {
  static char c;
  while ((c = getc()) < '0' || c > '9')
    ;
  a = c - '0';
  while ((c = getc()) <= '9' && c >= '0') a = (a << 3) + (a << 1) + c - '0';
}
int head[1048577], nxt[1000005], w[1000005], tot = 0;
unsigned long long val[1000005], g[1000005], vl[1000005];
int a[1000005], b[1000005], n, m;
unsigned long long seed = 20011006, ans = 0;
inline unsigned long long rnd() {
  seed ^= (seed << 13ll);
  seed ^= (seed >> 17ll);
  seed ^= (seed << 5ll);
  return seed;
}
inline void query(unsigned long long o) {
  int bel = ((int)(o & 1048575ll)), i;
  for (i = head[bel]; i; i = nxt[i]) {
    if (vl[i] == o) {
      ans += (w[i]++);
      return;
    }
  }
  tot++;
  nxt[tot] = head[bel];
  head[bel] = tot;
  vl[tot] = o;
  w[tot] = 1;
}
int main() {
  int i;
  read(n);
  read(m);
  for (i = 1; i <= n; i++) val[i] = rnd();
  for (i = 1; i <= m; i++) {
    read(a[i]);
    read(b[i]);
    g[a[i]] ^= val[b[i]];
    g[b[i]] ^= val[a[i]];
  }
  for (i = 1; i <= n; i++) query(g[i]);
  for (i = 1; i <= m; i++) {
    if ((g[a[i]] ^ val[b[i]]) == (g[b[i]] ^ val[a[i]])) ans++;
  }
  printf("%lld\n", ans);
  return 0;
}
