Go: package main

import (
	"bufio"
	"os"
	"strconv"
	"strings"
	"fmt"
)

var scanner = bufio.NewScanner(os.Stdin)

func main() {
	scanner.Scan()
	n, _ := strconv.Atoi(scanner.Text())
	for i := 0; i < n; i++ {
		scanner.Scan()
		input := strings.Split(scanner.Text(), " ")
		buf := make([]float64, len(input))
		for j := range buf {
			buf[j], _ = strconv.ParseFloat(input[j], 64)
		}
		p1 := complex(buf[0], buf[1])
		p2 := complex(buf[2], buf[3])
		p3 := complex(buf[4], buf[5])
		pk := complex(buf[6], buf[7])
		ps := complex(buf[8], buf[9])
		kin := isAtSameSide(p3, pk, []complex128{p1, p2}) &&
			isAtSameSide(p1, pk, []complex128{p2, p3}) &&
			isAtSameSide(p2, pk, []complex128{p3, p1})
		sin := isAtSameSide(p3, ps, []complex128{p1, p2}) &&
			isAtSameSide(p1, ps, []complex128{p2, p3}) &&
			isAtSameSide(p2, ps, []complex128{p3, p1})
		if (kin || sin) && !(kin && sin) {
			fmt.Println("OK")
		} else {
			fmt.Println("NG")
		}
	}
}

func isAtSameSide(a, b complex128, line []complex128) bool {
	sa := (real(line[1]) - real(line[0]))*(imag(a)-imag(line[0]))+
		(imag(line[1])-imag(line[0]))*(real(line[0])-real(a))
	sb := (real(line[1]) - real(line[0]))*(imag(b)-imag(line[0]))+
		(imag(line[1])-imag(line[0]))*(real(line[0])-real(b))
	return (sa > 0 && sb > 0) || (sa < 0 && sb < 0)
}

C++: #include <bits/stdc++.h>

using namespace std;
using ll = long long;
using pii = pair<int, int>;

const double PI = acos(-1);
const double EPS = 1e-10;
int sgn(double d) { return d > EPS ? 1 : d < -EPS ? -1 : 0; }

struct Point {
  double x, y;
  Point() {}
  Point (const double& x, const double& y) : x(x), y(y) {}
  Point& operator += (const Point& other) { x += other.x; y += other.y; return *this; }
  Point& operator -= (const Point& other) { x -= other.x; y -= other.y; return *this; }
  Point& operator *= (const double& factor) { x *= factor; y *= factor; return *this; }
  Point& operator /= (const double& factor) { x /= factor; y /= factor; return *this; }
};
using Vector = Point;
using Polygon = vector<Point>;
Point operator + (const Point&lhs, const Point& rhs) { return Point(lhs.x + rhs.x, lhs.y + rhs.y); }
Point operator - (const Point& lhs, const Point& rhs) { return Point(lhs.x - rhs.x, lhs.y - rhs.y); }
Point operator * (const Point& lhs, const double& factor) { return Point(lhs.x * factor, lhs.y * factor); }
Point operator * (const double& factor, const Point& rhs) { return Point(factor * rhs.x, factor * rhs.y); }
Point operator / (const Point& lhs, const double& factor) { return Point(lhs.x / factor, lhs.y / factor); }
double operator * (const Point& lhs, const Point& rhs) { return lhs.x * rhs.x + lhs.y * rhs.y; }
double operator ^ (const Point& lhs, const Point& rhs) { return lhs.x * rhs.y - lhs.y * rhs.x; }
bool operator == (const Point& lhs, const Point& rhs) { return sgn(lhs.x - rhs.x) == 0 && sgn(lhs.y - rhs.y) == 0; }
bool operator != (const Point& lhs, const Point& rhs) { return !(lhs == rhs); }
bool operator < (const Point& lhs, const Point& rhs) { return sgn(lhs.x - rhs.x) ? lhs.x < rhs.x : lhs.y < rhs.y; }
bool operator > (const Point& lhs, const Point& rhs) { return rhs < lhs; }
bool operator <= (const Point& lhs, const Point& rhs) { return !(lhs > rhs); }
bool operator >= (const Point& lhs, const Point& rhs) { return !(lhs < rhs); }
istream& operator >> (istream& is, Point& point) { return is >> point.x >> point.y; }
ostream& operator << (ostream& os, Point& point) { return os << "(" << point.x << "," << point.y << ")"; }
double norm(const Point& point) { return point.x * point.x + point.y * point.y; }
double abs(const Point& point) { return sqrt(norm(point)); }
double arg(const Point& point) { return atan2(point.y, point.x); }
Point polar(const double& a, const double& r) { return Point(cos(r) * a, sin(r) * a); }
bool sort_x(Point lhs, Point rhs) { return sgn(lhs.x - rhs.x) ? lhs.x < rhs.x : lhs.y < rhs.y; }
bool sort_y(Point lhs, Point rhs) { return sgn(lhs.y - rhs.y) ? lhs.y < rhs.y : lhs.x < rhs.x; }

static const int IN = 2;
static const int ON = 1;
static const int OUT = 0;
int contain(const Polygon& ps, const Point& p) {
  int n = ps.size(), x = 0;
  for (int i = 0; i < n; i++) {
    Point a = ps[i] - p, b = ps[(i + 1) % n] - p;
    if (sgn(a ^ b) == 0 && sgn(a * b) != 1) return 1;
    if (a.y > b.y) swap(a, b);
    if (sgn(a.y) != 1 && sgn(b.y) == 1 && sgn(a ^ b) == 1) x ^= 1;
  }
  return x ? 2 : 0;
}

int main() {
  cin.tie(0);
  ios_base::sync_with_stdio(false);
  cout << fixed << setprecision(10);
  
  int n;
  cin >> n;
  for (int i = 0; i < n; i++) {
    Polygon ps(3);
    Point k, s;
    for (int j = 0; j < 3; j++) {
      cin >> ps[j];
    }
    cin >> k >> s;
    cout << (contain(ps, k) ^ contain(ps, s) ? "OK" : "NG") << endl;
  }

  return 0;
}

C++: #define _USE_MATH_DEFINES
#include <iostream>
#include <sstream>
#include <cmath>
#include <algorithm>
#include <queue>
#include <stack>
#include <limits>
#include <map>
#include <string>
#include <cstring>
#include <set>
#include <deque>

using namespace std;

typedef long long ll;
typedef pair<double,int> P;

static const double eps = 10e-6;

class intersect_triangle{
private:
	double dst[3];
	double orig[3], dir[3];
	double vert0[3],vert1[3],vert2[3];

	double dot(double v1[3],double v2[3]){
		return v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2];
	}
	void cross(double dest[3],double v1[3],double v2[3]){
		dest[0] = v1[1]*v2[2]-v1[2]*v2[1];
		dest[1] = v1[2]*v2[0]-v1[0]*v2[2];
		dest[2] = v1[0]*v2[1]-v1[1]*v2[0];
	}

	void sub(double dest[3],double v1[3], double v2[3]){
		dest[0] = v1[0]-v2[0];
		dest[1] = v1[1]-v2[1];
		dest[2] = v1[2]-v2[2];
	}
public:
	intersect_triangle(double xp1,double yp1,double xp2,double yp2,double xp3,double yp3,
		double xk,double yk){
		vert0[0] = xp1;
		vert0[1] = yp1;
		vert0[2] = 0;

		vert1[0] = xp2;
		vert1[1] = yp2;
		vert1[2] = 0;

		vert2[0] = xp3;
		vert2[1] = yp3;
		vert2[2] = 0;

		orig[0] = xk;
		orig[1] = yk;
		orig[2] = -1;

		dst[0] = xk;
		dst[1] = yk;
		dst[2] = 1;

		double len = sqrt(pow(dst[0]-orig[0],2.0)+pow(dst[1]-orig[1],2.0)+pow(dst[2]-orig[2],2.0));
		dir[0] = (dst[0]-orig[0])/len;
		dir[1] = (dst[1]-orig[1])/len;
		dir[2] = (dst[2]-orig[2])/len;
	}

	bool is_intersect(){
		double edge1[3],edge2[3],tvec[3],pvec[3],qvec[3];
		double det,inv_det,t=0,v=0,u=0;

		sub(edge1,vert1,vert0);
		sub(edge2,vert2,vert0);

		cross(pvec,dir,edge2);

		det=dot(edge1,pvec);

		if(det > -eps && det < eps) return false;

		inv_det = 1.0/det;

		sub(tvec,orig,vert0);

		u=dot(tvec,pvec)*inv_det;
		if(u < 0.0 || u > 1.0) return false;

		cross(qvec,tvec,edge1);

		v=dot(dir,qvec) * inv_det;
		if(v < 0.0 || u+v > 1.0) return false;

		t = dot(edge2,qvec) * inv_det;

		return true;

	}
};

int main(){
	int n;
	scanf("%d",&n);

	for(int i=0;i<n;i++){
		double xp1,yp1,xp2,yp2,xp3,yp3,xk,yk,xs,ys;
		scanf("%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
			&xp1,&yp1,&xp2,&yp2,&xp3,&yp3,&xk,&yk,&xs,&ys);
		intersect_triangle inter_t1(xp1,yp1,xp2,yp2,xp3,yp3,xk,yk);
		intersect_triangle inter_t2(xp1,yp1,xp2,yp2,xp3,yp3,xs,ys);
		printf("%s\n",(inter_t1.is_intersect() && inter_t2.is_intersect()) 
			|| (!inter_t1.is_intersect() && !inter_t2.is_intersect())
			? "NG" : "OK");
	}
}

C++: #include<iostream>
using namespace std;struct P{float x,y;int operator-=(P&a){x-=a.x;y-=a.y;}};P A,B,C,S,G;int X(P S){C.x=(B.y*S.x-B.x*S.y)/(A.x*B.y-A.y*B.x);C.y=(A.y*S.x-A.x*S.y)/(A.y*B.x-A.x*B.y);return C.x>0&&C.y>0&&C.x+C.y<1;}main(){cin>>A.x;while(cin>>A.x>>A.y>>B.x>>B.y>>C.x>>C.y>>S.x>>S.y>>G.x>>G.y){A-=C;B-=C;S-=C;G-=C;X(S)^X(G)?cout<<"OK\n":cout<<"NG\n";}return 0;}