context("K-Permutations")

test_that("K-Permutations - npermutations", {
    expect_equal(npermutations(6, 3), 120)
    expect_equal(npermutations(x = LETTERS[1:6], k = 3), 120)
    expect_error(npermutations(14, 10), "integer overflow")
    expect_error(npermutations(x = LETTERS[1:14], k = 10), "integer overflow")
    expect_equal(npermutations(14, 10, bigz = TRUE), gmp::as.bigz("3632428800"))
    expect_equal(npermutations(6, 0), 1)
    expect_equal(npermutations(6, 7), 0)
    expect_error(npermutations(6, -1), "expect integer")
    expect_error(npermutations(6, 1.5), "expect integer")

    expect_equal(npermutations(0, 0), 1)
    expect_equal(npermutations(0, 1), 0)
})

test_that("K-Permutations - permutations", {
    perm <- permutations(6, 3)
    expect_equal(nrow(perm), 120)
    expect_equal(ncol(perm), 3)
    expect_equal(perm[1, ], 1:3)
    expect_equal(perm[120, ], 6:4)

    perm <- permutations(6, 3, layout = "row")
    expect_equal(nrow(perm), 120)
    expect_equal(ncol(perm), 3)
    expect_equal(perm[1, ], 1:3)
    expect_equal(perm[120, ], 6:4)

    perm <- permutations(6, 3, layout = "column")
    expect_equal(ncol(perm), 120)
    expect_equal(nrow(perm), 3)
    expect_equal(perm[, 1], 1:3)
    expect_equal(perm[, 120], 6:4)

    perm <- permutations(6, 3, layout = "list")
    expect_equal(length(perm), 120)
    expect_equal(perm[[1]], 1:3)
    expect_equal(perm[[120]], 6:4)

    perm <- permutations(x = LETTERS[1:6], k = 3)
    expect_equal(nrow(perm), 120)
    expect_equal(ncol(perm), 3)
    expect_equal(perm[1, ], LETTERS[1:3])
    expect_equal(perm[120, ], LETTERS[6:4])

    expect_error(permutations(14, 10), "too many results")
    expect_error(permutations(6, -1), "expect integer")
    expect_error(permutations(6, 1.5), "expect integer")
    expect_equal(dim(permutations(6, 0)), c(1, 0))
    expect_equal(dim(permutations(6, 7)), c(0, 7))
    expect_equal(dim(permutations(0, 0)), c(1, 0))
    expect_equal(dim(permutations(0, 1)), c(0, 1))
})

test_that("K-Permutations - ipermutations", {
    iperm <- ipermutations(6, 3)
    perm <- permutations(6, 3)
    expect_equal(iperm$collect(), perm)
    expect_equal(iperm$getnext(), 1:3)
    expect_equal(iperm$getnext(), c(1, 2, 4))
    iperm$getnext(110)
    expect_equal(nrow(iperm$getnext(10)), 8)
    expect_equal(iperm$getnext(), NULL)

    perm <- permutations(6, 3, layout = "row")
    expect_equal(iperm$collect(), perm)
    expect_equal(iperm$getnext(layout = "row"), t(1:3))
    expect_equal(iperm$getnext(layout = "row"), t(c(1, 2, 4)))
    iperm$getnext(110, layout = "row")
    expect_equal(nrow(iperm$getnext(10)), 8)
    expect_equal(iperm$getnext(layout = "row"), NULL)

    perm <- permutations(6, 3, layout = "column")
    expect_equal(iperm$collect(layout = "column"), perm)
    expect_equal(iperm$getnext(layout = "column"), t(t(1:3)))
    expect_equal(iperm$getnext(layout = "column"), t(t(c(1, 2, 4))))
    iperm$getnext(110, layout = "column")
    expect_equal(ncol(iperm$getnext(10, layout = "column")), 8)
    expect_equal(iperm$getnext(layout = "column"), NULL)

    perm <- permutations(6, 3, layout = "list")
    expect_equal(iperm$collect(layout = "list"), perm)
    expect_equal(iperm$getnext(layout = "list"), list(1:3))
    expect_equal(iperm$getnext(layout = "list"), list(c(1, 2, 4)))
    iperm$getnext(110, layout = "list")
    expect_equal(length(iperm$getnext(10, layout = "list")), 8)
    expect_equal(iperm$getnext(layout = "list"), NULL)

    iperm <- ipermutations(6, 0)
    expect_equal(dim(iperm$collect()), c(1, 0))
    expect_equal(iperm$getnext(), integer(0))
    iperm <- ipermutations(6, 7)
    expect_equal(dim(iperm$collect()), c(0, 7))
    expect_equal(iperm$getnext(), NULL)
    expect_error(ipermutations(6, -1), "expect integer")
    expect_error(ipermutations(6, 1.5), "expect integer")
})

test_that("Permutations - index", {
    expect_equal(permutations(5, 3, index = 1:60), permutations(5, 3))
    expect_equal(permutations(5, 3, index = as.numeric(1:60)), permutations(5, 3))
    expect_equal(permutations(5, 3, index = as.character(1:60)), permutations(5, 3))
    expect_equal(permutations(5, 3, index = gmp::as.bigz(1:60)), permutations(5, 3))
    expect_equal(permutations(5, 3, index = 2), c(1, 2, 4))
    expect_equal(permutations(5, 3, index = 10), c(1, 5, 2))
    expect_error(permutations(5, 3, index = -1), "invalid index")
    expect_error(permutations(5, 3, index = 1.5), "invalid index")
    expect_error(permutations(5, 3, index = "-1"), "invalid index")
    expect_error(permutations(5, 3, index = "1.5"), "invalid index")

    expect_equal(permutations(50, 30, index = 2), c(1:29, 31))
    expect_equal(permutations(50, 30, index = npermutations(50, 30, bigz = TRUE)), 50:21)
    expect_error(permutations(50, 30, index = -1), "invalid index")
    expect_error(permutations(50, 30, index = 1.5), "invalid index")
    expect_error(permutations(50, 30, index = "-1"), "invalid index")
    expect_error(permutations(50, 30, index = "1.5"), "invalid index")

    expect_equal(permutations(5, 3, index = 1:60, layout = "row"), permutations(5, 3, layout = "row"))
    expect_equal(permutations(5, 3, index = as.numeric(1:60), layout = "row"), permutations(5, 3, layout = "row"))
    expect_equal(permutations(5, 3, index = as.character(1:60), layout = "row"), permutations(5, 3, layout = "row"))
    expect_equal(permutations(5, 3, index = gmp::as.bigz(1:60), layout = "row"), permutations(5, 3, layout = "row"))
    expect_equal(permutations(5, 3, index = 2, layout = "row")[1, ], c(1, 2, 4))
    expect_equal(permutations(5, 3, index = 10, layout = "row")[1, ], c(1, 5, 2))
    expect_equal(permutations(50, 30, index = 2, layout = "row")[1, ], c(1:29, 31))

    expect_equal(permutations(5, 3, index = 1:60, layout = "column"), permutations(5, 3, layout = "column"))
    expect_equal(permutations(5, 3, index = as.numeric(1:60), layout = "column"), permutations(5, 3, layout = "column"))
    expect_equal(permutations(5, 3, index = as.character(1:60), layout = "column"), permutations(5, 3, layout = "column"))
    expect_equal(permutations(5, 3, index = gmp::as.bigz(1:60), layout = "column"), permutations(5, 3, layout = "column"))
    expect_equal(permutations(5, 3, index = 2, layout = "column")[, 1], c(1, 2, 4))
    expect_equal(permutations(5, 3, index = 10, layout = "column")[, 1], c(1, 5, 2))
    expect_equal(permutations(50, 30, index = 2, layout = "column")[, 1], c(1:29, 31))

    expect_equal(permutations(5, 3, index = 1:60, layout = "list"), permutations(5, 3, layout = "list"))
    expect_equal(permutations(5, 3, index = as.numeric(1:60), layout = "list"), permutations(5, 3, layout = "list"))
    expect_equal(permutations(5, 3, index = as.character(1:60), layout = "list"), permutations(5, 3, layout = "list"))
    expect_equal(permutations(5, 3, index = gmp::as.bigz(1:60), layout = "list"), permutations(5, 3, layout = "list"))
    expect_equal(permutations(5, 3, index = 2, layout = "list"), list(c(1, 2, 4)))
    expect_equal(permutations(5, 3, index = 10, layout = "list"), list(c(1, 5, 2)))
    expect_equal(permutations(50, 30, index = 2, layout = "list"), list(c(1:29, 31)))

    expect_error(permutations(0, 1, index = 1), "invalid index")
    expect_equal(permutations(0, 0, index = 1), integer(0))
    expect_error(permutations(0, 1, index = gmp::as.bigz(1)), "invalid index")
    expect_equal(permutations(0, 0, index = gmp::as.bigz(1)), integer(0))
})

test_that("K-Permutations - skip", {
    expect_equal(permutations(6, 3, skip = 120), permutations(6, 3))
    expect_equal(permutations(6, 3, skip = 3), permutations(6, 3)[4:120, ])
    expect_equal(permutations(6, 3, skip = 3, nitem = 4), permutations(6, 3)[4:7, ])
    expect_equal(permutations(6, 3, skip = gmp::as.bigz(3), nitem = 4), permutations(6, 3)[4:7, ])
})
