Написание пользовательской функции к MathCAD и двумерные массивы
От: zzealot Украина  
Дата: 26.07.12 08:03
Оценка:
Здравствуйте.
Пишу пользовательскую функцию к Маткад. Делается это через DLL. Интерфейс (ИМХО) реализован довольно коряво. Например, программисту доступны только два типа — COMPLEXSCALAR & COMPLEXARRAY. Есть еще строковый тип данных. А вот обычных вещественных и целочисленных не предусмотрено. Вот как это выглядит в заголовочном файле Маткада:


// complex scalar type
typedef struct tagCOMPLEXSCALAR {
    double real;
    double imag;
} COMPLEXSCALAR;

// complex array type
typedef struct tagCOMPLEXARRAY  {
    unsigned int rows;
    unsigned int cols;
    double **hReal; // hReal[cols][rows],  == NULL when the real part is zero 
    double **hImag; // hImag[cols][rows],  == NULL when the imaginary part is zero
} COMPLEXARRAY;



Вот как выглядит пользовательский модуль (данная функция меняет местами столбцы и строки) X — исходные данные , Y — результат:

LRESULT transposeFunction( LPCOMPLEXARRAY      Y,   LPCCOMPLEXARRAY     X   )
    {
        unsigned int i, j, k4;
        
        // allocate space for the return array Y
        if ( !MathcadArrayAllocate( Y,  // allocate space for Y 
                    X->cols,    //  with X cols
                    X->rows,    //  and X rows
                    X->hReal != NULL,   //  allocate the real part if X has a real part 
                    X->hImag != NULL    //  allocate the imaginary part if X has 
                                //  an imaginary part
                    ) ) 
            return 2;           // if allocation is insufficient
                                // return the error code        
        
        for ( i = 0; i < Y->cols; i++ )
        {
            if ( isUserInterrupted( ) ) 
            {
                MathcadArrayFree( Y );
                return  3;      // user interrupted
            }            
            for ( j = 0; j < Y->rows; j++ )     
            {                
                if ( X->hReal != NULL )     
                    Y->hReal[i][j] = X->hReal[j][i];
                if ( X->hImag != NULL )     
                    Y->hImag[i][j] = X->hImag[j][i]; 
            }
        }                       
        return 0;               // return 0 to indicate there was no error            
    }


Из текста видно, что программист вынужден каждый раз явно указывать мнимую и действительную части элемента массива, что в случае сложного алгоритма начинает сильно мешать. Я хотел было сделать промежуточный интерфейс, позволяющий работать только с действительной частью.
Однако заметил, что в объявлении типа не указываются размеры массива, а просто :
double **hReal;
Отсюда вопрос — а как же компилятор генерирует код, например такой:
Y->hReal[i][j] = 555;
ведь для этого как минимум надо знать величину второй размерности, т.е. Y->hReal[i][10]

PS: Маткад это знает, поскольку в структуре COMPLEXARRAY есть размеры матрицы, он передает это функции во время выполнения.
Функция работает корректно. Пробовал другие фукнции, в которых разное число столбцов и строк — тоже все нормально.
Почитал Страуструпа — он пишет, что для адресации надо обязательно знать хотя бы второй размер, и предлагает такое решение (неудобно):
void print_mij (int* m, int dim1, int dim2)
{
  for (int i=0; i<dim1; i++) {
    for ( int j=0; j<dim2; j++)
       cout << m(i*dim2+j) << '\t';
    cout << '\n';
  }
}
mathcad c++ array
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.