There is a right triangle with legs of length a and b. Your task is to determine whether it is possible to locate the triangle on the plane in such a way that none of its sides is parallel to the coordinate axes. All the vertices must have integer coordinates. If there exists such a location, you have to output the appropriate coordinates of vertices.

Input

The first line contains two integers a, b (1 ≤ a, b ≤ 1000), separated by a single space.

Output

In the first line print either "YES" or "NO" (without the quotes) depending on whether the required location exists. If it does, print in the next three lines three pairs of integers — the coordinates of the triangle vertices, one pair per line. The coordinates must be integers, not exceeding 109 in their absolute value.

Examples

Input

1 1


Output

NO


Input

5 5


Output

YES
2 1
5 5
-2 4


Input

5 10


Output

YES
-10 4
-2 -2
1 2
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.OutputStreamWriter;
import java.io.BufferedWriter;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.*;

public class Main {
    static Reader in = null;
    static PrintWriter out = null;

    static class Point {
        long x, y;
        Point(long x, long y) {
            this.x = x;
            this.y = y;
        }
        long dist2(Point p) {
            return (this.x - p.x) * (this.x - p.x) + (this.y - p.y) * (this.y - p.y);
        }
        double dist(Point p) {
            return Math.sqrt((this.x - p.x) * (this.x - p.x) + (this.y - p.y) * (this.y - p.y));
        }
        double dist(PointReal p) {
            return Math.sqrt((this.x - p.x) * (this.x - p.x) + (this.y - p.y) * (this.y - p.y));
        }
        public String toString() {
            return "[x, y]: " + "[" + x + ", " + y + "]";
        }
    }

    static class PointReal {
        double x, y;
        PointReal(double x, double y) {
            this.x = x;
            this.y = y;
        }
        double dist(PointReal p) {
            return Math.sqrt((this.x - p.x) * (this.x - p.x) + (this.y - p.y) * (this.y - p.y));
        }
        double dist(Point p) {
            return Math.sqrt((this.x - p.x) * (this.x - p.x) + (this.y - p.y) * (this.y - p.y));
        }
        public String toString() {
            return "[x, y]: " + "[" + x + ", " + y + "]";
        }
    }

    static class Line {
        long a, b, c;
        Line(Point p1, Point p2) {
            this.a = p1.y - p2.y;
            this.b = p2.x - p1.x;
            this.c = p1.x * p2.y - p2.x * p1.y;
        }
        Line(long a, long b, long c) {
            this.a = a;
            this.b = b;
            this.c = c;
        }
        boolean isParallel(Line l) {
            return (this.a * l.b == l.a * this.b);
        }
        boolean isPerpendicular(Line l) {
            return (this.a * l.a + this.b * l.b) == 0;
        }
        PointReal intersectionWith(Line l) {
            double d = this.a * l.b - l.a * this.b;
            if(d == 0) return null;
            return new PointReal((this.b * l.c - l.b * this.c) / d, (this.c * l.a - l.c * this.a) / d);
        }
        Line getPerpendicularLineThrough(Point p) {
            return new Line(-b, a, b * p.x - a * p.y);
        }
        public String toString() {
            return "[a, b, c]: " + "[" + a + ", " + b + ", " + c + "]";
        }
    }

    static class Pair implements Comparable<Pair> {
        int x, y;
        Pair(int x, int y) {
            this.x = x;
            this.y = y;
        }
        public int compareTo(Pair p) {
            return (this.x == p.x) ? this.y - p.y : this.x - p.x;
        }
        public String toString() {
            return "[x, y]: " + "[" + x + ", " + y + "]";
        }
    }

    static double dist(double x1, double y1, double x2, double y2) {
        return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
    }

    static int gcd(int a, int b) {
        while(b != 0) {
            int c = a%b;
            a = b;
            b = c;
        }
        return a;
    }

    static void solve() throws IOException {
        int a = in.nextInt();
        int b = in.nextInt();
        int[] sqrt = new int[(int)1e6+10];
        for(int i=1; i<=1000; i++) sqrt[i*i] = i;
        if(a > b) { int t = a; a = b; b = t; }
        int g = gcd(a, b);
        int x = -1, y = -1;
        boolean flag = false;
        for(int i=1; i<g; i++) {
            if(sqrt[g*g - i*i] != 0) {
                x = i;
                y = sqrt[g*g - i*i];
                flag = true;
                break;
            }
        }
        if(!flag) {
            out.println("NO");
            return;
        }
        out.println("YES");
        out.println(0 + " " + 0);
        int x1 = (a/g * x), y1 = (a/g * y), x2 = ((b/g) * -y), y2 = ((b/g) * x);
        if(y1 == y2) {
            if(x1 == x2) {
                out.println("NO");
                return;
            }
            int t = y1; y1 = x1; x1 = t;
            t = y2; y2 = x2; x2 = t;
            x2 *= -1; y2 *= -1;
        }
        out.println(x1 + " " + y1);
        out.println(x2 + " " + y2);
    }

    public static void main(String[] args) {
        try {
            OutputStreamWriter osw = new OutputStreamWriter(System.out);
            BufferedWriter bw = new BufferedWriter(osw);
            in = new Reader();
            out = new PrintWriter(bw);

            solve();
//            test();

            out.close();
            bw.close();
            osw.close();
            in.close();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

    static void test() throws IOException {
//        probabilityChecker((int)1e5);
//        int n = in.nextInt();
//        SkipListSet ss = new SkipListSet(16);
//        for(int i=0; i<n; i++) {
//            ss.add(in.nextInt());
//            out.println("Element no. " + (1) + ": " + ss.elementAt(1));
//        }
//        int[] buf = ss.toArray();
//        for(int i=0; i<n; i++) out.println(buf[i]);
//        out.println();
//        int m = in.nextInt();
//        for(int i=0; i<m; i++) {
//            int k = in.nextInt();
//            out.println("Element removed " + k + ": " + ss.remove(k));
//            out.println("Element no. " + (i+1) + ": " + ss.elementAt(i+1));
//            printArray(ss.toArray());
//        }
//        for(int x: ss.toArray) {
//            out.println(x);
//        }

        Fruit f = Fruit.APPLE;
        Fruit[] buf = Fruit.values();
        TestUtils.shuffle(buf, new Random());
        TestUtils.printArray(buf, out);
        Arrays.sort(buf);
        TestUtils.printArray(buf, out);
    }

    static enum Fruit {
        APPLE, ORANGE, MANGO, BANANA;
    }

    static void assertion(boolean f) {
        if(!f) throw new AssertionError();
    }
    static void assertion(boolean f, String msg) {
        if(!f) throw new AssertionError(msg);
    }
    static void dbg(String msg, PrintWriter out) {
        out.println(msg);
    }

    static int huh(int mL, Random rand) {
        int h = 1;
        while(rand.nextInt() <= 0 && h < mL) h++;
        return h;
    }

    static void probabilityChecker(int n) {
        Random rand = new Random();
        int[] b = new int[16];
        for(int i=1; i<n; i++) {
            b[huh(b.length-1, rand)]++;
        }
        for(int i=0; i<16; i++) {
            out.println((double)b[i]/n);
        }
    }

    static class TestUtils {
        static <T> void shuffle(T[] a, Random rand) {
            for (int i = 1, n = a.length; i<n; i++) {
                int j = rand.nextInt(i + 1);
                T t = a[i]; a[i] = a[j]; a[j] = t;
            }
        }
        static void shuffle(int[] a, Random rand) {
            for (int i = 1, n = a.length; i<n; i++) {
                int j = rand.nextInt(i + 1);
                int t = a[i]; a[i] = a[j]; a[j] = t;
            }
        }
        static void shuffle(long[] a, Random rand) {
            for (int i = 1, n = a.length; i<n; i++) {
                int j = rand.nextInt(i + 1);
                long t = a[i]; a[i] = a[j]; a[j] = t;
            }
        }
        static void shuffle(double[] a, Random rand) {
            for (int i = 1, n = a.length; i<n; i++) {
                int j = rand.nextInt(i + 1);
                double t = a[i]; a[i] = a[j]; a[j] = t;
            }
        }
        static <T> void printArray(T[] buf, PrintWriter out) {
            out.print("[");
            for(int i=0, n = buf.length; i<n; i++) out.print(" " + buf[i]);
            out.println(" ]");
        }
        static void printArray(int[] buf, PrintWriter out) {
            out.print("[");
            for(int i=0, n = buf.length; i<n; i++) out.print(" " + buf[i]);
            out.println(" ]");
        }
        static void printArray(long[] buf, PrintWriter out) {
            out.print("[");
            for(int i=0, n = buf.length; i<n; i++) out.print(" " + buf[i]);
            out.println(" ]");
        }
        static void printArray(double[] buf, PrintWriter out) {
            out.print("[");
            for(int i=0, n = buf.length; i<n; i++) out.print(" " + buf[i]);
            out.println(" ]");
        }
    }

    static class SkipListSet {
        class Node {
            int x, h, cnt[];
            Node[] next;
            Node(int x, int h) {
                this.h = h;
                this.x = x;
                this.next = new Node[h];
                this.cnt = new int[h];
            }
        }

        Random rand;
        int maxLevel, size, pos[];
        Node head, prev[];

        SkipListSet(int maxLevel) {
            this.rand = new Random();
            this.maxLevel = maxLevel;
            this.size = 0;
            this.head = new Node(-1, maxLevel);
            this.pos = new int[maxLevel];
            this.prev = new Node[maxLevel];
        }
        int getLevel() {
            int l = 1;
            while(rand.nextInt() <= 0 && l < maxLevel) l++;
            return l;
        }
        void add(int x) {
            Node u = head, v = new Node(x, getLevel());
            int p = 0;
            for(int i=maxLevel-1; i>=0; i--) {
                for( ; u.next[i] != null && u.next[i].x < x; p += u.cnt[i], u = u.next[i]);
                if(u.next[i] != null) u.cnt[i]++;
                prev[i] = u;
                pos[i] = p;
            }
            int at = p+1;
            for(int i=0; i<v.h; i++) {
                v.next[i] = prev[i].next[i];
                prev[i].next[i] = v;
                if(v.next[i] != null) v.cnt[i] = pos[i] + prev[i].cnt[i] - at;
                prev[i].cnt[i] = at - pos[i];
            }
            this.size++;
        }
        boolean remove(int x) {
            Node u = head, v = null;
            for(int i=maxLevel-1, at = 0; i>=0; i--) {
                for( ; u.next[i] != null && u.next[i].x < x; at += u.cnt[i], u = u.next[i]);
                if(u.next[i] != null && u.next[i].x == x) {
                    if(v == null) v = u.next[i];
                    else for( ; u.next[i] != v; at += u.cnt[i], u = u.next[i]);
                }
                if(u.next[i] != null) u.cnt[i]--;
                prev[i] = u;
            }
            if(v == null) return false;
            for(int i=0; i<v.h; i++) {
                prev[i].next[i] = v.next[i];
                prev[i].cnt[i] = prev[i].cnt[i] + v.cnt[i];
            }
            this.size--;
            return true;
        }
        int getIndex(int x) {
            Node u = head;
            for(int i=maxLevel-1, at = 0; i>=0; i--) {
                for( ; u.next[i] != null && u.next[i].x < x; at += u.cnt[i], u = u.next[i]);
                if(u.next[i] != null && u.next[i].x == x) return at;
            }
            return -1;
        }
        int elementAt(int k) {
            Node u = head;
            for(int i=maxLevel-1, at = 0; i >= 0; i--) {
                for( ; u.next[i] != null && u.cnt[i] + at < k; at += u.cnt[i], u = u.next[i]);
                if(u.next[i] != null && u.cnt[i] + at == k) return u.next[i].x;
            }
            return Integer.MAX_VALUE;
        }
//        int first() {
//            return (size == 0) ? Integer.MAX_VALUE : head.next[0].x;
//        }
//        int last() {
//            Node u = head;
//            for(int i=maxLevel-1; i>=0; i--) while(u.next[i] != null) u = u.next[i];
//            return (size == 0) ? Integer.MAX_VALUE : u.x;
//        }
        int[] toArray() {
            int[] buf = new int[size];
            Node u = head.next[0];
            for(int i=0; i<size; i++) {
                buf[i] = u.x;
                u = u.next[0];
            }
            return buf;
        }
    }

    static class Reader {
        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(isr);
        StringTokenizer tk = new StringTokenizer("");
        String s = null;

        String nextLine() throws IOException {
            while((s = br.readLine()) != null && s.length() == 0);
            return s;
        }
        String next() throws IOException {
            if(!tk.hasMoreTokens()) tk = new StringTokenizer(nextLine());
            return tk.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 close() throws  IOException {
            br.close();
            isr.close();
        }
    }
}
