2020-09-25 20:48:10 +08:00
|
|
|
use nalgebra_sparse::pattern::{SparsityPattern, SparsityPatternFormatError};
|
|
|
|
|
2023-10-31 01:50:56 +08:00
|
|
|
#[test]
|
|
|
|
fn sparsity_pattern_default() {
|
|
|
|
// Check that the pattern created with `Default::default()` is equivalent to a zero-sized pattern.
|
|
|
|
let pattern = SparsityPattern::default();
|
|
|
|
let zero = SparsityPattern::zeros(0, 0);
|
2023-11-13 06:17:33 +08:00
|
|
|
|
2023-10-31 01:50:56 +08:00
|
|
|
assert_eq!(pattern.major_dim(), zero.major_dim());
|
|
|
|
assert_eq!(pattern.minor_dim(), zero.minor_dim());
|
|
|
|
assert_eq!(pattern.major_offsets(), zero.major_offsets());
|
|
|
|
assert_eq!(pattern.minor_indices(), zero.minor_indices());
|
|
|
|
|
|
|
|
assert_eq!(pattern.nnz(), 0);
|
|
|
|
}
|
|
|
|
|
2020-09-25 20:48:10 +08:00
|
|
|
#[test]
|
|
|
|
fn sparsity_pattern_valid_data() {
|
|
|
|
// Construct pattern from valid data and check that selected methods return results
|
|
|
|
// that agree with expectations.
|
|
|
|
|
|
|
|
{
|
|
|
|
// A pattern with zero explicitly stored entries
|
2021-01-26 00:26:27 +08:00
|
|
|
let pattern =
|
|
|
|
SparsityPattern::try_from_offsets_and_indices(3, 2, vec![0, 0, 0, 0], Vec::new())
|
|
|
|
.unwrap();
|
2020-09-25 20:48:10 +08:00
|
|
|
|
|
|
|
assert_eq!(pattern.major_dim(), 3);
|
|
|
|
assert_eq!(pattern.minor_dim(), 2);
|
|
|
|
assert_eq!(pattern.nnz(), 0);
|
|
|
|
assert_eq!(pattern.major_offsets(), &[0, 0, 0, 0]);
|
|
|
|
assert_eq!(pattern.minor_indices(), &[]);
|
|
|
|
assert_eq!(pattern.lane(0), &[]);
|
|
|
|
assert_eq!(pattern.lane(1), &[]);
|
|
|
|
assert_eq!(pattern.lane(2), &[]);
|
|
|
|
assert!(pattern.entries().next().is_none());
|
|
|
|
|
2021-01-25 23:04:29 +08:00
|
|
|
assert_eq!(pattern, SparsityPattern::zeros(3, 2));
|
2020-09-25 20:48:10 +08:00
|
|
|
|
|
|
|
let (offsets, indices) = pattern.disassemble();
|
|
|
|
assert_eq!(offsets, vec![0, 0, 0, 0]);
|
|
|
|
assert_eq!(indices, vec![]);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
// Arbitrary pattern
|
|
|
|
let offsets = vec![0, 2, 2, 5];
|
|
|
|
let indices = vec![0, 5, 1, 2, 3];
|
|
|
|
let pattern =
|
|
|
|
SparsityPattern::try_from_offsets_and_indices(3, 6, offsets.clone(), indices.clone())
|
2021-01-26 00:26:27 +08:00
|
|
|
.unwrap();
|
2020-09-25 20:48:10 +08:00
|
|
|
|
|
|
|
assert_eq!(pattern.major_dim(), 3);
|
|
|
|
assert_eq!(pattern.minor_dim(), 6);
|
|
|
|
assert_eq!(pattern.major_offsets(), offsets.as_slice());
|
|
|
|
assert_eq!(pattern.minor_indices(), indices.as_slice());
|
|
|
|
assert_eq!(pattern.nnz(), 5);
|
|
|
|
assert_eq!(pattern.lane(0), &[0, 5]);
|
|
|
|
assert_eq!(pattern.lane(1), &[]);
|
|
|
|
assert_eq!(pattern.lane(2), &[1, 2, 3]);
|
2021-01-26 00:26:27 +08:00
|
|
|
assert_eq!(
|
|
|
|
pattern.entries().collect::<Vec<_>>(),
|
|
|
|
vec![(0, 0), (0, 5), (2, 1), (2, 2), (2, 3)]
|
|
|
|
);
|
2020-09-25 20:48:10 +08:00
|
|
|
|
|
|
|
let (offsets2, indices2) = pattern.disassemble();
|
|
|
|
assert_eq!(offsets2, offsets);
|
|
|
|
assert_eq!(indices2, indices);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn sparsity_pattern_try_from_invalid_data() {
|
|
|
|
{
|
|
|
|
// Empty offset array (invalid length)
|
|
|
|
let pattern = SparsityPattern::try_from_offsets_and_indices(0, 0, Vec::new(), Vec::new());
|
2021-01-26 00:26:27 +08:00
|
|
|
assert_eq!(
|
|
|
|
pattern,
|
|
|
|
Err(SparsityPatternFormatError::InvalidOffsetArrayLength)
|
|
|
|
);
|
2020-09-25 20:48:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
// Offset array invalid length for arbitrary data
|
|
|
|
let offsets = vec![0, 3, 5];
|
|
|
|
let indices = vec![0, 1, 2, 3, 5];
|
|
|
|
|
|
|
|
let pattern = SparsityPattern::try_from_offsets_and_indices(3, 6, offsets, indices);
|
2021-01-26 00:26:27 +08:00
|
|
|
assert!(matches!(
|
|
|
|
pattern,
|
|
|
|
Err(SparsityPatternFormatError::InvalidOffsetArrayLength)
|
|
|
|
));
|
2020-09-25 20:48:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
// Invalid first entry in offsets array
|
|
|
|
let offsets = vec![1, 2, 2, 5];
|
|
|
|
let indices = vec![0, 5, 1, 2, 3];
|
|
|
|
let pattern = SparsityPattern::try_from_offsets_and_indices(3, 6, offsets, indices);
|
2021-01-26 00:26:27 +08:00
|
|
|
assert!(matches!(
|
|
|
|
pattern,
|
|
|
|
Err(SparsityPatternFormatError::InvalidOffsetFirstLast)
|
|
|
|
));
|
2020-09-25 20:48:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
// Invalid last entry in offsets array
|
|
|
|
let offsets = vec![0, 2, 2, 4];
|
|
|
|
let indices = vec![0, 5, 1, 2, 3];
|
|
|
|
let pattern = SparsityPattern::try_from_offsets_and_indices(3, 6, offsets, indices);
|
2021-01-26 00:26:27 +08:00
|
|
|
assert!(matches!(
|
|
|
|
pattern,
|
|
|
|
Err(SparsityPatternFormatError::InvalidOffsetFirstLast)
|
|
|
|
));
|
2020-09-25 20:48:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
// Invalid length of offsets array
|
|
|
|
let offsets = vec![0, 2, 2];
|
|
|
|
let indices = vec![0, 5, 1, 2, 3];
|
|
|
|
let pattern = SparsityPattern::try_from_offsets_and_indices(3, 6, offsets, indices);
|
2021-01-26 00:26:27 +08:00
|
|
|
assert!(matches!(
|
|
|
|
pattern,
|
|
|
|
Err(SparsityPatternFormatError::InvalidOffsetArrayLength)
|
|
|
|
));
|
2020-09-25 20:48:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
// Nonmonotonic offsets
|
|
|
|
let offsets = vec![0, 3, 2, 5];
|
|
|
|
let indices = vec![0, 1, 2, 3, 4];
|
|
|
|
let pattern = SparsityPattern::try_from_offsets_and_indices(3, 6, offsets, indices);
|
2021-01-26 00:26:27 +08:00
|
|
|
assert_eq!(
|
|
|
|
pattern,
|
|
|
|
Err(SparsityPatternFormatError::NonmonotonicOffsets)
|
|
|
|
);
|
2020-09-25 20:48:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
// Nonmonotonic minor indices
|
|
|
|
let offsets = vec![0, 2, 2, 5];
|
|
|
|
let indices = vec![0, 2, 3, 1, 4];
|
|
|
|
let pattern = SparsityPattern::try_from_offsets_and_indices(3, 6, offsets, indices);
|
2021-01-26 00:26:27 +08:00
|
|
|
assert_eq!(
|
|
|
|
pattern,
|
|
|
|
Err(SparsityPatternFormatError::NonmonotonicMinorIndices)
|
|
|
|
);
|
2020-09-25 20:48:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
// Minor index out of bounds
|
|
|
|
let offsets = vec![0, 2, 2, 5];
|
|
|
|
let indices = vec![0, 6, 1, 2, 3];
|
|
|
|
let pattern = SparsityPattern::try_from_offsets_and_indices(3, 6, offsets, indices);
|
2021-01-26 00:26:27 +08:00
|
|
|
assert_eq!(
|
|
|
|
pattern,
|
|
|
|
Err(SparsityPatternFormatError::MinorIndexOutOfBounds)
|
|
|
|
);
|
2020-09-25 20:48:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
// Duplicate entry
|
|
|
|
let offsets = vec![0, 2, 2, 5];
|
|
|
|
let indices = vec![0, 5, 2, 2, 3];
|
|
|
|
let pattern = SparsityPattern::try_from_offsets_and_indices(3, 6, offsets, indices);
|
|
|
|
assert_eq!(pattern, Err(SparsityPatternFormatError::DuplicateEntry));
|
|
|
|
}
|
2021-01-26 00:26:27 +08:00
|
|
|
}
|