Ada_Ru форум

Обсуждение языка Ада

Создание собственного целочисленного типа.

Оставить новое сообщение

Сообщения

Alexey Veselovsky
Создание собственного целочисленного типа.
2009-03-24 14:35:25

Возможно ли в аде создать новый числовой тип (например тип больших натуральных чисел), чтобы синтаксические правила обращения с ним были те же, что и в случае встроенные типов.

 

Т.е. чтобы можно было также делать подтипы и т.п.

Alexey Veselovsky wrote:

Возможно ли в аде создать новый числовой тип (например тип больших натуральных чисел), чтобы синтаксические правила обращения с ним были те же, что и в случае встроенные типов.

 

Можно пробовать. Всё зависит от конкретной реализации. А вот если в GNAT такового нет, то можно (и нужно!) написать соотвествующее пожелание разработчикам.

Возможно ли в аде создать новый числовой тип (например тип больших натуральных чисел), чтобы синтаксические правила обращения с ним были те же, что и в случае встроенные типов.

 

Можно пробовать. Всё зависит от конкретной реализации. А вот если в GNAT такового нет, то можно (и нужно!) написать соотвествующее пожелание разработчикам.

 

Так. Стоп. А что по этому поводу говорит нам стандарт?

 

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

использовать вместо.

On Tue, 24 Mar 2009 20:05:54 +0300, you wrote:

 

Возможно ли в аде создать новый числовой тип (например тип больших

натуральных чисел), чтобы синтаксические правила обращения с ним были те же, что и в случае встроенные типов.

 

Можно пробовать. Всё зависит от конкретной реализации. А вот если в GNAT такового нет, то можно (и нужно!) написать соотвествующее пожелание разработчикам.

 

>Так. Стоп. А что по этому поводу говорит нам стандарт?

 

>Вообще, хотелось бы чтобы компилер умел бы выбирать тип по даденому >диапазону значение. Если диапазон укладывается в стандартные типы, то >используются они, если не укладываются, то смотрится что можно

>использовать вместо.

 

Куда смотреть? Дальше только небо...

 

Вообще, есть два слабых места настоящего стандарта Ada:

 

1. Компиляторам разрешено отвергать декларации типов, со слишком "большим" диапазоном. В принципе, он должен бы допускать все, что душе угодно.

type Large is range 0..2**1024; -- нет проблем

 

К сожалению это не так просто, как кажется. Если Вы напишете

 

type Kaputt is range 0..2**(2**(2**1024));

 

то ясно, что это компилироваться не может никак. Так что граница все таки есть. Как ее указать в стандарте?

 

2. Нет стандартного BigNum-а. Что забавно, так то, что на самом деле он есть, и называется Universal_Integer. Более того, он даже существует во время исполнения! Есть не статические выражения Universal_Integer! Например

((Integer'Pos (2)**Integer'Pos (1024))**Integer'Pos (1024)...

 

и т.п. Это можно вложить в Integer'Val и т.д. Вместо констант использовать переменные. В общем, дырка, в том смысле, что Universal_Integer

"протекает". Ну а если так, то чего бы Universal_Integer не выложить в пакет Standard?

 

--

Regards,

Dmitry A. Kazakov

http://www.dmitry-kazakov.de

Dmitry A. Kazakov wrote:

 

А вот позвольте вам не позволить!

 

К сожалению это не так просто, как кажется. Если Вы напишете

 

type Kaputt is range 0..2**(2**(2**1024));

 

то ясно, что это компилироваться не может никак. Так что граница все таки

есть. Как ее указать в стандарте?

 

КАКАЯ граница? Или - граница ЧЕГО ИМЕННО? И - а ЗАЧЕМ ее указывать в стандарте?

 

2. Нет стандартного BigNum-а. Что забавно, так то, что на самом деле он

есть, и называется Universal_Integer. Более того, он даже существует во

время исполнения! Есть не статические выражения Universal_Integer! Например

 

((Integer'Pos (2)**Integer'Pos (1024))**Integer'Pos (1024)...

 

Дык, а чего в нем нестатического с точки зрения главы 4.9 Стандарта?

Alexey Veselovsky wrote:

Возможно ли в аде создать новый числовой тип (например тип больших натуральных чисел), чтобы синтаксические правила обращения с ним были те же, что и в случае встроенные типов.

 

Т.е. чтобы можно было также делать подтипы и т.п.

Простите, а какова, собственно, практическая цель? Арифметика произвольных

точности/диапазона с подтипами и применимость атрибутов скалярных типов?

 

Боюсь, невозможно, ибо будет чудовищно неэффективно. И, главное, непонятно,

кому, когда и зачем нужно...

Sergey I. Rybin пишет:

 

Боюсь, невозможно, ибо будет чудовищно неэффективно. И, главное, непонятно,

кому, когда и зачем нужно...

 

Криптография

 

-- If you want to get to the top, you have to start at the bottom

Можно пробовать. Всё зависит от конкретной реализации. А вот если в GNAT такового нет, то можно (и нужно!) написать соотвествующее пожелание разработчикам.

 

>Так. Стоп. А что по этому поводу говорит нам стандарт?

 

>Вообще, хотелось бы чтобы компилер умел бы выбирать тип по даденому >диапазону значение. Если диапазон укладывается в стандартные типы, то >используются они, если не укладываются, то смотрится что можно

>использовать вместо.

 

Куда смотреть? Дальше только небо...

 

Вообще, есть два слабых места настоящего стандарта Ada:

 

1. Компиляторам разрешено отвергать декларации типов, со слишком "большим" диапазоном. В принципе, он должен бы допускать все, что душе угодно.

  type Large is range 0..2**1024; -- нет проблем

 

К сожалению это не так просто, как кажется. Если Вы напишете

 

  type Kaputt is range 0..2**(2**(2**1024));

 

то ясно, что это компилироваться не может никак. Так что граница все таки есть. Как ее указать в стандарте?

 

procedure Kaputt is

begin

Kaputt;

end Kaputt;

 

ясно что также не может компилироваться никак. однако компилируется.

Также и с типами.

Либо не также, а чтобы было возможно на каждый из диапазонов

"прицепить" соответствующую реализацию целочисленного типа. Либо чтобы было можно явно указать какой реализации отдавать предпочтение. Ведь число может храниться (и обрабатываться) многими способами... Где-то выигрываем на одном. где-то на другом.

 

В С++ в этом плане как-то проще т.к. там изначально нет механизма создания таких вот "диапазонных" типов, поэтому там шаблон оных

"больших числ" вполне может ввести такую операцию и это ничему не будет противоречить.

 

Т.е.:

typedef Int<32> int32; // если архитектура умеет 32 бита, то будет использоваться 32 бита встроенный int.

typedef Int<64> int64; // также будет какой-нибудь long long если архитектура умеет.

typedef Int<1024> int1024; // будет использоваться своя реализация целого числа.

typedef Int big_int; // будет использоваться своя реализация числа произвольной (не ограниченой) длины.

Простите, а какова, собственно, практическая цель? Арифметика произвольных точности/диапазона с подтипами и применимость атрибутов скалярных типов?

Боюсь, невозможно, ибо будет чудовищно неэффективно. И, главное, непонятно, кому, когда и зачем нужно...

 

Всякие разные модулярные арифметики используемые в криптографии.

 

Например, частная задачка (лаба специальности Компьютерная Безопастность): Найти все решения уравнения:

 

1/X1 + 1/X2 + ... + 1/Xn = A/B

(X1 ... Xn , A, B -- числа натуральные).

 

Попробуйте это решить без больших чисел. Собственно тут сами решения будут таковыми числами (20ти и более значными). В java вот есть

стандартный класс -- BigInteger... Но им пользоваться не очень удобно, увы. От Ады хотелось бы бОльшей абстракции и consistensy.

On Tue, 24 Mar 2009 23:59:05 +0300, you wrote:

 

Dmitry A. Kazakov wrote:

 

А вот позвольте вам не позволить!

 

К сожалению это не так просто, как кажется. Если Вы напишете

 

type Kaputt is range 0..2**(2**(2**1024));

 

то ясно, что это компилироваться не может никак. Так что граница все таки есть. Как ее указать в стандарте?

 

КАКАЯ граница? Или - граница ЧЕГО ИМЕННО?

 

Минимальное размер множества значений целочисленного типа поддерживаемый любой реализации компилятора Ады.

 

И - а ЗАЧЕМ ее указывать в стандарте?

 

Чтобы обеспечить портируемость программ. Например

 

type Long_Long_Unsigned is mod 2**128;

 

не гарантируется.

 

2. Нет стандартного BigNum-а. Что забавно, так то, что на самом деле он есть, и называется Universal_Integer. Более того, он даже существует во время исполнения! Есть не статические выражения Universal_Integer! Например

((Integer'Pos (2)**Integer'Pos (1024))**Integer'Pos (1024)...

 

Дык, а чего в нем нестатического с точки зрения главы 4.9 Стандарта?

 

А то, что вместо литералов переменные писать можно. И тогда вся статичность испаряется. Вы можете написать вот такую "наглую" реализацию длинного умножения без использования "старшего" типа или разбиения на блоки:

with Interfaces; use Interfaces;

procedure Long_Mul (X, Y : Unsigned_32; H, L : out Unsigned_32) is begin

H := Unsigned_32'Val (

(Unsigned_32'Pos (X) * Unsigned_32'Pos (Y)) / 2**32);

L := Unsigned_32'Val (

(Unsigned_32'Pos (X) * Unsigned_32'Pos (Y)) mod 2**32);

end Long_Mul;

 

Не гарантирую, что будет работать с Unsigned_64, но по идее должно бы. Лень искать закрыта ли эта дырка "сверху" или нет. Но в теории, вся арифметика происходит в Universal_Integer. Так что "честный" компилятор должен Universal_Integer поддерживать в run-time.

 

--

Regards,

Dmitry A. Kazakov

http://www.dmitry-kazakov.de

On Wed, 25 Mar 2009 01:44:11 +0300, you wrote:

 

Можно пробовать. Всё зависит от конкретной реализации. А вот если в GNAT

такового нет, то можно (и нужно!) написать соотвествующее пожелание разработчикам.

 

>Так. Стоп. А что по этому поводу говорит нам стандарт?

 

>Вообще, хотелось бы чтобы компилер умел бы выбирать тип по даденому >диапазону значение. Если диапазон укладывается в стандартные типы, то >используются они, если не укладываются, то смотрится что можно

>использовать вместо.

 

Куда смотреть? Дальше только небо...

 

Вообще, есть два слабых места настоящего стандарта Ada:

 

1. Компиляторам разрешено отвергать декларации типов, со слишком "большим" диапазоном. В принципе, он должен бы допускать все, что душе угодно.

  type Large is range 0..2**1024; -- нет проблем

 

К сожалению это не так просто, как кажется. Если Вы напишете

 

  type Kaputt is range 0..2**(2**(2**1024));

 

то ясно, что это компилироваться не может никак. Так что граница все таки есть. Как ее указать в стандарте?

 

procedure Kaputt is

begin

Kaputt;

end Kaputt;

 

ясно что также не может компилироваться никак. однако компилируется.

 

Ничего подобного. Kaputt - легальная программа. То, что она завершается по Storage_Error - дело программиста.

 

Также и с типами.

 

Нет. Типы в Аде статические. Речь не идет о времени исполнения. type Kaputt не компилируется потому, что некоторые его статические атрибуты

невычислимы. Т.е. его спецификация не вычислима. Спецификация procedure Kaputt замечательно вычислима.

 

Либо не также, а чтобы было возможно на каждый из диапазонов

"прицепить" соответствующую реализацию целочисленного типа. Либо чтобы было можно явно указать какой реализации отдавать предпочтение. Ведь число может храниться (и обрабатываться) многими способами... Где-то выигрываем на одном. где-то на другом.

 

А, это. Да, я об этом долдонил годами, что должны быть абстрактные целочисленные типы вместо уродских generic классов "range <>", "mod <>", "(<>)". Никто все равно не слушает.

 

В С++ в этом плане как-то проще т.к. там изначально нет механизма создания таких вот "диапазонных" типов, поэтому там шаблон оных

"больших числ" вполне может ввести такую операцию и это ничему не будет противоречить.

 

Не вижу, почему в С++ это проще. Ну-ка зарядите пользовательский тип под квадратные скобки char[]...

 

Т.е.:

typedef Int<32> int32; // если архитектура умеет 32 бита, то будет использоваться 32 бита встроенный int.

 

type Int_32 is range -2**31-1..2**31-1;

 

Где разница?

 

--

Regards,

Dmitry A. Kazakov

http://www.dmitry-kazakov.de

Dmitry A. Kazakov wrote:

 

Чтобы обеспечить портируемость программ. Например

 

type Long_Long_Unsigned is mod 2**128;

 

не гарантируется.

 

На мой взгляд, цель поставлена неверно. Арифметика - в принципе

не портируемая вещь, и если компилятор вам говорит, что такое

вот объявление типа он не в состоянии корректно обработать - так

чего же еще от него хотеть? Компилятор не дал вам возможность получить

исполняемый файл для программы с непонятно какой арифметикой, за

это ему надо в ножки кланяться - а саму программу напильником

дорабатывать.

 

((Integer'Pos (2)**Integer'Pos (1024))**Integer'Pos (1024)...

Дык, а чего в нем нестатического с точки зрения главы 4.9 Стандарта?

 

А то, что вместо литералов переменные писать можно. И тогда вся статичность

испаряется.

Тогда да.

 

Но в теории, вся арифметика

происходит в Universal_Integer.

В теории - да. Ну и что?

 

Так что "честный" компилятор должен

Universal_Integer поддерживать в run-time.

 

Есть честные компиляторы, а есть - индустриально востребованные. Мы занимаемся

вторыми. На первые просто нет ресурса, хотя, безусловно, проблема интересная.

 

Вы же вроде как наши клиенты - ну так и поднимите этот вопрос в виде официального

запроса от клиента - получите убедительный и квалифицированный ответ от наших

зубров (мне самому интересно стало, но собственные умные мысли кончились).

 

Я так думаю, как только возникнет индустриальный запрос - так и найдется удовлетворяющее

индустрию решение. Но, боюсь, в виде встроенного типа, или типа, выглядящего как

встроенный, такое решение не получится - из соображений ресурсоемкости, причем -

во всех смыслах.

Sergey I. Rybin wrote:

 

Я так думаю, как только возникнет индустриальный запрос - так и найдется удовлетворяющее

индустрию решение. Но, боюсь, в виде встроенного типа, или типа, выглядящего как

встроенный, такое решение не получится - из соображений ресурсоемкости, причем -

во всех смыслах.

 

Насколько я понимаю ситуацию, библиотеки высокоточной целочисленной, плавающей и десятичной арифметики сейчас являются частью GCC, так что возможно путь тут и не такой уж далёкий. Другое дело пока кто-то не наберётся храбрости заявить "ХОЧУ!!!", дело никуда не сдвинится.

[что поскипал, с тем согласен.]

 

В С++ в этом плане как-то проще т.к. там изначально нет механизма

создания таких вот "диапазонных" типов, поэтому там шаблон оных

"больших числ" вполне может ввести такую операцию и это ничему не

будет противоречить.

Не вижу, почему в С++ это проще. Ну-ка зарядите пользовательский тип под

квадратные скобки char[]...

А это уже массивы, с про них у С/С++ отедльная грустная песня ;-)

Получится только либо круглые, либо угловые скобки (в зависимости от того, хочется ли в рантайме длину массива задавать, либо же во время компиляции).

 

Т.е.:

typedef Int<32> int32; // если архитектура умеет 32 бита, то будет

использоваться 32 бита встроенный int.

type Int_32 is range -2**31-1..2**31-1;

Где разница?

Разница в следующих строчках.

type Int_1024 is range -2**1024-1 .. 2**1024-1;

не получится, а вот

typedef Int<1024> int1024; // получится.

 

Единообразие спецификации для 32, 64, Nбитных чисел. При этом реализацие у них может сильно различаться.

On Wed, 25 Mar 2009 13:03:30 +0300, you wrote:

 

Т.е.:

typedef Int<32> int32; // если архитектура умеет 32 бита, то будет использоваться 32 бита встроенный int.

type Int_32 is range -2**31-1..2**31-1;

Где разница?

 

Разница в следующих строчках.

type Int_1024 is range -2**1024-1 .. 2**1024-1;

не получится, а вот

typedef Int<1024> int1024; // получится.

 

typedef Int<1024 десять миллионов нулей 0> int1024...;

 

тоже получится? Где разница?

 

Единообразие спецификации для 32, 64, Nбитных чисел. При этом реализацие у них может сильно различаться.

 

Аналогично: единообразная спецификация для range L..U, реализация может отличатся...

 

Разницы нет и быть не может. Адовское описание целочисленных типов немного более общее. Только и всего. Поддержка и тех и других описаний возможна в разумных пределах. Проблема - установить степень разумности.

 

--

Regards,

Dmitry A. Kazakov

http://www.dmitry-kazakov.de

Dmitry A. Kazakov wrote:

 

Проблема - установить степень разумности.

 

Это совсем рядом с проблемой поиска смысла жизни :)))

On Wed, 25 Mar 2009 12:41:20 +0300, you wrote:

 

Dmitry A. Kazakov wrote:

 

Чтобы обеспечить портируемость программ. Например

 

type Long_Long_Unsigned is mod 2**128;

 

не гарантируется.

 

На мой взгляд, цель поставлена неверно. Арифметика - в принципе

не портируемая вещь, и если компилятор вам говорит, что такое

вот объявление типа он не в состоянии корректно обработать - так чего же еще от него хотеть?

 

type Short_Short_Unsigned is mod 2**1;

 

Хотеть можно? Где граница?

 

Компилятор не дал вам возможность получить

исполняемый файл для программы с непонятно какой арифметикой, за это ему надо в ножки кланяться - а саму программу напильником

дорабатывать.

 

Это не аргумент. С этой точки зрения компилятор, который вообще ничего не компилирует - просто великолепен. Дизайн хорошего языка программирования предполагает:

 

1. Отсутствие случайных ограничений

2. Регламентирование не случайных ограничений стандартом

 

Оба этих принципа здесь нарушены.

 

Но в теории, вся арифметика

происходит в Universal_Integer.

 

В теории - да. Ну и что?

 

Только то, что Universal_Integer существует на этапе исполнения и не может быть удален во время компиляции, как можно было бы думать об изначальном намерении разработчиков Ады. Так или иначе, Universal_Integer протек. Теперь надо решать, то ли течь заткнуть, то ли легализовать его run-time статус.

 

Так что "честный" компилятор должен

Universal_Integer поддерживать в run-time.

 

Есть честные компиляторы, а есть - индустриально востребованные. Мы занимаемся вторыми. На первые просто нет ресурса, хотя, безусловно, проблема интересная.

 

Это опасная дорожка. Индустриальная востребованность - вещь эмпирическая и неформальная. В случае языка программирования лучше пользоваться принципами полноты и непротиворечивости. Индустриально востребован VisualBasic, поболее Ады будет, и это - ни его, ни индустрию никак не красит.

 

Вы же вроде как наши клиенты - ну так и поднимите этот вопрос в виде официального

запроса от клиента - получите убедительный и квалифицированный ответ от наших зубров (мне самому интересно стало, но собственные умные мысли кончились).

 

Это не вопрос к AdaCore, а к языку. Мы используем это "фичу" только в одном месте, и не так нагло, как я сделал в Long_Mul.

 

Все работает ... пока. (:-))

 

Я так думаю, как только возникнет индустриальный запрос - так и найдется удовлетворяющее

индустрию решение. Но, боюсь, в виде встроенного типа, или типа, выглядящего как

встроенный, такое решение не получится - из соображений ресурсоемкости, причем -

во всех смыслах.

 

Решение давно найдено, есть алгоритмы для разных представлений чисел и т.п.

С моей точки зрения, проблема совсем не в этом, а в отсутствии абстрактных целочисленных типов. Ежели бы они были, то вся проблема автоматически перешла бы на уровень библиотек, а не ядра языка. Ну хочет товарищ целых чисел в десятичном упакованном формате, ну и делает их САМ. НО, реализуя СТАНДАРТНЫЙ интерфейс, который дает ему возможность вставлять это чудо везде, где ожидается целое число.

 

И ВСЕ!

 

--

Regards,

Dmitry A. Kazakov

http://www.dmitry-kazakov.de

Dmitry A. Kazakov wrote:

 

Это не аргумент. С этой точки зрения компилятор, который вообще ничего не

компилирует - просто великолепен.

Таких не бывает. В реальности - не бывает.

 

Дизайн хорошего языка программирования

предполагает:

 

1. Отсутствие случайных ограничений

2. Регламентирование не случайных ограничений стандартом

 

Оба этих принципа здесь нарушены.

 

Возможно, авторы языка пришли к выводу, что в данном случае

требуется именно такая "степень разумности". Кроме того, данное

решение датировано концом 70-х годов прошлого века...

 

Есть честные компиляторы, а есть - индустриально востребованные. Мы занимаемся

вторыми. На первые просто нет ресурса, хотя, безусловно, проблема интересная.

 

Это опасная дорожка. Индустриальная востребованность - вещь эмпирическая и

неформальная. В случае языка программирования лучше пользоваться принципами

полноты и непротиворечивости. Индустриально востребован VisualBasic,

поболее Ады будет, и это - ни его, ни индустрию никак не красит.

 

Теоретически - согласен. Но вот реальность такова, какова она есть.

У реально существующих разработчиков реально существующих трансляторов

реальные ресурсы есть ТОЛЬКО на разработку и поддержку индустриально востребованных

решений. Что совершенно не гарантирует, что индустриально востребованные

решения окажутся не то, чтобы лучшими, а хотя бы ну просто грамотными.

 

ЕДИНСТВЕННЫЙ способ сделать честный компилятор - найти сумасшедшего

миллионера, который вложит в проект несколько сотен миллионов

евров. Причем как бы мало не оказалось...

 

С моей точки зрения, проблема совсем не в этом, а в отсутствии абстрактных

целочисленных типов. Ежели бы они были, то вся проблема автоматически

перешла бы на уровень библиотек, а не ядра языка. Ну хочет товарищ целых

чисел в десятичном упакованном формате, ну и делает их САМ. НО, реализуя

СТАНДАРТНЫЙ интерфейс, который дает ему возможность вставлять это чудо

везде, где ожидается целое число.

 

И ВСЕ!

 

А вот это интересно, и если навскидку - разумно. Хотите видеть такое в

Аде 2015 - попытайтесь протолкнуть идею в ARG :)

Разница в следующих строчках.

type Int_1024 is range -2**1024-1 .. 2**1024-1;

не получится, а вот

typedef Int<1024> int1024; // получится.

typedef Int<1024 десять миллионов нулей 0> int1024...;

тоже получится? Где разница?

Разница в том, что в Аде 1024 не получится, а в С++, получится. С десятью миллионами нулей не получится нигде. Будет ошибка этапа компиляции.

 

Единообразие спецификации для 32, 64, Nбитных чисел. При этом реализацие у

них может сильно различаться.

Аналогично: единообразная спецификация для range L..U, реализация может

отличатся...

Разницы нет и быть не может. Адовское описание целочисленных типов немного

более общее. Только и всего. Поддержка и тех и других описаний возможна в

разумных пределах. Проблема - установить степень разумности.

Разница в том, что у С++ описание целочисленных типов наследовано от С, и оно крайне примитивно, зато имеется механизм шаблонов который мощнее дженериков Ады. Поэтому возможно с помощью них расширить систему тех же целочисленных типов С в С++ единообразно, чтобы поддерживались как обычные 32/64 бита, так и большие числа, скажем 1024 бита.

On Wed, 25 Mar 2009 14:03:53 +0300, you wrote:

 

А вот это интересно, и если навскидку - разумно. Хотите видеть такое в Аде 2015 - попытайтесь протолкнуть идею в ARG :)

 

Да, я вижу смайлик... (:-))

 

--

Regards,

Dmitry A. Kazakov

http://www.dmitry-kazakov.de

Dmitry A. Kazakov wrote:

On Wed, 25 Mar 2009 14:03:53 +0300, you wrote:

 

А вот это интересно, и если навскидку - разумно. Хотите видеть такое в

Аде 2015 - попытайтесь протолкнуть идею в ARG :)

 

Да, я вижу смайлик... (:-))

 

На самом деле - я вполне серьезно! Смайлик тут совсем не иронический.

На мой взгляд, те добавления, которые планируются в языке, куда как

менее разумны и полезны, чем вот это.

 

Другое дело, непросто это будет: довести такую идею до ARG

Новое сообщение:
Страницы: 1 2 3 4 5 6

Чтобы оставить новое сообщение необходимо Зарегистрироваться и Войти