context("K-Compositions")

test_that("Integer compositions in k comps - ncompositions", {
    expect_equal(ncompositions(10, 7), 84)
    expect_equal(ncompositions(10, 11), 0)
    expect_equal(sum(sapply(1:10, function(k) ncompositions(10, k))), 512)
    expect_equal(ncompositions(50, 5), 211876)
    expect_error(ncompositions(100, 10), "integer overflow")
    expect_equal(ncompositions(10, 7, bigz = TRUE), 84)
    expect_equal(ncompositions(50, 5, bigz = TRUE), 211876)
    expect_equal(ncompositions(100, 10, bigz = TRUE), gmp::as.bigz("1731030945644"))
    expect_equal(ncompositions(20, 0), 0)
    expect_equal(ncompositions(0, 0), 1)
    expect_error(ncompositions(20, -1), "expect integer")
    expect_error(ncompositions(20, 1.5), "expect integer")
})

test_that("Integer k-compositions - ascending compositions", {
    comp <- compositions(10, 7)
    expect_equal(nrow(comp), 84)
    expect_equal(ncol(comp), 7)
    expect_equal(comp[1, ], c(rep(1, 6), 4))
    expect_equal(comp[2, ], c(rep(1, 5), 2, 3))
    expect_equal(comp[84, ], c(4, rep(1, 6)))
    expect_true(all(apply(comp, 1, sum) == 10))

    comp <- compositions(10, 7, layout = "row")
    expect_equal(nrow(comp), 84)
    expect_equal(ncol(comp), 7)
    expect_equal(comp[1, ], c(rep(1, 6), 4))
    expect_equal(comp[2, ], c(rep(1, 5), 2, 3))
    expect_equal(comp[84, ], c(4, rep(1, 6)))
    expect_true(all(apply(comp, 1, sum) == 10))

    comp <- compositions(10, 7, layout = "column")
    expect_equal(nrow(comp), 7)
    expect_equal(ncol(comp), 84)
    expect_equal(comp[, 1], c(rep(1, 6), 4))
    expect_equal(comp[, 2], c(rep(1, 5), 2, 3))
    expect_equal(comp[, 84], c(4, rep(1, 6)))
    expect_true(all(apply(comp, 2, sum) == 10))

    comp <- compositions(10, 7, layout = "list")
    expect_equal(length(comp), 84)
    expect_equal(comp[[1]], c(rep(1, 6), 4))
    expect_equal(comp[[2]], c(rep(1, 5), 2, 3))
    expect_equal(comp[[84]], c(4, rep(1, 6)))
    expect_true(all(sapply(comp, sum) == 10))

    expect_error(compositions(100, 10), "too many results")
    expect_equal(dim(compositions(10, 11)), c(0, 11))
    expect_equal(dim(compositions(10, 11, layout = "column")), c(11, 0))
    expect_equal(length(compositions(10, 11, layout = "list")), 0)
    expect_error(compositions(20, -1), "expect integer")
    expect_error(compositions(20, 1.5), "expect integer")
})

test_that("Integer k-compositions - descending compositions", {
    comp <- compositions(10, 7, descending = TRUE)
    expect_equal(nrow(comp), 84)
    expect_equal(ncol(comp), 7)
    expect_equal(comp[1, ], c(4, rep(1, 6)))
    expect_equal(comp[2, ], c(3, 2, rep(1, 5)))
    expect_equal(comp[84, ], c(rep(1, 6), 4))
    expect_true(all(apply(comp, 1, sum) == 10))

    comp <- compositions(10, 7, descending = TRUE, layout = "row")
    expect_equal(nrow(comp), 84)
    expect_equal(ncol(comp), 7)
    expect_equal(comp[1, ], c(4, rep(1, 6)))
    expect_equal(comp[2, ], c(3, 2, rep(1, 5)))
    expect_equal(comp[84, ], c(rep(1, 6), 4))
    expect_true(all(apply(comp, 1, sum) == 10))

    comp <- compositions(10, 7, descending = TRUE, layout = "column")
    expect_equal(nrow(comp), 7)
    expect_equal(ncol(comp), 84)
    expect_equal(comp[, 1], c(4, rep(1, 6)))
    expect_equal(comp[, 2], c(3, 2, rep(1, 5)))
    expect_equal(comp[, 84], c(rep(1, 6), 4))
    expect_true(all(apply(comp, 2, sum) == 10))

    comp <- compositions(10, 7, descending = TRUE, layout = "list")
    expect_equal(length(comp), 84)
    expect_equal(comp[[1]], c(4, rep(1, 6)))
    expect_equal(comp[[2]], c(3, 2, rep(1, 5)))
    expect_equal(comp[[84]], c(rep(1, 6), 4))
    expect_true(all(sapply(comp, sum) == 10))

    expect_error(compositions(100, 10, descending = TRUE), "too many results")
    expect_equal(dim(compositions(10, 11, descending = TRUE)), c(0, 11))
    expect_equal(dim(compositions(10, 11, descending = TRUE, layout = "column")), c(11, 0))
    expect_equal(length(compositions(10, 11, descending = TRUE, layout = "list")), 0)
    expect_error(compositions(20, -1, descending = TRUE), "expect integer")
    expect_error(compositions(20, 1.5, descending = TRUE), "expect integer")
})

test_that("Integer k-compositions - ascending icompositions", {
    comp <- compositions(10, 7)
    icomp <- icompositions(10, 7)
    expect_is(icomp, "Compositions")
    expect_equal(icomp$collect(), comp)
    expect_equal(icomp$getnext(), comp[1, ])
    expect_equal(icomp$getnext(), comp[2, ])
    expect_equal(icomp$getnext(2), comp[3:4, ])
    icomp$getnext(50)
    expect_equal(nrow(icomp$getnext(50)), 30)
    expect_equal(icomp$getnext(), NULL)

    comp <- compositions(10, 7, layout = "row")
    icomp$reset()
    expect_equal(icomp$collect(layout = "row"), comp)
    expect_equal(icomp$getnext(layout = "row"), comp[1, , drop = FALSE])
    expect_equal(icomp$getnext(layout = "row"), comp[2, , drop = FALSE])
    expect_equal(icomp$getnext(2, layout = "row"), comp[3:4, ])
    icomp$getnext(50, layout = "row")
    expect_equal(nrow(icomp$getnext(50, layout = "row")), 30)
    expect_equal(icomp$getnext(layout = "row"), NULL)

    comp <- compositions(10, 7, layout = "column")
    icomp$reset()
    expect_equal(icomp$collect(layout = "column"), comp)
    expect_equal(icomp$getnext(layout = "column"), comp[, 1, drop = FALSE])
    expect_equal(icomp$getnext(layout = "column"), comp[, 2, drop = FALSE])
    expect_equal(icomp$getnext(2, layout = "column"), comp[, 3:4])
    icomp$getnext(50, layout = "column")
    expect_equal(ncol(icomp$getnext(50, layout = "column")), 30)
    expect_equal(icomp$getnext(layout = "column"), NULL)

    comp <- compositions(10, 7, layout = "list")
    icomp$reset()
    expect_equal(icomp$collect(layout = "list"), comp)
    expect_equal(icomp$getnext(layout = "list"), comp[1])
    expect_equal(icomp$getnext(layout = "list"), comp[2])
    expect_equal(icomp$getnext(2, layout = "list"), comp[3:4])
    icomp$getnext(50, layout = "list")
    expect_equal(length(icomp$getnext(50, layout = "list")), 30)
    expect_equal(icomp$getnext(layout = "list"), NULL)

    icomp <- icompositions(10, 11)
    expect_equal(dim(icomp$collect()), c(0, 11))
    expect_equal(icomp$getnext(), NULL)
    expect_error(icompositions(20, -1), "expect integer")
    expect_error(icompositions(20, 1.5), "expect integer")
})

test_that("Integer compositions - descending icompositions", {
    comp <- compositions(10, 7, descending = TRUE)
    icomp <- icompositions(10, 7, descending = TRUE)
    expect_is(icomp, "Compositions")
    expect_equal(icomp$collect(), comp)
    expect_equal(icomp$getnext(), comp[1, ])
    expect_equal(icomp$getnext(), comp[2, ])
    expect_equal(icomp$getnext(2), comp[3:4, ])
    icomp$getnext(50)
    expect_equal(nrow(icomp$getnext(50)), 30)
    expect_equal(icomp$getnext(50), NULL)

    comp <- compositions(10, 7, descending = TRUE, layout = "row")
    icomp$reset()
    expect_equal(icomp$collect(layout = "row"), comp)
    expect_equal(icomp$getnext(layout = "row"), comp[1, , drop = FALSE])
    expect_equal(icomp$getnext(layout = "row"), comp[2, , drop = FALSE])
    expect_equal(icomp$getnext(2, layout = "row"), comp[3:4, ])
    icomp$getnext(50, layout = "row")
    expect_equal(nrow(icomp$getnext(50, layout = "row")), 30)
    expect_equal(icomp$getnext(layout = "row"), NULL)

    comp <- compositions(10, 7, descending = TRUE, layout = "column")
    icomp$reset()
    expect_equal(icomp$collect(layout = "column"), comp)
    expect_equal(icomp$getnext(layout = "column"), comp[, 1, drop = FALSE])
    expect_equal(icomp$getnext(layout = "column"), comp[, 2, drop = FALSE])
    expect_equal(icomp$getnext(2, layout = "column"), comp[, 3:4])
    icomp$getnext(50, layout = "column")
    expect_equal(ncol(icomp$getnext(50, layout = "column")), 30)
    expect_equal(icomp$getnext(layout = "column"), NULL)

    comp <- compositions(10, 7, descending = TRUE, layout = "list")
    icomp$reset()
    expect_equal(icomp$collect(layout = "list"), comp)
    expect_equal(icomp$getnext(layout = "list"), comp[1])
    expect_equal(icomp$getnext(layout = "list"), comp[2])
    expect_equal(icomp$getnext(2, layout = "list"), comp[3:4])
    icomp$getnext(50, layout = "list")
    expect_equal(length(icomp$getnext(50, layout = "list")), 30)
    expect_equal(icomp$getnext(layout = "list"), NULL)

    icomp <- icompositions(10, 11, descending = TRUE)
    expect_equal(dim(icomp$collect()), c(0, 11))
    expect_equal(icomp$getnext(), NULL)
    expect_error(icompositions(20, -1, descending = TRUE), "expect integer")
    expect_error(icompositions(20, 1.5, descending = TRUE), "expect integer")
})

test_that("Integer k-compositions - index", {
    comp <- compositions(10, 7)
    expect_equal(compositions(10, 7, index = 1:84), comp)
    expect_equal(compositions(10, 7, index = as.numeric(1:84)), comp)
    expect_equal(compositions(10, 7, index = as.character(1:84)), comp)
    expect_equal(compositions(10, 7, index = gmp::as.bigz(1:84)), comp)
    expect_equal(compositions(10, 7, index = 2), c(rep(1, 5), 2, 3))
    expect_equal(compositions(10, 7, index = 84), c(4, rep(1, 6)))
    expect_equal(compositions(100, 10, index = 2), c(rep(1, 8), 2, 90))
    expect_equal(compositions(100, 10, index = "1731030945644"), c(91, rep(1, 9)))

    expect_error(compositions(5, 0, index = 1), "invalid index")
    expect_equal(compositions(0, 0, index = 1), integer(0))
    expect_error(compositions(0, 1, index = 1), "invalid index")

    comp <- compositions(10, 7, descending = TRUE)
    expect_equal(compositions(10, 7, descending = TRUE, index = 1:84), comp)
    expect_equal(compositions(10, 7, descending = TRUE, index = as.numeric(1:84)), comp)
    expect_equal(compositions(10, 7, descending = TRUE, index = as.character(1:84)), comp)
    expect_equal(compositions(10, 7, descending = TRUE, index = gmp::as.bigz(1:84)), comp)
    expect_equal(compositions(10, 7, descending = TRUE, index = 2), c(3, 2, rep(1, 5)))
    expect_equal(compositions(10, 7, descending = TRUE, index = 84), c(rep(1, 6), 4))
    expect_equal(compositions(100, 10, descending = TRUE, index = 2), c(90, 2, rep(1, 8)))
    expect_equal(compositions(100, 10, descending = TRUE, index = "1731030945644"), c(rep(1, 9), 91))

    expect_error(compositions(5, 0, descending = TRUE, index = 1), "invalid index")
    expect_equal(compositions(0, 0, descending = TRUE, index = 1), integer(0))
    expect_error(compositions(0, 1, descending = TRUE, index = 1), "invalid index")
})


test_that("Integer k-compositions - skip", {
    expect_equal(compositions(10, 7, skip = 84), compositions(10, 7))
    expect_equal(compositions(10, 7, skip = 3), compositions(10, 7)[4:84, ])
    expect_equal(compositions(10, 7, skip = 3, nitem = 4), compositions(10, 7)[4:7, ])
    expect_equal(compositions(10, 7, skip = gmp::as.bigz(3), nitem = 4), compositions(10, 7)[4:7, ])

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