#include <iostream>
#include <algorithm>
#include <numeric>
using namespace std;
// Segédfüggvény a legnagyobb közös osztóhoz (C++17-ben std::gcd is jó, de biztosra megyünk)
long long my_gcd(long long a, long long b) {
while (b) {
a %= b;
swap(a, b);
}
return a;
}
// Struktúra egy intervallum tárolására [start, end]
struct Interval {
long long start, end;
bool empty;
};
// Visszaadja a "rossz" intervallumot: azon koordinátákat [0, dim-1]-ben,
// ahonnan NEM lehet 'step' méretűt lépni (sem jobbra, sem balra).
// Rossz, ha: x + step >= dim ÉS x - step < 0
Interval get_bad_interval(long long dim, long long step) {
long long s = max(0LL, dim - step);
long long e = min(dim - 1, step - 1);
if (s > e) {
return {0, 0, true}; // Üres intervallum (nincs rossz mező)
}
return {s, e, false};
}
// Két intervallum metszetét vizsgálja. Igaz, ha a metszet NEM üres.
bool intervals_intersect(Interval a, Interval b) {
if (a.empty || b.empty) return false;
long long s = max(a.start, b.start);
long long e = min(a.end, b.end);
return s <= e;
}
void solve() {
long long N, M, H, W;
if (!(cin >> N >> M >> H >> W)) return;
// 1. Alapesetek
// Ha 1x1-es a tábla, már ott vagyunk mindenhol.
if (N == 1 && M == 1) {
cout << "YES" << endl;
return;
}
// Ha a tábla 1 dimenziós (de nem 1x1), és van bármilyen lépéskényszer (W,H >= 1),
// akkor nem tudunk elmozdulni a vonalról anélkül, hogy leessünk.
if (N == 1 || M == 1) {
cout << "NO" << endl;
return;
}
// 2. Paritás ellenőrzése
// Ha H+W páros, a (x+y) paritása sosem változik (vagy mindig változik ugyanúgy),
// így a tábla fele elérhetetlen (mint a futó a sakkban, vagy a huszár, ha nem váltana színt).
if ((H + W) % 2 == 0) {
cout << "NO" << endl;
return;
}
// 3. LNKO ellenőrzése
// Ha gcd(H, W) > 1, akkor a koordináták mindig a gcd többszöröseivel változnak.
if (my_gcd(H, W) > 1) {
cout << "NO" << endl;
return;
}
// 4. Szűk sávok (Narrow Strip) ellenőrzése
// Ha az egyik dimenzióban (pl N) nem tudunk H-t lépni, akkor abban az irányban
// csak W-t léphetünk. Ez azt jelenti, hogy a MÁSIK dimenzióban (M) mindig H-t kell lépnünk.
// Ha H > 1, akkor a másik dimenzióban nem érünk el minden sort.
if (N <= H && H > 1) { cout << "NO" << endl; return; }
if (N <= W && W > 1) { cout << "NO" << endl; return; }
if (M <= H && H > 1) { cout << "NO" << endl; return; }
if (M <= W && W > 1) { cout << "NO" << endl; return; }
// 5. Izolált mezők (Dead Squares)
// Megnézzük, vannak-e olyan mezők, ahonnan semelyik típusú ugrás nem hajtható végre.
// Ugrás 1: x-ben W, y-ban H. (Tiltva, ha x a bad_X_W-ben VAGY y a bad_Y_H-ban van)
// Ugrás 2: x-ben H, y-ban W. (Tiltva, ha x a bad_X_H-ban VAGY y a bad_Y_W-ben van)
Interval bx_w = get_bad_interval(N, W); // Rossz X-ek W lépéshez
Interval bx_h = get_bad_interval(N, H); // Rossz X-ek H lépéshez
Interval by_w = get_bad_interval(M, W); // Rossz Y-ok W lépéshez
Interval by_h = get_bad_interval(M, H); // Rossz Y-ok H lépéshez
// Akkor van baj, ha a két feltételrendszer metszete nem üres.
// A logikai feltétel: (x in bx_w OR y in by_h) AND (x in bx_h OR y in by_w)
// Ezt szétbontva 4 eset lehetséges (disztributivitás):
bool has_isolated = false;
// Eset 1: x mindkét lépéshez rossz (x in bx_w AND x in bx_h)
if (intervals_intersect(bx_w, bx_h)) has_isolated = true;
// Eset 2: y mindkét lépéshez rossz (y in by_h AND y in by_w)
if (intervals_intersect(by_h, by_w)) has_isolated = true;
// Eset 3: Ugrás 1 x miatt rossz, Ugrás 2 y miatt rossz (x in bx_w AND y in by_w)
// Ez egy téglalap alakú terület a táblán. Ha mindkét intervallum létezik, akkor a téglalap létezik.
if (!bx_w.empty && !by_w.empty) has_isolated = true;
// Eset 4: Ugrás 1 y miatt rossz, Ugrás 2 x miatt rossz (y in by_h AND x in bx_h)
if (!by_h.empty && !bx_h.empty) has_isolated = true;
if (has_isolated) {
cout << "NO" << endl;
} else {
cout << "YES" << endl;
}
}
int main() {
// Gyors I/O
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int T;
if (cin >> T) {
while (T--) {
solve();
}
}
return 0;
}