import java.io.*;
import java.util.*;

public class C {

	public C () throws IOException {
		String [] NM = r.readLine().split(" ");
		int N = Integer.parseInt(NM[0]);
		int M = Integer.parseInt(NM[1]);
		int [][] F = new int [2][M];
		for (int m = 0; m < M; ++m) {
			String [] ij = r.readLine().split(" ");
			int i = Integer.parseInt(ij[0]);
			int j = Integer.parseInt(ij[1]);
			F[0][m] = i-1;
			F[1][m] = j-1;
		}
		solve(N, M, F);
	}

	public void solve(int N, int M, int [][] F) {
		start();

		int [] C = new int [N];
		int mc = 0;
		for (int m = 0; m < M; ++m) {
			int i = F[0][m], j = F[1][m];
			++C[i]; ++C[j];
			mc = Math.max(mc, Math.max(C[i], C[j]));
		}

		int [][] CN = new int [1+mc][];
		int [] QN = new int [1+mc];
		for (int i = 0; i < N; ++i)
			++QN[C[i]];
		for (int i = 0; i <= mc; ++i) {
			CN[i] = new int [QN[i]];
			QN[i] = 0;
		}

		for (int i = 0; i < N; ++i)
			CN[C[i]][QN[C[i]]++] = i;

		// C[i] - The degree of profile #i
		// CN[i] - The # of profiles of degree i

		long cnt = 1L * CN[0].length * (CN[0].length - 1)/2;

		if (N == C[0])
			print(cnt);

		int [] ON = new int [N];
		for (int m = 0; m < M; ++m) {
			int i = F[0][m], j = F[1][m];
			if (C[i] == 1)
				++ON[j];
			if (C[j] == 1)
				++ON[i];
		}

		// ON[i] - # of profiles of degree 1 that are connected with profile #i

		long pairs = 0;
		for (int i = 0; i < N; ++i) {
			if (C[i] == 0)
				ON[i] = -1;
			else if (ON[i] == 1) {
				if (C[i] == 1)
					++pairs;
				else
					cnt += 1L * ON[i] * (ON[i] - 1)/2;
			}
		}
		cnt += pairs/2;

		int B = 0;
		for (int i = 0; i < N; ++i)
			if (ON[i] != 0)
				++B;

		if (N == B)
			print(cnt);

//		Profile [] FR = new Profile [N];
//		for (int i = 0; i < N; ++i)
//			if (ON[i] == 0)
//				FR[i] = new Profile(i, C[i]);

//		int [][] FR = new int [N][];
//		for (int i = 0; i < N; ++i)
//			if (ON[i] == 0) {
//				FR[i] = new int [1+C[i]];
//				Arrays.fill(FR[i], -1);
//			}

		long MOD = 1000000000000000007L;

//		for (int m = 0; m < M; ++m) {
//		int i = F[0][m], j = F[1][m];
//		if (ON[i] == 0) {
//			FR[i].friends[++FR[i].last] = j;
//			FR[i].hc = (FR[i].hc + 1L * (j+1) * (j+1) * (j+1)) % MOD;
//		}
//		if (ON[j] == 0) {
//			FR[j].friends[++FR[j].last] = i;
//			FR[j].hc = (FR[j].hc + 1L * (i+1) * (i+1) * (i+1)) % MOD;
//		}
//	}

		long [] HH = new long [N];

		Arrays.fill(C, 0);
		for (int m = 0; m < M; ++m) {
			int i = F[0][m], j = F[1][m];
			if (ON[i] == 0) {
//				FR[i][C[i]++] = j;
				HH[i] = (HH[i] + 1L * (j+1) * (j+1) * (j+1)) % MOD;
			}
			if (ON[j] == 0) {
//				FR[j][C[j]++] = i;
				HH[j] = (HH[j] + 1L * (i+1) * (i+1) * (i+1)) % MOD;
		}
	}

		Map<Long, Integer> HMAP = new HashMap<Long, Integer>();
		int [] H = new int [N];
		Arrays.fill(H, -1);
		for (int i = N-1; i >= 0; --i)
			if (ON[i] == 0) {
				long hc = HH[i]; // FR[i].hc;
				if (!HMAP.containsKey(hc)) {
					HMAP.put(hc, i);
					H[i] = -1;
				} else {
					int j = HMAP.put(hc, i);
					H[i] = j;
				}
			}

		for (int i = 0; i < N; ++i) {
			if (H[i] > 0) {
//				Map<Profile, Integer> MAP = new HashMap<Profile, Integer>();
//				MAP.put(FR[i], 1);
				long nn = 1L;
				int j = i;
				while (H[j] > 0) {
					++nn;
					int j2 = H[j]; H[j] = -1; j = j2;
//					if (!MAP.containsKey(FR[j]))
//						MAP.put(FR[j], 1);
//					else
//						MAP.put(FR[j], MAP.get(FR[j]) + 1);
				}
//				for (long v : MAP.values())
//					cnt += v * (v - 1) / 2;
				cnt += nn * (nn - 1) / 2;
			}
		}

		for (int i = 0; i < N; ++i)
			if (ON[i] == 0)
				//FR[i].hc = (FR[i].hc + 1L * (1+i) * (1+i) * (1+i)) % MOD;
				HH[i] = (HH[i] + 1L * (1+i) * (1+i) * (1+i)) % MOD;

		HMAP = new HashMap<Long, Integer>();
		H = new int [N];
		Arrays.fill(H, -1);
		for (int i = N-1; i >= 0; --i)
			if (ON[i] == 0) {
				long hc = HH[i]; // FR[i].hc;
				if (!HMAP.containsKey(hc)) {
					HMAP.put(hc, i);
					H[i] = -1;
				} else {
					int j = HMAP.put(hc, i);
					H[i] = j;
				}
			}

		for (int i = 0; i < N; ++i) {
			if (H[i] > 0) {
//				Map<Profile, Integer> MAP = new HashMap<Profile, Integer>();
				int j = i;
//				int last = ++FR[j].last;
//				if (FR[j].friends[last] == -1)
//					FR[j].friends[last] = j;
//				if (FR[j].friends[0] == -1)
//					for (int k = 1; k <= 1+last; ++k)
//						if (k <= last && FR[j].friends[k] < j)
//							FR[j].friends[k-1] = FR[j].friends[k];
//						else {
//							FR[j].friends[k-1] = j;
//							break;
//						}
//				MAP.put(FR[j], 1);
				long nn = 1L;
				while (H[j] > 0) {
					++nn;
					int j2 = H[j]; H[j] = -1; j = j2;
//					last = ++FR[j].last;
//					if (FR[j].friends[last] == -1)
//						FR[j].friends[last] = j;
//					if (FR[j].friends[0] == -1)
//						for (int k = 1; k <= last; ++k)
//							if (k <= last && FR[j].friends[k] < j)
//								FR[j].friends[k-1] = FR[j].friends[k];
//							else {
//								FR[j].friends[k-1] = j;
//								break;
//							}
//					if (!MAP.containsKey(FR[j]))
//						MAP.put(FR[j], 1);
//					else
//						MAP.put(FR[j], MAP.get(FR[j]) + 1);
				}
//				for (long v : MAP.values())
//					cnt += v * (v - 1) / 2;
				cnt += nn * (nn - 1) / 2;
			}
		}

		print(cnt);
	}

//	class Profile {
//		int last = -1;
//		final int id;
//		final int [] friends;
//		Profile (int i, int c) {
//			id = i;
//			friends = new int [1+c];
//			Arrays.fill(friends, -1);
//		}
//
//		long hc = 0;
////		public int hashCode() {
////			return hc;
////		}
//
//		boolean sorted = false;
//		public boolean equals(Object o) {
//			Profile p = (Profile)o;
//			if (p.last != last)
//				return false;
//
//			if (!sorted) {
//				Arrays.sort(friends);
//				sorted = true;
//			}
//			if (!p.sorted) {
//				Arrays.sort(p.friends);
//				p.sorted = true;
//			}
//
//			for (int i = 0; i <= last; ++i)
//				if (friends[i] != p.friends[i])
//					return false;
//			return true;
//		}
//
//		public String toString() {
//			return "#" + id + ": " + Arrays.toString(friends) + ", hc = " + hc;
//		}
//
//	}

	////////////////////////////////////////////////////////////////////////////////////

	static BufferedReader r;
	static long t;

	static void print2 (Object o) {
		System.out.println(o);
	}

	static void print (Object o) {
		print2(o);
		//print2((millis() - t) / 1000.0);
		System.exit(0);
	}

	static void run () throws IOException {
		r = new BufferedReader(new InputStreamReader(System.in));
		new C();
	}

	public static void main(String[] args) throws IOException {
		run();
	}

	static long millis() {
		return System.currentTimeMillis();
	}

	static void start() {
		t = millis();
	}
}


import java.io.*;
import java.util.*;

public class C {

	long MILL = 1000000L;

	public C () throws IOException {
		String [] NM = r.readLine().split(" ");
		int N = Integer.parseInt(NM[0]);
		int M = Integer.parseInt(NM[1]);
		long [] F = new long [M];
		for (int m = 0; m < M; ++m) {
			String [] ij = r.readLine().split(" ");
			int i = Integer.parseInt(ij[0]);
			int j = Integer.parseInt(ij[1]);
			F[m] = MILL * (i-1) + (j-1);
		}
		solve(N, M, F);
	}

	public void solve(int N, int M, long [] F) {
		long cnt = s1(N, M, F);
		F = Arrays.copyOf(F, M+N);
		for (int i = 0; i < N; ++i)
			F[M+i] = (1+MILL) * i;
		cnt += s1(N, M+N, F);
		//return cnt;
		print(cnt);
	}

	public long s1 (int N, int M, long [] F) {
		start();

		final int [] C = new int [N];
		for (int m = 0; m < M; ++m) {
			int i = (int)(F[m]/MILL), j = (int)(F[m]%MILL);
			++C[i];
			if (i != j)
				++C[j];
		}

		int [][] FR = new int [N][];
		for (int i = 0; i < N; ++i)
			FR[i] = new int[C[i]];

		Arrays.fill(C, 0);
		for (int m = 0; m < M; ++m) {
			int i = (int)(F[m]/MILL), j = (int)(F[m]%MILL);
			FR[i][C[i]++] = j;
			if (i != j)
				FR[j][C[j]++] = i;
		}

		for (int i = 0; i < N; ++i)
			if (C[i] >= 2)
				Arrays.sort(FR[i]);

		final int [] H = new int [N];
		for (int i = 0; i < N; ++i)
			for (int j = 0; j < C[i]; ++j)
				H[i] = (int)((H[i] * 37L + FR[i][j]) % 1000000007L);

		Integer [] FF = new Integer [N];
		for (int i = 0; i < N; ++i)
			FF[i] = i;

		Arrays.sort(FF, new Comparator<Integer>() {
			public int compare(Integer arg0, Integer arg1) {
				if (C[arg0] != C[arg1])
					return C[arg0] - C[arg1];
				else
					return H[arg0] - H[arg1];
			}
		});

		int p;
		for (p = 0; p < N; ++p) {
			int pp = FF[p];
			if (C[pp] > 0)
				break;
		}

		long cnt = 1L*p*(p-1)/2;

		for (; p < N; ) {
			int pp = FF[p], q;
			for (q = p; q < N; ++q) {
				int qq = FF[q];
				if (C[qq] != C[pp] || H[qq] != H[pp])
					break;
			}
			if (q - p > 1) {
				Map<String, Integer> MAP = new HashMap<String, Integer>();
				for (int i = p; i < q; ++i) {
					int ii = FF[i];
					String K = toString(FR[ii]);
					if (!MAP.containsKey(K))
						MAP.put(K, 0);
					MAP.put(K, MAP.get(K) + 1);
				}
				for (long v: MAP.values())
					cnt += v*(v-1)/2;
			}
			p = q;
		}

		return cnt;
	}

	String toString(int [] FR) {
		StringBuffer b = new StringBuffer();
		for (int f : FR)
			b.append(":" + f);
		return b.toString();
	}

	////////////////////////////////////////////////////////////////////////////////////

	static BufferedReader r;
	static long t;

	static void print2 (Object o) {
		System.out.println(o);
	}

	static void print (Object o) {
		print2(o);
		//print2((millis() - t) / 1000.0);
		System.exit(0);
	}

	static void run () throws IOException {
		r = new BufferedReader(new InputStreamReader(System.in));
		new C();
	}

	public static void main(String[] args) throws IOException {
		run();
	}

	static long millis() {
		return System.currentTimeMillis();
	}

	static void start() {
		t = millis();
	}
}


import java.io.*;
import java.util.*;

public class C implements Runnable {
    private MyScanner in;
    private PrintWriter out;

    private int[][] hash;
    private int k;
    private int[] MUL = { 1000000007, 1000000009 };

    private void add(HashMap<Long, Integer> num, long HMUL, int i) {
        long cur = 0, cm = 1;
        for (int j = 0; j < k; ++j) {
            cur += cm * hash[j][i];
            cm *= HMUL;
        }
        if (!num.containsKey(cur)) {
            num.put(cur, 1);
        } else {
            num.put(cur, num.get(cur) + 1);
        }
    }

    private void solve() {
        int n = in.nextInt();
        int m = in.nextInt();
        k = MUL.length;
        int[][] pow = new int[k][n + 1];
        for (int i = 0; i < k; ++i) {
            pow[i][0] = 1;
        }
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < k; ++j) {
                pow[j][i + 1] = pow[j][i] * MUL[j];
            }
        }
        hash = new int[MUL.length][n];
        for (int i = 0; i < m; ++i) {
            int v = in.nextInt() - 1;
            int u = in.nextInt() - 1;
            for (int j = 0; j < k; ++j) {
                hash[j][v] += pow[j][u + 1];
                hash[j][u] += pow[j][v + 1];
            }
        }
        HashMap<Long, Integer> num = new HashMap<Long, Integer>();
        long HMUL = 2000000009;
        for (int i = 0; i < n; ++i) {
            add(num, HMUL, i);
            for (int j = 0; j < k; ++j) {
                hash[j][i] += pow[j][i + 1];
            }
            add(num, HMUL, i);
        }
        long ans = 0;
        for (int i : num.values()) {
            ans += 1L * i * (i - 1) / 2;
        }
        out.println(ans);
    }

    @Override
    public void run() {
        in = new MyScanner();
        out = new PrintWriter(System.out);
        solve();
        in.close();
        out.close();
    }

    public static void main(String[] args) {
        new C().run();
    }

    static class MyScanner {
        private BufferedReader br;
        private StringTokenizer st;

        public MyScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        public void close() {
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        public String next() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                    return null;
                }
            }
            return st.nextToken();
        }

        public String nextLine() {
            try {
                st = null;
                return br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

        public double nextDouble() {
            return Double.parseDouble(next());
        }

        public boolean hasNext() {
            if (st != null && st.hasMoreTokens()) {
                return true;
            }
            try {
                while (br.ready()) {
                    st = new StringTokenizer(br.readLine());
                    if (st != null && st.hasMoreTokens()) {
                        return true;
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return false;
        }
    }
}


import java.io.*;
import java.util.*;

public class cf154c {
	public static void main(String[] args) throws Exception {
		FastScanner in = new FastScanner(System.in);
		int n = in.nextInt();
		int m = in.nextInt();
		int[] bases = new int[]{31,37,41,43,47};
		int k = bases.length;
		long[][] pow = new long[k][n];
		for(int i=0; i<k; i++) {
			pow[i][0] = 1;
			for(int j=1; j<n; j++)
				pow[i][j] = pow[i][j-1]*bases[i];
		}
		long[][] hashes = new long[k][n];
		for(int i=0; i<m; i++) {
			int a = in.nextInt()-1;
			int b = in.nextInt()-1;
			for(int j=0; j<k; j++) {
				hashes[j][a] += pow[j][b];
				hashes[j][b] += pow[j][a];
			}
		}
		long[] hashSum = new long[n];
		for(int i=0; i<n; i++)
			for(int j=0; j<k; j++)
				hashSum[i] += hashes[j][i];
		Arrays.sort(hashSum);
		long ans = 0;
		int prev = 0;
		for(int i=1; i<=n; i++)
			if(i==n || (hashSum[i] != hashSum[i-1])) {
				long len = i-prev;
				prev = i;
				ans += (len*len-len)/2;
			}
		Arrays.fill(hashSum, 0);
		for(int i=0; i<n; i++)
			for(int j=0; j<k; j++)
				hashSum[i] += hashes[j][i] + pow[j][i];
		Arrays.sort(hashSum);
		prev = 0;
		for(int i=1; i<=n; i++)
			if(i==n || (hashSum[i] != hashSum[i-1])) {
				long len = i-prev;
				prev = i;
				ans += (len*len-len)/2;
			}
		System.out.println(ans);
	}
	static class FastScanner {
		BufferedReader br;
		StringTokenizer st;

		FastScanner(InputStream in) throws Exception{
			br = new BufferedReader(new InputStreamReader(in));
			st = new StringTokenizer(br.readLine().trim());
		}
		public int numTokens() throws Exception {
			if(!st.hasMoreTokens()) {
				st = new StringTokenizer(br.readLine().trim());
				return numTokens();
			}
			return st.countTokens();
		}
		public String next() throws Exception {
			if(!st.hasMoreTokens()) {
				st = new StringTokenizer(br.readLine().trim());
				return next();
			}
			return st.nextToken();
		}
		public double nextDouble() throws Exception {
			return Double.parseDouble(next());
		}
		public long nextLong() throws Exception {
			return Long.parseLong(next());
		}
		public int nextInt() throws Exception {
			return Integer.parseInt(next());
		}
	}
}


import java.io.*;
import java.util.*;

public class cf154c {
	public static void main(String[] args) throws Exception {
		FastScanner in = new FastScanner(System.in);
		HashMap<TreeSet<Integer>,Integer> friendMap = new HashMap<TreeSet<Integer>,Integer>();
		int n = in.nextInt();
		int m = in.nextInt();
		@SuppressWarnings("unchecked")
		TreeSet<Integer>[] g = new TreeSet[n];
		for(int i=0; i<n; i++)
			g[i] = new TreeSet<Integer>();
		for(int i=0; i<m; i++) {
			int a = in.nextInt()-1;
			int b = in.nextInt()-1;
			g[a].add(b);
			g[b].add(a);
		}
		long ret = 0;
		for(int i=0; i<n; i++) {
			int v = 0;
			if(friendMap.containsKey(g[i]))
				v = friendMap.get(g[i]);
			ret += v;
			friendMap.put(g[i], v+1);
		}
		friendMap.clear();
		for(int i=0; i<n; i++)
			g[i].add(i);
		for(int i=0; i<n; i++) {
			int v = 0;
			if(friendMap.containsKey(g[i]))
				v = friendMap.get(g[i]);
			ret += v;
			friendMap.put(g[i], v+1);
		}
		System.out.println(ret);
	}
	static class FastScanner {
		BufferedReader br;
		StringTokenizer st;

		FastScanner(InputStream in) throws Exception{
			br = new BufferedReader(new InputStreamReader(in));
			st = new StringTokenizer(br.readLine().trim());
		}
		public int numTokens() throws Exception {
			if(!st.hasMoreTokens()) {
				st = new StringTokenizer(br.readLine().trim());
				return numTokens();
			}
			return st.countTokens();
		}
		public String next() throws Exception {
			if(!st.hasMoreTokens()) {
				st = new StringTokenizer(br.readLine().trim());
				return next();
			}
			return st.nextToken();
		}
		public double nextDouble() throws Exception {
			return Double.parseDouble(next());
		}
		public long nextLong() throws Exception {
			return Long.parseLong(next());
		}
		public int nextInt() throws Exception {
			return Integer.parseInt(next());
		}
	}
}


import java.util.*;

public class cf154c {
	public static void main(String[] args) throws Exception {
		FastScanner in = new FastScanner(System.in);
		HashMap<TreeSet<Integer>,Integer> friendMap = new HashMap<TreeSet<Integer>,Integer>();
		int n = in.nextInt();
		int m = in.nextInt();
		TreeSet<Integer>[] g = new TreeSet[n];
		for(int i=0; i<n; i++)
			g[i] = new TreeSet<Integer>();
		for(int i=0; i<m; i++) {
			int a = in.nextInt()-1;
			int b = in.nextInt()-1;
			g[a].add(b);
			g[b].add(a);
		}
		long ret = 0;
		for(int i=0; i<n; i++) {
			int v = 0;
			if(friendMap.containsKey(g[i]))
				v = friendMap.get(g[i]);
			ret += v;
			friendMap.put(g[i], v+1);
		}
		friendMap.clear();
		for(int i=0; i<n; i++)
			g[i].add(i);
		for(int i=0; i<n; i++) {
			int v = 0;
			if(friendMap.containsKey(g[i]))
				v = friendMap.get(g[i]);
			ret += v;
			friendMap.put(g[i], v+1);
		}
		System.out.println(ret);
	}
}


import java.io.*;
import java.util.*;

public class cf154c {
	public static void main(String[] args) throws Exception {
		FastScanner in = new FastScanner(System.in);
		int n = in.nextInt();
		int m = in.nextInt();
		int[] bases = new int[]{31,37,41,43,47,51,53};
		int k = bases.length;
		long[][] pow = new long[n][k];
		for(int i=0; i<k; i++) {
			pow[0][i] = 1;
			for(int j=1; j<n; j++)
				pow[j][i] = pow[j-1][i]*bases[i];
		}
		long[][] hashes = new long[n][k];
		for(int i=0; i<m; i++) {
			int a = in.nextInt()-1;
			int b = in.nextInt()-1;
			for(int j=0; j<k; j++) {
				hashes[a][j] += pow[b][j];
				hashes[b][j] += pow[a][j];
			}
		}
		long[] hashSum = new long[n];
		for(int i=0; i<n; i++)
			for(int j=0; j<k; j++)
				hashSum[i] += hashes[i][j];
		Arrays.sort(hashSum);
		long ans = 0;
		int prev = 0;
		for(int i=1; i<=n; i++)
			if(i==n || (hashSum[i] != hashSum[i-1])) {
				long len = i-prev;
				prev = i;
				ans += (len*len-len)/2;
			}
		Arrays.fill(hashSum, 0);
		for(int i=0; i<n; i++)
			for(int j=0; j<k; j++)
				hashSum[i] += hashes[i][j] + pow[i][j];
		Arrays.sort(hashSum);
		prev = 0;
		for(int i=1; i<=n; i++)
			if(i==n || (hashSum[i] != hashSum[i-1])) {
				long len = i-prev;
				prev = i;
				ans += (len*len-len)/2;
			}
		System.out.println(ans);
	}
	static class FastScanner {
		BufferedReader br;
		StringTokenizer st;

		FastScanner(InputStream in) throws Exception{
			br = new BufferedReader(new InputStreamReader(in));
			st = new StringTokenizer(br.readLine().trim());
		}
		public int numTokens() throws Exception {
			if(!st.hasMoreTokens()) {
				st = new StringTokenizer(br.readLine().trim());
				return numTokens();
			}
			return st.countTokens();
		}
		public String next() throws Exception {
			if(!st.hasMoreTokens()) {
				st = new StringTokenizer(br.readLine().trim());
				return next();
			}
			return st.nextToken();
		}
		public double nextDouble() throws Exception {
			return Double.parseDouble(next());
		}
		public long nextLong() throws Exception {
			return Long.parseLong(next());
		}
		public int nextInt() throws Exception {
			return Integer.parseInt(next());
		}
	}
}


import java.io.*;
import java.util.*;

public class cf154c {
	public static void main(String[] args) throws Exception {
		FastScanner in = new FastScanner(System.in);
		int n = in.nextInt();
		int m = in.nextInt();
		int[] bases = new int[]{31,37,41,43,47,51,53};
		int k = bases.length;
		long[][] pow = new long[k][n];
		for(int i=0; i<k; i++) {
			pow[i][0] = 1;
			for(int j=1; j<n; j++)
				pow[i][j] = pow[i][j-1]*bases[i];
		}
		long[][] hashes = new long[k][n];
		for(int i=0; i<m; i++) {
			int a = in.nextInt()-1;
			int b = in.nextInt()-1;
			for(int j=0; j<k; j++) {
				hashes[j][a] += pow[j][b];
				hashes[j][b] += pow[j][a];
			}
		}
		long[] hashSum = new long[n];
		for(int i=0; i<n; i++)
			for(int j=0; j<k; j++)
				hashSum[i] += hashes[j][i];
		Arrays.sort(hashSum);
		long ans = 0;
		int prev = 0;
		for(int i=1; i<=n; i++)
			if(i==n || (hashSum[i] != hashSum[i-1])) {
				long len = i-prev;
				prev = i;
				ans += (len*len-len)/2;
			}
		Arrays.fill(hashSum, 0);
		for(int i=0; i<n; i++)
			for(int j=0; j<k; j++)
				hashSum[i] += hashes[j][i] + pow[j][i];
		Arrays.sort(hashSum);
		prev = 0;
		for(int i=1; i<=n; i++)
			if(i==n || (hashSum[i] != hashSum[i-1])) {
				long len = i-prev;
				prev = i;
				ans += (len*len-len)/2;
			}
		System.out.println(ans);
	}
	static class FastScanner {
		BufferedReader br;
		StringTokenizer st;

		FastScanner(InputStream in) throws Exception{
			br = new BufferedReader(new InputStreamReader(in));
			st = new StringTokenizer(br.readLine().trim());
		}
		public int numTokens() throws Exception {
			if(!st.hasMoreTokens()) {
				st = new StringTokenizer(br.readLine().trim());
				return numTokens();
			}
			return st.countTokens();
		}
		public String next() throws Exception {
			if(!st.hasMoreTokens()) {
				st = new StringTokenizer(br.readLine().trim());
				return next();
			}
			return st.nextToken();
		}
		public double nextDouble() throws Exception {
			return Double.parseDouble(next());
		}
		public long nextLong() throws Exception {
			return Long.parseLong(next());
		}
		public int nextInt() throws Exception {
			return Integer.parseInt(next());
		}
	}
}


import java.io.*;
import java.util.*;

public class cf154c {
	public static void main(String[] args) throws Exception {
		FastScanner in = new FastScanner(System.in);
		int n = in.nextInt();
		int m = in.nextInt();
		int[] bases = new int[]{31,37,41,43,47,51,53,57};
		int k = bases.length;
		long[][] pow = new long[n][k];
		for(int i=0; i<k; i++) {
			pow[0][i] = 1;
			for(int j=1; j<n; j++)
				pow[j][i] = pow[j-1][i]*bases[i];
		}
		long[][] hashes = new long[n][k];
		for(int i=0; i<m; i++) {
			int a = in.nextInt()-1;
			int b = in.nextInt()-1;
			for(int j=0; j<k; j++) {
				hashes[a][j] += pow[b][j];
				hashes[b][j] += pow[a][j];
			}
		}
		long[] hashSum = new long[n];
		for(int i=0; i<n; i++)
			for(int j=0; j<k; j++)
				hashSum[i] += hashes[i][j];
		Arrays.sort(hashSum);
		long ans = 0;
		int prev = 0;
		for(int i=1; i<=n; i++)
			if(i==n || (hashSum[i] != hashSum[i-1])) {
				int len = i-prev;
				prev = i;
				ans += (len*len-len)/2;
			}
		Arrays.fill(hashSum, 0);
		for(int i=0; i<n; i++)
			for(int j=0; j<k; j++)
				hashSum[i] += hashes[i][j] + pow[i][j];
		Arrays.sort(hashSum);
		prev = 0;
		for(int i=1; i<=n; i++)
			if(i==n || (hashSum[i] != hashSum[i-1])) {
				int len = i-prev;
				prev = i;
				ans += (len*len-len)/2;
			}
		System.out.println(ans);
	}
	static class FastScanner {
		BufferedReader br;
		StringTokenizer st;

		FastScanner(InputStream in) throws Exception{
			br = new BufferedReader(new InputStreamReader(in));
			st = new StringTokenizer(br.readLine().trim());
		}
		public int numTokens() throws Exception {
			if(!st.hasMoreTokens()) {
				st = new StringTokenizer(br.readLine().trim());
				return numTokens();
			}
			return st.countTokens();
		}
		public String next() throws Exception {
			if(!st.hasMoreTokens()) {
				st = new StringTokenizer(br.readLine().trim());
				return next();
			}
			return st.nextToken();
		}
		public double nextDouble() throws Exception {
			return Double.parseDouble(next());
		}
		public long nextLong() throws Exception {
			return Long.parseLong(next());
		}
		public int nextInt() throws Exception {
			return Integer.parseInt(next());
		}
	}
}


import java.io.*;
import java.util.*;

public class cf154c {
	public static void main(String[] args) throws Exception {
		FastScanner in = new FastScanner(System.in);
		int n = in.nextInt();
		int m = in.nextInt();
		int[] bases = new int[]{31,37,41,43,47,51,53,57};
		int k = bases.length;
		long[][] pow = new long[n][k];
		for(int i=0; i<k; i++) {
			pow[0][i] = 1;
			for(int j=1; j<n; j++)
				pow[j][i] = pow[j-1][i]*bases[i];
		}
		long[][] hashes = new long[n][k];
		for(int i=0; i<m; i++) {
			int a = in.nextInt()-1;
			int b = in.nextInt()-1;
			for(int j=0; j<k; j++) {
				hashes[a][j] += pow[b][j];
				hashes[b][j] += pow[a][j];
			}
		}
		long[] hashSum = new long[n];
		for(int i=0; i<n; i++)
			for(int j=0; j<k; j++)
				hashSum[i] += hashes[i][j];
		Arrays.sort(hashSum);
		long ans = 0;
		int prev = 0;
		for(int i=1; i<=n; i++)
			if(i==n || (hashSum[i] != hashSum[i-1])) {
				long len = i-prev;
				prev = i;
				ans += (len*len-len)/2;
			}
		Arrays.fill(hashSum, 0);
		for(int i=0; i<n; i++)
			for(int j=0; j<k; j++)
				hashSum[i] += hashes[i][j] + pow[i][j];
		Arrays.sort(hashSum);
		prev = 0;
		for(int i=1; i<=n; i++)
			if(i==n || (hashSum[i] != hashSum[i-1])) {
				long len = i-prev;
				prev = i;
				ans += (len*len-len)/2;
			}
		System.out.println(ans);
	}
	static class FastScanner {
		BufferedReader br;
		StringTokenizer st;

		FastScanner(InputStream in) throws Exception{
			br = new BufferedReader(new InputStreamReader(in));
			st = new StringTokenizer(br.readLine().trim());
		}
		public int numTokens() throws Exception {
			if(!st.hasMoreTokens()) {
				st = new StringTokenizer(br.readLine().trim());
				return numTokens();
			}
			return st.countTokens();
		}
		public String next() throws Exception {
			if(!st.hasMoreTokens()) {
				st = new StringTokenizer(br.readLine().trim());
				return next();
			}
			return st.nextToken();
		}
		public double nextDouble() throws Exception {
			return Double.parseDouble(next());
		}
		public long nextLong() throws Exception {
			return Long.parseLong(next());
		}
		public int nextInt() throws Exception {
			return Integer.parseInt(next());
		}
	}
}


import java.io.*;
import java.util.*;

import static java.lang.Math.*;
import static java.util.Arrays.*;
import static java.util.Collections.*;
public class Main{
    public static void main(String[]args){
        InputStream in = System.in;
        PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));
        try{
            //          in = new BufferedInputStream(new FileInputStream(new File("input.txt")));
            //          out = new PrintWriter(new BufferedOutputStream(new FileOutputStream("output.txt")));
        }catch (Exception e) {
        }
        new Main().run(in,out);
        out.flush();
    }
    private void debug(Object...os){
        System.err.println(deepToString(os));
    }

    int M = (int)(1e9+7);

    private void run(InputStream in,PrintWriter out){
        int n=nextInt(in),m=nextInt(in);
        ArrayList<Integer>[] es = new ArrayList[n];
        for (int i = 0; i < n; i++) {
            es[i] = new ArrayList<Integer>();
        }
        for (int i = 0; i < m; i++) {
            int s=nextInt(in)-1,t=nextInt(in)-1;
            es[s].add(t);
            es[t].add(s);
        }
        long[] val = new long[n];
        for (int i = 0; i < n; i++) {
            val[i] = i==0 ? 1 : val[i-1] * M;
        }
        long res = 0;
        for(int k=0;k<2;k++){
            long[] hash=new long[n];
            for (int i = 0; i < n; i++) {
                for(int j : es[i]){
                    hash[i] += val[j];
                }
                if(k==1)hash[i] += val[i];
            }
            sort(hash);
            for(int i=0;i<hash.length;){
                int j=i;
                while(j<hash.length && hash[i]==hash[j])j++;
                long t = j-i;
                res += t*(t-1)/2;
                i=j;
            }
        }
        out.println(res);
    }

    private String nextLine(InputStream in) {
        try {
            StringBuilder res = new StringBuilder("");
            int c = in.read();
            if(c==-1)return null;
            while (c=='\n' || c=='\r'){
                c = in.read();
                if(c==-1)return null;
            }
            do {
                res.append((char) c);
                c=in.read();
            } while (c!='\n' && c!='\r');
            return res.toString();
        } catch (Exception e) {
            return null;
        }
    }

    private String next(InputStream in) {
        try {
            StringBuilder res = new StringBuilder("");
            int c = in.read();
            if(c==-1)return null;
            while (Character.isWhitespace(c)){
                c = in.read();
                if(c==-1)return null;
            }
            do {
                res.append((char) c);
            } while (!Character.isWhitespace(c = in.read()));
            return res.toString();
        } catch (Exception e) {
            return null;
        }
    }

    private int nextInt(InputStream in){
        try{
            int c=in.read();
            if(c==-1) return c;
            while(c!='-'&&(c<'0'||'9'<c)){
                c=in.read();
                if(c==-1) return c;
            }
            if(c=='-') return -nextInt(in);
            int res=0;
            do{
                res*=10;
                res+=c-'0';
                c=in.read();
            }while('0'<=c&&c<='9');
            return res;
        }catch(Exception e){
            return -1;
        }
    }

    private long nextLong(InputStream in){
        try{
            int c=in.read();
            if(c==-1) return c;
            while(c!='-'&&(c<'0'||'9'<c)){
                c=in.read();
                if(c==-1) return c;
            }
            if(c=='-') return -nextLong(in);
            long res=0;
            do{
                res*=10;
                res+=c-'0';
                c=in.read();
            }while('0'<=c&&c<='9');
            return res;
        }catch(Exception e){
            return -1;
        }
    }
}


import java.io.*;
import java.util.*;

import static java.lang.Math.*;
import static java.util.Arrays.*;
import static java.util.Collections.*;
public class Main{
	public static void main(String[]args){
		InputStream in = System.in;
		PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));
		try{
//			in = new BufferedInputStream(new FileInputStream(new File("input.txt")));
//			out = new PrintWriter(new BufferedOutputStream(new FileOutputStream("output.txt")));
		}catch (Exception e) {
		}
		new Main().run(in,out);
		out.flush();
	}
	private void debug(Object...os){
		System.err.println(deepToString(os));
	}

	private void run(InputStream in,PrintWriter out){
		int n=nextInt(in),m=nextInt(in);
		ArrayList<Integer>[] es=new ArrayList[n];
		for (int i = 0; i < n; i++) {
			es[i]=new ArrayList<Integer>();
		}
		for (int i = 0; i < m; i++) {
			int a=nextInt(in),b=nextInt(in);
			es[a-1].add(b-1);
			es[b-1].add(a-1);
		}
		HashMap<ArrayList<Integer>, Integer> map=new HashMap<ArrayList<Integer>, Integer>();
		for (int i = 0; i < n; i++) {
			ArrayList<Integer> list=new ArrayList<Integer>(es[i]);
			list.add(i);
			sort(list);
			sort(es[i]);
			Integer v = map.get(list);
			if(v==null)map.put(list,1);
			else map.put(list,v+1);
			list=es[i];
			v = map.get(list);
			if(v==null)map.put(list,1);
			else map.put(list,v+1);
		}
		long res = 0;
		for(int v : map.values()){
			res += (long)v*(v-1)/2;
		}
		out.println(res);
	}

	private int[] tois(Integer[] Is) {
		int[]is=new int[Is.length];
		for (int i = 0; i < is.length; i++) {
			is[i]=Is[i];
		}
		return is;
	}
	private String nextLine(InputStream in) {
		try {
			StringBuilder res = new StringBuilder("");
			int c = in.read();
			if(c==-1)return null;
			while (c=='\n' || c=='\r'){
				c = in.read();
				if(c==-1)return null;
			}
			do {
				res.append((char) c);
				c=in.read();
			} while (c!='\n' && c!='\r');
			return res.toString();
		} catch (Exception e) {
			return null;
		}
	}

	private String next(InputStream in) {
		try {
			StringBuilder res = new StringBuilder("");
			int c = in.read();
			if(c==-1)return null;
			while (Character.isWhitespace(c)){
				c = in.read();
				if(c==-1)return null;
			}
			do {
				res.append((char) c);
			} while (!Character.isWhitespace(c = in.read()));
			return res.toString();
		} catch (Exception e) {
			return null;
		}
	}

	private int nextInt(InputStream in){
		try{
			int c=in.read();
			if(c==-1) return c;
			while(c!='-'&&(c<'0'||'9'<c)){
				c=in.read();
				if(c==-1) return c;
			}
			if(c=='-') return -nextInt(in);
			int res=0;
			do{
				res*=10;
				res+=c-'0';
				c=in.read();
			}while('0'<=c&&c<='9');
			return res;
		}catch(Exception e){
			return -1;
		}
	}

	private long nextLong(InputStream in){
		try{
			int c=in.read();
			if(c==-1) return c;
			while(c!='-'&&(c<'0'||'9'<c)){
				c=in.read();
				if(c==-1) return c;
			}
			if(c=='-') return -nextLong(in);
			long res=0;
			do{
				res*=10;
				res+=c-'0';
				c=in.read();
			}while('0'<=c&&c<='9');
			return res;
		}catch(Exception e){
			return -1;
		}
	}
}


import java.io.*;
import java.util.*;

import static java.lang.Math.*;
import static java.util.Arrays.*;
import static java.util.Collections.*;
public class Main{
    public static void main(String[]args){
        InputStream in = System.in;
        PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));
        try{
            //          in = new BufferedInputStream(new FileInputStream(new File("input.txt")));
            //          out = new PrintWriter(new BufferedOutputStream(new FileOutputStream("output.txt")));
        }catch (Exception e) {
        }
        new Main().run(in,out);
        out.flush();
    }
    private void debug(Object...os){
        System.err.println(deepToString(os));
    }

    int M = (int)(1e9+7);

    private void run(InputStream in,PrintWriter out){
        int n=nextInt(in),m=nextInt(in);
        int[] ss=new int[m];
        int[] ts=new int[m];
        int[] cnt=new int[n];
        for (int i = 0; i < m; i++) {
            ss[i] = nextInt(in)-1;
            ts[i] = nextInt(in)-1;
            cnt[ss[i]]++;
            cnt[ts[i]]++;
        }
        int[][] es=new int[n][];
        for (int i = 0; i < n; i++) {
            es[i] = new int[cnt[i]];
            cnt[i] = 0;
        }
        for (int i = 0; i < m; i++) {
            es[ss[i]][cnt[ss[i]]++] = ts[i];
            es[ts[i]][cnt[ts[i]]++] = ss[i];
        }
        long[] val=new long[n];
        for (int i = 0; i < n; i++) {
            val[i] = i==0 ? 1 : val[i-1]*M;
        }
        long res = 0;
        for(int k=0;k<2;k++){
            long[] hash=new long[n];
            for (int i = 0; i < n; i++) {
                for(int j : es[i]){
                    hash[i] += val[j];
                }
                if(k==1)hash[i] += val[i];
            }
            sort(hash);
            for(int i=0;i<hash.length;){
                int j=i;
                while(j<hash.length && hash[i]==hash[j])j++;
                long t = j-i;
                res += t*(t-1)/2;
                i=j;
            }
        }
        out.println(res);
    }

    private String nextLine(InputStream in) {
        try {
            StringBuilder res = new StringBuilder("");
            int c = in.read();
            if(c==-1)return null;
            while (c=='\n' || c=='\r'){
                c = in.read();
                if(c==-1)return null;
            }
            do {
                res.append((char) c);
                c=in.read();
            } while (c!='\n' && c!='\r');
            return res.toString();
        } catch (Exception e) {
            return null;
        }
    }

    private String next(InputStream in) {
        try {
            StringBuilder res = new StringBuilder("");
            int c = in.read();
            if(c==-1)return null;
            while (Character.isWhitespace(c)){
                c = in.read();
                if(c==-1)return null;
            }
            do {
                res.append((char) c);
            } while (!Character.isWhitespace(c = in.read()));
            return res.toString();
        } catch (Exception e) {
            return null;
        }
    }

    private int nextInt(InputStream in){
        try{
            int c=in.read();
            if(c==-1) return c;
            while(c!='-'&&(c<'0'||'9'<c)){
                c=in.read();
                if(c==-1) return c;
            }
            if(c=='-') return -nextInt(in);
            int res=0;
            do{
                res*=10;
                res+=c-'0';
                c=in.read();
            }while('0'<=c&&c<='9');
            return res;
        }catch(Exception e){
            return -1;
        }
    }

    private long nextLong(InputStream in){
        try{
            int c=in.read();
            if(c==-1) return c;
            while(c!='-'&&(c<'0'||'9'<c)){
                c=in.read();
                if(c==-1) return c;
            }
            if(c=='-') return -nextLong(in);
            long res=0;
            do{
                res*=10;
                res+=c-'0';
                c=in.read();
            }while('0'<=c&&c<='9');
            return res;
        }catch(Exception e){
            return -1;
        }
    }
}


import java.io.*;
import java.util.*;

import static java.lang.Math.*;
import static java.util.Arrays.*;
import static java.util.Collections.*;
public class Main{
    public static void main(String[]args){
        InputStream in = System.in;
        PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));
        try{
//          in = new BufferedInputStream(new FileInputStream(new File("input.txt")));
//          out = new PrintWriter(new BufferedOutputStream(new FileOutputStream("output.txt")));
        }catch (Exception e) {
        }
        new Main().run(in,out);
        out.flush();
    }
    private void debug(Object...os){
        System.err.println(deepToString(os));
    }

    int M = (int)(1e9+7);

    private void run(InputStream in,PrintWriter out){
        int n=nextInt(in),m=nextInt(in);
        ArrayList<Integer>[] es = new ArrayList[n];
        for (int i = 0; i < n; i++) {
            es[i] = new ArrayList<Integer>();
        }
        for (int i = 0; i < m; i++) {
            int s=nextInt(in)-1,t=nextInt(in)-1;
            es[s].add(t);
            es[t].add(s);
        }
        long[] val = new long[n];
        for (int i = 0; i < n; i++) {
            val[i] = i==0 ? 1 : val[i-1] * M;
        }
        long[] hash=new long[n*2];
        for (int i = 0; i < n; i++) {
            for(int j : es[i]){
                hash[i*2] += val[j];
            }
            hash[i*2+1] = hash[i*2] + val[i];
        }
        sort(hash);
        long res = 0;
        for(int i=0;i<hash.length;){
            int j=i;
            while(j<hash.length && hash[i]==hash[j])j++;
            long t = j-i;
            res += t*(t-1)/2;
            i=j;
        }
        out.println(res);
    }

    private String nextLine(InputStream in) {
        try {
            StringBuilder res = new StringBuilder("");
            int c = in.read();
            if(c==-1)return null;
            while (c=='\n' || c=='\r'){
                c = in.read();
                if(c==-1)return null;
            }
            do {
                res.append((char) c);
                c=in.read();
            } while (c!='\n' && c!='\r');
            return res.toString();
        } catch (Exception e) {
            return null;
        }
    }

    private String next(InputStream in) {
        try {
            StringBuilder res = new StringBuilder("");
            int c = in.read();
            if(c==-1)return null;
            while (Character.isWhitespace(c)){
                c = in.read();
                if(c==-1)return null;
            }
            do {
                res.append((char) c);
            } while (!Character.isWhitespace(c = in.read()));
            return res.toString();
        } catch (Exception e) {
            return null;
        }
    }

    private int nextInt(InputStream in){
        try{
            int c=in.read();
            if(c==-1) return c;
            while(c!='-'&&(c<'0'||'9'<c)){
                c=in.read();
                if(c==-1) return c;
            }
            if(c=='-') return -nextInt(in);
            int res=0;
            do{
                res*=10;
                res+=c-'0';
                c=in.read();
            }while('0'<=c&&c<='9');
            return res;
        }catch(Exception e){
            return -1;
        }
    }

    private long nextLong(InputStream in){
        try{
            int c=in.read();
            if(c==-1) return c;
            while(c!='-'&&(c<'0'||'9'<c)){
                c=in.read();
                if(c==-1) return c;
            }
            if(c=='-') return -nextLong(in);
            long res=0;
            do{
                res*=10;
                res+=c-'0';
                c=in.read();
            }while('0'<=c&&c<='9');
            return res;
        }catch(Exception e){
            return -1;
        }
    }
}


import java.io.*;
import java.util.*;

import static java.lang.Math.*;
import static java.util.Arrays.*;
import static java.util.Collections.*;
public class Main{
    public static void main(String[]args){
        InputStream in = System.in;
        PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));
        try{
//          in = new BufferedInputStream(new FileInputStream(new File("input.txt")));
//          out = new PrintWriter(new BufferedOutputStream(new FileOutputStream("output.txt")));
        }catch (Exception e) {
        }
        new Main().run(in,out);
        out.flush();
    }
    private void debug(Object...os){
        System.err.println(deepToString(os));
    }

    private void run(InputStream in,PrintWriter out){
//      test(out);
//      out.flush();
        int n=nextInt(in),m=nextInt(in);
        ArrayList<Integer>[] es=new ArrayList[n];
        for (int i = 0; i < n; i++) {
            es[i]=new ArrayList<Integer>();
        }
        for (int i = 0; i < m; i++) {
            int a=nextInt(in),b=nextInt(in);
            es[a-1].add(b-1);
            es[b-1].add(a-1);
        }
        solve(n,es,out);
    }
    void test(PrintWriter out){
        long start = System.currentTimeMillis();
        int n=1000000;
        int m=1000000;
//      out.println(n+" "+m);
        ArrayList<Integer>[] es=new ArrayList[n];
        for (int i = 0; i < n; i++) {
            es[i]=new ArrayList<Integer>();
        }
        Random rnd = new Random();
        for (int i = 0; i < m; i++) {
            int to = rnd.nextInt(n);
            int from = rnd.nextInt(n);
//          out.println(from + " "+to);
            es[from].add(to);
            es[to].add(from);
        }
//      System.err.println("hoge");
        solve(n,es,out);
        long time = System.currentTimeMillis()-start;
        System.out.println(time);
//      System.err.println("hgua");
    }

    private void solve(int n,ArrayList<Integer>[] es,PrintWriter out){
        Array[] as = new Array[n*2];
        int t=0;
        for (int i = 0; i < n; i++) {
            int[] is = tois(es[i].toArray(new Integer[0]));
            sort(is);
            es[i].add(i);
            as[t++] = new Array(is);
            is = tois(es[i].toArray(new Integer[0]));
            sort(is);
            as[t++] = new Array(is);
        }
        sort(as);
        long res=0;
        for (int i = 0; i < as.length;) {
            int j=i;
            while(j<as.length && as[i].equals(as[j]))j++;
            long k = j-i;
            res += k*(k-1)/2;
            i=j;
        }
        out.println(res);
    }
    class Array implements Comparable<Array>{
        int[] is;
        Array(int[] is){
            this.is=is;
        }
        @Override
        public int hashCode() {
            return Arrays.hashCode(is);
        }
        @Override
        public boolean equals(Object obj) {
            return Arrays.equals(((Array)obj).is,is);
        }
        public int compareTo(Array o) {
            if(is.length != o.is.length)return is.length - o.is.length;
            for (int i = 0; i < is.length; i++) {
                if(is[i]!=o.is[i])return is[i]-o.is[i];
            }
            return 0;
        }
    }

    private int[] tois(Integer[] Is) {
        int[]is=new int[Is.length];
        for (int i = 0; i < is.length; i++) {
            is[i]=Is[i];
        }
        return is;
    }
    private String nextLine(InputStream in) {
        try {
            StringBuilder res = new StringBuilder("");
            int c = in.read();
            if(c==-1)return null;
            while (c=='\n' || c=='\r'){
                c = in.read();
                if(c==-1)return null;
            }
            do {
                res.append((char) c);
                c=in.read();
            } while (c!='\n' && c!='\r');
            return res.toString();
        } catch (Exception e) {
            return null;
        }
    }

    private String next(InputStream in) {
        try {
            StringBuilder res = new StringBuilder("");
            int c = in.read();
            if(c==-1)return null;
            while (Character.isWhitespace(c)){
                c = in.read();
                if(c==-1)return null;
            }
            do {
                res.append((char) c);
            } while (!Character.isWhitespace(c = in.read()));
            return res.toString();
        } catch (Exception e) {
            return null;
        }
    }

    private int nextInt(InputStream in){
        try{
            int c=in.read();
            if(c==-1) return c;
            while(c!='-'&&(c<'0'||'9'<c)){
                c=in.read();
                if(c==-1) return c;
            }
            if(c=='-') return -nextInt(in);
            int res=0;
            do{
                res*=10;
                res+=c-'0';
                c=in.read();
            }while('0'<=c&&c<='9');
            return res;
        }catch(Exception e){
            return -1;
        }
    }

    private long nextLong(InputStream in){
        try{
            int c=in.read();
            if(c==-1) return c;
            while(c!='-'&&(c<'0'||'9'<c)){
                c=in.read();
                if(c==-1) return c;
            }
            if(c=='-') return -nextLong(in);
            long res=0;
            do{
                res*=10;
                res+=c-'0';
                c=in.read();
            }while('0'<=c&&c<='9');
            return res;
        }catch(Exception e){
            return -1;
        }
    }
}


import java.awt.*;
import java.awt.geom.*;
import java.io.*;
import java.math.*;
import java.text.*;
import java.util.*;
import java.util.Queue;

/*
	br = new BufferedReader(new FileReader("input.txt"));
	pw = new PrintWriter(new BufferedWriter(new FileWriter("output.txt")));
	br = new BufferedReader(new InputStreamReader(System.in));
	pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
 */

public class Main {
	private static BufferedReader br;
	private static StringTokenizer st;
	private static PrintWriter pw;

	static final long HASH = 3137;

	public static void main(String[] args) throws IOException	{
		br = new BufferedReader(new InputStreamReader(System.in));
		pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
		//int qq = 1;
		int qq = Integer.MAX_VALUE;
		//int qq = readInt();
		for(int casenum = 1; casenum <= qq; casenum++)	{
			int n = readInt();
			int m = readInt();
			long[] curr = new long[n];
			while(m-- > 0)	{
				int a = readInt()-1;
				int b = readInt()-1;
				curr[a] += pow(HASH, b);
				curr[b] += pow(HASH, a);
			}
			Map<Long, Integer> map = new HashMap<Long, Integer>();
			for(int i = 0; i < n; i++)	{
				Integer ret = map.get(curr[i]);
				if(ret == null)	{
					ret = 0;
				}
				map.put(curr[i], ++ret);
				curr[i] += pow(HASH, i);
				Integer ret2 = map.get(curr[i]);
				if(ret2 == null)	{
					ret2 = 0;
				}
				map.put(curr[i], ++ret2);
			}
			long ret = 0;
			for(long key: map.keySet())	{
				long a = map.get(key);
				ret += a * (a-1) / 2;
			}
			pw.println(ret);
		}
		pw.close();
	}

	public static long pow(long b, long e)	{
		long r = 1;
		while(e > 0)	{
			if((e&1)==1)	{
				r *= b;
			}
			b *= b;
			e >>= 1;
		}
		return r;
	}

	private static long readLong() throws IOException	{
		return Long.parseLong(nextToken());
	}

	private static double readDouble() throws IOException	{
		return Double.parseDouble(nextToken());
	}

	private static int readInt() throws IOException	{
		return Integer.parseInt(nextToken());
	}

	private static String nextToken() throws IOException	{
		while(st == null || !st.hasMoreTokens())	{
			if(!br.ready())	{
				pw.close();
				System.exit(0);
			}
			st = new StringTokenizer(br.readLine().trim());
		}
		return st.nextToken();
	}
}


import java.awt.*;
import java.awt.geom.*;
import java.io.*;
import java.math.*;
import java.text.*;
import java.util.*;
import java.util.Queue;

/*
	br = new BufferedReader(new FileReader("input.txt"));
	pw = new PrintWriter(new BufferedWriter(new FileWriter("output.txt")));
	br = new BufferedReader(new InputStreamReader(System.in));
	pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
 */

public class Main {
	private static BufferedReader br;
	private static StringTokenizer st;
	private static PrintWriter pw;

	static final long HASH = 3137;

	public static void main(String[] args) throws IOException	{
		br = new BufferedReader(new InputStreamReader(System.in));
		pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
		//int qq = 1;
		int qq = Integer.MAX_VALUE;
		//int qq = readInt();
		for(int casenum = 1; casenum <= qq; casenum++)	{
			int n = readInt();
			int m = readInt();
			LinkedList<Integer>[] edges = new LinkedList[n];
			for(int i = 0; i < n; i++)	{
				edges[i] = new LinkedList<Integer>();
			}
			while(m-- > 0)	{
				int a = readInt()-1;
				int b = readInt()-1;
				edges[a].add(b);
				edges[b].add(a);
			}
			Map<Long, Integer> map = new HashMap<Long, Integer>();
			for(int i = 0; i < n; i++)	{
				LinkedList<Integer> out = edges[i];
				long curr = 0;
				for(int out2: out)	{
					curr += pow(HASH, out2);
				}
				Integer ret = map.get(curr);
				if(ret == null)	{
					ret = 0;
				}
				map.put(curr, ++ret);
				curr += pow(HASH, i);
				Integer ret2 = map.get(curr);
				if(ret2 == null)	{
					ret2 = 0;
				}
				map.put(curr, ++ret2);
			}
			long ret = 0;
			for(long key: map.keySet())	{
				long a = map.get(key);
				ret += a * (a-1) / 2;
			}
			pw.println(ret);
		}
		pw.close();
	}

	public static long pow(long b, long e)	{
		long r = 1;
		while(e > 0)	{
			if((e&1)==1)	{
				r *= b;
			}
			b *= b;
			e >>= 1;
		}
		return r;
	}

	private static long readLong() throws IOException	{
		return Long.parseLong(nextToken());
	}

	private static double readDouble() throws IOException	{
		return Double.parseDouble(nextToken());
	}

	private static int readInt() throws IOException	{
		return Integer.parseInt(nextToken());
	}

	private static String nextToken() throws IOException	{
		while(st == null || !st.hasMoreTokens())	{
			if(!br.ready())	{
				pw.close();
				System.exit(0);
			}
			st = new StringTokenizer(br.readLine().trim());
		}
		return st.nextToken();
	}
}


import java.awt.*;
import java.awt.geom.*;
import java.io.*;
import java.math.*;
import java.text.*;
import java.util.*;
import java.util.Queue;

/*
	br = new BufferedReader(new FileReader("input.txt"));
	pw = new PrintWriter(new BufferedWriter(new FileWriter("output.txt")));
	br = new BufferedReader(new InputStreamReader(System.in));
	pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
 */

public class Main {
	private static BufferedReader br;
	private static StringTokenizer st;
	private static PrintWriter pw;

	public static void main(String[] args) throws IOException	{
		br = new BufferedReader(new InputStreamReader(System.in));
		pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
		//int qq = 1;
		int qq = Integer.MAX_VALUE;
		//int qq = readInt();
		long[] pow = new long[1000005];
		final long HASH = 3137;
		pow[0] = 1;
		for(int i = 1; i < pow.length; i++)	{
			pow[i] = pow[i-1] * HASH;
		}
		for(int casenum = 1; casenum <= qq; casenum++)	{
			int n = readInt();
			int m = readInt();
			LinkedList<Integer>[] edges = new LinkedList[n];
			for(int i = 0; i < n; i++)	{
				edges[i] = new LinkedList<Integer>();
			}
			while(m-- > 0)	{
				int a = readInt()-1;
				int b = readInt()-1;
				edges[a].add(b);
				edges[b].add(a);
			}
			HashMap<Long, Integer> map = new HashMap<Long, Integer>();
			for(int i = 0; i < n; i++)	{
				LinkedList<Integer> out = edges[i];
				long curr = 0;
				for(int out2: out)	{
					curr += pow[out2];
				}
				Integer ret = map.get(curr);
				if(ret == null)	{
					ret = 0;
				}
				map.put(curr, ++ret);
				curr += pow[i];
				Integer ret2 = map.get(curr);
				if(ret2 == null)	{
					ret2 = 0;
				}
				map.put(curr, ++ret2);
			}
			long ret = 0;
			for(long key: map.keySet())	{
				long a = map.get(key);
				ret += a * (a-1) / 2;
			}
			pw.println(ret);
		}
		pw.close();
	}

	private static long readLong() throws IOException	{
		return Long.parseLong(nextToken());
	}

	private static double readDouble() throws IOException	{
		return Double.parseDouble(nextToken());
	}

	private static int readInt() throws IOException	{
		return Integer.parseInt(nextToken());
	}

	private static String nextToken() throws IOException	{
		while(st == null || !st.hasMoreTokens())	{
			if(!br.ready())	{
				pw.close();
				System.exit(0);
			}
			st = new StringTokenizer(br.readLine().trim());
		}
		return st.nextToken();
	}
}


import java.awt.*;
import java.awt.geom.*;
import java.io.*;
import java.math.*;
import java.text.*;
import java.util.*;
import java.util.Queue;

/*
	br = new BufferedReader(new FileReader("input.txt"));
	pw = new PrintWriter(new BufferedWriter(new FileWriter("output.txt")));
	br = new BufferedReader(new InputStreamReader(System.in));
	pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
 */

public class Main {
	private static BufferedReader br;
	private static StringTokenizer st;
	private static PrintWriter pw;

	public static void main(String[] args) throws IOException	{
		br = new BufferedReader(new InputStreamReader(System.in));
		pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
		//int qq = 1;
		int qq = Integer.MAX_VALUE;
		//int qq = readInt();
		long[] pow = new long[1000005];
		final long HASH = 3137;
		pow[0] = 1;
		for(int i = 1; i < pow.length; i++)	{
			pow[i] = pow[i-1] * HASH;
		}
		for(int casenum = 1; casenum <= qq; casenum++)	{
			int n = readInt();
			int m = readInt();
			LinkedList<Integer>[] edges = new LinkedList[n];
			for(int i = 0; i < n; i++)	{
				edges[i] = new LinkedList<Integer>();
			}
			while(m-- > 0)	{
				int a = readInt()-1;
				int b = readInt()-1;
				edges[a].add(b);
				edges[b].add(a);
			}
			Map<Long, Integer> map = new TreeMap<Long, Integer>();
			for(int i = 0; i < n; i++)	{
				LinkedList<Integer> out = edges[i];
				long curr = 0;
				for(int out2: out)	{
					curr += pow[out2];
				}
				Integer ret = map.get(curr);
				if(ret == null)	{
					ret = 0;
				}
				map.put(curr, ++ret);
				curr += pow[i];
				Integer ret2 = map.get(curr);
				if(ret2 == null)	{
					ret2 = 0;
				}
				map.put(curr, ++ret2);
			}
			long ret = 0;
			for(long key: map.keySet())	{
				long a = map.get(key);
				ret += a * (a-1) / 2;
			}
			pw.println(ret);
		}
		pw.close();
	}

	private static long readLong() throws IOException	{
		return Long.parseLong(nextToken());
	}

	private static double readDouble() throws IOException	{
		return Double.parseDouble(nextToken());
	}

	private static int readInt() throws IOException	{
		return Integer.parseInt(nextToken());
	}

	private static String nextToken() throws IOException	{
		while(st == null || !st.hasMoreTokens())	{
			if(!br.ready())	{
				pw.close();
				System.exit(0);
			}
			st = new StringTokenizer(br.readLine().trim());
		}
		return st.nextToken();
	}
}


import java.awt.*;
import java.awt.geom.*;
import java.io.*;
import java.math.*;
import java.text.*;
import java.util.*;
import java.util.Queue;

/*
	br = new BufferedReader(new FileReader("input.txt"));
	pw = new PrintWriter(new BufferedWriter(new FileWriter("output.txt")));
	br = new BufferedReader(new InputStreamReader(System.in));
	pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
 */

public class Main {
	private static BufferedReader br;
	private static StringTokenizer st;
	private static PrintWriter pw;

	static final long HASH = 3137;

	public static void main(String[] args) throws IOException	{
		br = new BufferedReader(new InputStreamReader(System.in));
		pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
		//int qq = 1;
		int qq = Integer.MAX_VALUE;
		//int qq = readInt();
		for(int casenum = 1; casenum <= qq; casenum++)	{
			int n = readInt();
			int m = readInt();
			long[] curr = new long[2*n];
			while(m-- > 0)	{
				int a = readInt()-1;
				int b = readInt()-1;
				curr[a] += pow(HASH, b);
				curr[b] += pow(HASH, a);
			}
			for(int i = 0; i < n; i++)	{
				curr[i+n] = curr[i] + pow(HASH, i);
			}
			Arrays.sort(curr);
			long ret = 0;
			for(int i = 0; i < curr.length;)	{
				int j = i+1;
				while(j < curr.length && curr[i] == curr[j])	{
					j++;
				}
				long diff = j-i;
				ret += diff * (diff-1) / 2;
				i = j;
			}
			pw.println(ret);
		}
		pw.close();
	}

	public static long pow(long b, long e)	{
		long r = 1;
		while(e > 0)	{
			if((e&1)==1)	{
				r *= b;
			}
			b *= b;
			e >>= 1;
		}
		return r;
	}

	private static long readLong() throws IOException	{
		return Long.parseLong(nextToken());
	}

	private static double readDouble() throws IOException	{
		return Double.parseDouble(nextToken());
	}

	private static int readInt() throws IOException	{
		return Integer.parseInt(nextToken());
	}

	private static String nextToken() throws IOException	{
		while(st == null || !st.hasMoreTokens())	{
			if(!br.ready())	{
				pw.close();
				System.exit(0);
			}
			st = new StringTokenizer(br.readLine().trim());
		}
		return st.nextToken();
	}
}


import java.util.*;
import java.io.*;
import java.lang.reflect.Array;
import java.math.*;

public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		/*try {
			inputStream = new FileInputStream("input.txt");
			outputStream = new FileOutputStream("output.txt");
		} catch (FileNotFoundException e) {
			System.err.println("File not found");
			return;
		}*/

		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		Solver solver = new Solver();
		solver.solve(in, out);
		out.close();
	}
}

class Solver {
	public static final int MAXN = 1000001;
	public static final long P = 1011001;
	public void solve(InputReader in, PrintWriter out) {
		int n = in.nextInt();
		int m = in.nextInt();
		int e[][] = new int[m][2];
		//ArrayList<Integer>[] r = new ArrayList[n];
		int[][] r = new int[n][];
		int[] cr = new int[n];
		long p[] = new long[MAXN];
		p[0] = 1;
		for (int i = 1; i < MAXN; i++) {
			p[i] = p[i - 1] * P;
		}

		long[][] h = new long[n][];
		long h1[] = new long[n];
		long h2[] = new long[n];
		for (int i = 0; i < m; i++) {
			int v = in.nextInt();
			int u = in.nextInt();
			v--;
			u--;
			e[i][0] = v;
			e[i][1] = u;
			cr[v]++;
			cr[u]++;
			h1[v] += p[u];
			h1[u] += p[v];
		}

		for (int i = 0; i < n; i++) {
			h2[i] = h1[i] + p[i];
		}
		Arrays.sort(h1);
		Arrays.sort(h2);
		long cur1 = 1;
		long ans1 = 0;
		for (int i = 1; i < n; i++) {
			if (h1[i] == h1[i - 1]) {
				cur1++;
			} else {
				ans1 += cur1 * (cur1 - 1) / 2;
				cur1 = 1;
			}
		}
		ans1 += cur1 * (cur1 - 1) / 2;
		cur1 = 1;
		for (int i = 1; i < n; i++) {
			if (h2[i] == h2[i - 1]) {
				cur1++;
			} else {
				ans1 += cur1 * (cur1 - 1) / 2;
				cur1 = 1;
			}
		}
		ans1 += cur1 * (cur1 - 1) / 2;
		out.println(ans1);

		for (int i = 0; i < n; i++) {
			r[i] = new int[cr[i]];
			cr[i] = 0;
		}
		for (int i = 0; i < m; i++) {
			int v = e[i][0];
			int u = e[i][1];
			r[v][cr[v]++] = u;
			r[u][cr[u]++] = v;
		}

		long[] a = new long[n];

		for (int i = 0; i < n; i++) {
			Arrays.sort(r[i]);
			h[i] = new long[r[i].length];
			if (r[i].length == 0)
				continue;
			h[i][0] = r[i][0] + 1;
			for (int j = 1; j < r[i].length; j++) {
				h[i][j] = h[i][j - 1] * P + r[i][j] + 1;
			}
			a[i] = h[i][r[i].length - 1];
		}
		Arrays.sort(a);
		long ans = 0;
		long cur = 1;
		for (int i = 1; i < n; i++) {
			if (a[i] == a[i - 1]) {
				cur++;
			} else {
				ans += cur * (cur - 1) / 2;
				cur = 1;
			}
		}
		ans += cur * (cur - 1) / 2;

		//int v, u, p1, p2, t, c;
		//boolean ind;
		if (m > 0) {
			int v = e[m - 1][0];
			int u = e[m - 1][1];
		}

		/*
		int v, i;
		for (i = 0; i < m; i++) {
			v = e[i][0];
			u = e[i][1];
		}
		*/
		//out.println(ans);
	}
}

class InputReader {
	private BufferedReader reader;
	private StringTokenizer tokenizer;

	public InputReader(InputStream stream) {
		reader = new BufferedReader(new InputStreamReader(stream));
		tokenizer = null;
	}

	public String next() {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			try {
				tokenizer = new StringTokenizer(reader.readLine());
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		return tokenizer.nextToken();
	}

	public long nextLong() {
		return Long.parseLong(next());
	}

	public int nextInt() {
		return Integer.parseInt(next());
	}

	public double nextDouble() {
		return Double.parseDouble(next());
	}
}


import java.util.*;
import java.io.*;
import java.lang.reflect.Array;
import java.math.*;

public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		/*try {
			inputStream = new FileInputStream("input.txt");
			outputStream = new FileOutputStream("output.txt");
		} catch (FileNotFoundException e) {
			System.err.println("File not found");
			return;
		}*/

		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		Solver solver = new Solver();
		solver.solve(in, out);
		out.close();
	}
}

class Solver {
	public static final int MAXN = 1000001;
	public static final long P = 1011001;
	public void solve(InputReader in, PrintWriter out) {
		int n = in.nextInt();
		int m = in.nextInt();
		int e[][] = new int[m][2];
		//ArrayList<Integer>[] r = new ArrayList[n];
		int[][] r = new int[n][];
		int[] cr = new int[n];
		long p[] = new long[MAXN];
		p[0] = 1;
		for (int i = 1; i < MAXN; i++) {
			p[i] = p[i - 1] * P;
		}
		long[][] h = new long[n][];

		for (int i = 0; i < m; i++) {
			int v = in.nextInt();
			int u = in.nextInt();
			v--;
			u--;
			e[i][0] = v;
			e[i][1] = u;
			cr[v]++;
			cr[u]++;
		}
		for (int i = 0; i < n; i++) {
			r[i] = new int[cr[i]];
			cr[i] = 0;
		}
		for (int i = 0; i < m; i++) {
			int v = e[i][0];
			int u = e[i][1];
			r[v][cr[v]++] = u;
			r[u][cr[u]++] = v;
		}

		long[] a = new long[n];

		for (int i = 0; i < n; i++) {
			Arrays.sort(r[i]);
			h[i] = new long[r[i].length];
			if (r[i].length == 0)
				continue;
			h[i][0] = r[i][0] + 1;
			for (int j = 1; j < r[i].length; j++) {
				h[i][j] = h[i][j - 1] * P + r[i][j] + 1;
			}
			a[i] = h[i][r[i].length - 1];
		}
		Arrays.sort(a);
		long ans = 0;
		long cur = 1;
		for (int i = 1; i < n; i++) {
			if (a[i] == a[i - 1]) {
				cur++;
			} else {
				ans += cur * (cur - 1) / 2;
				cur = 1;
			}
		}
		ans += cur * (cur - 1) / 2;

		for (int i = 0; i < m; i++) {
			int v = e[i][0];
			int u = e[i][1];
			int p1 = Arrays.binarySearch(r[v], u);
			int p2 = Arrays.binarySearch(r[u], v);
			if (p1 > p2) {
				int t = v;
				v = u;
				u = t;
				t = p1;
				p1 = p2;
				p2 = t;
			}
			int c = r[v].length;
			if (r[v].length == r[u].length) {
				boolean ind = true;
				if (p1 > 0) {
					ind = ind && (h[v][p1 - 1] == h[u][p1 - 1]);
				}
				ind = ind && (h[v][c - 1] - h[v][p2] * p[c - 1 - p2] == h[u][c - 1] - h[u][p2] * p[c - 1 - p2]);
				ind = ind && (h[v][p2] - h[v][p1] * p[p2 - p1] == ((p2 > 0)?(h[u][p2 - 1]):(0)) - ((p1 > 0)?(h[u][p1 - 1]):(0)) * p[p2 - p1]);
				if (ind)
					ans++;
			}
		}
		out.println(ans);
	}
}

class InputReader {
	private BufferedReader reader;
	private StringTokenizer tokenizer;

	public InputReader(InputStream stream) {
		reader = new BufferedReader(new InputStreamReader(stream));
		tokenizer = null;
	}

	public String next() {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			try {
				tokenizer = new StringTokenizer(reader.readLine());
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		return tokenizer.nextToken();
	}

	public long nextLong() {
		return Long.parseLong(next());
	}

	public int nextInt() {
		return Integer.parseInt(next());
	}

	public double nextDouble() {
		return Double.parseDouble(next());
	}
}


import java.util.*;
import java.io.*;
import java.lang.reflect.Array;
import java.math.*;

public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		/*try {
			inputStream = new FileInputStream("input.txt");
			outputStream = new FileOutputStream("output.txt");
		} catch (FileNotFoundException e) {
			System.err.println("File not found");
			return;
		}*/

		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		Solver solver = new Solver();
		solver.solve(in, out);
		out.close();
	}
}

class Solver {
	public static final int MAXN = 1000001;
	public static final long P = 1011001;
	public void solve(InputReader in, PrintWriter out) {
		int n = in.nextInt();
		int m = in.nextInt();
		int e[][] = new int[m][2];
		//ArrayList<Integer>[] r = new ArrayList[n];
		int[][] r = new int[n][];
		int[] cr = new int[n];
		long p[] = new long[MAXN];
		p[0] = 1;
		for (int i = 1; i < MAXN; i++) {
			p[i] = p[i - 1] * P;
		}

		long[][] h = new long[n][];
		long h1[] = new long[n];
		long h2[] = new long[n];
		for (int i = 0; i < m; i++) {
			int v = in.nextInt();
			int u = in.nextInt();
			v--;
			u--;
			e[i][0] = v;
			e[i][1] = u;
			cr[v]++;
			cr[u]++;
			h1[v] += p[u];
			h1[u] += p[v];
		}

		for (int i = 0; i < n; i++) {
			h2[i] = h1[i] + p[i];
		}
		Arrays.sort(h1);
		Arrays.sort(h2);
		long cur1 = 1;
		long ans1 = 0;
		for (int i = 1; i < n; i++) {
			if (h1[i] == h1[i - 1]) {
				cur1++;
			} else {
				ans1 += cur1 * (cur1 - 1) / 2;
				cur1 = 1;
			}
		}
		ans1 += cur1 * (cur1 - 1) / 2;
		cur1 = 1;
		for (int i = 1; i < n; i++) {
			if (h2[i] == h2[i - 1]) {
				cur1++;
			} else {
				ans1 += cur1 * (cur1 - 1) / 2;
				cur1 = 1;
			}
		}
		ans1 += cur1 * (cur1 - 1) / 2;
		out.println(ans1);

		for (int i = 0; i < n; i++) {
			r[i] = new int[cr[i]];
			cr[i] = 0;
		}
		for (int i = 0; i < m; i++) {
			int v = e[i][0];
			int u = e[i][1];
			r[v][cr[v]++] = u;
			r[u][cr[u]++] = v;
		}

		long[] a = new long[n];

		for (int i = 0; i < n; i++) {
			Arrays.sort(r[i]);
			h[i] = new long[r[i].length];
			if (r[i].length == 0)
				continue;
			h[i][0] = r[i][0] + 1;
			for (int j = 1; j < r[i].length; j++) {
				h[i][j] = h[i][j - 1] * P + r[i][j] + 1;
			}
			a[i] = h[i][r[i].length - 1];
		}
		Arrays.sort(a);
		long ans = 0;
		long cur = 1;
		for (int i = 1; i < n; i++) {
			if (a[i] == a[i - 1]) {
				cur++;
			} else {
				ans += cur * (cur - 1) / 2;
				cur = 1;
			}
		}
		ans += cur * (cur - 1) / 2;

		int v, u, p1, p2, t, c;
		boolean ind;
		for (int i = 0; i < m; i++) {
			v = e[i][0];
			u = e[i][1];
			p1 = Arrays.binarySearch(r[v], u);
			p2 = Arrays.binarySearch(r[u], v);
			if (p1 > p2) {
				t = v;
				v = u;
				u = t;
				t = p1;
				p1 = p2;
				p2 = t;
			}
			c = r[v].length;
			if (r[v].length == r[u].length) {
				ind = true;
				if (p1 > 0) {
					ind = ind && (h[v][p1 - 1] == h[u][p1 - 1]);
				}
				ind = ind && (h[v][c - 1] - h[v][p2] * p[c - 1 - p2] == h[u][c - 1] - h[u][p2] * p[c - 1 - p2]);
				ind = ind && (h[v][p2] - h[v][p1] * p[p2 - p1] == ((p2 > 0)?(h[u][p2 - 1]):(0)) - ((p1 > 0)?(h[u][p1 - 1]):(0)) * p[p2 - p1]);
				if (ind)
					ans++;
			}
		}
		//out.println(ans);
	}
}

class InputReader {
	private BufferedReader reader;
	private StringTokenizer tokenizer;

	public InputReader(InputStream stream) {
		reader = new BufferedReader(new InputStreamReader(stream));
		tokenizer = null;
	}

	public String next() {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			try {
				tokenizer = new StringTokenizer(reader.readLine());
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		return tokenizer.nextToken();
	}

	public long nextLong() {
		return Long.parseLong(next());
	}

	public int nextInt() {
		return Integer.parseInt(next());
	}

	public double nextDouble() {
		return Double.parseDouble(next());
	}
}


import java.util.*;
import java.io.*;
import java.lang.reflect.Array;
import java.math.*;

public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		/*try {
			inputStream = new FileInputStream("input.txt");
			outputStream = new FileOutputStream("output.txt");
		} catch (FileNotFoundException e) {
			System.err.println("File not found");
			return;
		}*/

		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		Solver solver = new Solver();
		solver.solve(in, out);
		out.close();
	}
}

class Solver {
	public static final int MAXN = 1000001;
	public static final long P = 1011001;
	public void solve(InputReader in, PrintWriter out) {
		int n = in.nextInt();
		int m = in.nextInt();
		int e[][] = new int[m][2];
		//ArrayList<Integer>[] r = new ArrayList[n];
		int[][] r = new int[n][];
		int[] cr = new int[n];
		long p[] = new long[MAXN];
		p[0] = 1;
		for (int i = 1; i < MAXN; i++) {
			p[i] = p[i - 1] * P;
		}

		long[][] h = new long[n][];
		long h1[] = new long[n];
		long h2[] = new long[n];
		for (int i = 0; i < m; i++) {
			int v = in.nextInt();
			int u = in.nextInt();
			v--;
			u--;
			e[i][0] = v;
			e[i][1] = u;
			cr[v]++;
			cr[u]++;
			h1[v] += p[u];
			h1[u] += p[v];
		}

		for (int i = 0; i < n; i++) {
			h2[i] = h1[i] + p[i];
		}
		Arrays.sort(h1);
		Arrays.sort(h2);
		long cur1 = 1;
		long ans1 = 0;
		for (int i = 1; i < n; i++) {
			if (h1[i] == h1[i - 1]) {
				cur1++;
			} else {
				ans1 += cur1 * (cur1 - 1) / 2;
				cur1 = 1;
			}
		}
		ans1 += cur1 * (cur1 - 1) / 2;
		cur1 = 1;
		for (int i = 1; i < n; i++) {
			if (h2[i] == h2[i - 1]) {
				cur1++;
			} else {
				ans1 += cur1 * (cur1 - 1) / 2;
				cur1 = 1;
			}
		}
		ans1 += cur1 * (cur1 - 1) / 2;
		out.println(ans1);

		for (int i = 0; i < n; i++) {
			r[i] = new int[cr[i]];
			cr[i] = 0;
		}
		for (int i = 0; i < m; i++) {
			int v = e[i][0];
			int u = e[i][1];
			r[v][cr[v]++] = u;
			r[u][cr[u]++] = v;
		}

		long[] a = new long[n];

		for (int i = 0; i < n; i++) {
			Arrays.sort(r[i]);
			h[i] = new long[r[i].length];
			if (r[i].length == 0)
				continue;
			h[i][0] = r[i][0] + 1;
			for (int j = 1; j < r[i].length; j++) {
				h[i][j] = h[i][j - 1] * P + r[i][j] + 1;
			}
			a[i] = h[i][r[i].length - 1];
		}
		Arrays.sort(a);
		long ans = 0;
		long cur = 1;
		for (int i = 1; i < n; i++) {
			if (a[i] == a[i - 1]) {
				cur++;
			} else {
				ans += cur * (cur - 1) / 2;
				cur = 1;
			}
		}
		ans += cur * (cur - 1) / 2;

		for (int i = 0; i < m; i++) {
			int v = e[i][0];
			int u = e[i][1];
			int p1 = Arrays.binarySearch(r[v], u);
			int p2 = Arrays.binarySearch(r[u], v);
			if (p1 > p2) {
				int t = v;
				v = u;
				u = t;
				t = p1;
				p1 = p2;
				p2 = t;
			}
			int c = r[v].length;
			if (r[v].length == r[u].length) {
				boolean ind = true;
				if (p1 > 0) {
					ind = ind && (h[v][p1 - 1] == h[u][p1 - 1]);
				}
				ind = ind && (h[v][c - 1] - h[v][p2] * p[c - 1 - p2] == h[u][c - 1] - h[u][p2] * p[c - 1 - p2]);
				ind = ind && (h[v][p2] - h[v][p1] * p[p2 - p1] == ((p2 > 0)?(h[u][p2 - 1]):(0)) - ((p1 > 0)?(h[u][p1 - 1]):(0)) * p[p2 - p1]);
				if (ind)
					ans++;
			}
		}
		//out.println(ans);
	}
}

class InputReader {
	private BufferedReader reader;
	private StringTokenizer tokenizer;

	public InputReader(InputStream stream) {
		reader = new BufferedReader(new InputStreamReader(stream));
		tokenizer = null;
	}

	public String next() {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			try {
				tokenizer = new StringTokenizer(reader.readLine());
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		return tokenizer.nextToken();
	}

	public long nextLong() {
		return Long.parseLong(next());
	}

	public int nextInt() {
		return Integer.parseInt(next());
	}

	public double nextDouble() {
		return Double.parseDouble(next());
	}
}


import java.util.*;
import java.io.*;
import java.lang.reflect.Array;
import java.math.*;

public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		/*try {
			inputStream = new FileInputStream("input.txt");
			outputStream = new FileOutputStream("output.txt");
		} catch (FileNotFoundException e) {
			System.err.println("File not found");
			return;
		}*/

		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		Solver solver = new Solver();
		solver.solve(in, out);
		out.close();
	}
}

class Solver {
	public static final int MAXN = 1000001;
	public static final long P = 1011001;
	public void solve(InputReader in, PrintWriter out) {
		int n = in.nextInt();
		int m = in.nextInt();
		int e[][] = new int[m][2];
		//ArrayList<Integer>[] r = new ArrayList[n];
		int[][] r = new int[n][];
		int[] cr = new int[n];
		long p[] = new long[MAXN];
		p[0] = 1;
		for (int i = 1; i < MAXN; i++) {
			p[i] = p[i - 1] * P;
		}

		long[][] h = new long[n][];
		long h1[] = new long[n];
		long h2[] = new long[n];
		for (int i = 0; i < m; i++) {
			int v = in.nextInt();
			int u = in.nextInt();
			v--;
			u--;
			e[i][0] = v;
			e[i][1] = u;
			cr[v]++;
			cr[u]++;
			h1[v] += p[u];
			h1[u] += p[v];
		}

		for (int i = 0; i < n; i++) {
			h2[i] = h1[i] + p[i];
		}
		Arrays.sort(h1);
		Arrays.sort(h2);
		long cur1 = 1;
		long ans1 = 0;
		for (int i = 1; i < n; i++) {
			if (h1[i] == h1[i - 1]) {
				cur1++;
			} else {
				ans1 += cur1 * (cur1 - 1) / 2;
				cur1 = 1;
			}
		}
		ans1 += cur1 * (cur1 - 1) / 2;
		cur1 = 1;
		for (int i = 1; i < n; i++) {
			if (h2[i] == h2[i - 1]) {
				cur1++;
			} else {
				ans1 += cur1 * (cur1 - 1) / 2;
				cur1 = 1;
			}
		}
		ans1 += cur1 * (cur1 - 1) / 2;
		out.println(ans1);

		for (int i = 0; i < n; i++) {
			r[i] = new int[cr[i]];
			cr[i] = 0;
		}
		for (int i = 0; i < m; i++) {
			int v = e[i][0];
			int u = e[i][1];
			r[v][cr[v]++] = u;
			r[u][cr[u]++] = v;
		}

		long[] a = new long[n];

		for (int i = 0; i < n; i++) {
			Arrays.sort(r[i]);
			h[i] = new long[r[i].length];
			if (r[i].length == 0)
				continue;
			h[i][0] = r[i][0] + 1;
			for (int j = 1; j < r[i].length; j++) {
				h[i][j] = h[i][j - 1] * P + r[i][j] + 1;
			}
			a[i] = h[i][r[i].length - 1];
		}
		Arrays.sort(a);
		long ans = 0;
		long cur = 1;
		for (int i = 1; i < n; i++) {
			if (a[i] == a[i - 1]) {
				cur++;
			} else {
				ans += cur * (cur - 1) / 2;
				cur = 1;
			}
		}
		ans += cur * (cur - 1) / 2;

		for (int i = 0; i < m; i++) {
			int v = e[i][0];
			int u = e[i][1];
			int p1 = 0;//Arrays.binarySearch(r[v], u);
			int p2 = 0;//Arrays.binarySearch(r[u], v);
			if (p1 > p2) {
				int t = v;
				v = u;
				u = t;
				t = p1;
				p1 = p2;
				p2 = t;
			}
			int c = r[v].length;
			if (r[v].length == r[u].length) {
				boolean ind = true;
				if (p1 > 0) {
					ind = ind && (h[v][p1 - 1] == h[u][p1 - 1]);
				}
				ind = ind && (h[v][c - 1] - h[v][p2] * p[c - 1 - p2] == h[u][c - 1] - h[u][p2] * p[c - 1 - p2]);
				ind = ind && (h[v][p2] - h[v][p1] * p[p2 - p1] == ((p2 > 0)?(h[u][p2 - 1]):(0)) - ((p1 > 0)?(h[u][p1 - 1]):(0)) * p[p2 - p1]);
				if (ind)
					ans++;
			}
		}
		//out.println(ans);
	}
}

class InputReader {
	private BufferedReader reader;
	private StringTokenizer tokenizer;

	public InputReader(InputStream stream) {
		reader = new BufferedReader(new InputStreamReader(stream));
		tokenizer = null;
	}

	public String next() {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			try {
				tokenizer = new StringTokenizer(reader.readLine());
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		return tokenizer.nextToken();
	}

	public long nextLong() {
		return Long.parseLong(next());
	}

	public int nextInt() {
		return Integer.parseInt(next());
	}

	public double nextDouble() {
		return Double.parseDouble(next());
	}
}


import java.util.*;
import java.io.*;
import java.lang.reflect.Array;
import java.math.*;

public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		Solver solver = new Solver();
		solver.solve(in, out);
		out.close();
	}
}

class Solver {
	public static final int MAXN = 1000001;
	public static final long P = 1011001;
	public void solve(InputReader in, PrintWriter out) {
		int n = in.nextInt();
		int m = in.nextInt();
		int e[][] = new int[m][2];
		ArrayList<Integer>[] r = new ArrayList[n];
		for (int i = 0; i < n; i++) {
			r[i] = new ArrayList<Integer>();
		}
		long p[] = new long[MAXN];
		p[0] = 1;
		for (int i = 1; i < MAXN; i++) {
			p[i] = p[i - 1] * P;
		}
		long[][] h = new long[n][];

		for (int i = 0; i < m; i++) {
			int v = in.nextInt();
			int u = in.nextInt();
			v--;
			u--;
			e[i][0] = v;
			e[i][1] = u;
			r[v].add(u);
			r[u].add(v);
		}

		long[] a = new long[n];

		for (int i = 0; i < n; i++) {
			Collections.sort(r[i]);
			h[i] = new long[r[i].size()];
			if (r[i].size() == 0)
				continue;
			h[i][0] = r[i].get(0) + 1;
			for (int j = 1; j < r[i].size(); j++) {
				h[i][j] = h[i][j - 1] * P + r[i].get(j) + 1;
			}
			a[i] = h[i][r[i].size() - 1];
		}
		Arrays.sort(a);
		long ans = 0;
		long cur = 1;
		for (int i = 1; i < n; i++) {
			if (a[i] == a[i - 1]) {
				cur++;
			} else {
				ans += cur * (cur - 1) / 2;
				cur = 1;
			}
		}
		ans += cur * (cur - 1) / 2;

		for (int i = 0; i < m; i++) {
			int v = e[i][0];
			int u = e[i][1];
			int p1 = Collections.binarySearch(r[v], u);
			int p2 = Collections.binarySearch(r[u], v);
			if (p1 > p2) {
				int t = v;
				v = u;
				u = t;
				t = p1;
				p1 = p2;
				p2 = t;
			}
			int c = r[v].size();
			if (r[v].size() == r[u].size()) {
				boolean ind = true;
				if (p1 > 0) {
					ind = ind && (h[v][p1 - 1] == h[u][p1 - 1]);
				}
				ind = ind && (h[v][c - 1] - h[v][p2] * p[c - 1 - p2] == h[u][c - 1] - h[u][p2] * p[c - 1 - p2]);
				ind = ind && (h[v][p2] - h[v][p1] * p[p2 - p1] == ((p2 > 0)?(h[u][p2 - 1]):(0)) - ((p1 > 0)?(h[u][p1 - 1]):(0)) * p[p2 - p1]);
				if (ind)
					ans++;
			}
		}
		out.println(ans);
	}
}

class InputReader {
	private BufferedReader reader;
	private StringTokenizer tokenizer;

	public InputReader(InputStream stream) {
		reader = new BufferedReader(new InputStreamReader(stream));
		tokenizer = null;
	}

	public String next() {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			try {
				tokenizer = new StringTokenizer(reader.readLine());
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		return tokenizer.nextToken();
	}

	public long nextLong() {
		return Long.parseLong(next());
	}

	public int nextInt() {
		return Integer.parseInt(next());
	}

	public double nextDouble() {
		return Double.parseDouble(next());
	}
}


import java.util.*;
import java.io.*;
import java.lang.reflect.Array;
import java.math.*;

public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		Solver solver = new Solver();
		solver.solve(in, out);
		out.close();
	}
}

class Solver {
	public static final int MAXN = 1000001;
	public static final long P = 1011001;
	public void solve(InputReader in, PrintWriter out) {
		int n = in.nextInt();
		int m = in.nextInt();
		long p[] = new long[MAXN];
		p[0] = 1;
		for (int i = 1; i < MAXN; i++) {
			p[i] = p[i - 1] * P;
		}
		long h1[] = new long[n];
		long h2[] = new long[n];
		for (int i = 0; i < m; i++) {
			int v = in.nextInt();
			int u = in.nextInt();
			v--;
			u--;
			h1[v] += p[u];
			h1[u] += p[v];
		}
		for (int i = 0; i < n; i++) {
			h2[i] = h1[i] + p[i];
		}
		Arrays.sort(h1);
		Arrays.sort(h2);
		long cur = 1;
		long ans = 0;
		for (int i = 1; i < n; i++) {
			if (h1[i] == h1[i - 1]) {
				cur++;
			} else {
				ans += cur * (cur - 1) / 2;
				cur = 1;
			}
		}
		ans += cur * (cur - 1) / 2;
		cur = 1;
		for (int i = 1; i < n; i++) {
			if (h2[i] == h2[i - 1]) {
				cur++;
			} else {
				ans += cur * (cur - 1) / 2;
				cur = 1;
			}
		}
		ans += cur * (cur - 1) / 2;
		out.print(ans);
	}
}

class InputReader {
	private BufferedReader reader;
	private StringTokenizer tokenizer;

	public InputReader(InputStream stream) {
		reader = new BufferedReader(new InputStreamReader(stream));
		tokenizer = null;
	}

	public String next() {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			try {
				tokenizer = new StringTokenizer(reader.readLine());
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		return tokenizer.nextToken();
	}

	public long nextLong() {
		return Long.parseLong(next());
	}

	public int nextInt() {
		return Integer.parseInt(next());
	}

	public double nextDouble() {
		return Double.parseDouble(next());
	}
}


import java.util.*;
import java.io.*;
import java.lang.reflect.Array;
import java.math.*;

public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		/*try {
			inputStream = new FileInputStream("input.txt");
			outputStream = new FileOutputStream("output.txt");
		} catch (FileNotFoundException e) {
			System.err.println("File not found");
			return;
		}*/

		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		Solver solver = new Solver();
		solver.solve(in, out);
		out.close();
	}
}

class Solver {
	public static final int MAXN = 1000001;
	public static final long P = 1011001;
	public void solve(InputReader in, PrintWriter out) {
		int n = in.nextInt();
		int m = in.nextInt();
		int e[][] = new int[m][2];
		//ArrayList<Integer>[] r = new ArrayList[n];
		int[][] r = new int[n][];
		int[] cr = new int[n];
		long p[] = new long[MAXN];
		p[0] = 1;
		for (int i = 1; i < MAXN; i++) {
			p[i] = p[i - 1] * P;
		}

		long[][] h = new long[n][];
		long h1[] = new long[n];
		long h2[] = new long[n];
		for (int i = 0; i < m; i++) {
			int v = in.nextInt();
			int u = in.nextInt();
			v--;
			u--;
			e[i][0] = v;
			e[i][1] = u;
			cr[v]++;
			cr[u]++;
			h1[v] += p[u];
			h1[u] += p[v];
		}

		for (int i = 0; i < n; i++) {
			h2[i] = h1[i] + p[i];
		}
		Arrays.sort(h1);
		Arrays.sort(h2);
		long cur1 = 1;
		long ans1 = 0;
		for (int i = 1; i < n; i++) {
			if (h1[i] == h1[i - 1]) {
				cur1++;
			} else {
				ans1 += cur1 * (cur1 - 1) / 2;
				cur1 = 1;
			}
		}
		ans1 += cur1 * (cur1 - 1) / 2;
		cur1 = 1;
		for (int i = 1; i < n; i++) {
			if (h2[i] == h2[i - 1]) {
				cur1++;
			} else {
				ans1 += cur1 * (cur1 - 1) / 2;
				cur1 = 1;
			}
		}
		ans1 += cur1 * (cur1 - 1) / 2;
		out.println(ans1);

		for (int i = 0; i < n; i++) {
			r[i] = new int[cr[i]];
			cr[i] = 0;
		}
		for (int i = 0; i < m; i++) {
			int v = e[i][0];
			int u = e[i][1];
			r[v][cr[v]++] = u;
			r[u][cr[u]++] = v;
		}

		long[] a = new long[n];

		for (int i = 0; i < n; i++) {
			Arrays.sort(r[i]);
			h[i] = new long[r[i].length];
			if (r[i].length == 0)
				continue;
			h[i][0] = r[i][0] + 1;
			for (int j = 1; j < r[i].length; j++) {
				h[i][j] = h[i][j - 1] * P + r[i][j] + 1;
			}
			a[i] = h[i][r[i].length - 1];
		}
		Arrays.sort(a);
		long ans = 0;
		long cur = 1;
		for (int i = 1; i < n; i++) {
			if (a[i] == a[i - 1]) {
				cur++;
			} else {
				ans += cur * (cur - 1) / 2;
				cur = 1;
			}
		}
		ans += cur * (cur - 1) / 2;

		//int v, u, p1, p2, t, c;
		//boolean ind;

		int v, i;
		for (i = 0; i < m; i++) {
			v = e[i][0];
			//u = e[i][1];
		}

		//out.println(ans);
	}
}

class InputReader {
	private BufferedReader reader;
	private StringTokenizer tokenizer;

	public InputReader(InputStream stream) {
		reader = new BufferedReader(new InputStreamReader(stream));
		tokenizer = null;
	}

	public String next() {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			try {
				tokenizer = new StringTokenizer(reader.readLine());
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		return tokenizer.nextToken();
	}

	public long nextLong() {
		return Long.parseLong(next());
	}

	public int nextInt() {
		return Integer.parseInt(next());
	}

	public double nextDouble() {
		return Double.parseDouble(next());
	}
}


import java.util.*;
import java.io.*;
import java.lang.reflect.Array;
import java.math.*;

public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		/*try {
			inputStream = new FileInputStream("input.txt");
			outputStream = new FileOutputStream("output.txt");
		} catch (FileNotFoundException e) {
			System.err.println("File not found");
			return;
		}*/

		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		Solver solver = new Solver();
		solver.solve(in, out);
		out.close();
	}
}

class Solver {
	public static final int MAXN = 1000001;
	public static final long P = 1011001;
	public void solve(InputReader in, PrintWriter out) {
		int n = in.nextInt();
		int m = in.nextInt();
		int e[][] = new int[m][2];
		//ArrayList<Integer>[] r = new ArrayList[n];
		int[][] r = new int[n][];
		int[] cr = new int[n];
		long p[] = new long[MAXN];
		p[0] = 1;
		for (int i = 1; i < MAXN; i++) {
			p[i] = p[i - 1] * P;
		}

		long[][] h = new long[n][];
		long h1[] = new long[n];
		long h2[] = new long[n];
		for (int i = 0; i < m; i++) {
			int v = in.nextInt();
			int u = in.nextInt();
			v--;
			u--;
			e[i][0] = v;
			e[i][1] = u;
			cr[v]++;
			cr[u]++;
			h1[v] += p[u];
			h1[u] += p[v];
		}

		for (int i = 0; i < n; i++) {
			h2[i] = h1[i] + p[i];
		}
		Arrays.sort(h1);
		Arrays.sort(h2);
		long cur1 = 1;
		long ans1 = 0;
		for (int i = 1; i < n; i++) {
			if (h1[i] == h1[i - 1]) {
				cur1++;
			} else {
				ans1 += cur1 * (cur1 - 1) / 2;
				cur1 = 1;
			}
		}
		ans1 += cur1 * (cur1 - 1) / 2;
		cur1 = 1;
		for (int i = 1; i < n; i++) {
			if (h2[i] == h2[i - 1]) {
				cur1++;
			} else {
				ans1 += cur1 * (cur1 - 1) / 2;
				cur1 = 1;
			}
		}
		ans1 += cur1 * (cur1 - 1) / 2;
		out.println(ans1);

		for (int i = 0; i < n; i++) {
			r[i] = new int[cr[i]];
			cr[i] = 0;
		}
		for (int i = 0; i < m; i++) {
			int v = e[i][0];
			int u = e[i][1];
			r[v][cr[v]++] = u;
			r[u][cr[u]++] = v;
		}

		long[] a = new long[n];

		for (int i = 0; i < n; i++) {
			Arrays.sort(r[i]);
			h[i] = new long[r[i].length];
			if (r[i].length == 0)
				continue;
			h[i][0] = r[i][0] + 1;
			for (int j = 1; j < r[i].length; j++) {
				h[i][j] = h[i][j - 1] * P + r[i][j] + 1;
			}
			a[i] = h[i][r[i].length - 1];
		}
		Arrays.sort(a);
		long ans = 0;
		long cur = 1;
		for (int i = 1; i < n; i++) {
			if (a[i] == a[i - 1]) {
				cur++;
			} else {
				ans += cur * (cur - 1) / 2;
				cur = 1;
			}
		}
		ans += cur * (cur - 1) / 2;

		int v, u, p1, p2, t, c;
		boolean ind;
		for (int i = 0; i < m; i++) {
			v = e[i][0];
			u = e[i][1];
			p1 = Arrays.binarySearch(r[v], u);
			p2 = Arrays.binarySearch(r[u], v);
			if (p1 > p2) {
				t = v;
				v = u;
				u = t;
				t = p1;
				p1 = p2;
				p2 = t;
			}
			/*
			c = r[v].length;
			if (r[v].length == r[u].length) {
				ind = true;
				if (p1 > 0) {
					ind = ind && (h[v][p1 - 1] == h[u][p1 - 1]);
				}
				ind = ind && (h[v][c - 1] - h[v][p2] * p[c - 1 - p2] == h[u][c - 1] - h[u][p2] * p[c - 1 - p2]);
				ind = ind && (h[v][p2] - h[v][p1] * p[p2 - p1] == ((p2 > 0)?(h[u][p2 - 1]):(0)) - ((p1 > 0)?(h[u][p1 - 1]):(0)) * p[p2 - p1]);
				if (ind)
					ans++;
			}
			*/
		}
		//out.println(ans);
	}
}

class InputReader {
	private BufferedReader reader;
	private StringTokenizer tokenizer;

	public InputReader(InputStream stream) {
		reader = new BufferedReader(new InputStreamReader(stream));
		tokenizer = null;
	}

	public String next() {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			try {
				tokenizer = new StringTokenizer(reader.readLine());
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		return tokenizer.nextToken();
	}

	public long nextLong() {
		return Long.parseLong(next());
	}

	public int nextInt() {
		return Integer.parseInt(next());
	}

	public double nextDouble() {
		return Double.parseDouble(next());
	}
}


import java.util.*;
import java.io.*;
import java.lang.reflect.Array;
import java.math.*;

public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		/*try {
			inputStream = new FileInputStream("input.txt");
			outputStream = new FileOutputStream("output.txt");
		} catch (FileNotFoundException e) {
			System.err.println("File not found");
			return;
		}*/

		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		Solver solver = new Solver();
		solver.solve(in, out);
		out.close();
	}
}

class Solver {
	public static final int MAXN = 1000001;
	public static final long P = 1011001;
	public void solve(InputReader in, PrintWriter out) {
		int n = in.nextInt();
		int m = in.nextInt();
		int e[][] = new int[m][2];
		//ArrayList<Integer>[] r = new ArrayList[n];
		int[][] r = new int[n][];
		int[] cr = new int[n];
		long p[] = new long[MAXN];
		p[0] = 1;
		for (int i = 1; i < MAXN; i++) {
			p[i] = p[i - 1] * P;
		}

		long[][] h = new long[n][];
		long h1[] = new long[n];
		long h2[] = new long[n];
		for (int i = 0; i < m; i++) {
			int v = in.nextInt();
			int u = in.nextInt();
			v--;
			u--;
			e[i][0] = v;
			e[i][1] = u;
			cr[v]++;
			cr[u]++;
			h1[v] += p[u];
			h1[u] += p[v];
		}

		for (int i = 0; i < n; i++) {
			h2[i] = h1[i] + p[i];
		}
		Arrays.sort(h1);
		Arrays.sort(h2);
		long cur1 = 1;
		long ans1 = 0;
		for (int i = 1; i < n; i++) {
			if (h1[i] == h1[i - 1]) {
				cur1++;
			} else {
				ans1 += cur1 * (cur1 - 1) / 2;
				cur1 = 1;
			}
		}
		ans1 += cur1 * (cur1 - 1) / 2;
		cur1 = 1;
		for (int i = 1; i < n; i++) {
			if (h2[i] == h2[i - 1]) {
				cur1++;
			} else {
				ans1 += cur1 * (cur1 - 1) / 2;
				cur1 = 1;
			}
		}
		ans1 += cur1 * (cur1 - 1) / 2;
		out.println(ans1);

		for (int i = 0; i < n; i++) {
			r[i] = new int[cr[i]];
			cr[i] = 0;
		}
		for (int i = 0; i < m; i++) {
			int v = e[i][0];
			int u = e[i][1];
			r[v][cr[v]++] = u;
			r[u][cr[u]++] = v;
		}

		long[] a = new long[n];

		for (int i = 0; i < n; i++) {
			Arrays.sort(r[i]);
			h[i] = new long[r[i].length];
			if (r[i].length == 0)
				continue;
			h[i][0] = r[i][0] + 1;
			for (int j = 1; j < r[i].length; j++) {
				h[i][j] = h[i][j - 1] * P + r[i][j] + 1;
			}
			a[i] = h[i][r[i].length - 1];
		}
		Arrays.sort(a);
		long ans = 0;
		long cur = 1;
		for (int i = 1; i < n; i++) {
			if (a[i] == a[i - 1]) {
				cur++;
			} else {
				ans += cur * (cur - 1) / 2;
				cur = 1;
			}
		}
		ans += cur * (cur - 1) / 2;

		int v, u, p1, p2, t, c;
		boolean ind;
		for (int i = 0; i < m; i++) {
			v = e[i][0];
			u = e[i][1];
			/*
			p1 = Arrays.binarySearch(r[v], u);
			p2 = Arrays.binarySearch(r[u], v);

			if (p1 > p2) {
				t = v;
				v = u;
				u = t;
				t = p1;
				p1 = p2;
				p2 = t;
			}

			c = r[v].length;
			if (r[v].length == r[u].length) {
				ind = true;
				if (p1 > 0) {
					ind = ind && (h[v][p1 - 1] == h[u][p1 - 1]);
				}
				ind = ind && (h[v][c - 1] - h[v][p2] * p[c - 1 - p2] == h[u][c - 1] - h[u][p2] * p[c - 1 - p2]);
				ind = ind && (h[v][p2] - h[v][p1] * p[p2 - p1] == ((p2 > 0)?(h[u][p2 - 1]):(0)) - ((p1 > 0)?(h[u][p1 - 1]):(0)) * p[p2 - p1]);
				if (ind)
					ans++;
			}
			*/
		}
		//out.println(ans);
	}
}

class InputReader {
	private BufferedReader reader;
	private StringTokenizer tokenizer;

	public InputReader(InputStream stream) {
		reader = new BufferedReader(new InputStreamReader(stream));
		tokenizer = null;
	}

	public String next() {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			try {
				tokenizer = new StringTokenizer(reader.readLine());
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		return tokenizer.nextToken();
	}

	public long nextLong() {
		return Long.parseLong(next());
	}

	public int nextInt() {
		return Integer.parseInt(next());
	}

	public double nextDouble() {
		return Double.parseDouble(next());
	}
}


import java.util.*;
import java.io.*;
import java.lang.reflect.Array;
import java.math.*;

public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		/*try {
			inputStream = new FileInputStream("input.txt");
			outputStream = new FileOutputStream("output.txt");
		} catch (FileNotFoundException e) {
			System.err.println("File not found");
			return;
		}*/

		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		Solver solver = new Solver();
		solver.solve(in, out);
		out.close();
	}
}

class Solver {
	public static final int MAXN = 1000001;
	public static final long P = 1011001;
	public void solve(InputReader in, PrintWriter out) {
		int n = in.nextInt();
		int m = in.nextInt();
		int e[][] = new int[m][2];
		//ArrayList<Integer>[] r = new ArrayList[n];
		int[][] r = new int[n][];
		int[] cr = new int[n];
		long p[] = new long[MAXN];
		p[0] = 1;
		for (int i = 1; i < MAXN; i++) {
			p[i] = p[i - 1] * P;
		}

		long[][] h = new long[n][];
		long h1[] = new long[n];
		long h2[] = new long[n];
		for (int i = 0; i < m; i++) {
			int v = in.nextInt();
			int u = in.nextInt();
			v--;
			u--;
			e[i][0] = v;
			e[i][1] = u;
			cr[v]++;
			cr[u]++;
			h1[v] += p[u];
			h1[u] += p[v];
		}

		for (int i = 0; i < n; i++) {
			h2[i] = h1[i] + p[i];
		}
		Arrays.sort(h1);
		Arrays.sort(h2);
		long cur1 = 1;
		long ans1 = 0;
		for (int i = 1; i < n; i++) {
			if (h1[i] == h1[i - 1]) {
				cur1++;
			} else {
				ans1 += cur1 * (cur1 - 1) / 2;
				cur1 = 1;
			}
		}
		ans1 += cur1 * (cur1 - 1) / 2;
		cur1 = 1;
		for (int i = 1; i < n; i++) {
			if (h2[i] == h2[i - 1]) {
				cur1++;
			} else {
				ans1 += cur1 * (cur1 - 1) / 2;
				cur1 = 1;
			}
		}
		ans1 += cur1 * (cur1 - 1) / 2;
		out.println(ans1);

		for (int i = 0; i < n; i++) {
			r[i] = new int[cr[i]];
			cr[i] = 0;
		}
		for (int i = 0; i < m; i++) {
			int v = e[i][0];
			int u = e[i][1];
			r[v][cr[v]++] = u;
			r[u][cr[u]++] = v;
		}

		long[] a = new long[n];

		for (int i = 0; i < n; i++) {
			Arrays.sort(r[i]);
			h[i] = new long[r[i].length];
			if (r[i].length == 0)
				continue;
			h[i][0] = r[i][0] + 1;
			for (int j = 1; j < r[i].length; j++) {
				h[i][j] = h[i][j - 1] * P + r[i][j] + 1;
			}
			a[i] = h[i][r[i].length - 1];
		}
		Arrays.sort(a);
		long ans = 0;
		long cur = 1;
		for (int i = 1; i < n; i++) {
			if (a[i] == a[i - 1]) {
				cur++;
			} else {
				ans += cur * (cur - 1) / 2;
				cur = 1;
			}
		}
		ans += cur * (cur - 1) / 2;
		/*
		for (int i = 0; i < m; i++) {
			int v = e[i][0];
			int u = e[i][1];
			int p1 = Arrays.binarySearch(r[v], u);
			int p2 = Arrays.binarySearch(r[u], v);
			if (p1 > p2) {
				int t = v;
				v = u;
				u = t;
				t = p1;
				p1 = p2;
				p2 = t;
			}
			int c = r[v].length;
			if (r[v].length == r[u].length) {
				boolean ind = true;
				if (p1 > 0) {
					ind = ind && (h[v][p1 - 1] == h[u][p1 - 1]);
				}
				ind = ind && (h[v][c - 1] - h[v][p2] * p[c - 1 - p2] == h[u][c - 1] - h[u][p2] * p[c - 1 - p2]);
				ind = ind && (h[v][p2] - h[v][p1] * p[p2 - p1] == ((p2 > 0)?(h[u][p2 - 1]):(0)) - ((p1 > 0)?(h[u][p1 - 1]):(0)) * p[p2 - p1]);
				if (ind)
					ans++;
			}
		}*/
		//out.println(ans);
	}
}

class InputReader {
	private BufferedReader reader;
	private StringTokenizer tokenizer;

	public InputReader(InputStream stream) {
		reader = new BufferedReader(new InputStreamReader(stream));
		tokenizer = null;
	}

	public String next() {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			try {
				tokenizer = new StringTokenizer(reader.readLine());
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		return tokenizer.nextToken();
	}

	public long nextLong() {
		return Long.parseLong(next());
	}

	public int nextInt() {
		return Integer.parseInt(next());
	}

	public double nextDouble() {
		return Double.parseDouble(next());
	}
}