Числа
NewLang является языком с динамической типизацией и явное указание типа не влияет на размер памяти, занимаемой переменной. Информация о типах используется при проверке их совместимости, когда существующему объекту присваивается значение другого типа. Такая операция возможна только тогда, когда типы совместимы между собой и допускают автоматическое приведение. Это справедливо как во время парсинга/компиляции исходного теста, так и во время выполнения в режимах интерпретатора и/или скомпилированного файла.
Арифметические типы
Все числа (кроме рациональных) в NewLang являются тензорами, т.е. массивами одного типа с произвольным количеством измерений и одинаковым размером столбцов в каждом. Единичное число, это тоже тензор нулевого размера.
Поддерживаются только знаковые целые числа, т.к. в без знаковых числах особая нужда отсутствует, а проблем с ними можно найти очень много на ровном месте.
Проблемы без знаковых чисел (из интернета):
Во-первых, вычитание двух без знаковых чисел, например 3 и 5. 3 минус 5 равно 4294967294, т.к. -2 не может быть представлено как без знаковое число. Во-вторых, непредвиденное поведение может возникнуть при смешивании целочисленных значений со знаком и без знака. С++ может свободно преобразовывать числа со знаком и без знака, но не проверяет диапазон, чтобы убедиться, что вы не переполняете свой тип данных.
Имена встроенных арифметических типов: :Int8, :Int16, :Int32, :Int64, :Float16, :Float32, :Float64, :Complex16, :Complex32, :Complex64 говорят сами за себя. И хотя среди них присуствуют названия, присущие беззнаковым числам (:Byte, :Word, :DWord и т.д.), они являются синонимами и применяются для взаимодействия с нативным C++ кодом.
Логический тип
Отдельным типом идет логический тип :Bool, который может принимать значения только 0 или 1 (false/true соответственно), и в зависимости от выполняемой операции тоже может быть отнесен к целочисленным типам, так и не входить в их состав (данный подход интерпретации логического типа данных был взят из библиотеки Torch).
// Treat bool as a distinct "category," to be consistent with type promotion // rules (e.g. `bool_tensor + 5 -> int64_tensor`). If `5` was in the same // category as `bool_tensor`, we would not promote. Differing categories // implies `bool_tensor += 5` is disallowed. // // NB: numpy distinguishes "unsigned" as a category to get the desired // `bool_tensor + 5 -> int64_tensor` behavior. We don't, because: // * We don't want the performance hit of checking the runtime sign of Scalars. // * `uint8_tensor + 5 -> int64_tensor` would be undesirable.
Индексация тензоров
Доступ к элементам тензора происходит по целочисленному индексу, который начинается с 0. Для многомерного тензора, индексы элемента перечисляются в квадратных скобках через запятую. Поддерживается доступ к элементам через отрицательный индекс, который обрабатывается точно так же, как в Python (-1 последний элемент, -2 предпоследний и т.д.).
В качесте индекса тензора могут быть использованы диапазоны которые обработываются точно так же как и в Python, а так же значение :None и многоточие ...
.
Значение :None, т.е. отсуствие индекса, означает произвольный размер тензора в одном конкретном измерении,
тогда как многоточие ...
обозначет произвольную размерность в любом количестве измерений (поэтому может встречаться в индексе тензора только однократно).
Литерал тензор в тексте программы записывается в квадратных скобках с обязательной завершающей запятой,
т.е. [1, 2,]
— это литерал одномерный тензор из двух чисел. После закрывающей скобки тип тензора может быть указан в явном виде.
Если тип не указан, то он выводится автоматически на основании указанных данных и выбирается минимально возможный байтовый размер,
который позволяет сохранить все значения без потери точности.
Примеры создания тензоров и преобразования их размерности можно посмотреть тут.
Рациональные числа
Для вычислений с неограниченной точностью в NewLang используются отдельный тип - рациональные числа.
Они записываются в форме обыкновенной дроби, в которой числитель должен быть целым числом, а знаменатель натуральным (целым без нуля).
В качестве разделителя дроби используется обратная косая черта, т.е. 1\1
- рациональное число 1, -5\1
- рациональное числа -5 и т.д.