Текст подпрограммы и версий
ams1r_c.zip , ams1c_c.zip
Тексты тестовых примеров
tams1r_c.zip , tams1c_c.zip

Подпрограмма:  ams1r_c

Назначение

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

Математическое описание

1. Задана теплицева матрица А размерности N*N:

                   | a0      a-1    a-2    ...  a-(N-2)   a-(N-1)  |
                   | a1      a0     a-1    ...  a-(N-3)   a-(N-2)  |
                   | a2      a1      a0    ...  a-(N-4)   a-(N-3)  |
(1)              | . . . . . . . . . . . . . . . . . . . . . . . . . . . .           ,
                   | aN-2  aN-3  aN-4  ...  a0         a-1        |
                   | aN-1  aN-2  aN-3  ...  a1         a0         |

которая определяется 2n - 1 элементами первой строки и первого столбца:

         a -(N-1), a -(N-2), ... , a -2, a -1, a0, a1, a2, ... , aN-2, aN-1 ; 

все элементы этой матрицы на любой ее диагонали, параллельной главной, равны между собой. Требуется вычислить вектор y = Ax = (y0, y1,..., yN - 1) , где вектор  x = (x0, x1,..., xN - 1) также задан.
Эта задача эквивалентна вычислению (вообще говоря) непериодической свертки двух последовательностей  as,  x j,  s = - (N - 1), ..., - 1, 0, 1, ..., N - 1,   j = 0, 1,..., N - 1 разной длины 2N - 1 и N соответственно [1], т.е.

                            N-1 
            ys      =      ∑     as -j x j  ,     s = 0, 1, ... , N-1 ,
                             j=0 

Дополним теплицеву матрицу А порядка N до циркулянтной матрицы А0 порядка М, которая определяется М элементами своего первого столбца:

         a -(N-1), a -(N-2), ... , a -1, a0, a1, ... , aN-1, 0, 0, ... , 0 , 

где М - наименьшая целая степень числа два, удовлетворяющая условию М ≥ 2N - 1, а число нулей K равно разности: К = М - (2N - 1) ≥  0.

Далее определим вектор  x0 длины М, получаемый из заданного вектора  x добавлением К + N - 1 нулей: x0 = (x0, x1,..., xN - 1, 0, 0,..., 0). Тогда исходная задача сводится к задаче умножения циркулянтной матрицы А0 на вектор  x0, которая решается в подпрограмме amc1r_c на основе алгоритма Быстрого Преобразования Фурье [2], при этом N компонент вычисленного вектора y0 = А0 x0 = (y00, y10,..., y0M - 1) будут совпадать с искомым вектором  y, а именно:  y0N - 1 + s = ys ,  s = 0, 1, ..., N - 1.

Аналогичный метод умножения теплицевой матрицы на вектор изложен в работе [3].

Реализованный в подпрограмме алгоритм требует памяти ЭВМ не менее 4N и не более 8N (из которых 3N занимает исходная информация). Время вычислений пропорционально М log2 М, т.е. по порядку не превосходит 4N (2 + log2N).

2. Пусть А - ханкелева матрица вида

               | a0         a1        a2     ...  aN-2    aN-1  |
               | a1         a2        a3     ...  aN-1    aN     |
               | a2         a3        a4     ...  aN       aN+1 |
(1)          | . . . . . . . . . . . . . . . . . . . . . . . . . . .                   ,
               | aN-2      aN-1    aN     ... a2N-4   a2N-3 |
               | aN-1      aN       aN+1 ... a2N-3   a2N-2 |

которая определяется 2N - 1 элементами первой строки и последнего столбца:

         a0, a1, ... , aN-1, aN, ... , a2N-3, a2N-2 ; 

все элементы этой матрицы на любой ее диагонали, параллельной побочной, равны между собой. В данном случае задача вычисления вектора y = Ax = (y0, y1,..., yN - 1) эквивалентна вычислению взаимной корреляции двух последовательностей  as,  xj,  s = 0, 1,..., 2N - 2,  j = 0, 1,..., N - 1 длины 2N - 1 и N соответственно [1], т.е.

                            N-1 
            ys      =      ∑     as+j x j ,    s = 0, 1, ... , N-1 ,
                             j=0 

в частности, при  xj = aj,  j = 0, 1,..., N - 1 вектор  y = Аx определяет автокорреляцию последовательности  as,  s = 0, 1, ..., 2N - 2.

Легко видеть, что ханкелева матрица А переходит в теплицеву T путем умножения слева на матрицу перестановок U вида

                               |                   1 |
                               |                1    |
                               |             .        |
                     U =    |          .           |    =   U -1 ,
                               |       .              |
                               |    1                |
                               | 1                   | 

т.е. Т = UА. Поэтому для получения вектора  y = Аx сначала вычисляется вектор Tx (по описанному выше алгоритму) и затем делается соответствующая перестановка его компонент, а именно:  y = U(Тx).

1.  Б.Голд, Ч.Pейдер. Цифровая обработка сигналов. М., "Советское радио", 1973.
2.  В.А.Морозов, Н.Н.Кирсанова, А.Ф.Сысоев. Комплекс алгоритмов быстрого преобразования Фурье дискретных рядов, сб. "Численный анализ на ФОPТPАНе", вып.15, Изд - во МГУ, М., 1976.
3.  В.В.Бадаева, В.А.Морозов. Алгоритмы быстрого и ускоренного решения некоторых специальных систем линейных алгебраических уравнений, Сб. "Численный анализ на ФОPТPАНе", вып.20, Изд - во МГУ, М., 1977.

Использование

    int ams1r_c (integer *n, integer *m, real *q, real *b, real *x)

Параметры

n - размерность исходной матрицы A, n ≥ 2 (тип: целый);
m - минимальная целая степень числа два, удовлетворяющая условию m ≥ 2n - 1 (тип: целый);
q - управляющий параметр (тип: вещественный):
q= 0. - если исходная матрица A теплицева,
q= 1. - если исходная матрица A ханкелева;
b - вещественный одномерный массив длины m, в первых 2n - 1 элементах которого содержатся заданные определяющие элементы теплицевой матрицы A: a- (n - 1),  a- (n - 2),..., a- 1, a0, a1, ..., an - 1 или ханкелевой матрицы A: a0, a1, ..., an - 1, an, ..., a2n - 3, a2n - 2;
x - вещественный одномерный массив длины m, в первых n элементах которого содержатся заданные компоненты вектора x = (x0, x1,..., xn - 1) на входе и вычисленные компоненты вектора y = (y0, y1,..., yn - 1), на выходе.

Версии

ams1c_c - вычисление произведения комплексной теплицевой или ханкелевой матрицы A на комплексный вектор  x. Для подпрограммы ams1c_c параметры b, x имеют тип complex.

Вызываемые подпрограммы

 amc1r_c -
 amc1c_c  
подпрограммы умножения вещественной циркулянтной матрицы на вещественный вектор и компексной циркулянтной матрицы на комплексный вектор на основе алгоритма Быстрого Преобразования Фурье (используются в ams1r_c и ams1c_c соответственно).

Замечания по использованию

  1. 

После выхода из подпрограмм ams1r_c и ams1c_c значения определяющих элементов исходной матрицы A в массиве b не сохраняются.

  2. 

Если матрица A циркулянтная (частный случай теплицевой),то целесообразно вместо подпрограмм ams1r_c, ams1c_c воспользоваться соответствующими подпрограммами amc1r_c и amc1c_c.

  3. 

Если теплицева матрица A имеет вид

          | a0         a1        a2         ...   aN-1  |
          | a-1        a0        a1         ...   aN-2  |
          | a-2        a-1       a0         ...   aN-3  |
          | . . . . . . . . . . . . . . . . . . . . . . . . .
          | a-(N-1)   a-(N-2)  a-(N-3)  ...  a0     | 
и задается 2N - 1 элементами первого столбца и первой строки:  a- (N - 1), a- 1, a0, a1, a2,..., aN - 1; то до обращения к подпрограммам ams1r_c, ams1c_c эти элементы следует упорядочить в массиве b по убыванию индексов:  aN - 1, ..., a1, a0, a- 1, a- 2, ..., a- (N - 1);

Пример использования

  
1.
int main(void)
{
    /* Initialized data */
    static float b[16] = { 1.f,2.f,3.f,4.f,5.f,6.f,7.f,8.f,9.f,10.f,11.f,0.f,
                           0.f,0.f,0.f,0.f };
    static float x[16] = { 1.f,-1.f,-2.f,0.f,1.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,
                           0.f,0.f,0.f,0.f };

    /* Local variables */
    extern int ams1r_c(int *, int *, float *, float *, float *);
    static int i__, m, n;
    static float q;

    n = 6;
    m = 16;
    q = 1.f;
    ams1r_c(&n, &m, &q, b, x);

    for (i__ = 1; i__ <= 6; ++i__) {
         printf("\n  %16.7e \n", x[i__ - 1]);
    }
/* L1: */
    return 0;
} /* main */


Результат:     y  =  ( -2., -3., -4., -5., -6., -7. )

2.
int main(void)
{
    /* Initialized data */
    static complex b[8] = { {4.f,-1.f},{3.f,2.f},{2.f,0.f},{1.f,1.f},
                            {-1.f,0.f},{0.f,-1.f},{2.f,1.f},{0.f,0.f} };
    static complex x[8] = { {1.f,-1.f},{-1.f,0.f},{-2.f,1.f},{3.f,-2.f},
                            {0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f} };

    /* Local variables */
    extern int ams1c_c(int *, int *, float *, complex *, complex *);
    static int i__, m, n;
    static float q;

    n = 4;
    m = 8;
    q = 0.f;
    ams1c_c(&n, &m, &q, b, x);

    for (i__ = 1; i__ <= 4; ++i__) {
         printf("\n  %20.12e %20.12e \n", x[i__ - 1].r, x[i__ - 1].i);
    }
/* L1: */
    return 0;
} /* main */

Результат:     y  =  ( (2., -12.), (7., 2.), (3., -6.), (10., 0.) )