context("Distinct Partitions")

test_that("Integer distinct partitions - npartitions", {
    expect_equal(npartitions(10, distinct = TRUE), 10)
    expect_equal(npartitions(100, distinct = TRUE), 444793)
    expect_error(npartitions(300, distinct = TRUE), "integer overflow")
    expect_equal(npartitions(10, distinct = TRUE, bigz = TRUE), 10)
    expect_equal(npartitions(100, distinct = TRUE, bigz = TRUE), 444793)
    expect_equal(npartitions(300, distinct = TRUE, bigz = TRUE), gmp::as.bigz("114872472064"))
    expect_equal(npartitions(0, distinct = TRUE), 1)
    expect_error(npartitions(-1, distinct = TRUE), "expect integer")
    expect_error(npartitions(1.5, distinct = TRUE), "expect integer")
})

test_that("Integer distinct partitions - ascending partitions", {
    part <- partitions(10, distinct = TRUE)
    expect_equal(nrow(part), 10)
    expect_equal(ncol(part), 4)
    expect_equal(part[1, ], 1:4)
    expect_equal(part[2, ], c(1, 2, 7, 0))
    expect_equal(part[10, ], c(10, rep(0, 3)))
    expect_true(all(apply(part, 1, sum) == 10))

    part <- partitions(10, distinct = TRUE, layout = "row")
    expect_equal(nrow(part), 10)
    expect_equal(ncol(part), 4)
    expect_equal(part[1, ], 1:4)
    expect_equal(part[2, ], c(1, 2, 7, 0))
    expect_equal(part[10, ], c(10, rep(0, 3)))
    expect_true(all(apply(part, 1, sum) == 10))

    part <- partitions(10, distinct = TRUE, layout = "column")
    expect_equal(nrow(part), 4)
    expect_equal(ncol(part), 10)
    expect_equal(part[, 1], 1:4)
    expect_equal(part[, 2], c(1, 2, 7, 0))
    expect_equal(part[, 10], c(10, rep(0, 3)))
    expect_true(all(apply(part, 2, sum) == 10))

    part <- partitions(10, distinct = TRUE, layout = "list")
    expect_equal(length(part), 10)
    expect_equal(part[[1]], 1:4)
    expect_equal(part[[2]], c(1, 2, 7))
    expect_equal(part[[10]], 10)
    expect_true(all(sapply(part, sum) == 10))

    expect_error(partitions(300, distinct = TRUE), "too many results")
    expect_error(partitions(-1, distinct = TRUE), "expect integer")
    expect_error(partitions(1.5, distinct = TRUE), "expect integer")
})

test_that("Integer distinct partitions - descending partitions", {
    part <- partitions(10, distinct = TRUE, descending = TRUE)
    expect_equal(nrow(part), 10)
    expect_equal(ncol(part), 4)
    expect_equal(part[1, ], c(10, 0, 0, 0))
    expect_equal(part[9, ], c(5, 3, 2, 0))
    expect_equal(part[10, ], 4:1)
    expect_true(all(apply(part, 1, sum) == 10))

    part <- partitions(10, distinct = TRUE, descending = TRUE, layout = "row")
    expect_equal(nrow(part), 10)
    expect_equal(ncol(part), 4)
    expect_equal(part[1, ], c(10, 0, 0, 0))
    expect_equal(part[9, ], c(5, 3, 2, 0))
    expect_equal(part[10, ], 4:1)
    expect_true(all(apply(part, 1, sum) == 10))

    part <- partitions(10, distinct = TRUE, descending = TRUE, layout = "column")
    expect_equal(nrow(part), 4)
    expect_equal(ncol(part), 10)
    expect_equal(part[, 1], c(10, 0, 0, 0))
    expect_equal(part[, 9], c(5, 3, 2, 0))
    expect_equal(part[, 10], 4:1)
    expect_true(all(apply(part, 2, sum) == 10))

    part <- partitions(10, distinct = TRUE, descending = TRUE, layout = "list")
    expect_equal(length(part), 10)
    expect_equal(part[[1]], 10)
    expect_equal(part[[9]], c(5, 3, 2))
    expect_equal(part[[10]], 4:1)
    expect_true(all(sapply(part, sum) == 10))

    expect_error(partitions(300, distinct = TRUE, descending = TRUE), "too many results")
    expect_error(partitions(-1, distinct = TRUE, descending = TRUE), "expect integer")
    expect_error(partitions(1.5, distinct = TRUE, descending = TRUE), "expect integer")
})

test_that("Integer distinct partitions - ascending ipartitions", {
    part <- partitions(20, distinct = TRUE)
    ipart <- ipartitions(20, distinct = TRUE)
    expect_is(ipart, "Partitions")
    expect_equal(ipart$collect(), part)
    expect_equal(ipart$getnext(), part[1, ])
    expect_equal(ipart$getnext(), part[2, ])
    expect_equal(ipart$getnext(2), part[3:4, ])
    ipart$getnext(40)
    expect_equal(nrow(ipart$getnext(40)), 20)
    expect_equal(ipart$getnext(), NULL)

    part <- partitions(20, distinct = TRUE, layout = "row")
    ipart$reset()
    expect_is(ipart, "Partitions")
    expect_equal(ipart$collect(), part)
    expect_equal(ipart$getnext(layout = "row"), part[1, , drop = FALSE])
    expect_equal(ipart$getnext(layout = "row"), part[2, , drop = FALSE])
    expect_equal(ipart$getnext(2, layout = "row"), part[3:4, ])
    ipart$getnext(40, layout = "row")
    expect_equal(nrow(ipart$getnext(40, layout = "row")), 20)
    expect_equal(ipart$getnext(layout = "column"), NULL)

    part <- partitions(20, distinct = TRUE, layout = "column")
    ipart$reset()
    expect_equal(ipart$collect(layout = "column"), part)
    expect_equal(ipart$getnext(layout = "column"), part[, 1, drop = FALSE])
    expect_equal(ipart$getnext(layout = "column"), part[, 2, drop = FALSE])
    expect_equal(ipart$getnext(2, layout = "column"), part[, 3:4])
    ipart$getnext(40, layout = "column")
    expect_equal(ncol(ipart$getnext(40, layout = "column")), 20)
    expect_equal(ipart$getnext(layout = "column"), NULL)

    part <- partitions(20, distinct = TRUE, layout = "list")
    ipart$reset()
    expect_equal(ipart$collect(layout = "list"), part)
    expect_equal(ipart$getnext(layout = "list"), part[1])
    expect_equal(ipart$getnext(layout = "list"), part[2])
    expect_equal(ipart$getnext(2, layout = "list"), part[3:4])
    ipart$getnext(40, layout = "list")
    expect_equal(length(ipart$getnext(40, layout = "list")), 20)
    expect_equal(ipart$getnext(layout = "list"), NULL)

    expect_error(ipartitions(-1), "expect integer")
    expect_error(ipartitions(1.5), "expect integer")
})

test_that("Integer distinct partitions - descending ipartitions", {
    part <- partitions(20, distinct = TRUE, descending = TRUE)
    ipart <- ipartitions(20, distinct = TRUE, descending = TRUE)
    expect_is(ipart, "Partitions")
    expect_equal(ipart$collect(), part)
    expect_equal(ipart$getnext(), part[1, ])
    expect_equal(ipart$getnext(), part[2, ])
    expect_equal(ipart$getnext(2), part[3:4, ])
    ipart$getnext(40)
    expect_equal(nrow(ipart$getnext(40)), 20)
    expect_equal(ipart$getnext(), NULL)

    part <- partitions(20, distinct = TRUE, descending = TRUE, layout = "row")
    ipart$reset()
    expect_equal(ipart$collect(layout = "row"), part)
    expect_equal(ipart$getnext(layout = "row"), part[1, , drop = FALSE])
    expect_equal(ipart$getnext(layout = "row"), part[2, , drop = FALSE])
    expect_equal(ipart$getnext(2, layout = "row"), part[3:4, ])
    ipart$getnext(40, layout = "row")
    expect_equal(nrow(ipart$getnext(40, layout = "row")), 20)
    expect_equal(ipart$getnext(layout = "row"), NULL)

    part <- partitions(20, distinct = TRUE, descending = TRUE, layout = "column")
    ipart$reset()
    expect_equal(ipart$collect(layout = "column"), part)
    expect_equal(ipart$getnext(layout = "column"), part[, 1, drop = FALSE])
    expect_equal(ipart$getnext(layout = "column"), part[, 2, drop = FALSE])
    expect_equal(ipart$getnext(2, layout = "column"), part[, 3:4])
    ipart$getnext(40, layout = "column")
    expect_equal(ncol(ipart$getnext(40, layout = "column")), 20)
    expect_equal(ipart$getnext(layout = "column"), NULL)

    part <- partitions(20, distinct = TRUE, descending = TRUE, layout = "list")
    ipart$reset()
    expect_equal(ipart$collect(layout = "list"), part)
    expect_equal(ipart$getnext(layout = "list"), part[1])
    expect_equal(ipart$getnext(layout = "list"), part[2])
    expect_equal(ipart$getnext(2, layout = "list"), part[3:4])
    ipart$getnext(40, layout = "list")
    expect_equal(length(ipart$getnext(40, layout = "list")), 20)
    expect_equal(ipart$getnext(layout = "list"), NULL)

    expect_error(ipartitions(-1, descending = TRUE), "expect integer")
    expect_error(ipartitions(1.5, descending = TRUE), "expect integer")
})


test_that("Integer distinct partitions - index", {
    part <- partitions(15, distinct = TRUE)
    expect_equal(partitions(15, distinct = TRUE, index = 1:27), part)
    expect_equal(partitions(15, distinct = TRUE, index = as.numeric(1:27)), part)
    expect_equal(partitions(15, distinct = TRUE, index = as.character(1:27)), part)
    expect_equal(partitions(15, distinct = TRUE, index = gmp::as.bigz(1:27)), part)
    expect_equal(partitions(15, distinct = TRUE, index = 2), c(1, 2, 3, 9, 0))
    expect_equal(partitions(15, distinct = TRUE, index = 27), c(15, rep(0, 4)))
    expect_equal(partitions(300, distinct = TRUE, index = 2), c(1:22, 47, 0))
    expect_equal(partitions(300, distinct = TRUE, index = "114872472064"), c(300, rep(0, 23)))

    expect_equal(partitions(0, distinct = TRUE, index = 1), integer(0))

    part <- partitions(15, distinct = TRUE, descending = TRUE)
    expect_equal(partitions(15, distinct = TRUE, descending = TRUE, index = 1:27), part)
    expect_equal(partitions(15, distinct = TRUE, descending = TRUE, index = as.numeric(1:27)), part)
    expect_equal(partitions(15, distinct = TRUE, descending = TRUE, index = as.character(1:27)), part)
    expect_equal(partitions(15, distinct = TRUE, descending = TRUE, index = gmp::as.bigz(1:27)), part)
    expect_equal(partitions(15, distinct = TRUE, descending = TRUE, index = 2), c(14, 1, rep(0, 3)))
    expect_equal(partitions(15, distinct = TRUE, descending = TRUE, index = 27), 5:1)
    expect_equal(partitions(300, distinct = TRUE, descending = TRUE, index = 2), c(299, 1, rep(0, 22)))
    expect_equal(partitions(300, distinct = TRUE, descending = TRUE, index = "114872472064"), 24:1)

    expect_equal(partitions(0, distinct = TRUE, descending = TRUE, index = 1), integer(0))
})



test_that("Integer distinct partitions - skip", {
    expect_equal(partitions(10, distinct = TRUE, skip = 10), partitions(10, distinct = TRUE))
    expect_equal(partitions(10, distinct = TRUE, skip = 3), partitions(10, distinct = TRUE)[4:10, ])
    expect_equal(partitions(10, distinct = TRUE, skip = 3, nitem = 4), partitions(10, distinct = TRUE)[4:7, ])
    expect_equal(partitions(10, distinct = TRUE, skip = gmp::as.bigz(3), nitem = 4), partitions(10, distinct = TRUE)[4:7, ])

    expect_equal(partitions(10, distinct = TRUE, descending = TRUE, skip = 10), partitions(10, distinct = TRUE, descending = TRUE))
    expect_equal(partitions(10, distinct = TRUE, descending = TRUE, skip = 3), partitions(10, distinct = TRUE, descending = TRUE)[4:10, ])
    expect_equal(partitions(10, distinct = TRUE, descending = TRUE, skip = 3, nitem = 4), partitions(10, distinct = TRUE, descending = TRUE)[4:7, ])
    expect_equal(partitions(10, distinct = TRUE, descending = TRUE, skip = gmp::as.bigz(3), nitem = 4), partitions(10, distinct = TRUE, descending = TRUE)[4:7, ])
})


test_that("Integer distinct partitions - small cases", {
    expect_equal(partitions(0, distinct = TRUE), matrix(0, nr = 1, nc = 0))
    expect_equal(partitions(0, 0, distinct = TRUE), matrix(0, nr = 1, nc = 0))
    expect_equal(partitions(0, 1, distinct = TRUE), matrix(0, nr = 0, nc = 1))
    expect_equal(partitions(1, distinct = TRUE), matrix(1, nr = 1, nc = 1))
    expect_equal(partitions(1, 0, distinct = TRUE), matrix(1, nr = 0, nc = 0))

    ipart <- ipartitions(0, distinct = TRUE)
    expect_equal(ipart$getnext(), integer(0))
    expect_equal(ipart$getnext(), NULL)

    ipart <- ipartitions(0, 0, distinct = TRUE)
    expect_equal(ipart$getnext(), integer(0))
    expect_equal(ipart$getnext(), NULL)

    ipart <- ipartitions(0, 1, distinct = TRUE)
    expect_equal(ipart$getnext(), NULL)
    expect_equal(ipart$getnext(), NULL)

    ipart <- ipartitions(1, distinct = TRUE)
    expect_equal(ipart$getnext(), 1)
    expect_equal(ipart$getnext(), NULL)

    ipart <- ipartitions(1, 0, distinct = TRUE)
    expect_equal(ipart$getnext(), NULL)
    expect_equal(ipart$getnext(), NULL)
})
