tests/testthat/test-cpp_dists.R

# Tests for C++ distance functions (row_euclidean_distance, row_mahalanobis_distance)

# ============================================================
# row_euclidean_distance()
# ============================================================

test_that("row_euclidean_distance: basic correctness", {
	X <- matrix(c(1, 0, 0, 1, 1, 1), nrow = 3, ncol = 2, byrow = TRUE)
	v <- c(0, 0)
	result <- row_euclidean_distance(X, v)
	expected <- c(1, 1, sqrt(2))
	expect_equal(result, expected, tolerance = 1e-10)
})

test_that("row_euclidean_distance: zero distance", {
	X <- matrix(c(1, 2, 1, 2), nrow = 2, ncol = 2, byrow = TRUE)
	v <- c(1, 2)
	result <- row_euclidean_distance(X, v)
	expect_equal(result, c(0, 0))
})

test_that("row_euclidean_distance: empty matrix returns empty vector", {
	X <- matrix(numeric(0), nrow = 0, ncol = 2)
	v <- c(1, 2)
	result <- row_euclidean_distance(X, v)
	expect_length(result, 0)
})

test_that("row_euclidean_distance: errors on dimension mismatch", {
	X <- matrix(1:6, nrow = 3, ncol = 2)
	v <- c(1, 2, 3) # 3 elements vs 2 columns
	expect_error(
		row_euclidean_distance(X, v),
		"Length.*must match"
	)
})

test_that("row_euclidean_distance: NA in v produces error", {
	X <- matrix(1:4, nrow = 2, ncol = 2)
	v <- c(1, NA)
	expect_error(
		row_euclidean_distance(X, v),
		"NA"
	)
})

test_that("row_euclidean_distance: NA in X produces NA result", {
	X <- matrix(c(1, NA, 3, 4), nrow = 2, ncol = 2, byrow = TRUE)
	v <- c(0, 0)
	result <- row_euclidean_distance(X, v)
	expect_true(is.na(result[1]))
	expect_false(is.na(result[2]))
})

test_that("row_euclidean_distance: single row", {
	X <- matrix(c(3, 4), nrow = 1)
	v <- c(0, 0)
	result <- row_euclidean_distance(X, v)
	expect_equal(result, 5)
})

# ============================================================
# row_mahalanobis_distance()
# ============================================================

test_that("row_mahalanobis_distance: identity S_inv = euclidean", {
	X <- matrix(c(1, 0, 0, 1, 1, 1), nrow = 3, ncol = 2, byrow = TRUE)
	v <- c(0, 0)
	S_inv <- diag(2)
	result <- row_mahalanobis_distance(X, v, S_inv)
	expected <- c(1, 1, sqrt(2))
	expect_equal(result, expected, tolerance = 1e-10)
})

test_that("row_mahalanobis_distance: empty matrix returns empty", {
	X <- matrix(numeric(0), nrow = 0, ncol = 2)
	v <- c(1, 2)
	S_inv <- diag(2)
	result <- row_mahalanobis_distance(X, v, S_inv)
	expect_length(result, 0)
})

test_that("row_mahalanobis_distance: errors on v length mismatch", {
	X <- matrix(1:6, nrow = 3, ncol = 2)
	v <- c(1, 2, 3)
	S_inv <- diag(2)
	expect_error(
		row_mahalanobis_distance(X, v, S_inv),
		"Length.*must match"
	)
})

test_that("row_mahalanobis_distance: errors on S_inv dimension mismatch", {
	X <- matrix(1:6, nrow = 3, ncol = 2)
	v <- c(1, 2)
	S_inv <- diag(3) # 3x3 instead of 2x2
	expect_error(
		row_mahalanobis_distance(X, v, S_inv),
		"square matrix"
	)
})

test_that("row_mahalanobis_distance: NA in v produces error", {
	X <- matrix(1:4, nrow = 2, ncol = 2)
	v <- c(NA, 2)
	S_inv <- diag(2)
	expect_error(
		row_mahalanobis_distance(X, v, S_inv),
		"NA"
	)
})

test_that("row_mahalanobis_distance: NA in X produces NA result", {
	X <- matrix(c(1, NA, 3, 4), nrow = 2, ncol = 2, byrow = TRUE)
	v <- c(0, 0)
	S_inv <- diag(2)
	result <- row_mahalanobis_distance(X, v, S_inv)
	expect_true(is.na(result[1]))
	expect_false(is.na(result[2]))
})

test_that("row_mahalanobis_distance: scaled S_inv gives scaled distances", {
	X <- matrix(c(1, 0), nrow = 1, ncol = 2)
	v <- c(0, 0)
	# With scale=4 on first dimension, mahalanobis distance should be 2*1 = 2
	S_inv <- matrix(c(4, 0, 0, 1), nrow = 2)
	result <- row_mahalanobis_distance(X, v, S_inv)
	expect_equal(result, 2.0, tolerance = 1e-10)
})

test_that("row_mahalanobis_distance: result is non-negative", {
	set.seed(42)
	X <- matrix(rnorm(200), nrow = 100, ncol = 2)
	v <- c(0, 0)
	S_inv <- solve(cov(X))
	result <- row_mahalanobis_distance(X, v, S_inv)
	expect_true(all(result >= 0, na.rm = TRUE))
})

Try the pintervals package in your browser

Any scripts or data that you put into this service are public.

pintervals documentation built on March 3, 2026, 5:06 p.m.