Параллельные вычисления коллективом ЭВМ на потоках данных
Метод и средства решения задач параллельно работающими ЭВМ без программирования их взаимодействия, что особенно важно в связи с быстрым развитием микроЭВМ. Унификация средств синхронной и асинхронной обработки потоков данных. На этой основе рост быстродействия вычислений (их распараллеливания по микроЭВМ) и сокращение затрат на программирование. Простейшие примеры вычислений, демонстрирующие метод и концепции. Попутно устранение застарелых проблем существующих языков программирования, включая оперирующих с потоками данных
Введение
С развитием микроэлектроники все ощутимее дефицит языков программирования задачи, решаемой параллельно работающими микроЭВМ без программирования их взаимодействия. Не простая для восприятия версия такого языка была предложена мною ранее ("http://tadviser.ru/a/150588"):
- Основная конструкция языка – суперпозиция функций ƒ(ƒ1(...), ƒ2(...), … , ƒn(...)), в которой каждая ƒi(...) с той же структурой, как и ƒ - все микроЭВМ, работающие параллельно, что обычно [1] считается невозможным для цифровых систем.
- У данных той же многоуровневой структуры 1 имена ƒ и ƒi - суть атомы: числа, строки, даты и др. В отличие от lisp [2,3] динамически распределяемая память (ДРП) под элементы структуры 1 допускает прямой доступ к узлу ƒi(...) по значению i.
- На входы (аргументы) функции ƒi (i=1-n) одновременно поступают потоки, каждый из элементов - атомов и/или ссылок на структуры 2, результаты поочередной обработки которых ƒi передает (поток) на соответствующий вход ƒ.
- Последовательность индексов - теперь поток данных и, в частности, определяет путь на иерархической структуре от ее корня (вершины) к элементу на любом уровне иерархии. Так индексирование элементов многомерных матриц распространяется на любые иерархические структуры.
- Элемент в потоке сопровождается свойствами (св-вами), определяемых его структурой или формируемых явно в ходе обработки, например, при сравнении элементов потоков. На входах (аргументы) и выходах ƒi устанавливаются фильтры, пропускающие элементы, отвечающие требуемым св-вам.
- Основной синтаксически определяемый выход функции можно дополнить другими - каналами, на которые подаются результаты вычислений, отвечающие условию, заданному фильтром (см.выше). Другие функции того же выражения 1 эти каналы определяют в качестве собственных входов (аргументов) - подобие Chanal языка Occam [5].
- Для конструирования функции предлагаются примитивы - встроенные (не программируемые) функции: фильтры (п.5), генераторы (источники) потоков, а также для синхроннной и асинхронной обработки потоков с подключением примитива _Calc с аргументом - микропрограммой в виде таблицы решений и др.
- Разрабатываемая пользователем на средствах п.7 конструкция функции ƒ имеет тот же вид 1, в которой ƒi - уже примитивы с массой настроек и микропрограмм _Calc в виде их аргументов. Полученную конструкцию функции вместе с формой обращения к ней можно сохранить в библиотеке и затем наряду с примитивами использовать в выражениях типа 1.
К сожалению реализация 7 и 8 концепций 1-6 оказалась не такой простой для восприятия, что вынудило продолжить поиск. Наипростейшее решение удалось найти, определив единую для всех функций ƒ и ƒi их внутреннюю иерархическую структуру (см.р.2).
Гид по NGFW. 10 наиболее заметных продуктов, доступных на российском рынке
Теперь уже не функция ƒi в выражении 1 представляется отдельной микроЭВМ, а каждый из элементов ее внутренней унифицированной структуры, также работающих параллельно и все на той же концепции потоков, формируемых, движущихся и обрабатываемых теперь явно и внутри этой структуры.
С повышением распараллеливания вычиcлений и быстродействия поднят уровень языка программирования, исчезла необходимость практически во всех встроенных функциях, включая _Calc с микропрограммами, при необходимости описав их как пользовательские и поместив в библиотеку. Нет необходимости и в отдельном описании формы обращения (вызова) к ƒi.
К сожалению реализацию всего этого принципиально нового и безусловно необходимого рано или поздно предстоит завершить другим, так как у меня для этого уже не осталось времени, сил и коллектива соответствующих исполнителей.
1. Минимум наследия из первой версии проекта
Исходные концепции (1-6) Введения остались прежними. Как и ранее ("http://tadviser.ru/a/149691") для описания структуры данных и языка используется метасимволика Бэкуса-Наура. Дополнительно в нежирные скобки [...] заключается часть описания, которая может отсутствовать. В скобки {...} включается часть описания, которая может отсутствовать или повторяться (итерация). В скобках /.../ - список обозначаемых символами св-в элемента структуры, который начинает символ '%'. Предваряющий обозначение св-ва код '~' отрицает его наличие.
1.1. Единая структура данных и программ
<Структура> ::= [<атом>]<Слой>
<Слой> ::= ([<Узел>]{,<Узел>})
Слой может быть пустым - без узлов - ().
<Узел> ::= [<Имя-индекс>:]<Неопределенный> | [<имя-индекс>:]<Структура>
<Неопределенный> ::= #
Помимо индекса 0, 1, 2,... , определяющего его номер в слое по порядку, узел может аналогично hash [2] иметь уникальное в пределах слоя имя-индекс.
Кодирование структуры - узла отличается от принятого в lisp: это пара ссылок
УКА – указатель атома и УКС – указатель слоя следующего уровня иерархии.
Отсутствие атома и/или слоя будем определять далее как УКА=0 и/или УКС=0, одновременное УКА=0 и УКС=0 - как неопределенный (#) узел. Фактически УКА и УКС - ссылки на отдельные блоки (БП) динамически распределяемой памяти (ДРП), соответственно, с атомом и слоем, причем БП со слоем содержит коды (пары УКА, УКС) его узлов слоя и помимо доступа по имени-индексу (если он определен) допускает прямой доступ к этим кодам по их индексам (номерам по порядку) 0, 1, 2, … (п.2.5).
1.2. Потоки и свойства их элементов
Физически поток состоит из элементов, поочередно передаваемых с одного и того же выхода (или канала) одной функции выражения (суперпозиции функций) на один и тот же вход (аргумент) - регистр другой в одном из следующих видов:
Атом /%A/ - передаваемое его значение непосредственно без использования ДРП.
R-значение /%R/ - пара ссылок УКА и УКС (п.1.1). Cледующие за %R св-ва %a[tom] и %l[ay] (%Ral) уточняют, соответственно, наличие атома и слоя узла по этим ссылкам или их отсутствие (УКА=0 и/или УКС=0) предваряющим св-во кодом '~'. При %R~a~l узел считается неопределенным и короче его значение и св-во можно обозначить как '#'.
V-значение /%V[li]/ - определяет номер - индекс /%i/ узла (R-значения) в слое по УКС /%l/. Таким образом, это - пара (УКС, индекс) - ссылка на R-значение (кратко Rзн-е).
Внимание! V-значение (кратко Vзн-е) устраняет еще отмеченные Барроном [2] проблемы современных L-языков, например, разную трактовку X в левой и правой частях оператора X:=X+1. Теперь этот оператор можно повторять и в потоках, невзирая на утверждения [4] о невозможности этого ("подстановок" в терминологии [4]) в потоковых ЭВМ: теперь элементами потока могут быть и Vзн-я.
1.2.1. Определение свойств элементов
И еще о св-вах, однозначно определяемых значением элемента как потока, так и любой структуры и потому не требующих их ведения и хранения рядом с этим элементом:
1) Св-ва %Ra и %A элементов сопровождаются св-вами их атомов - типом их значений:
- числа целые /%i[nter]/ и дробные /%f[loat]/,
- строки /%s[tring]/ ("строка"),
- даты /%d[ate]/,
- идентификаторы /%n[ame]/ имен-индексов, функций, каналов (выходов функций), идентификаторы примитивов,
- атом %{[~]<св-во>} /%p[ercent]/ из множества св-в или их отрицаний.
P.S. В описываемом множестве св-в могут находится не допускаемые у описываемых ими объекта одновременно. Например, число не может быть одновременно датой, или Rзн-е Vзн-ем, а атом слоем. Такие св-ва определяются как альтернативы: предполагается одно из этих св-в, например, %Rfs предполагает в Rзн-и наличие атома - числа либо строки. Альтернативы можно задавать и явно посредством символа '|', например, тот же %Rfs как %Rf|s.
2) Св-ва (1) типа атома сопровождают (рядом справа) уточняющие его значение св-ва, возможно предваряемые их отрицаниями '~':
+ | - положительное (>0) значение числа |
− | - отрицательное (<0) значение числа |
0 | - 0 типа атома: 0 (%i) или 0.0 (%f) числа, пустые строка и множество св-в |
1 | - нечетное целое /%i1/, |
2 | - четное /%i2/ |
3) Св-во %Rl0 Rзн-я определяет пустой слой.
4) Св-во %Vi0 фиксирует значение 0 индекса - начальный узел (Rзн-е) слоя по УКС Vзн-я.
5) Отсутствующие св-ва могут неявно определяться приведенными: например, %Rf и %af однозначно определяют %Raf. %f задает альтернативу - %Af|Raf
P.S. В последних примерах неясным остается наличие слоя Rзн-я: он есть (%l) или его нет (%~l).
1.3. Пространство памяти
Вместо глобальных переменных существующих языков программирования вводится "пространство" _Space, доступное всем функциям в качестве аргумента и операциям внутри их (п.2), в исходном виде - это структура _Space:() с пустым слоем /%R~al0/. Слой пространства _Space, как и слой по УКС любого Rзн-я можно пополнить узлами - подпространствами, в том числе с именами-индексами, обработать их, удалить и т.д.
Возможно и перемещение вглубь (по уровням иерархии) пространства, как и любой другой многоуровневой структуры, например посредством демонстрируемой п.3.9 пользовательской функции In, обрабатывающей (аргумент) поток индексов (целочисленных и/или имен-индексов) и возвращающей синхронно поток Vзн-й проходимых при этом узлов структуры. По мере прохождения In этого пути можно теперь обработать проходимые узлы (а не только последний, как принято) произвольным образом другой функцией, использующей In в качестве аргумента.
1.4. Литералы
<Литерал> ::= [<Атом[кроме имени]>]<Слой> | # [- Неопределенный элемент]
т.е. в общем случае (наличие слоя) это обычная многоуровневая структура по п.1.1. В случае атома - имени литерал вводится как аргумент примитива
_Lit(<Атом>[<Слой>])
В операциях внутренней структуры функций (п.2.5) _Lit не используется, ибо любая структура - операнд является литералом.
Литерал транслируется в код (п.1.1) многоуровневой структуры с выделением свободных блоков памяти (БП) ДРП под каждый атом и слой на всех уровнях иерархии, возвращая ссылки УКА и УКС (копии) на корневой узел (верхний уровень) структуры – Rзн-е /%Ral/. Если литерал является атомом (без слоя), то в отсутствие его уточнений (п.2.5.2.1) он кодируется со св-вом %A (вне ДРП).
Как и _Space литерал возвращает унарное (не поток) - единственное значение: атом /%A/ или Rзн-е. При попытке использовать его вместо потока он оформляется как поток из одного элемента, включая код завершения потока - неопределенный элемент со св-вом %E.
2. Описание пользовательской функции
Здесь все меняется на 100% в сравнении с первоначальным проектом ("http://tadviser.ru/a/157631") - вводится единая структура пользовательской функции:
<имя>:( | Params(<пар-р>{,<пар-р>}[,End(<операции>)]), | |
Ins(<вход>{,<вход>}), | ||
[,Synch(<синхробработка>{,синхробработка>}),] | ||
[Outs(<выход>{,<выход>})] | ||
) |
Структура "входа", синхробработки и "выхода" практически одинакова:
<Имя>:(<источник потока>,<пар-ры обработки>,<обработка потока>)
как и описываемая ниже организация из взаимодействия.
В обычном вызове <имя[функции]>(<аргумент>{,<аргумент>}) этой функции аргументы (значения, выражения) вводятся в следующем порядке: вначале пар-ры (параметры) Params, а затем входы Ins в порядке их описания.
1) Сначала обрабатываются параллельно унарные значения пар-ров Params (п.2.1). Часть их в Params задаются непосредственно (литерал) и в вызове функции отсутствуют, остальные берутся из вызова и при наличии операций обрабатываются ими.
2) Затем параллельно запускаются "обработки потоков" всех входов Ins, где каждый поток поступает либо извне (п.2.2.1) - от аргумента в вызове функции, либо генерируется собственным источником Well (п.2.2.2) "входа" и в этом случае соответствующий аргумент отсутствует в вызове функции. Рез-ты обработки очередого элемента потока подаются операцией
приемникам: либо непосредственно на выход функции, либо на синхрообработку или (асинхронную) обработку "выходом" секции Outs. Так что эти рез-ты фактически образуют несколько потоков по количеству перечисленных операциями (а) приемников.
3) Находящиеся в Synch и Outs работающие параллельно приемники обрабатывают элементы потоков (2) по мере их поступления от источников. Каждая синхрообработка разделяет (различает) поступающие к ней от различных источников потоки и обрабатывает их синхронно - по мере поступления очередного элемента от каждого из них и только затем обрабатывает этот набор - кортеж поступивших по одному элементу из каждого источника - входа или другой синхрообработки. Аналогично (2) синхрообработка формирует потоки рез-тов, направляемые ею перечисленным (2) приемникам, включая синхрообработки.
4) В отличие от синхрообработки каждый "выход" Outs обрабатывает очередной поступивший к нему элемент потока вне зависимости от его источника - асинхронно и лишь по завершении его обработки переходит к обработке следующего. При этом рез-ты обработки могут быть отправлены операцией => только непосредственно на описываемый "выходом" выход функции - основной или канал.
5) Обработка потока в (2), (3) и (4) имеет также одинаковую структуру:
<обработка потока>::= Begin:<операции>, Go:<операции>[, End:<операции>]
6) Едиными (одинаковыми) для обработки также являются ее пар-ры:
All - допустимое количество элементов потока, по умолчанию All не ограничивает число поступающих на обработку элементов и возможно фактически поток ограничивается его источником.
Sum - исходное значение итога обработки по потоку, в общем случае произвольно задаваемая структура, по умолчанию являющаяся является неопределенным.
Buf - размер (буфера) в количестве ждущих обработки элементов. Буфер хранит элементы для подачи их на обработку в порядке очередности их поступления и призван сократить потери времени обработки из-за приостановки источников потоков при занятости приемника обработкой очередных элементов. В случае кортежа этот пар-р фактически задает размер буферов для каждого из источников потоков кортежей. В отсутствие Buf он считается равным 0.
Значения этих пар-ров задаются явно литералом или пар-ром Params ссылкой на него по имени:
<пар-р обработки>::= <имя пар-ра обработки>:<значение>
7) До начала обработки потока (кортежей в случае синхрообработки) в 0 устанавливаются системные - автоматически (не операциями) ведущиеся пар-ры:
a) _N - к-во обработанных элементов (кортежей) потока.
b) <имя [приемника]> - к-во рез-тов, отправленных их приемнику.
P.S. Напомним, что приемников рез-тов обработки у входов Ins и синхрообработок может быть несколько и все они определяются из операций (2а). У "выхода" Outs приемник один - конкретный одноименный выход функции, включая основной Out, который даже в отсутствие явного определения его имени можно использовать как пар-р (b).
8) До начала обработки потока (кортежей в случае синхрообработки) запускаются операции Begin с равными 0 пар-рами (7), подготавливающие исходные данные для операций (9): например, уточняются значения All и Sum с учетом пар-ров Params, в ранг глобальных (общих по потоку аналогично Sum) с установкой их исх.значений переводится часть переменных a, b, ..., z, являющихся обычно локальными - определяемыми и действующими заново при обработке каждого очередного элемента потока (кортежа).
9) Операции Go каждый раз запускаются заново (цикл) для обработки очередного элемента потока (кортежа элементов по именам их источников), поступающего (поступающих в кортеже) вместе со св-вами сформированными источниками потоков. При этом необязательно корректируется и используется текущее значение итога Sum по потоку. По завершении цикла Go _N автоматически увеличивается на 1, а значения локальных a - z сбрасываются в неопределенные, возможно, с освобождением ДРП, занимаемой их значениями .
10) По завершении обработки (исчерпанию) потока, превышении его размера (к-ва элементов) значения All или прерывании обработки (операцией Go) запускаются операции End, формирующие итоги обработки, если, конечно раздел End определен. В разделе End Sum и пар-ры (7) имеют конечные значения на момент завершения или прерывания обработки потока (кортежей) в Go и могут быть обработаны с передачей результатов приемникам аналогично (2). В любом случае даже в отсутствие End, блокируется выполнение операций (прерывание) у источников обрабатываемого потока (потоков с кортежами).
2.1. Описание параметров
Пар-р имеет одиночное значение (не поток) и задается в виде
<имя>:<значение[-литерал]> и тогда в вызове функции он пропускается,
либо -
<имя>:[<операции>] и тогда исх.значение пар-ра из вызова функции обрабатывается операциями (если они есть!). Рез-т выполнения последней из них принимается в качестве его окончательного значения.
По завершении обработки пар-ров запускаются операции раздела End (если он есть), которые уточняют значения пар-ров, согласовывая их между собой, корректируют их значения уже по их именам.
Внимание! Имя пар-ра уникально НЕ только в пределах секции Params: его нельзя использовать в качестве имен объектов секций Ins, Synch и Outs.
2.2. Описание входов функции
<вход>::= <обрабатывающий поток> | <генерирующий поток>
Генерирующий поток вход отсутствует среди аргументов вызова функции, ибо источник этого потока определяется непосредственно в описании (Well) этого входа (п.3.2). Однако в отличие от пар-ров поступающие на входы или генерируемые ими элементы потоков обрабатываются параллельно и одинаково вне зависимости от того как формируется обрабатываемый поток.
2.2.1. Вход, обрабатывающий поток
<имя входа>:( | [<вид источника потока>,] |
[<пар-ры обработки>,] | |
<обработка потока> | |
) |
<вид источник потока> ::= Fun | Chanal | Any
Таким образом источником поступающего извне (аргумент функции) потока принимается любой: формирующий поток выражение (Fun), канал (Chanal) или любой из них (Any). Отсутствие вида источника потока эквивалентно его определению Any.
2.2.2. Вход, генерирующий поток
<имя входа>:( | Well:<источник потока>, |
[<пар-ры обработки>,] | |
[<обработка потока>] | |
) |
Отличие от входа п.2.2.1 состоит в следующем:
2.2.2.1. Источник потока определяется не аргументом вызова описываемой функции, а непосредственно здесь в самом описании входа:
1) Атом, заданный непосредственно или значением пар-ра из Params, повторяется указанное All число раз. В случае пар-ра с значением - структурой атом может быть получен уточнениями значения пар-ра, как операнда согласно п.2.5.2.1, причем без его фактического изменения.
2) _N - генерирует поток целых чисел 0, 1, 2, ...
3) Многоуровневая структура, заданная непосредственно (литерал) или значением пар-ра Params, как пространство (_Space) или его узел (подпространство) посредством уточнений по п.2.5.2.1. В этом случае автоматически производится ее обход по контуру (сверху-вниз и слева-направо) с генерацией Vзн-й проходимых при этом узлов.
4) Суперпозиция встроенных и библиотечных функций, использующих в качестве аргументов и пар-ры Params. Вводится единственная встроенная функция (примитив)
Stream(<элемент потока>{,<элемент потока>}),
генерирующая поочередно слева направо в качестве элементов потока значения своих аргументов.
Даже простейший источник потока For(<начало>, <к-во элементов потока>, <шаг>) вводится как библиотечная функция с соответствующим описанием (п.3.1).
2.2.2.2. В отсутствие "обработки потока" (Begin, Go и End) очередной генерируемый источником Well элемент потока автоматически направляется
- на синхробработку, если она единственная и в списке Regs содержит имя этого входа (см.п.2.3);
- иначе на основной выход Out функции.
В отсутствие All окончание (или прерывание) потока вместе с источником определяется самим источником, либо автоматически при остановке приемника этого потока.
2.3. Синхрообработка
<синхрообработка>::= | |
<имя-индекс>:( | Regs(<источник[потока]>{,<источник>}) |
[<пар-ры обработки>,] | |
<обработка потока> | |
) |
Особенности синхрообработки:
1) Ее имя отличается от имен выходов (п.2.3) раздела Outs, в отсутствие которого имя Out (основного выхода) можно присвоить одной из синхрообработок и даже передавать результаты обработки этой синхрообработке как на основной выход операцией => без указания имени.
2) На обработку синхрообработке входы Ins или другие синхрообработки (источники) направляют элементы (потоков) на обработку операцией
и для каждой указанной в этой операции именем синхрообработки автоматически формируется список Regs использующих эту операцию источников, состоящий НЕ менее, чем из их двух имен. Этот список можно корректировать вручную.
3) В случае единственной синхрообработки в Synch ее имя вместе с ограничивающими ее скобками может отсутствовать (см. пример п.3.5) и тогда при отсутствии Outs в операции => входов Ins имя это синхрообработки опускается, но подразумевается именно она.
4) Исх.значением рез-та операций Go является элемент кортежа из источника, определенного в Regs первым. Имена источников списка Regs используются в операциях Go как имена элементов обрабатываемого кортежа - операнды операций.
5) При занятости (переполнении) выделенного источнику из Regs буфера Buf на время обработки кортежа и освобождения буфера этот источник приостанавливается при выполнении операции => передачи элемента для следующего кортежа этой (!) синхрообработки.
6) При завершении одного из перечисленных Regs источников (св-во %E окончания потока), синхрообработка в последующих кортежах использует элемент (по имени источника), полученный от него последним.
2.4. Описание выходов Outs
Описание и обработка "выхода" здесь отличается от рассмотренных п.2.2 "входов" следующим:
1) Вместо имени входа - имя выхода. Следующая за ':' часть описания выхода может отсутствовать и тогда поступивший от источника потока элемент без обработки отправляется на соответствующий выход функции - Out или канал.
2) Источников потоков (с операциями =><имя выхода>) может быть много. Потому аналогично п.2.3 формируется их список Regs.
3) Поступающий на выход поток завершается запуском операций End выхода по исчерпании всех источников, определенных его списком Regs.
4) Единственным выходом Out (его описанием) можно заменить всю секцию Outs.
5) Определение Out может отсутствовать и в отсутствие единственной безимянной синхрообработки (п.2.3) операция => отправляет рез-т вычислений на основной - синтаксически определяемый выход функции.
6) При наличии выходов кроме Out - каналов в порядке их определения их можно переименовать в обращении (вызове) к функции дополнительным аргументом
2.5. Программирование операций разделов Begin, Go и End
2.5.1. Структура операций разделов Begin, Go и End
<операции> ::= [<условие>]<операция> | [<условие>],<блок операций>
<блок операций>::= (<операции>{,<операции>})
<условие> ::= <атом "Cв-ва">[!<операнд>]? | [ ~ ]?
Атом "Cв-ва" задается непосредственно согласно его определению (п.1.2.1, %p), либо значением пар-ра Params или переменной a - z и содержит требуемые св-ва (или их отрицание '~') операнда (справа от '!'), а в его отсутствие - рез-та предшествующей операции. Предельно краткое условие '?' ссылается на успешный рез-т проверки последнего условия в том же блоке операций, а '~?' отрицает его - эквивалент "Иначе (else)" классических языков. Отличие от общепринятых конструкций If...then...else здесь в том, что '?' и '~?' можно использовать многократно в блоке операций.
Исключение: В случае операций Go "выхода" Outs вводится еще один вариант условия:
разрешающего выполнение операции (блока) при обработке элемента от одного из перечисленных в условии источников Regs.
Операции (в т.ч. блоки) выполняются поочередно слева направо при выполнении условия или в его отсутствие.
У исполняемой первой операции раздела в качестве исх. рез-та автоматически принимается:
- для пар-ра Params его введенное в вызове функции значение,
- для раздела Begin - исх.Sum,
- для Go - очередной обрабатываемый элемент потока (первый из Regs для кортежа),
- для End - итоговое после обработки Go значение Sum.
<операция>::= [<код операции>][<операнд>]
<операнд>::= <объект обработки>{<уточнение>} | <имя выхода>
В отсутствие кода операции значение операнда принимается в качестве рез-та операции.
Код операции определяет ее суть. Операция как правило выполняется над рез-том предыдущей операции (не имеющим обозначения) и операндом.
Выполнение операции может быть прервано и обычно с сохранением ее исх. рез-та, пополнямым св-вом %X. Это вызывается разными факторами, например, отсутствием или недопустимым типом операнда, недопустимым соотношением св-в исх.рез-та и операнда, переполнением ДРП и др. При прерывании операции возможны следующие ситуации:
1) Выполнение операций раздела прекращается (прерывается) как и обработка потока (Go), если следующая операция не начинается условием с анализом наличия или отсутствия св-ва %X.
2) При прерывании операций пар-ра (Params) св-во %X приобретает и сам пар-р (его значение), которое будет передано вместе с его значением к началу прерванной операции в раздел End Params. При этом операции других пар-ров НЕ прерываются. Операции раздела End Params могут исключить св-во %X у пар-ров (п.2.5.3.1), иначе выполнение функции прекращается как и в (4)
3) При прерывании операций раздела Go и автоматически потока (кортежей) запускается раздел End той же части описания функции (входа, синхрообработки или выхода) со св-вом %X у исх.рез-та обработки.
4) В случае прерываний операций раздела End прерывается (прекращается) и выполнение функции, по всем ее выходам формируются (передаются приемникам) коды завершения потока со св-вом %X помимо %E, если раздел End не устранил свойство %X.
5) Св-во %X у исх.рез-та можно установить операцией (п.2.5.3.1) и тем самым фактически вызвать ту же реакцию (1-4) системы.
2.5.2. Объекты обработки
Такими объектами являются:
1) Пар-р Params (имя, п.2.1) и определяемая им структура
2) Элемент пространства _Space (раздел 1)
3) Итог Sum (в общем случае это структура), определяемый отдельно по каждому входу, синхрообработке и выходу функции, исх. значение которого определяется и уточняется разделом Begin
4) Пар-ры обработки раздела Go
5) Набор из 26-и переменных каждой секции, определяемых как a, b, ..., z
6) Литерал - структура
Все объекты, кроме переменных (5) и литералов (6), являются глобальными - обладают св-вом %G[lobal], т.е. доступны при обработке всех элементов потока и всеми разделами Begin, Go и End. Объекты (1) и (2) одинаково доступны и во всех секциях Ins, Synch и Outs.
Объекты (5) являются локальными - определяются отдельно для каждого очередного обрабатываемого элемента: делаются неопределенными (%#) при запуске операций раздела Go, теряя прежние значения. Вместе с тем допускается установка св-ва %G (п.2.5.3.1) у любого из объектов a - z, придающих им возможности объекта Sum в их использовании.
2.5.2.1 Уточнение операнда
Объект обработки в качестве операнда может сопровождаться (справа) последовательностью уточнений его элементов (атома, слоя, узла слоя), участвующих непосредственно в операции. Каждое из уточнений может иметь вид:
<уточнение> ::= %<[требуемые ]св-ва> | [<индекс[ узла слоя>]
<индекс узла слоя> ::= <целое> | <имя-индекс>
В последовательности применяемых к объекту уточнений каждое очередное применяется к рез-ту предыдущего и при приведении его к требуемым св-вам идентично операции п.2.5.3.1, в отличие от которой здесь свойства задаются явно (атомом). Уточнение [<индекс> идентично аналогичной операции '[' c Rзн-ем (п.2.5.3.3).
Как и в случае п.2.5.3.1 некорректность уточнения, например, в отсутствие возможности приведения операнда к нужному виду, блокирует выполнение следующих справа уточнений операнда и прерывает операцию с присвоением исходному НЕ меняющемся при этом рез-ту св-ва %X с соответствующей реакцией системы (п.2.5.1).
Пример: _Space[SubA%R - выделяет из пространства памяти - объекта _Space (Rзн-е) Vзн-е подпространства с именем SubA (1-е уточнение) и затем окончательно формирует (2-е уточнение %R) Rзн-е (пару УКА с УКС), указываемое этим Vзн-ем.
Внимание! При наличии кода операции в отличие от п.2.5.3.1 непосредственного преобразования объекта его уточнениями НЕ происходит: в процессе операции эти уточнения операнда происходят скрыто (неявно) и потому более эффективно как по быстродействию, так и в части экономии ДРП (памяти). Иначе р-том операции становится рез-т последнего (справа) уточнения. Не допускается изменение операцией (код) создаваемых уточнениями ссылок УКА и УКС или содержимого, указываемого ими: происходит прерывание операции с пополнением исх.р-з-та св-вом %X.
2.5.3. Коды и содержание операций
1) В отсутствие кода операции копия значения операнд с учетом его уточнений (п.2.5.2.1) принимается в качестве рез-та этой "операции", заменяя им исх.рез-т. При этом, как и в описываемых далее операциях, меняющих размеры атомов и слоев в ДРП и уникальные (не вторичные) ссылки (УКА, УКС) на них, возникает необходимость освобождения всей или части занимаемой ими ДРП или, напротив, расширения этой памяти за счет свободной части ДРП.
2) Содержание операции определяют виды исх.рез-та и/или операнда (с учетом уточнений по п.2.5.2.1), определяемые как
%A - атом,
%Ra~l - атом или ссылка (УКА) на него,
%R~al - слой или ссылка (УКС) на него,
%R[al] - Rзн-е с отличными от 0 УКА и УКС.
%V - Vзн-е
2.5.3.1. Приведение данных к требуемому свойствами виду
Эта первая и наиболее важная операция имеет вид условия без '?' (п.2.5.1) и приводит (преобразует) операнд или в его отсутствие исх.рез-т к требуемому явно (непосредственно атомом вида %p) задаваемыми св-вами виду (п.1.2).
Если "условие" ограничивается проверкой соответствия св-в операнда или рез-та требуемым, то здесь они приводятся к виду, требуемому этими св-вами, что возможно НЕ для всех исх.значений. В последних случаях операция прерывается (п.2.5.1). В случае приведения операнда исх.рез-т операции остается прежним.
Допустимые преобразования:
1) Исх.Vзн-е заменяется (рез-т) требованиями его свойств на:
%R - указываемое им значение,
%Ai - свой индекс,
%[l]~i - Rзн-е из УКА=0 и свой УКС (%Rl~a).
2) Исх.Rзн-е (пара УКА с УКС) может быть преобразовано требованиями св-в:
%A | - заменено копией атома (вне ДРП), указываемого УКА. При УКА=0 операция прерывается. Это преобразование можно дополнить требованиями (3) изменения типа полученной копии атома. |
%~a | - УКА сбрасывается в 0 |
%~l | - УКС сбрасывается в 0 |
%~a~l | - выполнение предыдущих %~a и %~l |
%Ai | - исх.%R~al заменяется размером слоя по УКС. |
%l0 | - не пустой слой (%l~0) по УКС сбрасывается до пустого. |
%l | - В отсутствие слоя (%R~l) создается пустой слой. |
%a0 | - сброс атома в 0-е значение его типа. |
%V | - меняется на Vзн-е - пару УКС с указываемым УКА индексом - целым (%i) или именем (%n), если, конечно, такой узел в слое по УКС существует (иначе прерывание %X). В отсутствие УКА индекс принимается равным 0. |
3) При исх.%A или %Ra можно изменить тип атома, затребовав св-ва с вариантами требуемых типов, из которых автоматически выбирается первый допустимый:
%s - значение любого типа преобразуется в его строковое отображение (строку) согласно синтаксиса.
%f - целое (%i) становится вещественным.
%i - вещественное (%f) преобразуется в целое (%i) с потерей дробной части, а не число заменяется на его размер согласно синтаксису (длина имени, строки, к-во св-в и их отрицаний).
%− - меняет знак '+' числа на '−'.
%~− или %+ - меняет знак '−' на '+'.
4) %A0 - сброс исх.атома в 0-е значение его типа.
5) Исх.%A (атом) может быть преобразовано в Rзн-е требованием %R[a~l]. В этом случае выделяется свободный блок (БП) памяти из ДРП, в который помещается копия исх. атома. УКА этого блока и УКС=0 образуют искомое Rзн-е.
6) Исх.%As (строка) по требованию %Ral рассматривается как синтаксическое изображение структуры, которая и транслируется в код с выделением свободной памяти ДРП под атомы и слои и формированием Rзн-я - ссылок УКА и УКС на эту структуру.
7) Любое значение (структура) может быть приведено к атому вида %Ap, содержащему св-ва исходного значения.
2.5.3.2. Операции с атомами
1) Операции '+', '−', '*', '/' выполняются c атомами исх.рез-та и операнда, возможно после его уточнений по п.2.5.2.1, но обязательно со св-вами %A или %Ra~l. Содержание операции определяется типами этих атомов. Рез-т операции замещает атом исх.рез-та непосредственно (%A) или в БП (ДРП) по УКА его Rзн-я и в этом последнем случае Rзн-е (УКА и УКС) исх.рез-та сохраняется.
</b>-</b> В случае числовых (виды %if) исх.рез-та и операнда это обычные арифметические операции, результаты которых определяются типами чисел: если оба- целые (%i), то и результат - целое число, иначе вещественное. Деление на 0 вызывает прерывание операции.
</b>-</b> К дате (%d) можно добавить (+) или вычесть (%−) целое (%i), получив новую дату. Вычесть из нее можно и дату, получив целое в днях.
</b>-</b> Операция '+' для атомов исх.тома и операнда - строк (%s) трактуется как катенация строк: строка операнда дописывается к строке рез-та.
</b>-</b> Операция '−' из атома - строки (%s) рез-та удаляет первое вхождение строки (%s) атома операнда. Операция '/' удаляет все вхождения.
</b>-</b> Операция '*' строку (%s) атома рез-та повторяет число раз, указываемое атомом операнда.
</b>-</b> Операция '/' атом - строку (%s) исх.рез-та сокращает (обрезает) удалением конечной его части до размера, указываемого целым числом - операндом.
2) Операции +=, −=, *=, /= отличаются от (1) тем, что в качестве объекта обработки принимается не исх.рез-т, а операнд. Принявший на себя роль операнда (1) исх.рез-т сохраняется.
2.5.3.3. Операции с R-значениями
1) [<индекс> - определение Vзн-я - УКС исх.Rзн-я и индекса, значение (%i) которого задается явно (литерал), переменной a-z, пар-ром Params.
2) [<имя-индекс> - в слое по УКС исх.Rзн-я разыскивается узел с именем-индексом и определяется его Vзн-е - рез-т операции.
3) Следующие операции выполняются со слоем Rзн-я со св-вами %R~al:
+ - слой пополняется
а) копией Rзн-я (пары УКА с УКС) операнда, задаваемого аналогично (1),
б) указанным операндом к-вом неопределенных Rзн-й,
в) неопределенным R-значением с указанным операндом - именем-индексом.
− - из слоя удаляются конечные узлы - пары (УКА,УКС) в количестве, указываемом операндом.
~ - из слоя удаляется узел с указанным операндом индексом - целым аналогично (1) или именем-индексом.
* - слой пополняется копией структуры, определяемой Rзн-ем операнда. При этом в отличие от '+' копируются атомы и слои структуры операнда с выделением свободной ДРП.
/ - в слое удаляются начальные узлы (Rзн-я) в количестве, указываемом операндом.
Пример ввода подпространства с именем-индексом SubA: _Space,+SubA
_Space всегда возвращает Rзн-е с УКА=0.
Операция '+' не меняет исх.Rзн-е (УКА и УКС).
4) Операции +=, −=, ~=, *= и /= отличаются от (3) тем, что производятся не со слоем исх. рез-та, а слоем операнда. Теперь в качестве операнда выступает исх.рез-т, сохраняющий свое значение к концу операции.
2.5.3.4. Операции с V-значениями
Напомним определение Vзн-я (п.1.2) как пары <УКС, индекс>, указывающей Rзн-е - узел в слое по УКС с индексом (0, 1, 2,...), и теперь операции с Vзн-ем:
1) + и −, соответственно, добавляют или вычитают из индекса Vзн-я рез-та значение операнда - атома типа целое (%Ai), формируя новое Vзн-е рез-та. При попытке установить отрицательное значение индекса последний автоматически сбрасывается в 0. В отсутствие Rзн-я, указываемого полученным Vзн-ем, операция прерывается с сохранением исх.Vзн-я со св-вом %X.
2) += и −= выполняются идентично (1) с той лишь разницей, что целочисленное значение атома - рез-та добавляется к индексу Vзн-я операнда и исх. рез-т (целое) сохраняет свое значение.
2.5.3.5. Передача значений
Ранее (п.п.2.2, 2.3 и 2.4) уже расматривалась операция => передачи рез-та предшествующей ей операции приемникам этого результата. Далее - еще операции передачи значений.
1) Операция <− выполняет следующие действия с исх.рез-том:
- в БП (ДРП) по УКА его Rзн-ия помещает копию атома операнда, удаляя оттуда свой атом;
- в его Rзн-ии замещает УКА или УКС аналогичными не равными 0 копиями ссылок Rзн-я операнда;
- указываемое им (Vзн-ем) Rзн-е замещает копией Rзн-я (копии УКА и УКС) операнда.
2) −> - эта операция аналогична (1) и отличается лишь тем, что выполняется не над исх. значением рез-та, а значением операнда - в роли операнда выступает исх.рез-т, не меняющий при этом значения.
Исключение: В случае операнда a-z или Sum без сопровождающих его уточнений (п.2.5.2.1) копия исх.рез-та (атома, ссылок) попросту замещает исх.значение операнда.
3) Операция <> производит обмен значениями исх.рез-та и операнда a - z
Пример: последовательность операций ABC(10,130,"Схема",22.77),−>_Space[SubA]
замещает Rзн-е, указываемое Vзн-ем подпространства с именем SubA на Rзн-е, созданное литералом ABC(...).
2.5.3.6. Измерение и Сравнение значений
Эти операции используют механизм св-в (п.1.2) значений, рассматривая атом "Св-ва" как множество св-в вместе с их отрицаниями (~):
1) & - пересечение множеств св-в рез-та и либо операнда, не являющегося атомом "Св-ва" (%Ap), либо (иначе) множеством св-в, представленных значением операнда - атомом. При этом рез-т - атом вида %Ap заменяет исходный к началу операции. В операции пересечения в каждом из множеств элементом является отдельное св-во вместе с необязательно предшествующим ему кодом '~' его отрицания.
2) | - объединение множеств св-в исх. рез-та и операнда, определяемого аналогично (3). При появлении в результате объединения (множестве) одновременно св-ва, например 'a' и его отрицания '~a' оба удаляются из рез-та операции.
3) Операции &= и |= идентичны (1) и (2), однако их рез-т замещает не исх. его значение, а значение операнда.
4) = - сравнение атомов (%A или %Ra) исх. рез-та и значения операнда (с учетом их уточнений по п.2.5.2.1). В итоге сравнения исх. сохраняемый к концу операции рез-т приобретает дополнительно св-ва:
\ | - один из атомов отсутствует или не совпадают их виды |
= | - значения атомов совпадают |
< | - значение атома рез-та меньше чем у атома операнда |
<= | - значение атома рез-та не больше чем у атома операнда |
> | - значение атома рез-та больше чем у атома операнда |
>= | - значение атома рез-та не меньше чем у атома операнда |
В начале операции перечисленные выше св-ва удаляются.
5) << - В случае вхождения атома (%Aspn или %Raspn) операнда , как подстроки, в атом аналогичного вида исх. рез-та (строка, имя-индекс или св-ва), как строку, рез-т приобретает допонительно св-во 'Y', предварительно (в начале операции) удаляемое.
6) >> - Отличается от (5) лишь тем, что проверяется вхождение атома рез-та, как подстроки, в атом операнда.
7) == - Сравнение УКА Rзн-й или индексов Vзн-й. В итоге среди св-в рез-та появляется или исчезает св-во '%='.
8) ~~ - Аналогично (7) сравнение УКС R- или Vзн-й.
Пример: Abc(11,22,33,44),->b,3,=b%~al%i
Целое 3 здесь сравнивается (операция =) с уточнением структуры b (Abc(...)) - %~al%i до размера слоя этой структуры, равного 4. В итоге рез-т 3 всей последовательности операций приобретает св-во %<. Еще раз обратим внимание на то, что при этом значение переменной b с исх.структурой остается прежним - не меняется при уточнении.
2.5.3.7. Дополнения к операции =>
1) Операцией =>Go прекращается выполнение операций Go и возобновляется следующий их цикл по обработке очередного элемента потока или кортежа (синхрообработки).
2) Операция =>End прекращает выполнение операций раздела Begin или Go и запускает операции раздела End.
3. Примеры описания пользовательских функций
3.1. Генератор потока rise, rise+h,rise+2*h,... в количестве q
For( | Params( | rise:(%~A|~i~f?0), |
q:(%Ai?%~−,~?1), | ||
h:(%Aif?(%0?1),~?1) | ||
), | ||
Ins(Calc: | (Well:0, All:q, Sum:rise, Go:(Sum,=>, h, +=Sum))) | |
) |
1) Введенный пользователем пар-р rise - не атом /~A/ или не числовой /~i~f/ устанавливается в 0 со св-вом %Af. У целочисленного q сбрасывается знак '−', если он есть. Не целочисленное значение принимается равным 1 со св-вом %Ai. Аналогично корректируется пар-р h с тем лишь дополнением, что его 0-е значение заменяется на 1 со св-вом %Af.
2) Вся реализация функции For состоит из единственного входа Calc - генератора потока из 0-ей (Well:0). При этом исх.значение Sum принимается равным значению пар-ра rise (Sum:rise).
3) Получив очередной 0 потока Well Go подает значение Sum на выход функции и затем увеличивает (+=) Sum на h. По исчерпании All циклов Go функция успешно завершается.
3.2. Генератор потока bnd1, bnd1+h,bnd1+2*h,...до bnd2
While( | Params( | bnd1:(%~A|~i~f?0%A), |
bnd2:(%~A|~i~f?0%A), | ||
h:%0?1, | ||
End:(bnd1,=bnd2, %>%−%h, ~?%~−%h) | ||
), | ||
Ins( | Sum:bnd1,Go:(Sum,=>,+h,−>Sum,=bnd2,%>?(h,%~−?%X), %<?(h,%−?%X))) | |
) |
1) В отличие от предыдущего генератора потока здесь в обработке пар-ров вводятся операции End, которые сравнивая по величине bnd1 и bnd2 устанавливают у шага h знак '−', если bnd1>bnd2 и сбрасывают его иначе.
2) Соответственно, усложняется контроль завершения потока: теперь Sum+h сравнивается с bnd2 с учетом знака h. В любом случае прерывание потока и его обработки происходит установкой св-ва %X, обычно устанавливаемого при сбое операции.
3) При наличии единственного входа его имя удалено вместе с ограничивающими описание входа скобками.
3.3. Генерация потока факториалов натуральных чисел
Fact(<n>[,<чет/нечет>]) – в отсутствие <чет/нечет> (пар-р Odd) генерирует ряд
1!, 2!, 3!, 4!, …, n! (1, 3, 6, 24, …).
Признак <чет/нечет> (п.1.2) пропускает на выход функции только, соответственно, факториалы четных или нечетных значений их аргументов n=1,2,…. В любом случае <n> - количество элементов выходного потока функции Fact. Признак <чет/нечет> может быть св-вом %1 (нечет) или %2 (чет) или любым числом с соответствующим св-вом %1 (нечет) или %2 (чет) согласно п.1.2. Отсутствие этих св-в эквивалентно отсутствию второго пар-ра (его неопределенности).
Описание функции:
Fact( | Params(n:(%Ai?%~−,~?0), Odd:(%Ai1|Ai2?%Ap,~?%K)), | |
Ins(Well=_N,Sum:1, Go:(+1,−>a,%~K!Odd?(%Ap,=Odd, %=?(Sum,=>)),a, *=Sum)), | ||
Out:(All:n) | ||
) |
1) У целочисленного пар-р n удаляется знак '−', если, конечно он есть. НЕ целочисленный пар-р сбрасывается в 0.
2) Второй целочисленный пар-р Odd приводится к виду %Ap (св-ва), если, конечно, он таким еще НЕ является, т.е. становится равным своим св-вам. Иначе (не целоочисленный пар-р) он пополняется св-вом %K.
3) Факториалы для каждого очередного номера _N = 0, 1, 2,... очередного генерируемого Sum подсчитываются коррекцией исх. Sum=1 (умножением на a=_N+1) при условии равенства св-в a=_N+1 и Odd - оба четные или нечетные целые.
4) По выдаче n результатов (факториалов) выход (All:n) закрывается, а вместе с ним генератор Well:_N натуральных чисел и завершается функция.
3.4. Генератор V-значений узлов слоя структуры
Описание функции:
Glay( | Params(S:(%V?%R, %~R|~l?%X), q:0, End:%~X!S?(S%~a%i!, −>q)), | |
Ins(Well=For(0,q,1), Go:(−>i; S[i,=>)), | ||
) |
1) Аргумент (пар-р S) функции - структура, задаваемая литералом, _Space, выражением посредством Vзн-я или Rзн-я. По Vзн-ю извлекается (%R) указываемое им Rзн-е. Если это все-таки не Rзн-е или оно лишено слоя, пар-р S приобретает св-во %X, в отсутствие которого пар-р q операциями End Params определяется как размер слоя структуры S.
2) В отличие от п.3.3 здесь вместо встроенного генератора натуральных чисел используется определенная ранее (п.3.1) функция For, работающая параллельно с Go Ins. Единственный вход Ins здесь лишен не только имени, но и скобок. Вид входа определяется наличием Well.
3.5. Вычисление Exp(x) - экспоненты
Вычисляющая Exp(x) подходящая дробь (выражение) из цепной в 5 циклов имеет вид [6,7]:
(1680+840x+180x2+20x3+x4) / (1680−840x+180x2−20x3+x4)
Описание функции:
Exp( | Params(x:%~A|~i~f?%X), | |
Ins( | A:(Well:Stream(1680,840,180,20,1), Go :=>), | |
B:(Well:x, All:5, Sum:1, Go:(%0!_N?1,~?(x,*=Sum,=>))) | ||
), | ||
Synch( | Regs(A,B), Begin:(%GAf0!a,%GAf0!b), | |
Go:(A,*B, +=a, %1!_N?−=b,~?+=b), | ||
End:(a,/b,=>) | ||
) | ||
) |
1) Единственный пар-р x с единственной операцией и потому выделяющие операции скобки отсутствуют (не обязательны). В случае св-ва введенного в вызове функции аргумента - не Атом /%~A/ или отсутствия св-в целого и вещественного /%~i~f/ пар-ру добавляется св-во %X, в отсутствие раздела End пар-ров вызывающее прерывание функции.
2) В разделе Ins определяются два генератора потока, из которых один фактически встроенный A (Stream), а второй B формирует поток степеней пар-ра 'x' из 5-и (All) элементов, начиная со степени 0. В обоих элементы потока операцией => направляются на синхрообработку (Synch).
3) Раздел Begin синхрообработки устанавливает св-ва %G[lobal] и одновременно %Af0 - установку в 0.0 переменных a и b.
4) Раздел Go одновременно подсчитывает суммы числителя и знаменателя подходящей дроби Exp (см.выше), соответственно, в значениях переменных a и b и раздел End вычисляет значение самой дроби - Exp и отправляет (=>) на выход функции.
3.6. Вычисление Sin(X)
Результат - сумма ряда членов ряда, вычисляемых рекуррентными формулами [6,7]:
U1=x, Uk+1= −x2*Uk/(2k*(2k+1)) для k=1,2,...
пока очередной член ряда по абсолютной величине не достигнет заданной погрешности - значения пар-ра ms в следующем описании функции:
Sin( | Params( | x:(%Aif?%f, ~?%X), ms:0.0001, x2:0, End:(x,*x,%−,−>x2)), | ||
Ins( | Well:_N, Sum:x, | |||
Begin:(x,−>u,%G!u), | ||||
Go:(+1,*2,−>k,+1,*=k, x2,*u,/k,−>u,+=Sum,?%~−, =ms, %<?=>End), | ||||
End:(Sum,=>) | ||||
) | ||||
) |
1) Исх. пар-р x - аргумент вводится в вызове Sin(x) функции и контролируется на соответствие св-вам %Aif (можно заменить на %Ai|f или %Ai|Af). Пар-р ms=0.0001, а x2 вычисляется как −x2 в разделе End Params.
2) Единственный вход генерирует (Well:_N) поток 0, 1, 2, ... и потому его имя отсутствует.
3) Пар-р x не допускает использование переменной x. Переменная u хранит очередной член ряда Uk, вычисляемый по рекуррентной формуле. С начала операций Go переменная k получает значение значение 2*(_N+1) и затем 2k*(2k+1) рекуррентной формулы.
4) Значение u (Uk) добавляется к сумме Sum ряда (+=Sum).
5) У значения 'u' (Uk) сбрасывается знак '−' (если он есть) и полученное значение сравнивается (=) с погрешностью ms: если оно меньше ms, то операции Go прекращаются операцией =>End перехода к разделу End, отправляющему Sum на выход функции.
3.7. Вычисление Cos(X)
Те же рекуррентные формулы с заменой (2k+1) на (2k-1). Следовательно в разделе Go выше (п.3.6) достаточно операции 'k,+1' заменить на 'k,-1'.
3.8. Вычисление Tg(x) – тангенса
Здесь с не меньшей чем в п.3.5 точностью достигается результат относительно простой подходящей дробью:
(945 *x − 105*x3 + x5) / (945 − 420*x2 + 15*x4)
Описание функции:
Tg( | Params(x:%~A|~i~f?%X), | |
Ins( | A1:(Well:Stream(945,-105,1), Go: =>sh1), | |
B1:(Well:1, All:3, Sum:x, Go:(Sum,%~0!_N?(*x,*x,−>Sum),=>sh1)), | ||
A2:(Well:Stream(945,−420,15), Go: =>sh2), | ||
B2:(Well:1, All:3, Sum:1, Go:(Sum,%~0!_N?(*x,*x,−>Sum),=>sh2)) | ||
), | ||
Synch( | sh1:(Regs(A1,B1), Sum:0.0, Go:(A1,*B1, +=Sum), End:(Sum,=>)), | |
sh2:(Regs(A2,B2), Sum:0.0, Go:(A2,*B2, +=Sum), End:(Sum,=>)), | ||
Out:(Regs(sh1,sh2), Go:(sh1, /sh2, =>)) | ||
) | ||
) |
Входы A1 и A2 генерируют потоки из коэффициентов, соответственно, числителя и знаменателя подходящей дроби,
а входы B1 и B2 - потоки из 3-х элементов, соответственно с нечетными и четными степенями x. Поскольку x определен как пар-р (Params) то это НЕ переменная, обозначаемая обычно латинской прописной буквой.
Основное отличие здесь от п.3.5 в том, что выход Out также определяется как синхрообработка, что позволяет синхрообработкам sh1 и sh2 в операции => не указывать явно ее имя Out. В синхрообработке же Out операция => означает вывод результата последней операции непосредственно на основной выход описываемой функции.
3.9. Индексирование многоуровневой структуры
Описание функции:
In( | Params(Struct:(%~R?%X), mInd:100, mDeep:9), | |||
Ins( | FUN, All:mDeep, | |||
Begin:(%G!s, Struct,−>s,%~a!s), | ||||
Go:( | −>i,%Ain?(s, %R~l?%l0, i),~?%X, | |||
%i?(%−?%X, =mInd, %>?%X, s%Ai, =i, %<=?(−i, %− +1, +=s), s[i, =>), | ||||
~?(s,[i,%~X? =>,~?(+i,[i, =>)), | ||||
%R,%~a,−>s | ||||
) | ||||
) | ||||
) |
Функция на определенной первым аргументом структуре (Rзн-и) по формируемому вторым аргументом потоку индексов формирует путь - поток (на выходе) Vзн-й соответствующих узлов структуры. При наличии единственного входа имя этого входа вместе с ограничивающими его содержимое (пар-ры и разделы) скобками отсутствует. Начиная с узла - самой структуры и далее для каждого очередного получаемого по единственному входу индекса функция (операции Go входа) выполняет следующие действия:
1) Сохраняет очередной индекс потока в переменной i.
2) В случае целочисленного индекса /%i</b>/ или имени-индекса /%n</b>/ выясняет в очередном узле (переменная s) - Rзн-и (для первого в потоке индекса это исходная структура Struct) наличие слоя и в его отсутствие (%R~l?) создает его пустым (%l0). Иначе - если очередной элемент потока - НЕ индекс, устанавливается св-во %X с прерыванием потока и вычислений.
3) В случае целочисленного индекса (%i?):
- Проверяется наличие у него знака − или превышение им максимально допустимого значения mInd. В обоих случаях поток и его обработка прерываются (завершение функции).
- Размер слоя узла (sA%i) сравнивается (=) с значением индекса i: если оно меньше или равно (%~<) индексу, то увеличенная на 1 разница между ними задает число неопределенных Rзн-й, пополняющих слой в s.
- Vзн-е элемента слоя - s[i отправляется (=>) на выход (поток) функции.
4) В случае индекса-имени - иначе (~?), чем условие (2), сходу делается попытка получить Vзн-е элемента s[i с этим индексом. В отсутствие прерывания этой операции полученное Vзн-е, как и в случае (2) отправляется на выход функции. Иначе слой s пополняется неопределенным Vзн-ем с этим именем-индексом, которое затем аналогично (3) отправляется на выход функции.
Внимание! s[i здесь представлено двумя операциями s, [i с тем, чтобы при прерывании второй из них следующая за ними операция в качестве исх.рез-та получила значение s.
5) В Rзн-и, указываемом полученным (3) или (4) Vзн-ем, удаляется атом (%~a, УКА=0), после чего оно помещается в s.
Используемая литература
- В.Г. Хорошевский. Инженерный анализ функционирования вычислительных машин и систем. М., `Радио и связь`, 1987
- Д.Баррон. Введение в языки программирования, М. `Мир`, 1980
- В.Жиров. Математическое обеспечение и проектирование структур ЭВМ. М. `Наука`, 1979
- К.Фути, Н. Судзуки. Языки программирования и схемотехника СБИС, М. `Мир`,1988
- Г.Джоунз. Программирование на языке ОККАМ. М. `Мир`,1989
- Э.Маделунг. Математический аппарат физики, справочное руководство. `Наука`, 1968, стр.85-87
- Э.Денисова, А.Кучер. Основы вычислительной математики. Санкт-Петербургский университет ИТ, Механики и Оптики, 2010, стр.24-25
Смотрите также
- Метод Янова анализа процессов с обратной связью
- Универсальная Функциональная Потоковая ЭВМ с параллельными вычислениями
- Функциональная Потоковая Машина. Программы, Данные и их обработка
- Функциональная потоковая ЭВМ. Примитвы настройки, микропрограммирование
- Функциональная потоковая ЭВМ. Основные функции, программа
- Функциональная Потоковая ЭВМ. Функции пользователя