Задали Алисе задачку, как бы так пользуясь целочисленной арифметикой на машинных uint'ах фиксированной битности посчитать для неотрицательного целого числа n результат n(n + 1)/2, если гарантируется только, что результат в машинный uint влезет.
Задача достаточно тривиально решается с применеием ветвлений: из n и (n + 1) поделить пополам то, которое чётное, и умножить на оставшееся.
Но оч.противно ветвить там, где можно не рушить конвейер, да и операций использовать минимум. Ясно, что понадобится одно умножение в конце и одно целочисленное деление на два. Целочисленное деление и извлечение остатка на самом деле происходят одновременно. Стало быть имеет смысл начать с
Если число n было чётное (т.е. r = 0), то ответ будет
Если число n было нечётное (т.е. r = 1), то умножать надо n на (n + 1)/2 = q + 1, т.к. деление у нас округляет вниз. То есть ответ
Совмещая получаем
Главное умерить пыл и не мучать этим Алису, ей это нафиг не надо.. :-)
Задача достаточно тривиально решается с применеием ветвлений: из n и (n + 1) поделить пополам то, которое чётное, и умножить на оставшееся.
Но оч.противно ветвить там, где можно не рушить конвейер, да и операций использовать минимум. Ясно, что понадобится одно умножение в конце и одно целочисленное деление на два. Целочисленное деление и извлечение остатка на самом деле происходят одновременно. Стало быть имеет смысл начать с
(q, r) = (n // 2, n % 2)
Если число n было чётное (т.е. r = 0), то ответ будет
q * (n + 1).
Если число n было нечётное (т.е. r = 1), то умножать надо n на (n + 1)/2 = q + 1, т.к. деление у нас округляет вниз. То есть ответ
(q + 1) * n.
Совмещая получаем
(q, r) = (n // 2, n % 2) result = (q + r)*(n + !r)
Главное умерить пыл и не мучать этим Алису, ей это нафиг не надо.. :-)