Я пишу диспетчер физической памяти, который получает некоторые интервалы памяти из BIOS, которые не используются критическими системными данными. Каждый интервал имеет 0 <= start <= 2^32 - 1
и 0 <= length <= 2^32
. Я уже отфильтровывал интервалы нулевой длины.Простой интервал/пересечение диапазона с переполнением
Учитывая два интервала S и T, я хочу обнаружить , как они пересекаются. Например, S начинается до T и заканчивается в пределах T (картинка a)? Или S начинается до T и заканчивается после T (картинка c)?
Можно подумать, что решение тривиально:
uint s_end = s_start + s_length;
uint t_end = t_start + t_length;
if (s_start < t_start)
// S starts before T
else if (s_start < t_end)
// S starts within T
else
// S starts after T
if (s_end <= t_start)
// S ends before T
else if (s_end <= t_end)
// S ends within T
else
// S ends after T
Проблема заключается в переполнении: Я технически ограничен 32-разрядное целое число и интервалы могут (и часто) использовать весь спектр имеющихся целые числа. Например, на рисунке b, t_end
равно 0 из-за переполнения. Или даже, как на рисунке ft_start = t_end = s_start = 0
пока t_length != 0
.
Как я могу заставить эти условия пересечения интервалов работать с учетом переполнения?
Переполнение меняет мои условия, но I действительно не может использовать для этого 64-битное целое (это было бы проще всего). Я знаю, что это должно быть возможно, используя некоторые умные перестановки моих условий и использование сложения и вычитания, но после создания бесконечных диаграмм и размышлений об этом в течение нескольких часов, я, похоже, не могу обернуть вокруг себя голову.
Хотя моя проблема с 32-разрядными целыми числами, в этом образе я использовал 4-битные целые числа только упростить. Проблема остается прежней.
Если у вас были парные пары начала и конца, было бы проще, потому что переполнения не было бы. Просто вычтите 1 из конца - это вызовет проблему, если у вас есть интервалы в 0 длины, но вы этого не сделаете. – harold
@harold Эти интервалы представляют диапазоны байтов. Чтобы представить все байты в 32-битной системе, я снова закончил бы с 0 начальным 0 при использовании инклюзивных пар начала/конца. – Virtlink
Нет, вы бы этого не сделали, в итоге вы получите [0, 0xFFFFFFFF]. Вы не можете включить 0 * дважды *. – harold