Войти
ФлеймФорумПроЭкты

Ü (Programmiersprache) (71 стр)

Страницы: 170 71 72 7376 Следующая »
#1050
15:41, 29 янв 2022

На счёт переголовы. Я кажись не совсем прав. Если реализовывать <=> внутри как-то так:

struct S
{
  f32 x;
  op<=>(S a, S b) : i32
  {
    if( a.x < b.x ) { return -1; }
    if( a.x > b.x ) { return +1; }
    return 0;
  }
}

То при вызове оператора <=> для <, <=, >, >= переголовы не выходит. При встраивании функции компилятор лишнюю переголову выкинет.
Ещё я подумываю, что можно реализовать оператор <=> для встроенных типов для удобства реализации своего оператора <=>.

#1051
15:48, 29 янв 2022

Panzerschrek[CN]
Значит проблема решена, можно тупо сделать < > внутри, вернув некий энам?

#1052
(Правка: 17:15) 16:51, 29 янв 2022

Panzerschrek[CN]
> Но мне не нравится, что он возвращает некий enum с тремя, а возможно четыремя
> значениями.
Совершенно точно вариантов должно быть как минимум четыре, иначе у тебя IEEE 754 отвалится.

Есть ещё вариант из PowerPC, общее сравнение - битовое поле с 4 флагами (less, equal, greater, unordered), частные случаи - это битовые маски:

bitfield Ordering { LT, EQ, GT, UO }

trait PartialOrd {
    fn compare(a: &Self, b: &Self) -> Ordering;
}

operator < </T: PartialOrd/> (a: &Self, b: &Self) {
    return compare(a, b) & LT;
}

operator <= </T: PartialOrd/> (a: &Self, b: &Self) {
    return compare(a, b) & (LT | EQ);
}

operator == </T: PartialOrd/> (a: &Self, b: &Self) {
    return compare(a, b) & EQ;
}

operator != </T: PartialOrd/> (a: &Self, b: &Self) {
    return not (compare(a, b) & EQ);
}

impl PartialOrd for f32 {
    fn compare(a: &f32, b: &f32) {
        return PartialOrd{
                LT = builtin_lt_f32(a, b),
                EQ = builtin_eq_f32(a, b),
                GT = builtin_gt_f32(a, b),
                // UO = builtin_uo_f32(a, b),
                // убогий апи???
                // но шланг вроде понимает: https://godbolt.org/z/q6beofba5
                UO = not (builtin_lteq_f32(a, b) or builtin_gt_f32(a, b)),
            };
    }
}
#1053
(Правка: 18:33) 18:29, 29 янв 2022

1 frag / 2 deaths
> вернув некий энам?
В ядро языка какой-то enum тащить даже не нужно. Хватит какого-нибудь встроенного знакового типа.

Имбирная Ведьмочка
> у тебя IEEE 754 отвалится
Плевать на всякие NaN. Отсортируются они как-нибудь компаратором вида

if( a > b ) return -1;
if( b < a ) return +1;
return 0;

> битовое поле с 4 флагами (less, equal, greater, unordered)
Избыточно, ибо less и equal исключают друг друга.

#1054
18:59, 29 янв 2022

Panzerschrek[CN]
> Избыточно, ибо less и equal исключают друг друга.
Видимо имеется в виду 4 возможных значения

#1055
(Правка: 20:13) 20:12, 29 янв 2022

Panzerschrek[CN]
> Плевать на всякие NaN.
Опять насаждаешь свои личные предубеждения? Таким путём у тебя получится язык, у которого единственная сфера применения - это компиляция самого себя. Потому что всё остальное ты сам же и запретил. Скриптинг? Нинужон. Веб-сервер? Нинужон. Геймдев? Нинужон. Физдижки, рейтрейсеры и софтрендеры? Тоже не пойдут - ведь это в первую очередь численные приложения, а на поддержку чисел ты прямо тут и поклал.

Panzerschrek[CN]
> Отсортируются они как-нибудь компаратором вида
>
> if( a > b ) return -1;
> if( b < a ) return +1;
> return 0;
Конкретно этот компаратор выдаст, что NaN равны всему на свете:

compare_panzerschrek(1, NaN) ==> 0
compare_panzerschrek(NaN, 2) ==> 0
compare_panzerschrek(1, 2) ==> а вот и не ноль, фиг там

Чтобы ты понимал, какая это лютая хрень, вот тебе зарисовка.

Квиксорт. Массив флоатов. Выбираем пивот. Там оказался NaN. Раскидываем по диапазонам - все элементы равны пивоту. Таким образом, обнаруживаем, что список уже отсортирован - там все элементы одного порядка. Поэтому даже не заморачиваемся с рекурсией, а выходим сразу.

Отсортированный массив: [NaN, 1, 10, -500, 0, -7e15, 8.9e26].

Panzerschrek[CN]
> Избыточно, ибо less и equal исключают друг друга.
Ну сделай енум на 4 варианта и сравнивай на равенство. Я не знаю, какой вариант LLVM оптимизирует лучше.

#1056
20:24, 29 янв 2022

Имбирная Ведьмочка
> Отсортированный массив: [NaN, 1, 10, -500, 0, -7e15, 8.9e26].
Мусор на входе - мусор на выходе. Если не нравится - напиши свой компаратор, учитывающий особенности NaN.

> NaN равны всему на свете
NaN в этом смысле диалектичен - он равен и одновременно неравен самому себе.

> Веб-сервер
> Геймдев
Разрешаю.

> Физдижки, рейтрейсеры
Кстати. У крестокомпилятора есть опция, которая превращает NaN в неопределённое поведение. Думаю, во всяких физдвижках всё именно так, ибо учитывать NaN - ненужная переголова.

> софтрендеры
Писал их ни раз. Там значительная часть вычислений - на целых числах. Плавучку использовал разве что в трансформациях до непосредственно растеризации.

#1057
(Правка: 21:56) 21:12, 29 янв 2022

Имбирная Ведьмочка
> Квиксорт. Массив флоатов. Выбираем пивот. Там оказался NaN. Раскидываем по
> диапазонам - все элементы равны пивоту.
Кривая какая-то у тебя сортировка. В Ü она такая. Там идёт раскидывание по двум диапазонам по критерию компаратора. Потом диапазоны рекурсивно досортируются. В случае, если выбранный медианный элемент - NaN, все элементы кроме него самого (включая другие NaN) окажутся во втором диапазоне. В случае, если медианный элемент не NaN - опять же NaN попадут во второй диапазон. В итоге так или иначе все NaN окажутся в конце.

Теперь что же будет, если будет массив не float, а массив структур с float внутри и перегруженным оператором <=>, как я показал выше? Оператор для сравнения чего-то с NaN вернёт 0. Это означает всегда false для упорядочивания через <. Ровно так, как уже есть сейчас.

Вообще, если чисто логически подумать, то в быстрой сортировке внутри идёт рекурсивное разделение чисел по двум спискам по некоторому предикату относительно некого числа. Если это число - NaN, то предикат всегда даёт один и тот же результат для всех чисел, что значит, что в итоге будут два списка, один с NaN, другой - с остальными числами. Если же опорное число не NaN, а сравнивают с ним NaN, то результат тоже не важен, NaN попадёт в какой-то итоговый список, не важно какой.
В итоге конечно в результирующем массиве может быть раскидано куча NaN в разных позициях, но если их убрать, то массив будет корректно отсортирован.

#1058
21:24, 29 янв 2022

Panzerschrek[CN]
> Если не нравится - напиши свой компаратор, учитывающий особенности NaN.
Так проще же просто другой язык взять.

#1059
12:01, 30 янв 2022

Ещё задумываюсь над автогенерацией оператора ==. По идее, это поможет убрать бойлерплейт с ручным его написанием.
Для структур можно его по умолчанию генерировать. Если поля - это целые числа, массивы, кортежи, то понятно, как их сравнивать. Если есть поля - сырые указатели, то тоже более-менее понятно. Поля типов классов с имеющимся оператором == тоже понятно, как сравнивать. А вот со ссылочными полями всё сложно, не понятно, что сравнивать - значение ссылки или значение по ссылке. Так что, думаю, в таком случае пусть программист сам определяет, как ему сравнивать их.

Думаю, также, что можно будет сравнивать автоматически кортежи и массивы, если для их элементов есть оператор ==.

#1060
21:44, 1 фев 2022

Обнаружил такой интересный случай:

struct S
{
  i32 a;
  i32 b;

  op==(S& l, S& r) : bool
  {
    return l.a == r.a && l.b == r.b;
  }
}
_ZN1SeqERKS_S1_:
  movl  (%rdi), %eax
  cmpl  (%rsi), %eax
  jne  .LBB0_1
  movl  4(%rdi), %eax
  cmpl  4(%rsi), %eax
  sete  %al
  retq
.LBB0_1:
  xorl  %eax, %eax
  retq

Компилятор чего-то не осиливает убрать ветвление в операторе && в таком тривиальном случае. Глянул на выхлоп clang - там такой фигни нету:

_Z7COmpareRK1SS1_:
        movl    (%rdi), %eax
        movl    4(%rdi), %ecx
        xorl    (%rsi), %eax
        xorl    4(%rsi), %ecx
        orl     %eax, %ecx
        sete    %al
        retq

Начал смотреть в LL код, понял, в чём проблема. Clang выставляет атрибут dereferenceable(8) на ссылочных параметрах, а Ü компилятор - нет. Без этого оптимизатор считает, что нельзя заранее прочитать из памяти, а то вдруг будет выход за границы.

#1061
(Правка: 7:25) 7:23, 2 фев 2022

Мне только что в голову пришла гениальнейшая идея.
У диграфов </ и /> есть такое нежелательное свойство - они требуют переключения шифт-кнопки во время набора. В каком-то смысле, они требуют по два с половиной нажатия - после набора <, нужно сначала отжать шифт, и только после этого - нажать /. При быстром наборе, очень легко вместо этих диграфов получить <? и ?>.
Соответственно, рекомендация - вместо прямого слеша подобрать такой символ, который тоже набирается при зажатом шифте.

(Идея пришла при очередном пользовании .~ и ^.)

#1062
9:30, 2 фев 2022

Имбирная Ведьмочка
> они требуют по два с половиной нажатия
Не страшно, привычка легко набирать </ /> быстро вырабатывается.

> <? и ?>
Занято

#1063
21:10, 5 фев 2022

Запилил генерацию оператора == для структур и классов.
Для структур он генерируется автоматически, если все поля сравнимы на равенство и нету ссылочных полей. Для классов аналогично, но генерацию оператора надо запрашивать через = default (по умолчанию оператор не генерируется).
В добавок к этому реализовал оператор == для контейнеров vector, optional, variant, если их элементы сравнимы на равенство.

Код Компилятора1 от таких изменений весьма сократился. Ушло множество написанных вручную операторов ==. В этом и есть смысл генерации - делать компилятором тривиальные вещи за программиста.

#1064
17:38, 7 фев 2022

Подумываю тут, что делать, если пользователь объявляет специальные методы (конструктор по умолчанию, конструктор копирования, оператор копирующего присваивания, деструктор, оператор сравнения на равенство) как unsafe.
Загвоздка тут в том, что эти методы компилятор вызывает самостоятельно в ряде случаев, как напрямую, так и при генерации методов других классов. Так вот, не совсем ясно, что в этом случае делать. Запрещать unsafe для этих методов? Не запрещать, но при попытке вызова проверять, что он происходит в unsafe блоке? Делать сгенерированные методы класса unsafe, если они содержат вызовы соответствующих unsafe методов для полей?

Короче, я пока не решил, как лучше поступить. Самым простым было бы тупо запретить указывать unsafe этим методам. Но возникает вопрос - вдруг таки для каких-то целей unsafe может быть полезен?

Страницы: 170 71 72 7376 Следующая »
ФлеймФорумПроЭкты