solverforge-solver 0.9.0

Solver engine for SolverForge
Documentation
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct SegmentRange {
    pub start: usize,
    pub end: usize,
}

impl SegmentRange {
    pub const fn new(start: usize, end: usize) -> Self {
        Self { start, end }
    }

    pub const fn len(self) -> usize {
        self.end - self.start
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct SegmentRelocationCoords {
    pub source_entity_index: usize,
    pub source_range: SegmentRange,
    pub dest_entity_index: usize,
    pub dest_position: usize,
}

impl SegmentRelocationCoords {
    pub const fn new(
        source_entity_index: usize,
        source_start: usize,
        source_end: usize,
        dest_entity_index: usize,
        dest_position: usize,
    ) -> Self {
        Self {
            source_entity_index,
            source_range: SegmentRange::new(source_start, source_end),
            dest_entity_index,
            dest_position,
        }
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct SegmentRelocationLayout {
    pub exact: SegmentRelocationCoords,
    pub inverse: SegmentRelocationCoords,
}

pub(crate) fn derive_segment_relocation_layout(
    source_entity_index: usize,
    source_start: usize,
    source_end: usize,
    dest_entity_index: usize,
    dest_position: usize,
) -> SegmentRelocationLayout {
    let exact = SegmentRelocationCoords::new(
        source_entity_index,
        source_start,
        source_end,
        dest_entity_index,
        dest_position,
    );
    let moved_len = exact.source_range.len();
    let inverse = SegmentRelocationCoords::new(
        dest_entity_index,
        dest_position,
        dest_position + moved_len,
        source_entity_index,
        source_start,
    );

    SegmentRelocationLayout { exact, inverse }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct SegmentSwapCoords {
    pub first_entity_index: usize,
    pub first_range: SegmentRange,
    pub second_entity_index: usize,
    pub second_range: SegmentRange,
}

impl SegmentSwapCoords {
    pub const fn new(
        first_entity_index: usize,
        first_start: usize,
        first_end: usize,
        second_entity_index: usize,
        second_start: usize,
        second_end: usize,
    ) -> Self {
        Self {
            first_entity_index,
            first_range: SegmentRange::new(first_start, first_end),
            second_entity_index,
            second_range: SegmentRange::new(second_start, second_end),
        }
    }

    pub const fn is_intra_list(self) -> bool {
        self.first_entity_index == self.second_entity_index
    }

    pub fn ordered_ranges(self) -> (SegmentRange, SegmentRange) {
        if self.first_range.start <= self.second_range.start {
            (self.first_range, self.second_range)
        } else {
            (self.second_range, self.first_range)
        }
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct SegmentSwapLayout {
    pub exact: SegmentSwapCoords,
    pub inverse: SegmentSwapCoords,
}

pub(crate) fn derive_segment_swap_layout(
    first_entity_index: usize,
    first_start: usize,
    first_end: usize,
    second_entity_index: usize,
    second_start: usize,
    second_end: usize,
) -> SegmentSwapLayout {
    let exact = SegmentSwapCoords::new(
        first_entity_index,
        first_start,
        first_end,
        second_entity_index,
        second_start,
        second_end,
    );
    let first_len = exact.first_range.len();
    let second_len = exact.second_range.len();

    let inverse = if !exact.is_intra_list() {
        SegmentSwapCoords::new(
            first_entity_index,
            first_start,
            first_start + second_len,
            second_entity_index,
            second_start,
            second_start + first_len,
        )
    } else if first_start < second_start {
        SegmentSwapCoords::new(
            first_entity_index,
            first_start,
            first_start + second_len,
            second_entity_index,
            second_start - first_len + second_len,
            second_start - first_len + second_len + first_len,
        )
    } else {
        SegmentSwapCoords::new(
            first_entity_index,
            first_start - second_len + first_len,
            first_start - second_len + first_len + second_len,
            second_entity_index,
            second_start,
            second_start + first_len,
        )
    };

    SegmentSwapLayout { exact, inverse }
}