There is an array a of 2^{30} integers, indexed from 0 to 2^{30}-1. Initially, you know that 0 ≤ a_i < 2^{30} (0 ≤ i < 2^{30}), but you do not know any of the values. Your task is to process queries of two types:

  * 1 l r x: You are informed that the bitwise xor of the subarray [l, r] (ends inclusive) is equal to x. That is, a_l ⊕ a_{l+1} ⊕ … ⊕ a_{r-1} ⊕ a_r = x, where ⊕ is the bitwise xor operator. In some cases, the received update contradicts past updates. In this case, you should ignore the contradicting update (the current update).
  * 2 l r: You are asked to output the bitwise xor of the subarray [l, r] (ends inclusive). If it is still impossible to know this value, considering all past updates, then output -1.



Note that the queries are encoded. That is, you need to write an online solution.

Input

The first line contains a single integer q (1 ≤ q ≤ 2 ⋅ 10^5) — the number of queries.

Each of the next q lines describes a query. It contains one integer t (1 ≤ t ≤ 2) — the type of query.

The given queries will be encoded in the following way: let last be the answer to the last query of the second type that you have answered (initially, last = 0). If the last answer was -1, set last = 1.

  * If t = 1, three integers follow, l', r', and x' (0 ≤ l', r', x' < 2^{30}), meaning that you got an update. First, do the following: l = l' ⊕ last, r = r' ⊕ last, x = x' ⊕ last 

and, if l > r, swap l and r.

This means you got an update that the bitwise xor of the subarray [l, r] is equal to x (notice that you need to ignore updates that contradict previous updates).

  * If t = 2, two integers follow, l' and r' (0 ≤ l', r' < 2^{30}), meaning that you got a query. First, do the following: l = l' ⊕ last, r = r' ⊕ last 

and, if l > r, swap l and r.

For the given query, you need to print the bitwise xor of the subarray [l, r]. If it is impossible to know, print -1. Don't forget to change the value of last.




It is guaranteed there will be at least one query of the second type.

Output

After every query of the second type, output the bitwise xor of the given subarray or -1 if it is still impossible to know.

Examples

Input

12
2 1 2
2 1 1073741822
1 0 3 4
2 0 0
2 3 3
2 0 3
1 6 7 3
2 4 4
1 0 2 1
2 0 0
2 4 4
2 0 0


Output

-1
-1
-1
-1
5
-1
6
3
5


Input

4
1 5 5 9
1 6 6 5
1 6 5 10
2 6 5


Output

12

Note

In the first example, the real queries (without being encoded) are:

  * 12
  * 2 1 2
  * 2 0 1073741823
  * 1 1 2 5
  * 2 1 1
  * 2 2 2
  * 2 1 2
  * 1 2 3 6
  * 2 1 1
  * 1 1 3 0
  * 2 1 1
  * 2 2 2
  * 2 3 3


  * The answers for the first two queries are -1 because we don't have any such information on the array initially. 
  * The first update tells us a_1 ⊕ a_2 = 5. Note that we still can't be certain about the values a_1 or a_2 independently (for example, it could be that a_1 = 1, a_2 = 4, and also a_1 = 3, a_2 = 6). 
  * After we receive all three updates, we have enough information to deduce a_1, a_2, a_3 independently. 



In the second example, notice that after the first two updates we already know that a_5 ⊕ a_6 = 12, so the third update is contradicting, and we ignore it.
import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.io.Closeable;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(null, new TaskAdapter(), "", 1 << 27);
        thread.start();
        thread.join();
    }

    static class TaskAdapter implements Runnable {
        @Override
        public void run() {
            InputStream inputStream = System.in;
            OutputStream outputStream = System.out;
            FastInput in = new FastInput(inputStream);
            FastOutput out = new FastOutput(outputStream);
            DDeductionQueries solver = new DDeductionQueries();
            solver.solve(1, in, out);
            out.close();
        }
    }

    static class DDeductionQueries {
        int alloc = 0;

        public void solve(int testNumber, FastInput in, FastOutput out) {
            int q = in.readInt();
            int last = 0;

            OppositeDSU[] dsu = new OppositeDSU[30];
            for (int i = 0; i < 30; i++) {
                dsu[i] = new OppositeDSU(q * 2);
            }
            IntegerHashMap map = new IntegerHashMap(2 * q, false);
            for (int i = 0; i < q; i++) {
                if (in.readInt() == 1) {
                    int l = (in.readInt() ^ last);
                    int r = (in.readInt() ^ last);

                    if (l > r) {
                        int tmp = l;
                        l = r;
                        r = tmp;
                    }
                    l--;

                    int x = in.readInt() ^ last;

                    int a = getItems(map, l);
                    int b = getItems(map, r);
                    boolean valid = true;
                    for (int j = 0; j < 30 && valid; j++) {
                        if (Bits.bitAt(x, j) == 0) {
                            if (dsu[j].xor(a, b) == 1) {
                                valid = false;
                            }
                        } else {
                            if (dsu[j].xor(a, b) == 0) {
                                valid = false;
                            }
                        }
                    }

                    if (!valid) {
                        continue;
                    }

                    for (int j = 0; j < 30; j++) {
                        if (Bits.bitAt(x, j) == 0) {
                            dsu[j].same(a, b);
                        } else {
                            dsu[j].different(a, b);
                        }
                    }
                } else {
                    int l = (in.readInt() ^ last);
                    int r = (in.readInt() ^ last);

                    if (l > r) {
                        int tmp = l;
                        l = r;
                        r = tmp;
                    }
                    l--;

                    boolean hasSolution = true;
                    int a = getItems(map, l);
                    int b = getItems(map, r);
                    for (int j = 0; j < 30 && hasSolution; j++) {
                        hasSolution = dsu[j].xor(a, b) != -1;
                    }

                    if (!hasSolution) {
                        out.println(-1);
                        last = 1;
                        continue;
                    }

                    int ans = 0;
                    for (int j = 0; j < 30; j++) {
                        ans = Bits.setBit(ans, j, 1 == dsu[j].xor(a, b));
                    }

                    out.println(ans);
                    last = ans;
                }
            }
        }

        public int getItems(IntegerHashMap map, int key) {
            int item = map.getOrDefault(key, Integer.MIN_VALUE);
            if (item == Integer.MIN_VALUE) {
                map.put(key, item = alloc++);
            }
            return item;
        }

    }

    static class FastInput {
        private final InputStream is;
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastInput(InputStream is) {
            this.is = is;
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    bufLen = -1;
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

    }

    static class IntegerHashMap {
        private int[] slot;
        private int[] next;
        private int[] keys;
        private int[] values;
        private int alloc;
        private boolean[] removed;
        private int mask;
        private int size;
        private boolean rehash;

        public IntegerHashMap(int cap, boolean rehash) {
            this.mask = (1 << (32 - Integer.numberOfLeadingZeros(cap - 1))) - 1;
            slot = new int[mask + 1];
            next = new int[cap + 1];
            keys = new int[cap + 1];
            values = new int[cap + 1];
            removed = new boolean[cap + 1];
            this.rehash = rehash;
        }

        private void doubleCapacity() {
            int newSize = Math.max(next.length + 10, next.length * 2);
            next = Arrays.copyOf(next, newSize);
            keys = Arrays.copyOf(keys, newSize);
            values = Arrays.copyOf(values, newSize);
            removed = Arrays.copyOf(removed, newSize);
        }

        public void alloc() {
            alloc++;
            if (alloc >= next.length) {
                doubleCapacity();
            }
            next[alloc] = 0;
            removed[alloc] = false;
            size++;
        }

        private void rehash() {
            int[] newSlots = new int[Math.max(16, slot.length * 2)];
            int newMask = newSlots.length - 1;
            for (int i = 0; i < slot.length; i++) {
                if (slot[i] == 0) {
                    continue;
                }
                int head = slot[i];
                while (head != 0) {
                    int n = next[head];
                    int s = hash(keys[head]) & newMask;
                    next[head] = newSlots[s];
                    newSlots[s] = head;
                    head = n;
                }
            }
            this.slot = newSlots;
            this.mask = newMask;
        }

        private int hash(int x) {
            int h = Integer.hashCode(x);
            return h ^ (h >>> 16);
        }

        public void put(int x, int y) {
            put(x, y, true);
        }

        public void put(int x, int y, boolean cover) {
            int h = hash(x);
            int s = h & mask;
            if (slot[s] == 0) {
                alloc();
                slot[s] = alloc;
                keys[alloc] = x;
                values[alloc] = y;
            } else {
                int index = findIndexOrLastEntry(s, x);
                if (keys[index] != x) {
                    alloc();
                    next[index] = alloc;
                    keys[alloc] = x;
                    values[alloc] = y;
                } else if (cover) {
                    values[index] = y;
                }
            }
            if (rehash && size >= slot.length) {
                rehash();
            }
        }

        public int getOrDefault(int x, int def) {
            int h = hash(x);
            int s = h & mask;
            if (slot[s] == 0) {
                return def;
            }
            int index = findIndexOrLastEntry(s, x);
            return keys[index] == x ? values[index] : def;
        }

        private int findIndexOrLastEntry(int s, int x) {
            int iter = slot[s];
            while (keys[iter] != x) {
                if (next[iter] != 0) {
                    iter = next[iter];
                } else {
                    return iter;
                }
            }
            return iter;
        }

        public IntegerEntryIterator iterator() {
            return new IntegerEntryIterator() {
                int index = 1;
                int readIndex = -1;


                public boolean hasNext() {
                    while (index <= alloc && removed[index]) {
                        index++;
                    }
                    return index <= alloc;
                }


                public int getEntryKey() {
                    return keys[readIndex];
                }


                public int getEntryValue() {
                    return values[readIndex];
                }


                public void next() {
                    if (!hasNext()) {
                        throw new IllegalStateException();
                    }
                    readIndex = index;
                    index++;
                }
            };
        }

        public String toString() {
            IntegerEntryIterator iterator = iterator();
            StringBuilder builder = new StringBuilder("{");
            while (iterator.hasNext()) {
                iterator.next();
                builder.append(iterator.getEntryKey()).append("->").append(iterator.getEntryValue()).append(',');
            }
            if (builder.charAt(builder.length() - 1) == ',') {
                builder.setLength(builder.length() - 1);
            }
            builder.append('}');
            return builder.toString();
        }

    }

    static class FastOutput implements AutoCloseable, Closeable {
        private StringBuilder cache = new StringBuilder(10 << 20);
        private final Writer os;

        public FastOutput(Writer os) {
            this.os = os;
        }

        public FastOutput(OutputStream os) {
            this(new OutputStreamWriter(os));
        }

        public FastOutput println(int c) {
            cache.append(c).append('\n');
            return this;
        }

        public FastOutput flush() {
            try {
                os.append(cache);
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
            return this;
        }

        public void close() {
            flush();
            try {
                os.close();
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }

        public String toString() {
            return cache.toString();
        }

    }

    static interface IntegerEntryIterator {
        boolean hasNext();

        void next();

        int getEntryKey();

        int getEntryValue();

    }

    static class OppositeDSU {
        int[] ps;
        int[] ranks;
        int n;

        public OppositeDSU(int n) {
            this.n = n;
            ps = new int[n * 2];
            ranks = new int[n * 2];
            for (int i = 0; i < ps.length; i++) {
                ps[i] = i;
            }
        }

        private int opposite(int i) {
            return i < n ? i + n : i - n;
        }

        public int find(int i) {
            return ps[i] == ps[ps[i]] ? ps[i] : (ps[i] = find(ps[i]));
        }

        public int xor(int a, int b) {
            if (find(a) == find(b)) {
                return 0;
            }
            if (find(a) == find(opposite(b))) {
                return 1;
            }
            return -1;
        }

        public void different(int a, int b) {
            merge0(a, opposite(b));
            merge0(opposite(a), b);
        }

        public void same(int a, int b) {
            merge0(a, b);
            merge0(opposite(a), opposite(b));
        }

        private void merge0(int a, int b) {
            a = find(a);
            b = find(b);
            if (a == b) {
                return;
            }
            if (ranks[a] == ranks[b]) {
                ranks[a]++;
            }
            if (ranks[a] > ranks[b]) {
                ps[b] = a;
            } else {
                ps[a] = b;
            }
        }

    }

    static class Bits {
        private Bits() {
        }

        public static int bitAt(int x, int i) {
            return (x >> i) & 1;
        }

        public static int setBit(int x, int i, boolean v) {
            if (v) {
                x |= 1 << i;
            } else {
                x &= ~(1 << i);
            }
            return x;
        }

    }
}

