# 4D Vertex structure

struct Vertex4D
    dx::Float32
    dy::Float32
    dz::Float32
    dw::Float32
    xsvp::Int64
    ysvp::Int64
    zsvp::Int64
    wsvp::Int64

    function Vertex4D(xsv::Int, ysv::Int, zsv::Int, wsv::Int)
        ssv = Float32((xsv + ysv + zsv + wsv) * UNSKEW_4D)
        new(-xsv - ssv, -ysv - ssv, -zsv - ssv, -wsv - ssv,
            (xsv * PRIME_X)%Int64,
            (ysv * PRIME_Y)%Int64,
            (zsv * PRIME_Z)%Int64,
            (wsv * PRIME_W)%Int64)
    end
end
Vertex4D(v) = Vertex4D(((v >> 0) & 3) - 1, ((v >> 2) & 3) - 1,
                       ((v >> 4) & 3) - 1, ((v >> 6) & 3) - 1)

# Lookup Tables & Gradients

const vertex_ind = [
     7,17,22,24,25,26,28,29,35,36,39,40,53,54,57,58,64,65,67,68,
     7,17,22,25,26,28,29,35,36,40,53,54,58,65,68,
     1, 3, 5, 7,15,17,22,25,26,29,36,40,54,58,65,68,
     1, 7, 8,17,18,22,23,25,26,29,36,40,54,58,65,68,69,
     7,17,24,25,26,28,29,35,39,40,53,57,58,67,68,
     3, 7,17,25,26,28,29,35,36,39,40,53,54,57,58,68,
     3, 7,17,25,26,28,29,36,40,54,58,68,
     3, 7, 8,17,18,25,26,28,29,36,40,54,58,68,69,
     2, 3, 6, 7,16,17,24,25,28,29,39,40,57,58,67,68,
     3, 7,17,25,26,28,29,39,40,57,58,68,
     3, 7,17,25,26,28,29,40,58,68,
     3, 7, 8,17,18,25,26,28,29,30,40,58,68,69,
     2, 7, 9,17,19,24,25,27,28,29,39,40,57,58,67,68,71,
     3, 7, 9,17,19,25,26,28,29,39,40,57,58,68,71,
     3, 7, 9,17,19,25,26,28,29,31,40,58,68,71,
     3, 7,10,17,20,25,26,28,29,30,31,40,58,68,69,71,72,
     7,22,24,25,26,28,35,36,39,40,53,64,65,67,68,
     5, 7,22,25,26,28,29,35,36,39,40,53,54,64,65,68,
     5, 7,22,25,26,29,35,36,40,54,65,68,
     5, 7, 8,22,23,25,26,29,35,36,40,54,65,68,69,
     6, 7,24,25,26,28,29,35,36,39,40,53,57,64,67,68,
     7,25,26,28,29,35,36,39,40,53,58,65,67,68,
     7,25,26,28,29,35,36,39,40,54,58,65,68,69,
     7, 8,25,26,29,36,40,41,54,58,65,68,69,
     6, 7,24,25,28,29,35,39,40,57,67,68,
     7,25,26,28,29,35,36,39,40,57,58,67,68,71,
     7,25,26,28,29,35,36,39,40,58,68,
     7, 8,25,26,28,29,36,40,41,58,68,69,
     6, 7, 9,24,25,27,28,29,35,39,40,57,67,68,71,
     7, 9,25,28,29,39,40,43,57,58,67,68,71,
     7, 9,25,26,28,29,39,40,43,58,68,71,
     7,10,25,26,28,29,40,41,43,58,68,69,71,72,
     4, 5, 6, 7,21,22,24,25,35,36,39,40,64,65,67,68,
     5, 7,22,25,26,35,36,39,40,64,65,68,
     5, 7,22,25,26,35,36,40,65,68,
     5, 7, 8,22,23,25,26,35,36,37,40,65,68,69,
     6, 7,24,25,28,35,36,39,40,64,67,68,
     7,25,26,28,29,35,36,39,40,64,65,67,68,76,
     7,25,26,28,29,35,36,39,40,65,68,
     7, 8,25,26,29,35,36,40,41,65,68,69,
     6, 7,24,25,28,35,39,40,67,68,
     7,25,26,28,29,35,36,39,40,67,68,
     7,25,26,28,29,35,36,39,40,68,
     7, 8,25,26,28,29,35,36,39,40,41,68,69,
     6, 7, 9,24,25,27,28,35,39,40,42,67,68,71,
     7, 9,25,28,29,35,39,40,43,67,68,71,
     7, 9,25,26,28,29,35,36,39,40,43,68,71,
     7,25,26,28,29,36,39,40,41,43,58,68,69,71,72,
     4, 7,11,22,24,25,32,34,35,36,39,40,64,65,67,68,76,
     5, 7,11,22,25,26,32,35,36,39,40,64,65,68,76,
     5, 7,11,22,25,26,32,35,36,40,44,65,68,76,
     5, 7,12,22,25,26,33,35,36,37,40,44,65,68,69,76,77,
     6, 7,11,24,25,28,34,35,36,39,40,64,67,68,76,
     7,11,25,35,36,39,40,46,64,65,67,68,76,
     7,11,25,26,35,36,39,40,46,65,68,76,
     7,12,25,26,35,36,40,41,46,65,68,69,76,77,
     6, 7,11,24,25,28,34,35,39,40,45,67,68,76,
     7,11,25,28,35,36,39,40,46,67,68,76,
     7,11,25,26,28,29,35,36,39,40,46,68,76,
     7,25,26,29,35,36,39,40,41,46,65,68,69,76,77,
     6, 7,13,24,25,28,35,38,39,40,42,45,67,68,71,76,78,
     7,13,25,28,35,39,40,43,46,67,68,71,76,78,
     7,25,28,29,35,36,39,40,43,46,67,68,71,76,78,
     7,25,26,28,29,35,36,39,40,41,43,46,68,69,71,76,79,
    17,22,24,25,26,28,35,53,54,57,58,64,65,67,68,
    15,17,22,25,26,28,29,35,36,53,54,57,58,64,65,68,
    15,17,22,25,26,29,36,53,54,58,65,68,
    15,17,18,22,23,25,26,29,36,53,54,58,65,68,69,
    16,17,24,25,26,28,29,35,39,53,54,57,58,64,67,68,
    17,25,26,28,29,35,40,53,54,57,58,65,67,68,
    17,25,26,28,29,36,40,53,54,57,58,65,68,69,
    17,18,25,26,29,36,40,54,58,59,65,68,69,
    16,17,24,25,28,29,39,53,57,58,67,68,
    17,25,26,28,29,39,40,53,54,57,58,67,68,71,
    17,25,26,28,29,40,53,54,57,58,68,
    17,18,25,26,28,29,40,54,58,59,68,69,
    16,17,19,24,25,27,28,29,39,53,57,58,67,68,71,
    17,19,25,28,29,39,40,57,58,61,67,68,71,
    17,19,25,26,28,29,40,57,58,61,68,71,
    17,20,25,26,28,29,40,58,59,61,68,69,71,72,
    21,22,24,25,26,28,35,36,39,53,54,57,64,65,67,68,
    22,25,26,28,35,36,40,53,54,58,64,65,67,68,
    22,25,26,29,35,36,40,53,54,58,64,65,68,69,
    22,23,25,26,29,36,40,54,58,65,66,68,69,
    24,25,26,28,35,39,40,53,57,58,64,65,67,68,
    25,26,28,29,35,36,39,40,53,54,57,58,64,65,67,68,
     7,17,22,25,26,28,29,35,36,40,53,54,58,65,68,69,
    25,26,29,36,40,54,58,65,68,69,
    24,25,28,29,35,39,40,53,57,58,64,67,68,71,
     7,17,24,25,26,28,29,35,39,40,53,57,58,67,68,71,
     7,17,25,26,28,29,35,36,39,40,53,54,57,58,65,67,68,69,71,
    25,26,28,29,36,40,54,58,65,68,69,
    24,25,27,28,29,39,40,57,58,67,68,70,71,
    25,28,29,39,40,57,58,67,68,71,
    25,26,28,29,39,40,57,58,67,68,71,
    25,26,28,29,40,58,68,69,71,72,
    21,22,24,25,35,36,39,53,64,65,67,68,
    22,25,26,35,36,39,40,53,54,64,65,67,68,76,
    22,25,26,35,36,40,53,54,64,65,68,
    22,23,25,26,35,36,40,54,65,66,68,69,
    24,25,28,35,36,39,40,53,57,64,65,67,68,76,
     7,22,24,25,26,28,35,36,39,40,53,64,65,67,68,76,
     7,22,25,26,28,29,35,36,39,40,53,54,58,64,65,67,68,69,76,
    25,26,29,35,36,40,54,58,65,68,69,
    24,25,28,35,39,40,53,57,64,67,68,
     7,24,25,26,28,29,35,36,39,40,53,57,58,64,65,67,68,71,76,
     7,25,26,28,29,35,36,39,40,58,65,67,68,
     7,25,26,28,29,35,36,39,40,54,58,65,68,69,
    24,25,27,28,35,39,40,57,67,68,70,71,
    25,28,29,35,39,40,57,58,67,68,71,
     7,25,26,28,29,35,36,39,40,57,58,67,68,71,
     7,25,26,28,29,36,39,40,58,68,69,71,72,
    21,22,24,25,32,34,35,36,39,53,64,65,67,68,76,
    22,25,32,35,36,39,40,64,65,67,68,74,76,
    22,25,26,32,35,36,40,64,65,68,74,76,
    22,25,26,33,35,36,40,65,66,68,69,74,76,77,
    24,25,34,35,36,39,40,64,65,67,68,75,76,
    25,35,36,39,40,64,65,67,68,76,
    25,26,35,36,39,40,64,65,67,68,76,
    25,26,35,36,40,65,68,69,76,77,
    24,25,28,34,35,39,40,64,67,68,75,76,
    25,28,35,36,39,40,64,65,67,68,76,
     7,25,26,28,29,35,36,39,40,64,65,67,68,76,
     7,25,26,29,35,36,39,40,65,68,69,76,77,
    24,25,28,35,38,39,40,67,68,70,71,75,76,78,
    25,28,35,39,40,67,68,71,76,78,
     7,25,28,29,35,36,39,40,67,68,71,76,78,
    25,26,28,29,35,36,39,40,68,69,71,76,79,
    14,15,16,17,21,22,24,25,53,54,57,58,64,65,67,68,
    15,17,22,25,26,53,54,57,58,64,65,68,
    15,17,22,25,26,53,54,58,65,68,
    15,17,18,22,23,25,26,53,54,55,58,65,68,69,
    16,17,24,25,28,53,54,57,58,64,67,68,
    17,25,26,28,29,53,54,57,58,64,65,67,68,86,
    17,25,26,28,29,53,54,57,58,65,68,
    17,18,25,26,29,53,54,58,59,65,68,69,
    16,17,24,25,28,53,57,58,67,68,
    17,25,26,28,29,53,54,57,58,67,68,
    17,25,26,28,29,53,54,57,58,68,
    17,18,25,26,28,29,53,54,57,58,59,68,69,
    16,17,19,24,25,27,28,53,57,58,60,67,68,71,
    17,19,25,28,29,53,57,58,61,67,68,71,
    17,19,25,26,28,29,53,54,57,58,61,68,71,
    17,25,26,28,29,40,54,57,58,59,61,68,69,71,72,
    21,22,24,25,35,53,54,57,64,65,67,68,
    22,25,26,35,36,53,54,57,58,64,65,67,68,86,
    22,25,26,35,36,53,54,58,64,65,68,
    22,23,25,26,36,53,54,58,65,66,68,69,
    24,25,28,35,39,53,54,57,58,64,65,67,68,86,
    17,22,24,25,26,28,35,53,54,57,58,64,65,67,68,86,
    17,22,25,26,28,29,35,36,40,53,54,57,58,64,65,67,68,69,86,
    25,26,29,36,40,53,54,58,65,68,69,
    24,25,28,35,39,53,57,58,64,67,68,
    17,24,25,26,28,29,35,39,40,53,54,57,58,64,65,67,68,71,86,
    17,25,26,28,29,40,53,54,57,58,65,67,68,
    17,25,26,28,29,36,40,53,54,57,58,65,68,69,
    24,25,27,28,39,53,57,58,67,68,70,71,
    25,28,29,39,40,53,57,58,67,68,71,
    17,25,26,28,29,39,40,53,54,57,58,67,68,71,
    17,25,26,28,29,40,54,57,58,68,69,71,72,
    21,22,24,25,35,53,64,65,67,68,
    22,25,26,35,36,53,54,64,65,67,68,
    22,25,26,35,36,53,54,64,65,68,
    22,23,25,26,35,36,53,54,64,65,66,68,69,
    24,25,28,35,39,53,57,64,65,67,68,
    22,24,25,26,28,35,36,39,40,53,54,57,58,64,65,67,68,76,86,
    22,25,26,35,36,40,53,54,58,64,65,67,68,
    22,25,26,29,35,36,40,53,54,58,64,65,68,69,
    24,25,28,35,39,53,57,64,67,68,
    24,25,28,35,39,40,53,57,58,64,65,67,68,
    25,26,28,29,35,36,39,40,53,54,57,58,64,65,67,68,
    25,26,28,29,35,36,40,53,54,58,65,67,68,69,
    24,25,27,28,35,39,53,57,64,67,68,70,71,
    24,25,28,29,35,39,40,53,57,58,64,67,68,71,
    25,26,28,29,35,39,40,53,57,58,65,67,68,71,
    25,26,28,29,36,39,40,54,57,58,65,67,68,69,71,72,
    21,22,24,25,32,34,35,53,64,65,67,68,73,76,
    22,25,32,35,36,53,64,65,67,68,74,76,
    22,25,26,32,35,36,53,54,64,65,68,74,76,
    22,25,26,35,36,40,54,64,65,66,68,69,74,76,77,
    24,25,34,35,39,53,64,65,67,68,75,76,
    25,35,36,39,40,53,64,65,67,68,76,
    22,25,26,35,36,39,40,53,54,64,65,67,68,76,
    22,25,26,35,36,40,54,64,65,68,69,76,77,
    24,25,28,34,35,39,53,57,64,67,68,75,76,
    24,25,28,35,36,39,40,53,57,64,65,67,68,76,
    25,26,28,35,36,39,40,53,58,64,65,67,68,76,
    25,26,29,35,36,39,40,54,58,64,65,67,68,69,76,77,
    24,25,28,35,39,40,57,64,67,68,70,71,75,76,78,
    24,25,28,35,39,40,57,64,67,68,71,76,78,
    25,28,29,35,36,39,40,57,58,64,65,67,68,71,76,78,
    25,26,28,29,35,36,39,40,58,65,67,68,69,71,76,
    14,17,22,24,25,47,50,52,53,54,57,58,64,65,67,68,86,
    15,17,22,25,26,47,50,53,54,57,58,64,65,68,86,
    15,17,22,25,26,47,50,53,54,58,65,68,80,86,
    15,17,22,25,26,48,51,53,54,55,58,65,68,69,80,86,87,
    16,17,24,25,28,47,52,53,54,57,58,64,67,68,86,
    17,25,47,53,54,57,58,64,65,67,68,82,86,
    17,25,26,47,53,54,57,58,65,68,82,86,
    17,25,26,48,53,54,58,59,65,68,69,82,86,87,
    16,17,24,25,28,47,52,53,57,58,67,68,81,86,
    17,25,28,47,53,54,57,58,67,68,82,86,
    17,25,26,28,29,47,53,54,57,58,68,82,86,
    17,25,26,29,53,54,57,58,59,65,68,69,82,86,87,
    16,17,24,25,28,49,53,56,57,58,60,67,68,71,81,86,88,
    17,25,28,49,53,57,58,61,67,68,71,82,86,88,
    17,25,28,29,53,54,57,58,61,67,68,71,82,86,88,
    17,25,26,28,29,53,54,57,58,59,61,68,69,71,82,86,89,
    21,22,24,25,35,50,52,53,54,57,64,65,67,68,86,
    22,25,50,53,54,57,58,64,65,67,68,84,86,
    22,25,26,50,53,54,58,64,65,68,84,86,
    22,25,26,51,53,54,58,65,66,68,69,84,86,87,
    24,25,52,53,54,57,58,64,65,67,68,85,86,
    25,53,54,57,58,64,65,67,68,86,
    25,26,53,54,57,58,64,65,67,68,86,
    25,26,53,54,58,65,68,69,86,87,
    24,25,28,52,53,57,58,64,67,68,85,86,
    25,28,53,54,57,58,64,65,67,68,86,
    17,25,26,28,29,53,54,57,58,64,65,67,68,86,
    17,25,26,29,53,54,57,58,65,68,69,86,87,
    24,25,28,53,56,57,58,67,68,70,71,85,86,88,
    25,28,53,57,58,67,68,71,86,88,
    17,25,28,29,53,54,57,58,67,68,71,86,88,
    25,26,28,29,53,54,57,58,68,69,71,86,89,
    21,22,24,25,35,50,52,53,64,65,67,68,83,86,
    22,25,35,50,53,54,64,65,67,68,84,86,
    22,25,26,35,36,50,53,54,64,65,68,84,86,
    22,25,26,36,53,54,58,64,65,66,68,69,84,86,87,
    24,25,35,52,53,57,64,65,67,68,85,86,
    25,35,53,54,57,58,64,65,67,68,86,
    22,25,26,35,36,53,54,57,58,64,65,67,68,86,
    22,25,26,36,53,54,58,64,65,68,69,86,87,
    24,25,28,35,39,52,53,57,64,67,68,85,86,
    24,25,28,35,39,53,54,57,58,64,65,67,68,86,
    25,26,28,35,40,53,54,57,58,64,65,67,68,86,
    25,26,29,36,40,53,54,57,58,64,65,67,68,69,86,87,
    24,25,28,39,53,57,58,64,67,68,70,71,85,86,88,
    24,25,28,39,53,57,58,64,67,68,71,86,88,
    25,28,29,39,40,53,54,57,58,64,65,67,68,71,86,88,
    25,26,28,29,40,53,54,57,58,65,67,68,69,71,86,
    21,22,24,25,35,53,62,63,64,65,67,68,73,76,83,86,90,
    22,25,35,53,62,64,65,67,68,74,76,84,86,90,
    22,25,35,36,53,54,64,65,67,68,74,76,84,86,90,
    22,25,26,35,36,53,54,64,65,66,68,69,74,76,84,86,91,
    24,25,35,53,63,64,65,67,68,75,76,85,86,90,
    25,35,53,64,65,67,68,76,86,90,
    22,25,35,36,53,54,64,65,67,68,76,86,90,
    25,26,35,36,53,54,64,65,68,69,76,86,91,
    24,25,35,39,53,57,64,65,67,68,75,76,85,86,90,
    24,25,35,39,53,57,64,65,67,68,76,86,90,
    25,35,36,39,40,53,54,57,58,64,65,67,68,76,86,90,
    25,26,35,36,40,53,54,58,64,65,67,68,69,76,86,
    24,25,28,35,39,53,57,64,67,68,70,71,75,76,85,86,92,
    25,28,35,39,53,57,64,67,68,71,76,86,92,
    25,28,35,39,40,53,57,58,64,65,67,68,71,76,86,
    25,26,28,29,35,36,39,40,53,54,57,58,64,65,67,68,69,71,76,86,
]

const offsets_4D =
    UInt16[  20,  35,  51,  68,  83,  99, 111, 126, 142, 154, 164, 178, 195, 210, 224, 241,
            256, 272, 284, 299, 315, 329, 343, 356, 368, 382, 393, 405, 420, 433, 445, 459,
            475, 487, 497, 511, 523, 537, 548, 560, 570, 581, 591, 604, 618, 630, 643, 658,
            675, 690, 704, 721, 736, 749, 761, 775, 789, 801, 814, 829, 846, 860, 875, 892,
            907, 923, 935, 950, 966, 980, 994,1007,1019,1033,1044,1056,1071,1084,1096,1110,
           1126,1140,1154,1167,1181,1197,1213,1223,1237,1253,1272,1283,1296,1306,1317,1327,
           1339,1353,1364,1376,1390,1406,1425,1436,1447,1466,1479,1493,1505,1516,1530,1543,
           1558,1571,1583,1597,1610,1620,1631,1641,1653,1664,1678,1691,1705,1715,1728,1741,
           1757,1769,1779,1793,1805,1819,1830,1842,1852,1863,1873,1886,1900,1912,1925,1940,
           1952,1966,1977,1989,2003,2019,2038,2049,2060,2079,2092,2106,2118,2129,2143,2156,
           2166,2177,2187,2200,2211,2230,2243,2257,2267,2280,2296,2310,2323,2337,2351,2367,
           2381,2393,2406,2421,2433,2444,2458,2471,2484,2498,2512,2528,2543,2556,2572,2587,
           2604,2619,2633,2650,2665,2678,2690,2704,2718,2730,2743,2758,2775,2789,2804,2821,
           2836,2849,2861,2875,2888,2898,2909,2919,2931,2942,2956,2969,2983,2993,3006,3019,
           3033,3045,3058,3073,3085,3096,3110,3123,3136,3150,3164,3180,3195,3208,3224,3239,
           3256,3270,3285,3302,3316,3326,3339,3352,3367,3380,3396,3411,3428,3441,3456,3476]

const lookup_4D =
    Vertex4D.([0x01,0x04,0x05,0x10,0x11,0x14,0x15,0x16,0x19,0x1a,0x25,0x26,0x29,0x40,0x41,0x44,
               0x45,0x46,0x49,0x4a,0x50,0x51,0x52,0x54,0x55,0x56,0x58,0x59,0x5a,0x5b,0x5e,0x61,
               0x62,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6d,0x6e,0x76,0x79,0x7a,0x85,0x86,
               0x89,0x91,0x92,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9d,0x9e,0xa1,0xa4,0xa5,
               0xa6,0xa7,0xa9,0xaa,0xab,0xad,0xae,0xaf,0xb5,0xb6,0xb9,0xba,0xbb,0xbe,0xbf,0xd6,
               0xd9,0xda,0xe5,0xe6,0xe9,0xea,0xeb,0xee,0xef,0xfa,0xfb,0xfe])

