Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Язык программирования (и ОС) ФОРТ (FORTH) S023: Массивы


Информационный Канал Subscribe.Ru

S023: Массивы

--------------------------------------------------------------------------------
Массив -- структура данных, состоящая из множества переменных. С помощью массива
описываются величины, получаемые с датчиков, например измерения температуры,
выполненные через фиксированный интервал времени: 
C(++)
float temp[]={ +20.4, +18.6, +10.3, +5.0, +1.2, -0.3, -2.7 };

int undef[12];      // неинициализирвоанный массив из 13 элементов (0..12)

Python
temp = [ +20.4, +18.6, +10.3, +5.0, +1.2, -0.3, -2.7 ]
print temp[3]

Это примеры одномерных массивов, или векторов. 
Каждый элемент вектора адресуется целым неотрицательным числом от 0 до длина_массива-1
-- индексом массива. 

Массив поддерживает операции чтения и записи элемента: 

C(++)
printf("T(3)=%f\n",temp[3]);       // чтение элемента массива
T[5]=+12.6;                        // запись элемента массива

Python
print temp[3]
t[5]=+12.6

Массивы могут быть и многомерными, например распределение температуры по поверхности
(измерения в узлах прямоугольной сетки): 
C(++)
float temp[4][4]={
     { 1, 2, 3, 4 },
     { 1, 2, 4, 4 },
     { 1, 3, 4, 6 },
     { 1, 3, 6, 7 }
};

Python
temp=[
     [ 1, 2, 3, 4 ],
     [ 1, 2, 4, 4 ],
     [ 1, 3, 4, 6 ],
     [ 1, 3, 6, 7 ]
]

Форт
Стандартный Форт не поддерживает массивов, и если вы хотите работать с ними в
Форте, вам будет необходимо расширить язык, определив свои слова для работы с
массивами. 
Прежде всего нужно решить, как вы будете хранить массивы в памяти. Например,
матрицы 4x4 с float элементами размером 32 бита: 

a00 a10 a20 a30
 ...
a03 a13 a23 a33

будем хранить в памяти линейно: 
a00 a10 a20 a30 ... a03 a13 a23 a33

направление увеличения адресов -->

Один floating элемент имеет размер в байтах 
4 CONSTANT FCELL

Для операций с плавающей точкой используем отдельный аппаратный стек сопроцессора
287..487 или модуль FPU процессора Pentium. 
Для загрузки чисел из памяти на стек FPU (F-стек) и обратно используем слова,
определенные на ассемблере: 

F@   (D: addr -- ) (F: -- f )

читает 32-битное float из памяти форт-системы с адреса addr на стек FPU

F!   (D: addr -- ) (F: f -- )

записывает float с вершины стека FPU в память с адреса addr

D: состояние стека данных
F: состояние стека FPU

Компиляция матрицы: 
CREATE filter
S" +0.5" F,    S" +0.5" F,    S" +1.0" F,    S" +1.0" F,
S" +1.0" F,    S" +1.0" F,    S" +1.0" F,    S" +1.0" F,
S" +1.0" F,    S" +1.0" F,    S" +1.0" F,    S" -0.5" F,
S" +1.0" F,    S" +1.0" F,    S" -0.5" F,    S" -0.5" F,

Слово CREATE создаст слово filter, которое при исполнении будет класть в стек
данных адрес элемента a00, который одновременно является адресом всей матрицы.

В Форте желательно придерживаться правила: если объект не умещается в одной ячейке
стека данных, то он размещается в памяти, а для работы с объектом используется
указатель на него -- адрес первого байта объекта. Например это строки по стандарту
FORTH-83 (но не FORTH-94). 

Аналогично вместо адреса памяти можно использовать другой идентификатор, например
номер сектора на диске, если объект полностью умещается (и хранится) в этом секторе.


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

Для чтения/записи элементов матрицы по их координатам нам нужно определить слово


4x4[] ( i j matrix -- addr )

которое будет возвращать адрес элемента aij. Этот адрес мы будем использовать
для чтения элемента на стек FPU словом F@ и записи элемента со стека FPU F!.

4 CONSTANT WIDTH    \ длина одной строки матрицы

: 4x4[] ( i j matrix -- addr )
\ пересчитать координаты i,j элемента матрицы хранящейся в памяти начиная
\ с адреса matrix, в адрес этого элемента
     -ROT      ( matrix i j )
     WIDTH *   ( maxtrix i j*4 )
     +         ( matrix j*4+i )
\ j*4+i -- пересчет 2D координаты (i;j) в 1D индекс
     FCELL *   ( matrix (j*4+i)*4 )
\ (j*4+i)*4 -- преобразуем индекс в смещение элемента aij в байтах
\ относительно начала матрицы
     +         ( addr )
\ прибавляя смещение к адресу матрицы, получаем абсолютный адрес aij
;

Для удобства определим слова 
: 4x4@    ( D: i j matrix -- ) ( F: -- f )
\ чтение элемента aij матрицы matrix сразу на стек FPU
     4x4[] F@
;

: 4x4!    ( D: i j matrix -- ) ( F: f -- )
\ запись aij со стека FPU в матрицу matrix
     4x4[] F!
;

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

Задание
Напишите расширение Форта для работы со строками, не пользуясь строковыми словами
вашей Форт-системы. Варианты хранения строк в памяти: 
счетная строка: первый байт -- длина строки (0..255), остальные байты -- символы
ASCII 
ASCIIZ строка: байты -- символы ASCII, последний байт 0 -- конец строки (формат
хранения строк в стандартном C) 
строка FVM: первый cell -- длина строки (0..65535 для 16-битной FVM), остальные
cellы -- символы unicode 
Если ваша Форт-система поддерживает динамическое распределение памяти (аналог
malloc/realloc/free в С), храните строки в блоках динамической памяти. 

Subscribe.Ru
Поддержка подписчиков
Другие рассылки этой тематики
Другие рассылки этого автора
Подписан адрес:
Код этой рассылки: comp.soft.prog.forth
Отписаться
Вспомнить пароль

В избранное