Сергей Леонтьев@Serge3leo
Пользователь
Информация
- В рейтинге
- 478-й
- Откуда
- Москва, Москва и Московская обл., Россия
- Дата рождения
- Зарегистрирован
- Активность
Специализация
Инженер по производительности, Архитектор программного обеспечения
Старший
От 600 000 ₽
C
C++
C++ boost
Оптимизация кода
Unix
Git
Shell
P.S.
Что касается
cmp_ulp()иcmp_nulp(), то они, как и родительский тип с плавающей точкой, обладают частичной транзитивностью. Т.е. еслиstd:is_lteq(cmp_ulp(a, b))иstd::is_lteq(cmp_ulp(b, c)), тоstd::is_lteq(cmp_ulp(a, c)).Строго говоря, по сути, все варианты:
округлить, потом сравнить;
сравнить, с заданной точностью;
просто сравнить.
Имеют одинаковые свойства частичного порядка, но немного разные области применения. 😉
Хм. У чисел c плавающей точкой (по ISO/IEC 60559 или иных), по жизни, частичный порядок (к примеру, по С++ это
std::partial_ordering). Они, и по жизни, и по определению, иные. 😉Один из примеров, скажем, не только одинаковые элементы могут не иметь отношения равенства, но и наоборот, различные элементы могут равняться друг другу ( https://godbolt.org/z/Y8c541T33 ):
Что уж говорить за
<и>? Там ещё забавнее. 😉P.S.
По-моему,
fuzzy_float_eq(INFINITY, INFINITY)тоже не очень, но в остальном - более менее. Хотя, конечно, формализмаabsиtolне хватает.Кроме того, есть такие
D, которыеD != D. Так и да, частичный порядокВо-первых, для всех широко известных систем:
1.0000009901f == 1.0000009902fhttps://godbolt.org/z/3YxWzrTEr
Систему с
FLT_DECIMAL_DIG >= 10найти будет затруднительно, так что, пример, не очень (некоторые его назовут, в некотором смысле, ошибочным или вводящим в заблуждение 😉).Во-вторых, можете добавить в свою в копилку алгоритмов:
Наиболее популярные сценарии того, что раньше формально было UB, которое теперь уже точно не UB:
Раньше в преамбуле стандарта языка C, грубо говоря, было сказано: "аргумент библиотечной функции NULL - UB". Но, по сути, если он не использовался - это не UB. Поэтому в C23 добавили разъяснение того, что имелось ввиду, в сноске.
С делением на 0 аналогично, если его результат не влияет на выполнение программы, то это не UB (наверное, не уверен, неточно).
Кроме того, у компиляторов свои тараканы. К примеру, Clang:
В первом случае, может. И даже, некоторые, если попросят, могут выдать ошибку. Однако, не всегда можно выяснить, используется ли переменная
fooреально. Если не используется, то это, вроде как, и не UB.Кроме того, как известно, "Не спеши выполнить команду, ибо вскоре последует команда отставить!".
К примеру,
memset(NULL, 0, 0)- это UB или нет? Долгое время, считалось, что формально - UB, правда, всем было по барабану. Но не так давно, как только кто-то реально попытался это интерпретировать не формально, а реально как UB. Тут же, в C23 вышло разъяснение: "...or using any valid pointer with a size of 0". Говорят, с указанием, что уточнение имеет обратную силу. 😉P.S.
Как говорит, один мой мудрый товарищ: "Не надо мне связывать руки. Это бесполезно, я всё равно умнее всех этих компиляторов, к тому же и теорема Тьюринга на моей стороне."
Честно говоря, я сравнивал интерфейсы стандарта C++. Грубо говоря, стандарт у нас один, а разных компиляторов или инструментов много.
Что касается, конкретно, ThreadSanitizer, вроде как, он поддерживает обнаружение проблем в том числе исходя из первых принципов, т.е. исходя из отношения Happens Before. Но, как у всякого инструмента, есть сложности, ограничения и прочие несовершенства. Но на нём Свет клином не сошёлся же.
А так, да, для блокировок (мьютексы, спин-локи) есть более простые и быстрые алгоритмы. А всё, что связано с
wait()/notify_all()немного сложнее в настройке и несколько медленнее, и не важно этоstd::atomicилиstd::condition_variable.P.S.
Хотя
std::atomic, да, возможно сложнее инструментировать и больше проблем с разнообразием компиляторов и/или библиотек C++.Чисто по интерфейсу,
std::condition_variableв паре, скажем, сstd::mutex:Может использоваться только в одном адресном пространстве;
В описании интерфейса явно указывается на блокировку потока;
UB, в случае завершения потока владельца
std::mutexбез его освобождения;Размеры не специфицированы;
Имеют методы
native_handle().std::atomic:При наличии макроса
ATOMIC_..._LOCK_FREEможет использоваться в памяти, отображаемой в пространство нескольких процессов, смотрите [atomic.lockfree] (5);В описании интерфейса есть только слова, что более эффективно, чем простой опрос;
Формально, при завершении потока или процесса, без освобождения, нет UB, но нет и никаких гарантий, как, скажем, при использовании
PTHREAD_PROCESS_SHAREDи ошибкиEOWNERDEAD;Рекомендованный размер совпадает с размером базового типа, но это лишь рекомендация;
В целом,
std::atomicможет быть реализован, к примеру, на основе инструкцийMONITOR/MWAITили чего-то подобного, если они доступны.Это к тому, что анализ используемой в тесте C++ библиотеки и компилятора излишне краток.
Честно говоря, так себе ответ. К примеру:
UB, часто, вызывает предупреждение компилятора, но при использовании ключей вида
-Werror=div-by-zeroможет вызвать ошибку компиляции.Тоже UB, вероятно, если какое-либо НЛО не изменит
boo.Но если первый вариант UB, ещё где-то, как-то присутствует в ответе "chatgpt", то второй вариант даже и не упомянут.
Тоже ошибка, вызваная наивным прекраснодушием. К примеру, из предполагаемых нововведений C2Y: N3349: Abs Without Undefined Behavior. Что-бы хотя бы создать возможность устранения UB надо потрудиться. И таких поправок за тридцать с лишним лет, накопилось... Ни вагонов, ни тележек, не хватит.
Тоже так себе. Дело не в проверке, а в возможности/невозможности/отсутствия необходимости определить гарантированное состояние на момент ошибки. На примере деления на 0: как именно проистекает ошибка, какие операции с памятью/потоками выполнятся, а какие нет и т.п.
В общем, ИМХО, это не ответ, а иллюзия ответа. Наверное, тех, кто им недоволен, понять можно.
Хм, я точно не проверял, но на первый взгляд кажется, что до Glibc 2.34 (2021-08-01) это было бы непросто.
Строго говоря, есть свойства идеальной матрицы Вандермонда и свойства округлённой до заданной точности матрицы Вандермонда, и они отличаются. Отдельный вопрос - сетка, который тоже имеет много гититк, ну пусть останется равномерной:
Конечно же, есть. Во-первых, метод вычисления числа обусловленности выбран не самый точный, в NumPy есть быстрая функция
np.linalg.cond(matrix), а есть более точное разложениеnp.linalg.svd(matrix, compute_uv=False).Легко видеть, что число обусловленности идеальной матрицы Вандермонда неограниченно растёт по одному закону, округленной матрицы Вандермонда тоже растёт неограниченно, но по другому закону точка перегиба:
. Ну, а вычисленная оценка числа обусловленности ограничена точностью её вычисления.
Это да, точность входной матрицы влияет.
А в этом деле, тест с использованием
np.float32практически бесполезен, поскольку NumPy всё равно накапливает скалярное произведение наnp.float64.Я Вас умоляю...
Как бы, есть, только она всё равно от сетки зависит. Впрочем, для данной конкретной сетки, на графике и так всё видно.
Интересно, есть ли тому объяснение, что
precomit.shдолжен начинаться не с обычного шебанг#!, а с какого-нибудь непустого, к примеру, с эквивалента пустого шебанга:#!/usr/bin/env sh?Замечательно, после установки окружения по вашим рецептам, `cmake`/`ctest` отработали как положено со следующими ключами:
Все тесты собрались, в количестве, запустились, коды возврата и выдача проверилась, хорь, и это неплохо.
Прошу прощения, но режет глаз. Разрешите напомнить современное, более менее строгое, определение, параграф 13 раздел 6.10.1 Conditional inclusion, C23:
И так было всегда, например, параграф 6 (примерно) раздел 3.8.1 Conditional inclusion, C88 Third review X3J11 88-090 May 13 1988:
В первой редакции книги K&R, вроде как, это свойство забыли упомянуть, но аксакалы помнят, помнят, как работал их компилятор.
Правильно писать коротко и ясно:
Это как посмотреть, код
if (index < 0 || index >= forecast.Forecast.Count)проблемный - не работает сNaN, а если написатьif (0 <= index && index < forecast.Forecast.Count), то при работе по IEC 60559, всё будет корректно.А так, да, конечно, лучше, когда всё вместе, и интерфейс надёжный, и код надёжный. Хотя,
NaNможет просочиться и через интерфейс без деления, например, ввиду недостатка данных.Честно говоря, модель
Mail.Ru(Яндекс, и др.) не предусматривает такового "хранения", переустановка или новое устройство - новый ключ. А "хранение" - это лишнее, необязательное и небезопасное действие.Впрочем, если, лично Вам, оно нравится и у Вас есть специальный шифрблокнот для этого, почему нет?
Как что? Так сразу правительство. Берите выше.
Возрастные коэффициенты смертности мирных лет (1896-1897), смертей на 1000 данного возраста:
0.: 370.0 (от рождения до года)0-1.: 132.5 (от рождения до двух лет)
5-9.: 11.9
10-14.: 5.4
15-19.: 5.8
20-24.: 7.5
25-29.: 8.1
30-34.: 8.7
35-39.: 10.3
40-44.: 11.8
45-49.: 15.6
50-54.: 18.5
55-59.: 29.4
60-64.: 34.4
65-74.: 64.5
75-...: 111.4
А здесь война. Надо только правильно сообразить, как эти числа преобразовать, что бы можно было бы их сравнить. Думаю, видно не только детскую смертность, но и войну тоже.