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, u;
		for (int 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 e1[] = new int[m];
		int e2[] = new int[m];
		//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--;
			e1[i] = v;
			e2[i] = 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 = e1[i];
			int u = e2[i];
			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 = e1[i];
			int u = e2[i];
			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;
		/*
		int v, u;
		for (int 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;

		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][];
		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.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.StringTokenizer;

public class C154 {

	static StringTokenizer st;
	static BufferedReader in;
	static long ans;
	static long[]a;
	static int n;
	public static void main(String[] args) throws IOException {
		in = new BufferedReader(new InputStreamReader(System.in));
		PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
		int q = 1000003;
		n = nextInt();
		int m = nextInt();
		long[]pow = new long[n+1];
		pow[0] = 1;
		for (int i = 1; i <= n; i++) {
			pow[i] = pow[i-1] * q;
		}
		long[]hash = new long[n+1];
		a = new long[n+1];
		for (int i = 1; i <= m; i++) {
			int v1 = nextInt();
			int v2 = nextInt();
			hash[v1] += pow[v2];
			hash[v2] += pow[v1];
		}
		a = hash.clone();
		calc();
		for (int i = 1; i <= n; i++) {
			hash[i] += pow[i];
		}
		a = hash.clone();
		calc();
		System.out.println(ans);
		pw.close();
	}
	private static void calc() {
		Arrays.sort(a, 1, n+1);
		int cnt = 0;
		for (int i = 1; i <= n; i++) {
			if (a[i]==a[i-1] || i==1)
				cnt++;
			else {
				ans += (long)cnt*(cnt-1)/2;
				cnt = 1;
			}
		}
		ans += (long)cnt*(cnt-1)/2;
	}

	private static int nextInt() throws IOException{
		return Integer.parseInt(next());
	}

	private static long nextLong() throws IOException{
		return Long.parseLong(next());
	}

	private static double nextDouble() throws IOException{
		return Double.parseDouble(next());
	}

	private static String next() throws IOException {
        while (st == null || !st.hasMoreTokens()) {
            st = new StringTokenizer(in.readLine());
        }
        return st.nextToken();
    }
}


import java.awt.Point;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.io.*;
import java.math.BigInteger;
import static java.math.BigInteger.*;
import java.util.*;

public class C{
    class Item
    {
        int[]a;
        public int hashCode()
        {
            return getMyHashCode(3217,a);
        }
        public boolean equals(Object other)
        {
            int[]b=(((Item)other).a);
            for(int x: new int[]{3217})
                if(getMyHashCode(x,a)!=getMyHashCode(x,b))
                    return false;
            return b.length==a.length;

        }
        int getMyHashCode(int x,int[]a)
        {
            int res=0;
            for(int y: a)
                res=x*res+y;
            return res;
        }
    }
    class Pair implements Comparable<Pair>
    {
        int x,y;
        public int compareTo(Pair other)
        {
            if(x!=other.x)
                return x-other.x;
            return y-other.y;
        }
        public int hashCode()
        {
            return 3217*x+y;
        }
        public boolean equals(Object other)
        {
            Pair p=(Pair)other;
            return p.x==x && p.y==y;
        }
    }

    void solve()throws Exception
    {

        int n=nextInt();
        int m=nextInt();
        Pair[]a=new Pair[2*m];
        int[]deg=new int[n];
        for(int i=0;i<m;i++)
        {
            int x=nextInt()-1;
            int y=nextInt()-1;
            Pair cur=new Pair();
            cur.x=x;
            cur.y=y;
            a[2*i]=cur;
            cur=new Pair();
            cur.x=y;
            cur.y=x;
            a[2*i+1]=cur;
            deg[x]++;
            deg[y]++;
        }
        Arrays.sort(a);
        int[][]h=new int[2][n+1];
        int[][]pow=new int[2][n+1];
        int[]key=new int[]{31,1000000007};
        for(int j=0;j<2;j++)
        {
            pow[j][0]=1;
            for(int i=1;i<=n;i++)
                pow[j][i]=pow[j][i-1]*key[j];
        }

        for(int i=0;i<2*m;i++)
        {
            int x=a[i].x;
            int y=a[i].y;
            for(int j=0;j<2;j++)
                h[j][x]+=pow[j][y+1];
        }
        long res=0;
        HashMap<Pair,Integer>map=new HashMap<Pair,Integer>();
        for(int i=0;i<n;i++)
            {
                Pair cur=new Pair();
                cur.x=h[0][i];
                cur.y=h[1][i];
                if(!map.containsKey(cur))
                    map.put(cur,1);
                else
                {
                    int p=map.get(cur);
                    res+=p;
                    map.put(cur,p+1);
                }
            }
        map.clear();
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<2;j++)
                h[j][i]+=pow[j][i+1];
        }
               for(int i=0;i<n;i++)
            {
                Pair cur=new Pair();
                cur.x=h[0][i];
                cur.y=h[1][i];
                if(!map.containsKey(cur))
                    map.put(cur,1);
                else
                {
                    int p=map.get(cur);
                    res+=p;
                    map.put(cur,p+1);
                }
            }
        System.out.println(res);

    }
    ////////////
    BufferedReader reader;
    PrintWriter writer;
    StringTokenizer stk;
    void run()throws Exception
    {
        reader=new BufferedReader(new InputStreamReader(System.in));
        stk=null;
        writer=new PrintWriter(System.out);
        solve();
        reader.close();
        writer.close();
    }
    int nextInt()throws Exception
    {
        return Integer.parseInt(nextToken());
    }

    long nextLong()throws Exception
    {
        return Long.parseLong(nextToken());

    }
    double nextDouble()throws Exception
    {
        return Double.parseDouble(nextToken());

    }

    String nextString()throws Exception
    {
        return nextToken();
    }
    String nextLine()throws Exception
    {
        return reader.readLine();
    }
    String nextToken()throws Exception
    {
        if(stk==null || !stk.hasMoreTokens())
        {
            stk=new StringTokenizer(nextLine());
            return nextToken();

        }
        return stk.nextToken();
    }

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

}


import java.awt.Point;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.io.*;
import java.math.BigInteger;
import static java.math.BigInteger.*;
import java.util.*;

public class C{
    class Item
    {
        int[]a;
        public int hashCode()
        {
            return getMyHashCode(3217,a);
        }
        public boolean equals(Object other)
        {
            int[]b=(((Item)other).a);
            for(int x: new int[]{3217})
                if(getMyHashCode(x,a)!=getMyHashCode(x,b))
                    return false;
            return b.length==a.length;

        }
        int getMyHashCode(int x,int[]a)
        {
            int res=0;
            for(int y: a)
                res=x*res+y;
            return res;
        }
    }
    class Pair implements Comparable<Pair>
    {
        int x,y;
        public int compareTo(Pair other)
        {
            if(x!=other.x)
                return x-other.x;
            return y-other.y;
        }
        public int hashCode()
        {
            return 3217*x+y;
        }
        public boolean equals(Object other)
        {
            Pair p=(Pair)other;
            return p.x==x && p.y==y;
        }
    }

    void solve()throws Exception
    {

        int n=nextInt();

        int m=nextInt();

        Pair[]a=new Pair[2*m];
        int[]deg=new int[n];
        for(int i=0;i<m;i++)
        {
            int x=nextInt()-1;
            int y=nextInt()-1;
            Pair cur=new Pair();
            cur.x=x;
            cur.y=y;
            a[2*i]=cur;
            cur=new Pair();
            cur.x=y;
            cur.y=x;
            a[2*i+1]=cur;
            deg[x]++;
            deg[y]++;
        }
        //Arrays.sort(a);
        int[][]h=new int[2][n+1];
        int[][]pow=new int[2][n+1];
        int[]key=new int[]{31,1000000007};
        for(int j=0;j<2;j++)
        {
            pow[j][0]=1;
            for(int i=1;i<=n;i++)
                pow[j][i]=pow[j][i-1]*key[j];
        }

        for(int i=0;i<2*m;i++)
        {
            int x=a[i].x;
            int y=a[i].y;
            for(int j=0;j<2;j++)
                h[j][x]+=pow[j][y+1];
        }
        long res=0;
        HashMap<Pair,Integer>map=new HashMap<Pair,Integer>();
        for(int i=0;i<n;i++)
            {
                Pair cur=new Pair();
                cur.x=h[0][i];
                cur.y=h[1][i];
                if(!map.containsKey(cur))
                    map.put(cur,1);
                else
                {
                    int p=map.get(cur);
                    res+=p;
                    map.put(cur,p+1);
                }
            }
        map.clear();
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<2;j++)
                h[j][i]+=pow[j][i+1];
        }
               for(int i=0;i<n;i++)
            {
                Pair cur=new Pair();
                cur.x=h[0][i];
                cur.y=h[1][i];
                if(!map.containsKey(cur))
                    map.put(cur,1);
                else
                {
                    int p=map.get(cur);
                    res+=p;
                    map.put(cur,p+1);
                }
            }
        System.out.println(res);

    }
    ////////////
    BufferedReader reader;
    PrintWriter writer;
    StringTokenizer stk;
    int atBuffer;
    int numChars;
    byte[]buffer;
    InputStream stream;
    void run()throws Exception
    {
        stream=System.in;
        buffer=new byte[1024];
        numChars=0;
        atBuffer=buffer.length;
        //reader=new BufferedReader(new InputStreamReader(System.in));
        //stk=null;
        writer=new PrintWriter(System.out);
        solve();
        //reader.close();
        //writer.close();
    }
    int nextInt()throws Exception
    {
          return nextInt2();
        //return Integer.parseInt(nextToken());
    }
    int readChar()throws Exception
    {
        if(atBuffer>=numChars)
        {
            atBuffer=0;
            numChars=stream.read(buffer);
            return readChar();
        }
        return buffer[atBuffer++];
    }
    boolean isSpaceChar(int ch)
    {
        return ch==' ' || ch=='\n' || ch=='\t' || ch=='\r' || ch==-1;
    }
    int nextInt2()throws Exception
    {
        int c=readChar();
        while (isSpaceChar(c))
            c=readChar();
        int sign=1;
        if(c=='-')
        {
            sign=-1;
            c=readChar();
        }
        int res=0;
        while (!isSpaceChar(c))
        {
            res=10*res+c-'0';
            c=readChar();
        }
        return sign*res;
    }

    long nextLong()throws Exception
    {
        return Long.parseLong(nextToken());

    }
    double nextDouble()throws Exception
    {
        return Double.parseDouble(nextToken());

    }

    String nextString()throws Exception
    {
        return nextToken();
    }
    String nextLine()throws Exception
    {
        return reader.readLine();
    }
    String nextToken()throws Exception
    {
        if(stk==null || !stk.hasMoreTokens())
        {
            stk=new StringTokenizer(nextLine());
            return nextToken();

        }
        return stk.nextToken();
    }

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

}


import java.awt.Point;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.io.*;
import java.math.BigInteger;
import static java.math.BigInteger.*;
import java.util.*;

public class C{
    class Item
    {
        int[]a;
        public int hashCode()
        {
            return getMyHashCode(31,a);
        }
        public boolean equals(Object other)
        {
            int[]b=(((Item)other).a);
            for(int x: new int[]{31,17,3217})
                if(getMyHashCode(x,a)!=getMyHashCode(x,b))
                    return false;
            return true;

        }
        int getMyHashCode(int x,int[]a)
        {
            int res=0;
            for(int y: a)
                res=x*res+y;
            return res;
        }
    }
    int[]set;
    int[]edges;
    int[]nodes;
    void solve()throws Exception
    {
        long isolate=0;
        int n=nextInt();
        int m=nextInt();
        int[]a=new int[m];
        int[]b=new int[m];
        int[]deg=new int[n];
        for(int i=0;i<m;i++)
        {
            int x=nextInt()-1;
            int y=nextInt()-1;
            a[i]=x;
            b[i]=y;
            deg[x]++;
            deg[y]++;
        }
        int[][]g=new int[n][];
        for(int i=0;i<n;i++)
            g[i]=new int[deg[i]];
        for(int i=0;i<n;i++)
            deg[i]=0;
        for(int i=0;i<m;i++)
        {
            int x=a[i];
            int y=b[i];
            g[x][deg[x]++]=y;
            g[y][deg[y]++]=x;
        }
        for(int i=0;i<n;i++)
            Arrays.sort(g[i]);
        long res=0;
        boolean []vis=new boolean[n];
        for(int i=0;i<n;i++)
            if(deg[i]==0)
            {
                isolate++;
                vis[i]=true;
            }
        res=isolate*(isolate-1)/2;
        for(int i=0;i<n;i++)
            if(!vis[i])
            {
                Queue<Integer>q=new LinkedList<Integer>();
                q.add(i);
                vis[i]=true;
                HashMap<Item,Integer>map=new HashMap<Item,Integer>();
                while (q.size()>0)
                {
                    int at=q.remove();
                    int[]_ar=g[at];
                    Item ar=new Item();
                    ar.a=_ar;
                    if(!map.containsKey(ar))
                        map.put(ar,1);
                    else
                    {
                        int cur=map.get(ar);
                        res+=cur;
                        map.put(ar,cur+1);
                    }

                    for(int x: g[at])
                        if(!vis[x])
                        {
                            vis[x]=true;
                            q.add(x);
                        }
                }

            }

        vis=new boolean[n];
        for(int i=0;i<n;i++)
        {
            if(deg[i]==0)
            {
                vis[i]=true;
            }
            else
            {
                int[]other=new int[g[i].length+1];
                for(int j=0;j<other.length;j++)
                {
                    if(j==g[i].length)
                        other[j]=i;
                    else
                        other[j]=g[i][j];
                }
                Arrays.sort(other);
                g[i]=other;
            }
        }

        for(int i=0;i<n;i++)
                    if(!vis[i])
                    {
                        Queue<Integer>q=new LinkedList<Integer>();
                        q.add(i);
                        vis[i]=true;
                        HashMap<Item,Integer>map=new HashMap<Item,Integer>();
                        while (q.size()>0)
                        {
                            int at=q.remove();
                            int[]_ar=g[at];
                            Item ar=new Item();
                            ar.a=_ar;
                            if(!map.containsKey(ar))
                                map.put(ar,1);
                            else
                            {
                                int cur=map.get(ar);
                                res+=cur;
                                map.put(ar,cur+1);
                            }

                            for(int x: g[at])
                                if(!vis[x])
                                {
                                    vis[x]=true;
                                    q.add(x);
                                }
                        }

                    }

        System.out.println(res);

    }

    private void union(int x, int y) {
        x=find(x);
        y=find(y);
        if(x==y)
        {
            edges[x]++;
        }
        else
        {
            set[y]=x;
            nodes[x]+=nodes[y];
            edges[x]+=edges[y];
            edges[x]++;
        }
    }
    int find(int x)
    {
        if(set[x]==x)
            return x;
        return set[x]=find(set[x]);
    }

    ////////////
    BufferedReader reader;
    PrintWriter writer;
    StringTokenizer stk;
    void run()throws Exception
    {
        reader=new BufferedReader(new InputStreamReader(System.in));
        stk=null;
        writer=new PrintWriter(System.out);
        solve();
        reader.close();
        writer.close();
    }
    int nextInt()throws Exception
    {
        return Integer.parseInt(nextToken());
    }

    long nextLong()throws Exception
    {
        return Long.parseLong(nextToken());

    }
    double nextDouble()throws Exception
    {
        return Double.parseDouble(nextToken());

    }

    String nextString()throws Exception
    {
        return nextToken();
    }
    String nextLine()throws Exception
    {
        return reader.readLine();
    }
    String nextToken()throws Exception
    {
        if(stk==null || !stk.hasMoreTokens())
        {
            stk=new StringTokenizer(nextLine());
            return nextToken();

        }
        return stk.nextToken();
    }

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

}


import java.awt.Point;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.io.*;
import java.math.BigInteger;
import static java.math.BigInteger.*;
import java.util.*;

public class C{
    class Item
    {
        int[]a;
        public int hashCode()
        {
            return getMyHashCode(3217,a);
        }
        public boolean equals(Object other)
        {
            int[]b=(((Item)other).a);
            for(int x: new int[]{3217})
                if(getMyHashCode(x,a)!=getMyHashCode(x,b))
                    return false;
            return b.length==a.length;

        }
        int getMyHashCode(int x,int[]a)
        {
            int res=0;
            for(int y: a)
                res=x*res+y;
            return res;
        }
    }
    class Pair implements Comparable<Pair>
    {
        int x,y;
        public int compareTo(Pair other)
        {
            if(x!=other.x)
                return x-other.x;
            return y-other.y;
        }
    }
    int[]set;
    int[]edges;
    int[]nodes;
    void solve()throws Exception
    {
        long isolate=0;
        int n=nextInt();
        int m=nextInt();
        Pair[]a=new Pair[2*m];
        int[]deg=new int[n];
        for(int i=0;i<m;i++)
        {
            int x=nextInt()-1;
            int y=nextInt()-1;
            Pair cur=new Pair();
            cur.x=x;
            cur.y=y;
            a[2*i]=cur;
            cur=new Pair();
            cur.x=y;
            cur.y=x;
            a[2*i+1]=cur;
            deg[x]++;
            deg[y]++;
        }
        Arrays.sort(a);
        int[][]g=new int[n][];
        for(int i=0;i<n;i++)
        {
            g[i]=new int[deg[i]];
            if(deg[i]==0)
                isolate++;
        }
        for(int i=0;i<n;i++)
            deg[i]=0;
        for(int i=0;i<2*m;i++)
        {
            int x=a[i].x;
            int y=a[i].y;
            g[x][deg[x]++]=y;
        }
        long res=0;
        HashMap<Item,Integer>map=new HashMap<Item,Integer>();
        for(int i=0;i<n;i++)
            {
                    int[]_ar=g[i];
                    Item ar=new Item();
                    ar.a=_ar;
                    if(!map.containsKey(ar))
                        map.put(ar,1);
                    else
                    {
                        int cur=map.get(ar);
                        res+=cur;
                        map.put(ar,cur+1);
                    }
            }

        map.clear();

        for(int i=0;i<n;i++)
        {
            g[i]=merge(g[i],i);
        }

        for(int i=0;i<n;i++)
                    {
                            int[]_ar=g[i];
                            Item ar=new Item();
                            ar.a=_ar;
                            if(!map.containsKey(ar))
                                map.put(ar,1);
                            else
                            {
                                int cur=map.get(ar);
                                res+=cur;
                                map.put(ar,cur+1);
                            }
                    }

        System.out.println(res);

    }

    private int[] merge(int[] a, int x) {
        int[]res=new int[a.length+1];
        int at=0;
        while (at<a.length && a[at]<x)
            res[at]=a[at++];
        res[at]=x;
        while (at<a.length)
            res[1+at]=a[at++];
        return res;
    }

    private void union(int x, int y) {
        x=find(x);
        y=find(y);
        if(x==y)
        {
            edges[x]++;
        }
        else
        {
            set[y]=x;
            nodes[x]+=nodes[y];
            edges[x]+=edges[y];
            edges[x]++;
        }
    }
    int find(int x)
    {
        if(set[x]==x)
            return x;
        return set[x]=find(set[x]);
    }

    ////////////
    BufferedReader reader;
    PrintWriter writer;
    StringTokenizer stk;
    void run()throws Exception
    {
        reader=new BufferedReader(new InputStreamReader(System.in));
        stk=null;
        writer=new PrintWriter(System.out);
        solve();
        reader.close();
        writer.close();
    }
    int nextInt()throws Exception
    {
        return Integer.parseInt(nextToken());
    }

    long nextLong()throws Exception
    {
        return Long.parseLong(nextToken());

    }
    double nextDouble()throws Exception
    {
        return Double.parseDouble(nextToken());

    }

    String nextString()throws Exception
    {
        return nextToken();
    }
    String nextLine()throws Exception
    {
        return reader.readLine();
    }
    String nextToken()throws Exception
    {
        if(stk==null || !stk.hasMoreTokens())
        {
            stk=new StringTokenizer(nextLine());
            return nextToken();

        }
        return stk.nextToken();
    }

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

}


import java.awt.Point;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.io.*;
import java.math.BigInteger;
import static java.math.BigInteger.*;
import java.util.*;

public class C{
    class Item
    {
        int[]a;
        public int hashCode()
        {
            return getMyHashCode(31,a);
        }
        public boolean equals(Object other)
        {
            int[]b=(((Item)other).a);
            for(int x: new int[]{31,17,3217})
                if(getMyHashCode(x,a)!=getMyHashCode(x,b))
                    return false;
            return b.length==a.length;

        }
        int getMyHashCode(int x,int[]a)
        {
            int res=0;
            for(int y: a)
                res=x*res+y;
            return res;
        }
    }
    class Pair implements Comparable<Pair>
    {
        int x,y;
        public int compareTo(Pair other)
        {
            if(x!=other.x)
                return x-other.x;
            return y-other.y;
        }
    }
    int[]set;
    int[]edges;
    int[]nodes;
    void solve()throws Exception
    {
        long isolate=0;
        int n=nextInt();
        int m=nextInt();
        Pair[]a=new Pair[2*m];
        int[]deg=new int[n];
        for(int i=0;i<m;i++)
        {
            int x=nextInt()-1;
            int y=nextInt()-1;
            Pair cur=new Pair();
            cur.x=x;
            cur.y=y;
            a[2*i]=cur;
            cur=new Pair();
            cur.x=y;
            cur.y=x;
            a[2*i+1]=cur;
            deg[x]++;
            deg[y]++;
        }
        Arrays.sort(a);
        int[][]g=new int[n][];
        for(int i=0;i<n;i++)
        {
            g[i]=new int[deg[i]];
            if(deg[i]==0)
                isolate++;
        }
        for(int i=0;i<n;i++)
            deg[i]=0;
        for(int i=0;i<2*m;i++)
        {
            int x=a[i].x;
            int y=a[i].y;
            g[x][deg[x]++]=y;
        }
        long res=0;
        HashMap<Item,Integer>map=new HashMap<Item,Integer>();
        for(int i=0;i<n;i++)
            {
                    int[]_ar=g[i];
                    Item ar=new Item();
                    ar.a=_ar;
                    if(!map.containsKey(ar))
                        map.put(ar,1);
                    else
                    {
                        int cur=map.get(ar);
                        res+=cur;
                        map.put(ar,cur+1);
                    }
            }

        map.clear();

        for(int i=0;i<n;i++)
        {
            g[i]=merge(g[i],i);
        }

        for(int i=0;i<n;i++)
                    {
                            int[]_ar=g[i];
                            Item ar=new Item();
                            ar.a=_ar;
                            if(!map.containsKey(ar))
                                map.put(ar,1);
                            else
                            {
                                int cur=map.get(ar);
                                res+=cur;
                                map.put(ar,cur+1);
                            }
                    }

        System.out.println(res);

    }

    private int[] merge(int[] a, int x) {
        int[]res=new int[a.length+1];
        int at=0;
        while (at<a.length && a[at]<x)
            res[at]=a[at++];
        res[at]=x;
        while (at<a.length)
            res[1+at]=a[at++];
        return res;
    }

    private void union(int x, int y) {
        x=find(x);
        y=find(y);
        if(x==y)
        {
            edges[x]++;
        }
        else
        {
            set[y]=x;
            nodes[x]+=nodes[y];
            edges[x]+=edges[y];
            edges[x]++;
        }
    }
    int find(int x)
    {
        if(set[x]==x)
            return x;
        return set[x]=find(set[x]);
    }

    ////////////
    BufferedReader reader;
    PrintWriter writer;
    StringTokenizer stk;
    void run()throws Exception
    {
        reader=new BufferedReader(new InputStreamReader(System.in));
        stk=null;
        writer=new PrintWriter(System.out);
        solve();
        reader.close();
        writer.close();
    }
    int nextInt()throws Exception
    {
        return Integer.parseInt(nextToken());
    }

    long nextLong()throws Exception
    {
        return Long.parseLong(nextToken());

    }
    double nextDouble()throws Exception
    {
        return Double.parseDouble(nextToken());

    }

    String nextString()throws Exception
    {
        return nextToken();
    }
    String nextLine()throws Exception
    {
        return reader.readLine();
    }
    String nextToken()throws Exception
    {
        if(stk==null || !stk.hasMoreTokens())
        {
            stk=new StringTokenizer(nextLine());
            return nextToken();

        }
        return stk.nextToken();
    }

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

}


import java.awt.Point;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.io.*;
import java.math.BigInteger;
import static java.math.BigInteger.*;
import java.util.*;

public class C{
    class Item
    {
        int[]a;
        public int hashCode()
        {
            return Arrays.hashCode(a);
        }
        public boolean equals(Object other)
        {
            return Arrays.equals(((Item)other).a,a);
        }
    }
    int[]set;
    int[]edges;
    int[]nodes;
    void solve()throws Exception
    {
        long isolate=0;
        int n=nextInt();
        int m=nextInt();
        int[]a=new int[m];
        int[]b=new int[m];
        int[]deg=new int[n];
        for(int i=0;i<m;i++)
        {
            int x=nextInt()-1;
            int y=nextInt()-1;
            a[i]=x;
            b[i]=y;
            deg[x]++;
            deg[y]++;
        }
        int[][]g=new int[n][];
        for(int i=0;i<n;i++)
            g[i]=new int[deg[i]];
        for(int i=0;i<n;i++)
            deg[i]=0;
        for(int i=0;i<m;i++)
        {
            int x=a[i];
            int y=b[i];
            g[x][deg[x]++]=y;
            g[y][deg[y]++]=x;
        }
        for(int i=0;i<n;i++)
            Arrays.sort(g[i]);
        long res=0;
        boolean []vis=new boolean[n];
        for(int i=0;i<n;i++)
            if(deg[i]==0)
            {
                isolate++;
                vis[i]=true;
            }
        res=isolate*(isolate-1)/2;
        for(int i=0;i<n;i++)
            if(!vis[i])
            {
                Queue<Integer>q=new LinkedList<Integer>();
                q.add(i);
                vis[i]=true;
                HashMap<Item,Integer>map=new HashMap<Item,Integer>();
                while (q.size()>0)
                {
                    int at=q.remove();
                    int[]_ar=g[at];
                    Item ar=new Item();
                    ar.a=_ar;
                    if(!map.containsKey(ar))
                        map.put(ar,1);
                    else
                    {
                        int cur=map.get(ar);
                        res+=cur;
                        map.put(ar,cur+1);
                    }

                    for(int x: g[at])
                        if(!vis[x])
                        {
                            vis[x]=true;
                            q.add(x);
                        }
                }

            }

        vis=new boolean[n];
        for(int i=0;i<n;i++)
        {
            if(deg[i]==0)
            {
                vis[i]=true;
            }
            else
            {
                int[]other=new int[g[i].length+1];
                for(int j=0;j<other.length;j++)
                {
                    if(j==g[i].length)
                        other[j]=i;
                    else
                        other[j]=g[i][j];
                }
                Arrays.sort(other);
                g[i]=other;
            }
        }

        for(int i=0;i<n;i++)
                    if(!vis[i])
                    {
                        Queue<Integer>q=new LinkedList<Integer>();
                        q.add(i);
                        vis[i]=true;
                        HashMap<Item,Integer>map=new HashMap<Item,Integer>();
                        while (q.size()>0)
                        {
                            int at=q.remove();
                            int[]_ar=g[at];
                            Item ar=new Item();
                            ar.a=_ar;
                            if(!map.containsKey(ar))
                                map.put(ar,1);
                            else
                            {
                                int cur=map.get(ar);
                                res+=cur;
                                map.put(ar,cur+1);
                            }

                            for(int x: g[at])
                                if(!vis[x])
                                {
                                    vis[x]=true;
                                    q.add(x);
                                }
                        }

                    }

        System.out.println(res);

    }

    private void union(int x, int y) {
        x=find(x);
        y=find(y);
        if(x==y)
        {
            edges[x]++;
        }
        else
        {
            set[y]=x;
            nodes[x]+=nodes[y];
            edges[x]+=edges[y];
            edges[x]++;
        }
    }
    int find(int x)
    {
        if(set[x]==x)
            return x;
        return set[x]=find(set[x]);
    }

    ////////////
    BufferedReader reader;
    PrintWriter writer;
    StringTokenizer stk;
    void run()throws Exception
    {
        reader=new BufferedReader(new InputStreamReader(System.in));
        stk=null;
        writer=new PrintWriter(System.out);
        solve();
        reader.close();
        writer.close();
    }
    int nextInt()throws Exception
    {
        return Integer.parseInt(nextToken());
    }

    long nextLong()throws Exception
    {
        return Long.parseLong(nextToken());

    }
    double nextDouble()throws Exception
    {
        return Double.parseDouble(nextToken());

    }

    String nextString()throws Exception
    {
        return nextToken();
    }
    String nextLine()throws Exception
    {
        return reader.readLine();
    }
    String nextToken()throws Exception
    {
        if(stk==null || !stk.hasMoreTokens())
        {
            stk=new StringTokenizer(nextLine());
            return nextToken();

        }
        return stk.nextToken();
    }

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

}


import java.awt.Point;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.io.*;
import java.math.BigInteger;
import static java.math.BigInteger.*;
import java.util.*;

public class C{
    class Item
    {
        int[]a;
        public int hashCode()
        {
            return getMyHashCode(3217,a);
        }
        public boolean equals(Object other)
        {
            int[]b=(((Item)other).a);
            for(int x: new int[]{3217})
                if(getMyHashCode(x,a)!=getMyHashCode(x,b))
                    return false;
            return b.length==a.length;

        }
        int getMyHashCode(int x,int[]a)
        {
            int res=0;
            for(int y: a)
                res=x*res+y;
            return res;
        }
    }
    class Pair implements Comparable<Pair>
    {
        int x,y;
        public int compareTo(Pair other)
        {
            if(x!=other.x)
                return x-other.x;
            return y-other.y;
        }
        public int hashCode()
        {
            return 3217*x+y;
        }
        public boolean equals(Object other)
        {
            Pair p=(Pair)other;
            return p.x==x && p.y==y;
        }
    }

    void solve()throws Exception
    {

        int n=nextInt();
        int m=nextInt();
        Pair[]a=new Pair[2*m];
        int[]deg=new int[n];
        for(int i=0;i<m;i++)
        {
            int x=nextInt()-1;
            int y=nextInt()-1;
            Pair cur=new Pair();
            cur.x=x;
            cur.y=y;
            a[2*i]=cur;
            cur=new Pair();
            cur.x=y;
            cur.y=x;
            a[2*i+1]=cur;
            deg[x]++;
            deg[y]++;
        }
        //Arrays.sort(a);
        int[][]h=new int[2][n+1];
        int[][]pow=new int[2][n+1];
        int[]key=new int[]{31,1000000007};
        for(int j=0;j<2;j++)
        {
            pow[j][0]=1;
            for(int i=1;i<=n;i++)
                pow[j][i]=pow[j][i-1]*key[j];
        }

        for(int i=0;i<2*m;i++)
        {
            int x=a[i].x;
            int y=a[i].y;
            for(int j=0;j<2;j++)
                h[j][x]+=pow[j][y+1];
        }
        long res=0;
        HashMap<Pair,Integer>map=new HashMap<Pair,Integer>();
        for(int i=0;i<n;i++)
            {
                Pair cur=new Pair();
                cur.x=h[0][i];
                cur.y=h[1][i];
                if(!map.containsKey(cur))
                    map.put(cur,1);
                else
                {
                    int p=map.get(cur);
                    res+=p;
                    map.put(cur,p+1);
                }
            }
        map.clear();
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<2;j++)
                h[j][i]+=pow[j][i+1];
        }
               for(int i=0;i<n;i++)
            {
                Pair cur=new Pair();
                cur.x=h[0][i];
                cur.y=h[1][i];
                if(!map.containsKey(cur))
                    map.put(cur,1);
                else
                {
                    int p=map.get(cur);
                    res+=p;
                    map.put(cur,p+1);
                }
            }
        System.out.println(res);

    }
    ////////////
    BufferedReader reader;
    PrintWriter writer;
    StringTokenizer stk;
    void run()throws Exception
    {
        reader=new BufferedReader(new InputStreamReader(System.in));
        stk=null;
        writer=new PrintWriter(System.out);
        solve();
        reader.close();
        writer.close();
    }
    int nextInt()throws Exception
    {
        return Integer.parseInt(nextToken());
    }

    long nextLong()throws Exception
    {
        return Long.parseLong(nextToken());

    }
    double nextDouble()throws Exception
    {
        return Double.parseDouble(nextToken());

    }

    String nextString()throws Exception
    {
        return nextToken();
    }
    String nextLine()throws Exception
    {
        return reader.readLine();
    }
    String nextToken()throws Exception
    {
        if(stk==null || !stk.hasMoreTokens())
        {
            stk=new StringTokenizer(nextLine());
            return nextToken();

        }
        return stk.nextToken();
    }

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

}


import java.awt.Point;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.io.*;
import java.math.BigInteger;
import static java.math.BigInteger.*;
import java.util.*;

public class C{
    class Pair implements Comparable<Pair>
    {
        int x,y;
        public int compareTo(Pair other)
        {
            if(x!=other.x)
                return x-other.x;
            return y-other.y;
        }
        public int hashCode()
        {
            return 3217*x+y;
        }
        public boolean equals(Object other)
        {
            Pair p=(Pair)other;
            return p.x==x && p.y==y;
        }
    }

    void solve()throws Exception
    {

        int n=nextInt();
        int m=nextInt();
        Pair[]a=new Pair[2*m];
        int[]deg=new int[n];
        for(int i=0;i<m;i++)
        {
            int x=nextInt()-1;
            int y=nextInt()-1;
            Pair cur=new Pair();
            cur.x=x;
            cur.y=y;
            a[2*i]=cur;
            cur=new Pair();
            cur.x=y;
            cur.y=x;
            a[2*i+1]=cur;
            deg[x]++;
            deg[y]++;
        }
        //Arrays.sort(a);
        int[]h=new int[n+1];
        int[]pow=new int[n+1];
        int[]key=new int[]{1000000007};
        pow[0]=1;
        for(int i=1;i<=n;i++)
            pow[i]=pow[i-1]*key[0];
        for(int i=0;i<2*m;i++)
        {
            int x=a[i].x;
            int y=a[i].y;
            h[x]+=pow[y+1];
        }
        long res=0;
        HashMap<Integer,Integer>map=new HashMap<Integer,Integer>();
        for(int i=0;i<n;i++)
            {
                int cur=h[i];
                if(!map.containsKey(cur))
                    map.put(cur,1);
                else
                {
                    int p=map.get(cur);
                    res+=p;
                    map.put(cur,p+1);
                }
            }
        map.clear();
        for(int i=0;i<n;i++)
        {
           h[i]+=pow[i+1];
        }
        for(int i=0;i<n;i++)
            {
                int cur=h[i];
                if(!map.containsKey(cur))
                    map.put(cur,1);
                else
                {
                    int p=map.get(cur);
                    res+=p;
                    map.put(cur,p+1);
                }
            }

        System.out.println(res);

    }
    ////////////
    BufferedReader reader;
    PrintWriter writer;
    StringTokenizer stk;
    void run()throws Exception
    {
        reader=new BufferedReader(new InputStreamReader(System.in));
        stk=null;
        writer=new PrintWriter(System.out);
        solve();
        reader.close();
        writer.close();
    }
    int nextInt()throws Exception
    {
        return Integer.parseInt(nextToken());
    }

    long nextLong()throws Exception
    {
        return Long.parseLong(nextToken());

    }
    double nextDouble()throws Exception
    {
        return Double.parseDouble(nextToken());

    }

    String nextString()throws Exception
    {
        return nextToken();
    }
    String nextLine()throws Exception
    {
        return reader.readLine();
    }
    String nextToken()throws Exception
    {
        if(stk==null || !stk.hasMoreTokens())
        {
            stk=new StringTokenizer(nextLine());
            return nextToken();

        }
        return stk.nextToken();
    }

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

}


import static java.lang.Math.*;
import static java.lang.System.currentTimeMillis;
import static java.lang.System.exit;
import static java.lang.System.arraycopy;
import static java.util.Arrays.sort;
import static java.util.Arrays.binarySearch;
import static java.util.Arrays.fill;
import java.util.*;
import java.io.*;
import java.math.BigInteger;

public class Main {

	public static void main(String[] args) throws IOException {
		try {
			if (new File("input.txt").exists())
				System.setIn(new FileInputStream("input.txt"));
		} catch (SecurityException e) {
		}
		new Main().run();
	}

	BufferedReader in;
	PrintWriter out;
	StringTokenizer st = new StringTokenizer("");
	private void run() throws IOException {
		in = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(System.out);
		solve();
		in.close();
		out.close();
	}

	long base = BigInteger.probablePrime(27, new Random(812581)).longValue();

	int maxN = 100000;
	long h1[] = new long[maxN];
	long h2[] = new long[maxN];

	void solve() throws IOException{
		int n = nextInt();
		int m = nextInt();
		for(int i = 0; i < m; i++){
			int a = nextInt() - 1;
			int b = nextInt() - 1;
			h1[a] += pow(base, b);
			h1[b] += pow(base, a);
		}
		for(int i = 0; i < n; i++)
			h2[i] = h1[i] + pow(base, i);
		out.println(ans(h1, n) + ans(h2, n));
	}
	private long ans(long[] h, int n) {
		sort(h, 0, n);
		long ret = 0;
		long cnt = 0;
		for(int i = 0; i < n; i++){
			if(cnt == 0 || h[i] != h[i - 1]){
				ret += (cnt - 1) * cnt / 2;
				cnt = 0;
			}
			cnt++;
		}
		ret += (cnt - 1) * cnt / 2;
		return ret;
	}
	long pow(long b, int pow){
		long ret = 1;
		while(pow > 0){
			if((pow & 1) != 0)
				ret *= b;
			pow >>= 1;
			b *= b;
		}
		return ret;
	}

	class MultiList{
		int[] head, vert, next;
		int cnt;
		public MultiList(int h, int s) {
			s++;
			head = new int[h];
			vert = new int[s];
			next = new int[s];
			cnt = 1;
		}
		void add(int h, int v){
			vert[cnt] = v;
			next[cnt] = head[h];
			head[h] = cnt++;
		}
	}

	void chk(boolean b) {
		if (b)
			return;
		System.out.println(new Error().getStackTrace()[1]);
		exit(999);
	}
	void deb(String fmt, Object... args) {
		System.out.printf(Locale.US, fmt + "%n", args);
	}
	String nextToken() throws IOException {
		while (!st.hasMoreTokens())
			st = new StringTokenizer(in.readLine());
		return st.nextToken();
	}
	int nextInt() throws IOException {
		return Integer.parseInt(nextToken());
	}
	long nextLong() throws IOException {
		return Long.parseLong(nextToken());
	}
	double nextDouble() throws IOException {
		return Double.parseDouble(nextToken());
	}
	String nextLine() throws IOException {
		st = new StringTokenizer("");
		return in.readLine();
	}
	boolean EOF() throws IOException {
		while (!st.hasMoreTokens()) {
			String s = in.readLine();
			if (s == null)
				return true;
			st = new StringTokenizer(s);
		}
		return false;
	}
}


import static java.lang.Math.*;
import static java.lang.System.currentTimeMillis;
import static java.lang.System.exit;
import static java.lang.System.arraycopy;
import static java.util.Arrays.sort;
import static java.util.Arrays.binarySearch;
import static java.util.Arrays.fill;
import java.util.*;
import java.io.*;
import java.math.BigInteger;

public class Main {

	public static void main(String[] args) throws IOException {
		try {
			if (new File("input.txt").exists())
				System.setIn(new FileInputStream("input.txt"));
		} catch (SecurityException e) {
		}
		new Main().run();
	}

	BufferedReader in;
	PrintWriter out;
	StringTokenizer st = new StringTokenizer("");
	private void run() throws IOException {
		in = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(System.out);
		solve();
		in.close();
		out.close();
	}

	long base = BigInteger.probablePrime(27, new Random(812581)).longValue();

	int maxN = 1000000;
	long h1[] = new long[maxN];
	long h2[] = new long[maxN];

	void solve() throws IOException{
		int n = nextInt();
		int m = nextInt();
		for(int i = 0; i < m; i++){
			int a = nextInt() - 1;
			int b = nextInt() - 1;
			h1[a] += pow(base, b);
			h1[b] += pow(base, a);
		}
		for(int i = 0; i < n; i++)
			h2[i] = h1[i] + pow(base, i);
		out.println(ans(h1, n) + ans(h2, n));
	}
	private long ans(long[] h, int n) {
		sort(h, 0, n);
		long ret = 0;
		long cnt = 0;
		for(int i = 0; i < n; i++){
			if(cnt == 0 || h[i] != h[i - 1]){
				ret += (cnt - 1) * cnt / 2;
				cnt = 0;
			}
			cnt++;
		}
		ret += (cnt - 1) * cnt / 2;
		return ret;
	}
	long pow(long b, int pow){
		long ret = 1;
		while(pow > 0){
			if((pow & 1) != 0)
				ret *= b;
			pow >>= 1;
			b *= b;
		}
		return ret;
	}

	void chk(boolean b) {
		if (b)
			return;
		System.out.println(new Error().getStackTrace()[1]);
		exit(999);
	}
	void deb(String fmt, Object... args) {
		System.out.printf(Locale.US, fmt + "%n", args);
	}
	String nextToken() throws IOException {
		while (!st.hasMoreTokens())
			st = new StringTokenizer(in.readLine());
		return st.nextToken();
	}
	int nextInt() throws IOException {
		return Integer.parseInt(nextToken());
	}
	long nextLong() throws IOException {
		return Long.parseLong(nextToken());
	}
	double nextDouble() throws IOException {
		return Double.parseDouble(nextToken());
	}
	String nextLine() throws IOException {
		st = new StringTokenizer("");
		return in.readLine();
	}
	boolean EOF() throws IOException {
		while (!st.hasMoreTokens()) {
			String s = in.readLine();
			if (s == null)
				return true;
			st = new StringTokenizer(s);
		}
		return false;
	}
}


import static java.util.Arrays.*;
import static java.lang.Math.*;
import static java.math.BigInteger.*;
import java.util.*;
import java.math.*;
import java.io.*;

public class C implements Runnable
{
    String file = "input";

    boolean TEST = System.getProperty("ONLINE_JUDGE") == null;

    void solve() throws IOException
    {
        int n = nextInt(), m = nextInt();
        long[] pow = new long[n];
        long[] hash = new long[n];
        final long p = 31;
        pow[0] = 1;
        for(int i = 1; i < n; i++) pow[i] = pow[i - 1] * p;

        int[][] edge = new int[m][2];
        for(int i = 0; i < m; i++)
        {
            int u = nextInt() - 1;
            int v = nextInt() - 1;
            hash[u] += pow[v];
            hash[v] += pow[u];
            edge[i][0] = u;
            edge[i][1] = v;
        }
        long res = 0;
        for(int i = 0; i < m; i++)
        {
            int u = edge[i][0];
            int v = edge[i][1];

            if(hash[u] + pow[u] == hash[v] + pow[v]) res++;
        }

        sort(hash);
        long start = 0, current = hash[0];
        for(int i = 1; i < n; i++)
            if(hash[i] != current)
            {
                res += (i - start) * (i - start - 1) / 2;
                current = hash[i];
                start = i;
            }
        res += (n - start) * (n - start - 1) / 2;
        out.println(res);
    }

    String next() throws IOException
    {
        while(st == null || !st.hasMoreTokens()) st = new StringTokenizer(input.readLine());
        return st.nextToken();
    }

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

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

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

    void print(Object... o)
    {
        System.out.println(deepToString(o));
    }

    void gcj(Object o)
    {
        String s = String.valueOf(o);
        out.println("Case #" + test + ": " + s);
        System.out.println("Case #" + test + ": " + s);
    }

    BufferedReader input;
    PrintWriter out;
    StringTokenizer st;
    int test;

    void init() throws IOException
    {
        if(TEST) input = new BufferedReader(new FileReader(file + ".in"));
        else input = new BufferedReader(new InputStreamReader(System.in));
        out = new PrintWriter(new BufferedOutputStream(System.out));
    }

    public static void main(String[] args) throws IOException
    {
        new Thread(null, new C(), "", 1 << 20).start();
    }

    public void run()
    {
        try
        {
            init();
            if(TEST)
            {
                int runs = nextInt();
                for(int i = 0; i < runs; i++) solve();
            }
            else solve();
            out.close();
        }
        catch(Exception e)
        {
            e.printStackTrace();
            System.exit(1);
        }
    }
}


import static java.util.Arrays.*;
import static java.lang.Math.*;
import static java.math.BigInteger.*;
import java.util.*;
import java.math.*;
import java.io.*;

public class C implements Runnable
{
	String file = "input";

	boolean TEST = System.getProperty("ONLINE_JUDGE") == null;

	void solve() throws IOException
	{
		int n = nextInt(), m = nextInt();
		long[] pow = new long[n];
		long[] hash = new long[n];
		final long p = 29;
		pow[0] = 1;
		for(int i = 1; i < n; i++) pow[i] = pow[i - 1] * p;

		int[][] edge = new int[m][2];
		for(int i = 0; i < m; i++)
		{
			int u = nextInt() - 1;
			int v = nextInt() - 1;
			hash[u] += pow[v];
			hash[v] += pow[u];
			edge[i][0] = u;
			edge[i][1] = v;
		}
		long res = 0;
		for(int i = 0; i < m; i++)
		{
			int u = edge[i][0];
			int v = edge[i][1];

			if(hash[u] + pow[u] == hash[v] + pow[v]) res++;
		}

		sort(hash);
		long start = 0, current = hash[0];
		for(int i = 1; i < n; i++)
			if(hash[i] != current)
			{
				res += (i - start) * (i - start - 1) / 2;
				current = hash[i];
				start = i;
			}
		res += (n - start) * (n - start - 1) / 2;
		out.println(res);
	}

	String next() throws IOException
	{
		while(st == null || !st.hasMoreTokens()) st = new StringTokenizer(input.readLine());
		return st.nextToken();
	}

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

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

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

	void print(Object... o)
	{
		System.out.println(deepToString(o));
	}

	void gcj(Object o)
	{
		String s = String.valueOf(o);
		out.println("Case #" + test + ": " + s);
		System.out.println("Case #" + test + ": " + s);
	}

	BufferedReader input;
	PrintWriter out;
	StringTokenizer st;
	int test;

	void init() throws IOException
	{
		if(TEST) input = new BufferedReader(new FileReader(file + ".in"));
		else input = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(new BufferedOutputStream(System.out));
	}

	public static void main(String[] args) throws IOException
	{
		new Thread(null, new C(), "", 1 << 20).start();
	}

	public void run()
	{
		try
		{
			init();
			if(TEST)
			{
				int runs = nextInt();
				for(int i = 0; i < runs; i++) solve();
			}
			else solve();
			out.close();
		}
		catch(Exception e)
		{
			e.printStackTrace();
			System.exit(1);
		}
	}
}


import static java.util.Arrays.*;
import static java.lang.Math.*;
import static java.math.BigInteger.*;
import java.util.*;
import java.math.*;
import java.io.*;

public class C implements Runnable
{
    String file = "input";

    boolean TEST = System.getProperty("ONLINE_JUDGE") == null;

    void solve() throws IOException
    {
        int n = nextInt(), m = nextInt();
        long[] pow = new long[n];
        long[] hash = new long[n];
        final long p = 10007;
        pow[0] = 1;
        for(int i = 1; i < n; i++) pow[i] = pow[i - 1] * p;

        int[][] edge = new int[m][2];
        for(int i = 0; i < m; i++)
        {
            int u = nextInt() - 1;
            int v = nextInt() - 1;
            hash[u] += pow[v];
            hash[v] += pow[u];
            edge[i][0] = u;
            edge[i][1] = v;
        }
        long res = 0;
        for(int i = 0; i < m; i++)
        {
            int u = edge[i][0];
            int v = edge[i][1];

            if(hash[u] + pow[u] == hash[v] + pow[v]) res++;
        }

        sort(hash);
        long start = 0, current = hash[0];
        for(int i = 1; i < n; i++)
            if(hash[i] != current)
            {
                res += (i - start) * (i - start - 1) / 2;
                current = hash[i];
                start = i;
            }
        res += (n - start) * (n - start - 1) / 2;
        out.println(res);
    }

    String next() throws IOException
    {
        while(st == null || !st.hasMoreTokens()) st = new StringTokenizer(input.readLine());
        return st.nextToken();
    }

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

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

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

    void print(Object... o)
    {
        System.out.println(deepToString(o));
    }

    void gcj(Object o)
    {
        String s = String.valueOf(o);
        out.println("Case #" + test + ": " + s);
        System.out.println("Case #" + test + ": " + s);
    }

    BufferedReader input;
    PrintWriter out;
    StringTokenizer st;
    int test;

    void init() throws IOException
    {
        if(TEST) input = new BufferedReader(new FileReader(file + ".in"));
        else input = new BufferedReader(new InputStreamReader(System.in));
        out = new PrintWriter(new BufferedOutputStream(System.out));
    }

    public static void main(String[] args) throws IOException
    {
        new Thread(null, new C(), "", 1 << 20).start();
    }

    public void run()
    {
        try
        {
            init();
            if(TEST)
            {
                int runs = nextInt();
                for(int i = 0; i < runs; i++) solve();
            }
            else solve();
            out.close();
        }
        catch(Exception e)
        {
            e.printStackTrace();
            System.exit(1);
        }
    }
}


#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#define N 120
#define M 10020
#define G 1000000000LL
using namespace std;

long long a[N], f[N];
int t[M], x[M], l[M], r[M];
long long v[M];

int main(void)
{
    int n, m;
    int i, j;
    long long o;

    scanf("%d %d", &n, &m);
    for(i = 1; i <= n; i ++)
        scanf("%I64d", &a[i]);
    for(i = 2, f[0] = f[1] = 1LL; i <= n; i ++)
        f[i] = (f[i - 1] + f[i - 2]) % G;
    for(i = 0; i < m; i ++)
    {
        scanf("%d", &t[i]);
        if(t[i] == 1)
        {
            scanf("%d %I64d", &x[i], &v[i]);
            a[x[i]] = v[i];
        }
        if(t[i] == 2)
        {
            scanf("%d %d", &l[i], &r[i]);
            for(j = o = 0; l[i] + j <= r[i]; j ++)
                (o += f[j] * a[l[i] + j] % G) %= G;
            printf("%I64d\n", o);
        }
    }

    return 0;
}


#include<bits/stdc++.h>

using namespace std;

#define ff first
#define ss second
#define pb push_back
#define mp make_pair
#define all(x) x.begin(),x.end()
#define sz(x) ((int)x.size())

const int MOD = 1e9;

typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
const int MAXN = 2e5+5;
ll pre[MAXN];
ll f[MAXN];
struct node {
	ll m0,m1,lazy;
};
struct node v[3*MAXN];
int ar[MAXN];
typedef vector<vector<ll> > matrix;
matrix unit;
matrix multiplyMatrix(matrix a, matrix b) {
	matrix res=a;
	for(int i=0;i<sz(res);i++) for(int j=0;j<sz(res[0]);j++) res[i][j]=0;
	for(int i=0;i<sz(res);i++) for(int j=0;j<sz(res);j++) for(int k=0;k<sz(res);k++) {
		res[i][j]+=a[i][k]*b[k][j]%MOD;
		if(res[i][j]>=MOD) res[i][j]-=MOD;
	}
	return res;
}
matrix power(matrix m, ll z) {
	if(z==0) return unit;
	if(z==1) return m;
	matrix p = power(m,z/2);
	p=multiplyMatrix(p,p);
	if(z%2==0) return p;
	else return multiplyMatrix(p,m);
}
ll multiply(ll a, ll b, ll c) {
	swap(a,b);
	matrix m;
	m.resize(2);
	for(int i=0;i<2;i++) m[i].resize(2);
	m[0][0]=1;
	m[0][1]=1;
	m[1][0]=1;
	m[1][1]=0;
	m = power(m,c);
	ll r = m[0][0]*a;
	r%=MOD;
	r += m[0][1]*b%MOD;
	if(r>=MOD) r-=MOD;
	return r;
}
void build(int node, int start, int end) {
	if(start==end) {
		v[node].m0=ar[start];
		v[node].m1=ar[start];
		// cout<<node<<" "<<start<<" "<<end<<" "<<v[node].m0<<" "<<v[node].m1<<endl;
		return;
	}
	int mid=(start+end)>>1;
	build(2*node,start,mid);
	build(2*node+1,mid+1,end);
	int mul = mid-start+1;
	ll z = multiply(v[2*node+1].m0,v[2*node+1].m1,mul-1);
	v[node].m0=v[2*node].m0+z;
	if(v[node].m0>=MOD) v[node].m0-=MOD;
	z = multiply(v[2*node+1].m0,v[2*node+1].m1,mul);
	v[node].m1=v[2*node].m1+z;
	if(v[node].m1>=MOD) v[node].m1-=MOD;
	// cout<<node<<" "<<start<<" "<<end<<" "<<v[node].m0<<" "<<v[node].m1<<endl;
}
void update(int node, int start, int end, int qs, int qe, int vv, bool q) {
	if(v[node].lazy) {
		int len=end-start+1;
		v[node].m0 += pre[len-1]*v[node].lazy%MOD;
		v[node].m1 += ((pre[len]-pre[0]+MOD)%MOD)*v[node].lazy%MOD;
		if(start!=end) v[2*node].lazy+=v[node].lazy,v[2*node+1].lazy+=v[node].lazy;
		v[node].lazy=0;
	}
	if(start>end or qe<start or qs>end) return;
	if(start>=qs and end<=qe) {
		if(!q) {
			v[node].m0=vv;
			v[node].m1=vv;
		}
		else {
			int len=end-start+1;
			v[node].lazy+=vv;
			v[node].m0 += pre[len-1]*v[node].lazy%MOD;
			v[node].m1 += ((pre[len]-pre[0]+MOD)%MOD)*v[node].lazy%MOD;
			if(start!=end) v[2*node].lazy+=v[node].lazy,v[2*node+1].lazy+=v[node].lazy;
			v[node].lazy=0;
		}
		return;
	}
	int mid=(start+end)>>1;
	update(2*node,start,mid,qs,qe,vv,q);
	update(2*node+1,mid+1,end,qs,qe,vv,q);
	int mul = mid-start+1;
	ll z = multiply(v[2*node+1].m0,v[2*node+1].m1,mul-1);
	v[node].m0=v[2*node].m0+z;
	if(v[node].m0>=MOD) v[node].m0-=MOD;
	z = multiply(v[2*node+1].m0,v[2*node+1].m1,mul);
	v[node].m1=v[2*node].m1+z;
	if(v[node].m1>=MOD) v[node].m1-=MOD;
}
pll query(int node, int start, int end, int qs, int qe) {
	if(v[node].lazy) {
		int len=end-start+1;
		v[node].m0 += pre[len-1]*v[node].lazy%MOD;
		v[node].m1 += ((pre[len]-pre[0]+MOD)%MOD)*v[node].lazy%MOD;
		if(start!=end) v[2*node].lazy+=v[node].lazy,v[2*node+1].lazy+=v[node].lazy;
		v[node].lazy=0;
	}
	if(start>end or qe<start or qs>end) return mp(-1,-1);
	if(start>=qs and end<=qe) {
		return mp(v[node].m0,v[node].m1);
	}
	int mid=(start+end)>>1;
	pll z1 = query(2*node,start,mid,qs,qe);
	pll z2 = query(2*node+1,mid+1,end,qs,qe);
	// cout<<node<<" "<<start<<" "<<mid<<" "<<end<<" "<<z1.ff<<" "<<z1.ss<<" "<<z2.ff<<" "<<z2.ss<<endl;
	int mul = mid-start+1;
	ll z = multiply(v[2*node+1].m0,v[2*node+1].m1,mul-1);
	v[node].m0=v[2*node].m0+z;
	if(v[node].m0>=MOD) v[node].m0-=MOD;
	z = multiply(v[2*node+1].m0,v[2*node+1].m1,mul);
	v[node].m1=v[2*node].m1+z;
	if(v[node].m1>=MOD) v[node].m1-=MOD;
	if(z1.ff==-1) return z2;
	if(z2.ff==-1) return z1;
	int lf = min(mid-start+1,mid-qs+1);
	ll v1 = multiply(z2.ff,z2.ss,lf-1);
	z1.ff += v1;
	if(z1.ff>=MOD) z1.ff-=MOD;
	v1 = multiply(z2.ff,z2.ss,lf);
	z1.ss += v1;
	if(z1.ss>=MOD) z1.ss-=MOD;
	return z1;
}
int main() {
	// freopen("TASK.in","r",stdin);freopen("TASK.out","w",stdout);
	unit.resize(2);
	unit[0].resize(2);
	unit[1].resize(2);
	unit[0][0]=unit[1][1]=1;
	unit[0][1]=unit[1][0]=0;
	int n,m;
	cin>>n>>m;
	f[0]=f[1]=1;
	pre[0]=1;
	pre[1]=2;
	for(int i=2;i<MAXN;i++) {
		f[i]=f[i-1]+f[i-2];
		if(f[i]>=MOD) f[i]-=MOD;
		pre[i]=pre[i-1]+f[i];
		if(pre[i]>=MOD) pre[i]-=MOD;
	}
	for(int i=1;i<=n;i++) scanf("%d",&ar[i]);
	build(1,1,n);
	while(m--) {
		int t,l,r;
		scanf("%d%d%d",&t,&l,&r);
		if(t==1) update(1,1,n,l,l,r,false);
		else if(t==2) printf("%lld\n",query(1,1,n,l,r).ff);
		else {
			int d;
			scanf("%d",&d);
			update(1,1,n,l,r,d,true);
		}
	}
	return 0;
}


#include<bits/stdc++.h>

using namespace std;

#define ff first
#define ss second
#define pb push_back
#define mp make_pair
#define all(x) x.begin(),x.end()
#define sz(x) ((int)x.size())

const int MOD = 1e9;

typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
const int MAXN = 2e5+5;
ll pre[MAXN];
ll f[MAXN];
struct node {
	ll m0,m1,lazy;
};
struct node v[3*MAXN];
int ar[MAXN];
typedef vector<vector<ll> > matrix;
matrix unit;
matrix multiplyMatrix(matrix a, matrix b) {
	matrix res=a;
	for(int i=0;i<sz(res);i++) for(int j=0;j<sz(res[0]);j++) res[i][j]=0;
	for(int i=0;i<sz(res);i++) for(int j=0;j<sz(res);j++) for(int k=0;k<sz(res);k++) {
		res[i][j]+=a[i][k]*b[k][j]%MOD;
		if(res[i][j]>=MOD) res[i][j]-=MOD;
	}
	return res;
}
matrix power(matrix m, ll z) {
	if(z==0) return unit;
	if(z==1) return m;
	matrix p = power(m,z/2);
	p=multiplyMatrix(p,p);
	if(z%2==0) return p;
	else return multiplyMatrix(p,m);
}
ll multiply(ll a, ll b, ll c) {
	swap(a,b);
	matrix m;
	m.resize(2);
	for(int i=0;i<2;i++) m[i].resize(2);
	m[0][0]=1;
	m[0][1]=1;
	m[1][0]=1;
	m[1][1]=0;
	m = power(m,c);
	ll r = m[0][0]*a;
	r%=MOD;
	r += m[0][1]*b%MOD;
	if(r>=MOD) r-=MOD;
	return r;
}
void build(int node, int start, int end) {
	if(start==end) {
		v[node].m0=ar[start];
		v[node].m1=ar[start];
		// cout<<node<<" "<<start<<" "<<end<<" "<<v[node].m0<<" "<<v[node].m1<<endl;
		return;
	}
	int mid=(start+end)>>1;
	build(2*node,start,mid);
	build(2*node+1,mid+1,end);
	int mul = mid-start+1;
	ll z = multiply(v[2*node+1].m0,v[2*node+1].m1,mul-1);
	v[node].m0=v[2*node].m0+z;
	if(v[node].m0>=MOD) v[node].m0-=MOD;
	z = multiply(v[2*node+1].m0,v[2*node+1].m1,mul);
	v[node].m1=v[2*node].m1+z;
	if(v[node].m1>=MOD) v[node].m1-=MOD;
	// cout<<node<<" "<<start<<" "<<end<<" "<<v[node].m0<<" "<<v[node].m1<<endl;
}
void update(int node, int start, int end, int qs, int qe, int vv, bool q) {
	if(v[node].lazy) {
		int len=end-start+1;
		v[node].m0 += pre[len-1]*v[node].lazy%MOD;
		v[node].m1 += ((pre[len]-pre[0]+MOD)%MOD)*v[node].lazy%MOD;
		if(start!=end) v[2*node].lazy+=v[node].lazy,v[2*node+1].lazy+=v[node].lazy;
		v[node].lazy=0;
	}
	if(start>end or qe<start or qs>end) return;
	if(start>=qs and end<=qe) {
		if(!q) {
			v[node].m0=vv;
			v[node].m1=vv;
		}
		else {
			int len=end-start+1;
			v[node].lazy+=vv;
			v[node].m0 += pre[len-1]*v[node].lazy%MOD;
			v[node].m1 += ((pre[len]-pre[0]+MOD)%MOD)*v[node].lazy%MOD;
			if(start!=end) v[2*node].lazy+=v[node].lazy,v[2*node+1].lazy+=v[node].lazy;
			v[node].lazy=0;
		}
		return;
	}
	int mid=(start+end)>>1;
	update(2*node,start,mid,qs,qe,vv,q);
	update(2*node+1,mid+1,end,qs,qe,vv,q);
	int mul = mid-start+1;
	ll z = multiply(v[2*node+1].m0,v[2*node+1].m1,mul-1);
	v[node].m0=v[2*node].m0+z;
	if(v[node].m0>=MOD) v[node].m0-=MOD;
	z = multiply(v[2*node+1].m0,v[2*node+1].m1,mul);
	v[node].m1=v[2*node].m1+z;
	if(v[node].m1>=MOD) v[node].m1-=MOD;
}
pll query(int node, int start, int end, int qs, int qe) {
	if(v[node].lazy) {
		int len=end-start+1;
		v[node].m0 += pre[len-1]*v[node].lazy%MOD;
		v[node].m1 += ((pre[len]-pre[0]+MOD)%MOD)*v[node].lazy%MOD;
		if(start!=end) v[2*node].lazy+=v[node].lazy,v[2*node+1].lazy+=v[node].lazy;
		v[node].lazy=0;
	}
	if(start>end or qe<start or qs>end) return mp(-1,-1);
	if(start>=qs and end<=qe) {
		return mp(v[node].m0,v[node].m1);
	}
	int mid=(start+end)>>1;
	pll z1 = query(2*node,start,mid,qs,qe);
	pll z2 = query(2*node+1,mid+1,end,qs,qe);
	int mul = mid-start+1;
	ll z = multiply(v[2*node+1].m0,v[2*node+1].m1,mul-1);
	v[node].m0=v[2*node].m0+z;
	if(v[node].m0>=MOD) v[node].m0-=MOD;
	z = multiply(v[2*node+1].m0,v[2*node+1].m1,mul);
	v[node].m1=v[2*node].m1+z;
	if(v[node].m1>=MOD) v[node].m1-=MOD;
	if(z1.ff==-1) return z2;
	if(z2.ff==-1) return z1;
	int lf = mid-qs+1;
	ll v1 = multiply(z2.ff,z2.ss,lf-1);
	z1.ff += v1;
	if(z1.ff>=MOD) z1.ff-=MOD;
	v1 = multiply(z2.ff,z2.ss,lf);
	z1.ss += v1;
	if(z1.ss>=MOD) z1.ss-=MOD;
	return z1;
}
int main() {
	// freopen("TASK.in","r",stdin);freopen("TASK.out","w",stdout);
	unit.resize(2);
	unit[0].resize(2);
	unit[1].resize(2);
	unit[0][0]=unit[1][1]=1;
	unit[0][1]=unit[1][0]=0;
	int n,m;
	cin>>n>>m;
	f[0]=f[1]=1;
	pre[0]=1;
	pre[1]=2;
	for(int i=2;i<MAXN;i++) {
		f[i]=f[i-1]+f[i-2];
		if(f[i]>=MOD) f[i]-=MOD;
		pre[i]=pre[i-1]+f[i];
		if(pre[i]>=MOD) pre[i]-=MOD;
	}
	for(int i=1;i<=n;i++) scanf("%d",&ar[i]);
	build(1,1,n);
	while(m--) {
		int t,l,r;
		scanf("%d%d%d",&t,&l,&r);
		if(t==1) update(1,1,n,l,l,r,false);
		else if(t==2) printf("%lld\n",query(1,1,n,l,r).ff);
		else {
			int d;
			scanf("%d",&d);
			update(1,1,n,l,r,d,true);
		}
	}
	return 0;
}


/*
 If I'm gonna survive
 I'll make it barely alive
 */
#include <bits/stdc++.h>
//#define int long long
#define hash hashhash
#define X first
#define Y second
#define endl "\n"
#define Mp make_pair
using namespace std;
inline int in(){int32_t x ; scanf("%d",&x) ; return x ; }
inline long long lin(){long long x ; scanf("%lld",&x) ; return x ;}
char ch[4000010];
inline string get(){ scanf("%s",ch) ; return string(ch) ; }
inline void read(int *a , int n ) { for (int i = 0 ; i < n ; i ++) a[i] = in() ; }
template <class blank> inline void out(blank x) {cout << x << endl ; exit(0) ;}
template <class blank> inline void smin(blank &a , blank b) {a = min(a , b) ;}
template <class blank> inline void smax(blank &a , blank b) {a = max(a , b) ; }
typedef pair<int , int > pii;
typedef long double ld;
typedef unsigned long long ull;
typedef long long ll;
typedef vector<int> vi;
typedef vector<pii> vii;
const int maxn  = 2e5  + 10;
const int maxm = 2e6 + 10;
const int maxlg = 61;
const int base = 29;
//const int mod = 1e9 + 7;
const int mod = 1e9;
const int inf = 2e18 + 10;
int a[maxn],n,q,lazy[4*maxn],fib[maxn],fibSum[maxn];
pii stree[4*maxn];
inline int rel(int x) {if (x >= mod) return x - mod ; return x ; }
inline void merge(int p , int lenLeft)
{
    stree[p].X = (ll)(stree[2 * p + 1].X + 1LL * stree[2 * p + 2].X * (lenLeft == 1 ? 0 : fib[lenLeft - 2])
                  + 1LL * stree[2 * p + 2].Y * fib[lenLeft - 1]) % mod;
    stree[p].Y = (ll)(stree[2 * p + 1].Y + 1LL * stree[2 * p + 2].X * fib[lenLeft - 1]
                  + 1LL * stree[2 * p + 2].Y * fib[lenLeft]) % mod;
}
inline void build(int p = 0 , int l = 0 , int r = n - 1)
{
    if (l == r)
    {
        stree[p].X = stree[p].Y = a[l];
        return ;
    }
    int mid = (l + r) >> 1;
    build(2 * p + 1 , l , mid) , build(2 * p + 2 , mid + 1 , r);
    merge(p,mid-l+1);
}

inline void apply(int p , int val , int len)
{
    lazy[p] = rel(lazy[p] + val);
    stree[p].X = rel(stree[p].X + 1LL * val * fibSum[len - 1] % mod);
    stree[p].Y = rel(stree[p].Y + 1LL * val * (fibSum[len] - 1) % mod);
}
inline void shift(int p , int len)
{
    if (lazy[p])
    {
        int RightLen = len/2 , LeftLen = len - RightLen;
        apply(2*p+1,lazy[p],LeftLen) , apply(2*p+2,lazy[p],RightLen);
        lazy[p] = 0;
    }
}
inline void update(int x , int p = 0 , int l = 0 , int r = n - 1)
{
    if (l > x ||r < x) return ;
    if (l == r) {stree[p].X = stree[p].Y = a[x]; return ;}
    int mid = (l + r) >> 1;
    shift(p,r-l+1);
    update(x,2*p+1,l,mid);
    update(x,2*p+2,mid+1,r);
    merge(p,mid-l+1);
}

inline void add(int ql , int qr , int val , int p = 0 , int l = 0 , int r = n - 1)
{
    if (l > qr || r < ql ) return ;
    if (l >= ql && r <= qr){
        apply(p,val,r-l+1);
        return;
    }
    int mid = (l + r) >> 1;
    shift(p,r-l+1);
    add(ql,qr,val,2*p+1,l,mid) , add(ql,qr,val,2*p+2,mid+1,r);
    merge(p,mid-l+1);
}
pii ret;
int cur = 0;
inline void get(int ql , int qr , int p = 0 , int l = 0 , int r = n - 1)
{
    if (l > qr || r < ql ) return ;
    if (l >= ql && r <= qr)
    {
        if (cur == 0) {ret = stree[p] ; cur = r - l + 1 ; return ;}
        pii pre = ret;
        ret.X = (ll)(pre.X + 1LL * stree[p].X * (cur == 1 ? 0 : fib[cur - 2]) + 1LL * stree[p].Y * fib[cur - 1]) % mod;
        ret.Y = (ll)(pre.Y + 1LL * stree[p].X * fib[cur - 1] + 1LL * stree[p].Y * fib[cur]) % mod;
        cur += r - l + 1;
        return ;
    }
    int mid = (l + r) >> 1;
    shift(p,r-l+1);
    get(ql,qr,2*p+1,l,mid);
    get(ql,qr,2*p+2,mid+1,r);
}
int32_t main()
{
    n = in() , q = in();
    fib[0] = fib[1] = fibSum[0] = 1; fibSum[1] = 2;
    for (int i = 2 ; i < maxn ; i ++){
        fib[i] = rel(fib[i-1]+fib[i-2]);
        fibSum[i] = rel(fibSum[i-1]+fib[i]);
    }
    read(a,n);
    build();
    while (q --)
    {
        int tp = in();
        if (tp == 1)
        {
            int x = in() - 1 , val = in();
            a[x] = val;
            update(x);
        }
        else if (tp == 2)
        {
            int l = in() - 1 , r = in() - 1;
            ret.first = ret.second = 0;
            cur = 0;
            get(l,r);
            printf("%d\n",ret.first);
        }
        else
        {
            int l = in() - 1 , r = in() - 1 , val = in();
            add(l,r,val);
        }
    }
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MAX=2e5+9,MOD=1e9;
pair<int,int> seg[4*MAX];
int n,m,x,lazy[4*MAX],fib[MAX],pfib[MAX];
pair<int,int> merge(pair<int,int> a,pair<int,int> b,int l,int mid)
{
	pair<int,int> ans;
	if (mid-l==1){ans.first=(a.first+b.second)%MOD,ans.second=(1LL*a.second+b.first+b.second)%MOD;return ans;}
	ans.first=(1LL*a.first+1LL*fib[mid-l-2]*b.first+1LL*fib[mid-l-1]*b.second)%MOD,ans.second=(1LL*a.second+1LL*fib[mid-l-1]*b.first+1LL*fib[mid-l]*b.second)%MOD;
	return ans;
}
void update(int v,int l,int r,int val)
{
	lazy[v]=(lazy[v]+val)%MOD;
	seg[v].first=(1LL*seg[v].first+1LL*pfib[r-l-1]*val)%MOD;
	seg[v].second=(1LL*seg[v].second+1LL*(pfib[r-l]-pfib[0])*val)%MOD;
}
void shift(int v,int l,int r)
{
	int mid = (l+r)/2;
	update(2*v,l,mid,lazy[v]),update(2*v+1,mid,r,lazy[v]);
	lazy[v] = 0;
}
void add(int v,int l,int r,int s,int e,int val)
{
	if (e<=l || s>=r) return;
	if (s<=l && e>=r){update(v,l,r,val); return;}
	int mid = (l+r)/2;
	shift(v,l,r);
	add(2*v,l,mid,s,e,val),add(2*v+1,mid,r,s,e,val);
	seg[v] = merge(seg[2*v],seg[2*v+1],l,mid);
}
pair<int,int> get(int v,int l,int r,int s,int e)
{
	if (s<=l && e>=r) return seg[v];
	int mid = (l+r)/2;
	shift(v,l,r);
	if (e<=mid)
		return get(2*v,l,mid,s,e);
	else if (s>=mid)
		return get(2*v+1,mid,r,s,e);
	else
		return merge(get(2*v,l,mid,s,mid),get(2*v+1,mid,r,mid,e),s,mid);
}
int main()
{
	ios_base::sync_with_stdio(0),cin.tie(0);
	cin>>n>>m;
	fib[0]=fib[1]=pfib[0]=1;
	for (int i=2;i<n;i++) fib[i]=(fib[i-1]+fib[i-2])%MOD;
	for (int i=1;i<n;i++) pfib[i]=(pfib[i-1]+fib[i])%MOD;
	for (int i=0;i<n;i++) cin>>x,add(1,0,n,i,i+1,x);
	for (int i=0;i<m;i++)
	{
		int c,x,y,d;
		cin>>c>>x>>y,x--;
		if (c==1) add(1,0,n,x,x+1,y-get(1,0,n,x,x+1).first);
		if (c==2) cout<<get(1,0,n,x,y).first<<'\n';
		if (c==3) cin>>d,add(1,0,n,x,y,d);
	}
	return 0;
}


#include<cstdio>
#include<algorithm>
#include<cstring>

#define N 200005

#define mid ((l+r)>>1)
#define ls  (t<<1)
#define rs  ((t<<1)|1)

const int Mo=(int)1e9;

struct Node
{
	  int mat[2][2];
	  int lenx,leny;
}B[N],C[N],tree[N*4],Ans;
int n,m,i,a[N],len[N*4],add[N*4];
int type,u,l,r,x;
inline Node operator +(Node a,Node b)
{
	  Node c=a;
	  int i,j;
	  for (i=0;i<a.lenx;++i)
	    for (j=0;j<a.leny;++j)
	      c.mat[i][j]=(a.mat[i][j]+b.mat[i][j])%Mo;
	  return c;
}
inline Node operator *(Node a,Node b)
{
	 Node c={0};
	 c.lenx=a.lenx; c.leny=b.leny;
	 int i,j,k;
	 for (k=0;k<a.leny;++k)
	  for (i=0;i<a.lenx;++i)
	    for (j=0;j<b.leny;++j)
	      (c.mat[i][j]+=1ll*a.mat[i][k]*b.mat[k][j]%Mo)%=Mo;
	 return c;
}
inline Node operator *(Node a,int b)
{
	  int i,j;
	  for (i=0;i<a.lenx;++i)
	    for (j=0;j<a.leny;++j)
	      a.mat[i][j]=1ll*a.mat[i][j]*b%Mo;
	  return a;
}
void change(int t,int c)
{
	Node A={0}; A.lenx=1;A.leny=2; A.mat[0][1]=c;
	tree[t]=tree[t]+(A*C[len[t]]);
	(add[t]+=c)%=Mo;
}
void down(int t)
{
	 if (!add[t]) return;
	 change(ls,add[t]); change(rs,add[t]);
	 add[t]=0;
}
void build_tree(int l,int r,int t)
{
	  len[t]=r-l+1;
	 if (l==r)
	 {
	 	 tree[t].lenx=1; tree[t].leny=2;
	 	 tree[t].mat[0][1]=a[l];
	 	 tree[t]=tree[t]*B[1];
	 }
	 else
	 {
	 	  build_tree(l,mid,ls); build_tree(mid+1,r,rs);
	 	  tree[t]=tree[ls]+(tree[rs]*B[len[ls]]);
	 }
}
void update(int ll,int c,int l,int r,int t)
{
	 if (l==r)
	 {
	 	 tree[t].mat[0][0]=0; tree[t].mat[0][1]=c;
	 	 tree[t]=tree[t]*B[1];
	 }
	 else
	 {
	 	  down(t);
	 	  if (ll<=mid) update(ll,c,l,mid,ls);
	 	  else update(ll,c,mid+1,r,rs);
	 	  tree[t]=tree[ls]+(tree[rs]*B[len[ls]]);
	 }
}
void ask(int ll,int rr,int l,int r,int t)
{
	  if (ll<=l&&r<=rr) Ans=Ans+(tree[t]*B[l-ll]);
	  else
	  {
	  	 down(t);
	  	 if (ll<=mid) ask(ll,rr,l,mid,ls);
	  	 if (rr>mid)  ask(ll,rr,mid+1,r,rs);
	  }
}
void modify(int ll,int rr,int c,int l,int r,int t)
{
	 if (ll<=l&&r<=rr) change(t,c);
	 else
	 {
	 	down(t);
	 	if (ll<=mid) modify(ll,rr,c,l,mid,ls);
	 	if (rr>mid)  modify(ll,rr,c,mid+1,r,rs);
	 	tree[t]=tree[ls]+(tree[rs]*B[len[ls]]);
	 }
}
int main()
{
	  scanf("%d%d",&n,&m);
	  B[0].lenx=B[0].leny=2; B[0].mat[0][0]=1; B[0].mat[1][1]=1;
	  B[1].mat[0][1]=1; B[1].mat[1][1]=1;
	  B[1].mat[1][0]=1; B[1].lenx=B[1].leny=2;
	  for (i=2;i<=n;++i) B[i]=B[i-1]*B[1];
	  C[1]=B[1]; for (i=2;i<=n;++i) C[i]=B[i]+C[i-1];
	  for (i=1;i<=n;++i) scanf("%d",&a[i]);
	  build_tree(1,n,1); Ans.lenx=1;Ans.leny=2;
	  for (;m--;)
	  {
	  	 scanf("%d",&type);
	  	 if (type==1)
	  	 {
	  	 	  scanf("%d%d",&u,&x);
	  	 	  update(u,x,1,n,1);
	  	 }
	  	 else if (type==2)
	  	 {
	  	 	 scanf("%d%d",&l,&r);
	  	 	 memset(Ans.mat,0,sizeof(Ans.mat));
	  	 	 ask(l,r,1,n,1);
	  	 	 printf("%d\n",Ans.mat[0][0]);
	  	 }
	  	 else if (type==3)
	  	 {
	  	 	 scanf("%d%d%d",&l,&r,&x);
	  	 	 modify(l,r,x,1,n,1);
	  	 }
      }
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

template<typename T>
void out(T x) { cout << x << endl; exit(0); }
#define watch(x) cout << (#x) << " is " << (x) << endl

const int maxn = 111;

int n,m,a[maxn];
ll fib[maxn];

int main() {
  ios_base::sync_with_stdio(false); cin.tie(0);  cout.tie(0);

  fib[0]=fib[1]=1;
  for (int i=2; i<maxn; i++) {
    fib[i] = fib[i-1] + fib[i-2];
  }

  cin>>n>>m;
  for (int i=1; i<=n; i++) {
    cin>>a[i];
  }

  while (m--) {
    int typ; cin>>typ;
    if (typ==1) {
      int x,v; cin>>x>>v;
      a[x]=v;
    } else if (typ==2) {
      int l,r; cin>>l>>r;
      ll cur = 0;
      for (int i=0; i<=r-l; i++) {
	cur += fib[i]*a[l+i];
	cur %= 1000000000;
      }
      cur %= 1000000000;
      cout<<cur<<'\n';
    }
  }

  return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

template<typename T>
void out(T x) { cout << x << endl; exit(0); }
#define watch(x) cout << (#x) << " is " << (x) << endl

const int maxn = 111;

int n,m,a[maxn];
ll fib[maxn];

int main() {
  ios_base::sync_with_stdio(false); cin.tie(0);  cout.tie(0);

  fib[0]=fib[1]=1;
  for (int i=2; i<maxn; i++) {
    fib[i] = fib[i-1] + fib[i-2];
    fib[i] %= 1000000000;
  }

  cin>>n>>m;
  for (int i=1; i<=n; i++) {
    cin>>a[i];
  }

  while (m--) {
    int typ; cin>>typ;
    if (typ==1) {
      int x,v; cin>>x>>v;
      a[x]=v;
    } else if (typ==2) {
      int l,r; cin>>l>>r;
      ll cur = 0;
      for (int i=0; i<=r-l; i++) {
	cur += fib[i]*a[l+i];
	cur %= 1000000000;
      }
      cur %= 1000000000;
      cout<<cur<<'\n';
    }
  }

  return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int N=200010;
const int mod=1e9;
int a[N],f[N];int n,m;
void fib()
{
	f[0]=1;f[1]=1;
	for(int i=2;i<=n;i++) f[i]=(f[i-1]+f[i-2])%mod;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	fib();
	for(int i=1;i<=m;i++)
	{
		int oo;scanf("%d",&oo);
		if(oo==1)
		{
			int t,x;scanf("%d%d",&t,&x);
			a[t]=x;
		}else if(oo==2)
		{
			int l,r;scanf("%d%d",&l,&r); int ans=0;
			for(int i=l;i<=r;i++)
			{
				(ans+=(f[i-l]*a[i])%mod)%=mod;
			}
			printf("%d\n",ans);
		}else
		{
			int l,r,x;scanf("%d%d%d",&l,&r,&x);
			for(int i=l;i<=r;i++) (a[i]+=x)%=mod;
	    }
	}
 }


#include<bits/stdc++.h>
using namespace std;
const int N=200010;
typedef long long ll;
const int mod=1e9;
ll a[N],f[N];int n,m;
void fib()
{
	f[0]=1;f[1]=1;
	for(int i=2;i<=n;i++) f[i]=(f[i-1]+f[i-2])%mod;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
	fib();
	for(int i=1;i<=m;i++)
	{
		int oo;scanf("%d",&oo);
		if(oo==1)
		{
			int t;ll x;scanf("%d%lld",&t,&x);
			a[t]=x;
		}else if(oo==2)
		{
			int l,r;scanf("%d%d",&l,&r); ll ans=0;
			for(int i=l;i<=r;i++)
			{
				(ans+=(f[i-l]*a[i])%mod)%=mod;
			}
			printf("%lld\n",ans);
		}else
		{
			int l,r;ll x;scanf("%d%d%lld",&l,&r,&x);
			for(int i=l;i<=r;i++) a[i]+=x;
	    }
	}
 }


#include<bits/stdc++.h>
#define ts cout<<"ok"<<endl
#define int long long
#define hh puts("")
#define mo 100000000
#define ls(x) ((x)<<1)
#define rs(x) ((x)<<1|1)
using namespace std;
int n,m,sum[1000005],f[1000005],tag[1000005];
int s1[1000005],s2[1000005];
//维护区间s1=a_l*f0+a_{l+1}*f1+a_{l+1}*f2
//s2=a_l*f1+a_{l+1}*f2+a_{l+1}*f3
inline int read(){
    int ret=0,ff=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-') ff=-ff;ch=getchar();}
    while(isdigit(ch)){ret=(ret<<3)+(ret<<1)+ch-'0';ch=getchar();}
    return ret*ff;
}
void write(int x){
    if(x>9) write(x/10);
    putchar(x%10+48);
}
inline int calc(int k,int len){
	if(!len) return s1[k];
	if(len==1) return s2[k];
	return (s1[k]*f[len-2]%mo+s2[k]*f[len-1]%mo)%mo;
}
void push_up(int l,int r,int k){
	int mid=(l+r)>>1;
	s1[k]=(s1[ls(k)]+calc(rs(k),mid-l+1))%mo;
	s2[k]=(s2[ls(k)]+calc(rs(k),mid-l+2))%mo;
}
inline void add(int l,int r,int k,int v){
	tag[k]=(tag[k]+v)%mo;
	s1[k]=(s1[k]+sum[r-l]*v%mo)%mo;
	s2[k]=(s2[k]+(sum[r-l+1]+mo-1)%mo*v%mo)%mo;
}
inline void push_down(int l,int r,int k){
	if(!tag[k]) return;
	int mid=(l+r)>>1;
	add(l,mid,ls(k),tag[k]);
	add(mid+1,r,rs(k),tag[k]);
	tag[k]=0;
}
void build(int l,int r,int x,int v,int k){
	if(l==r){
		s1[k]=s2[k]=v;
		return;
	}
	push_down(l,r,k);
	int mid=(l+r)>>1;
	if(x<=mid) build(l,mid,x,v,ls(k));
	else build(mid+1,r,x,v,rs(k));
	push_up(l,r,k);
}
inline int query(int l,int r,int x,int y,int k){
	if(x<=l&&r<=y) return calc(k,l-x);
	push_down(l,r,k);
	int mid=(l+r)>>1,res=0;
	if(x<=mid) res=(res+query(l,mid,x,y,ls(k)))%mo;
	if(mid+1<=y) res=(res+query(mid+1,r,x,y,rs(k)))%mo;
	return res;
}
void update(int l,int r,int x,int y,int v,int k){
	if(x<=l&&r<=y){
		add(l,r,k,v);
		return;
	}
	push_down(l,r,k);
	int mid=(l+r)>>1;
	if(x<=mid) update(l,mid,x,y,v,ls(k));
	if(mid+1<=y) update(mid+1,r,x,y,v,rs(k));
	push_up(l,r,k);
}
signed main(){
	n=read(),m=read();
	f[0]=f[1]=1;
	sum[0]=1;
	sum[1]=2;
	for(int i=2;i<=1000000;i++){
		f[i]=(f[i-1]+f[i-2])%mo;
		sum[i]=(sum[i-1]+f[i])%mo;
	}
	for(int i=1;i<=n;i++){
		int x=read();
		build(1,n,i,x,1);
	}
	while(m--){
		int opt=read();
		if(opt==1){
			int x=read(),v=read();
			build(1,n,x,v,1);
		}
		else if(opt==2){
			int l=read(),r=read();
			write(query(1,n,l,r,1)),hh;
		}
		else if(opt==3){
			int l=read(),r=read(),v=read();
			update(1,n,l,r,v,1);
		}
	}
    return 0;
}


#include<bits/stdc++.h>
#define ts cout<<"ok"<<endl
#define int long long
#define hh puts("")
#define mo 1000000000
#define ls(x) ((x)<<1)
#define rs(x) ((x)<<1|1)
using namespace std;
int n,m,sum[1000005],f[1000005],tag[1000005];
int s1[1000005],s2[1000005];
//维护区间s1=a_l*f0+a_{l+1}*f1+a_{l+1}*f2
//s2=a_l*f1+a_{l+1}*f2+a_{l+1}*f3
inline int read(){
    int ret=0,ff=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-') ff=-ff;ch=getchar();}
    while(isdigit(ch)){ret=(ret<<3)+(ret<<1)+ch-'0';ch=getchar();}
    return ret*ff;
}
void write(int x){
    if(x>9) write(x/10);
    putchar(x%10+48);
}
inline int calc(int k,int len){
	if(!len) return s1[k];
	if(len==1) return s2[k];
	return (s1[k]*f[len-2]%mo+s2[k]*f[len-1]%mo)%mo;
}
void push_up(int l,int r,int k){
	int mid=(l+r)>>1;
	s1[k]=(s1[ls(k)]+calc(rs(k),mid-l+1))%mo;
	s2[k]=(s2[ls(k)]+calc(rs(k),mid-l+2))%mo;
}
inline void add(int l,int r,int k,int v){
	tag[k]=(tag[k]+v)%mo;
	s1[k]=(s1[k]+sum[r-l]*v%mo)%mo;
	s2[k]=(s2[k]+(sum[r-l+1]+mo-1)%mo*v%mo)%mo;
}
inline void push_down(int l,int r,int k){
	if(!tag[k]) return;
	int mid=(l+r)>>1;
	add(l,mid,ls(k),tag[k]);
	add(mid+1,r,rs(k),tag[k]);
	tag[k]=0;
}
void build(int l,int r,int x,int v,int k){
	if(l==r){
		s1[k]=s2[k]=v;
		return;
	}
	push_down(l,r,k);
	int mid=(l+r)>>1;
	if(x<=mid) build(l,mid,x,v,ls(k));
	else build(mid+1,r,x,v,rs(k));
	push_up(l,r,k);
}
inline int query(int l,int r,int x,int y,int k){
	if(x<=l&&r<=y) return calc(k,l-x);
	push_down(l,r,k);
	int mid=(l+r)>>1,res=0;
	if(x<=mid) res=(res+query(l,mid,x,y,ls(k)))%mo;
	if(mid+1<=y) res=(res+query(mid+1,r,x,y,rs(k)))%mo;
	return res;
}
void update(int l,int r,int x,int y,int v,int k){
	if(x<=l&&r<=y){
		add(l,r,k,v);
		return;
	}
	push_down(l,r,k);
	int mid=(l+r)>>1;
	if(x<=mid) update(l,mid,x,y,v,ls(k));
	if(mid+1<=y) update(mid+1,r,x,y,v,rs(k));
	push_up(l,r,k);
}
signed main(){
	n=read(),m=read();
	f[0]=f[1]=1;
	sum[0]=1;
	sum[1]=2;
	for(int i=2;i<=1000000;i++){
		f[i]=(f[i-1]+f[i-2])%mo;
		sum[i]=(sum[i-1]+f[i])%mo;
	}
	for(int i=1;i<=n;i++){
		int x=read();
		build(1,n,i,x,1);
	}
	while(m--){
		int opt=read();
		if(opt==1){
			int x=read(),v=read();
			build(1,n,x,v,1);
		}
		else if(opt==2){
			int l=read(),r=read();
			write(query(1,n,l,r,1)),hh;
		}
		else if(opt==3){
			int l=read(),r=read(),v=read();
			update(1,n,l,r,v,1);
		}
	}
    return 0;
}