CLAPACK: undefined reference to

293 views
Skip to first unread message

snnwolf

unread,
Feb 6, 2008, 5:40:16 PM2/6/08
to matrixprogramming_ru
Привет всем.
Потребовалась эта библиока, а именно функция
cgels_(char*, long*, long*, long*, complex*, long*, complex*, long*,
complex*, long*, long*).
Но тянуть ее из кодов не вариант, т.к. тянет за собой много.
Я решил собрать библиотеку. (вся работа идет под линуксом)
Все прошло ок. Когда подключил библиотеку к проекту, то выскакивает
сея ошибка

$ make
g++ -Wl,-rpath,/opt/qt4/lib -o ../bin/vt main.o -L/opt/qt4/lib -L./
lib -lblas -llapack -lF77 -lQtCore -L/opt/qt4/lib -lz -lm -pthread -
lgthread-2.0 -lrt -lglib-2.0 -ldl -lpthread
main.o: In function `main':
main.cpp:(.text+0x322): undefined reference to `cgels_(char*, long*,
long*, long*, complex*, long*, complex*, long*, complex*, long*,
long*)'
collect2: выполнение ld завершилось с кодом возврата 1
make: *** [../bin/vt] Ошибка 1

Хотя компилятор то библиотеку находит (это факт), но получается, что
эта функция не определена, хотя есть в хедерах.
Может кто подскажет куда идти дальше, уже много перерыл, не знаю куда
обращаться.

ипользую
Linux Mops 6.0 с ядром 2.6.22.1

$ qmake -v
QMake version 2.01a
Using Qt version 4.3.1 in /opt/qt4/lib

Спасибо!!!

snnwolf

unread,
Feb 6, 2008, 5:47:01 PM2/6/08
to matrixprogramming_ru
Да.. и еще одно.. сам проект
src.pro
SOURCES += main.cpp
TEMPLATE = app
CONFIG += warn_on \
thread \
qt
TARGET = ../bin/vt
LIBS += -L./lib -lblas -lF77 -llapack
QT -= gui

$ls
Makefile ReadMe blaswrap.h clapack.h f2c.h f2ch.add lib/
main.cpp main.cpp~ main.o src.pro
$ ls lib
libF77.a libI77.a libblas.a liblapack.a

Evgenii Rudnyi

unread,
Feb 7, 2008, 1:57:31 PM2/7/08
to matrixprog...@googlegroups.com
> Все прошло ок. Когда подключил библиотеку к проекту, то выскакивает
> сея ошибка
>
> main.cpp:(.text+0x322): undefined reference to `cgels_(char*, long*,
> long*, long*, complex*, long*, complex*, long*, complex*, long*,
> long*)'

Есть немало причин для появления такой ошибки.

> Хотя компилятор то библиотеку находит (это факт), но получается, что
> эта функция не определена, хотя есть в хедерах.

Заголовочный файл используется при собственно компиляции. Он содержит
просто определение фукнции. Он не связан напрямую с библиотекой, где
находится эта функция. У ваш ошибка идет от linker, который не может
найти эту функцию в библиотеках.

> Может кто подскажет куда идти дальше, уже много перерыл, не знаю куда
> обращаться.

Хорошее начало - это использование программы nm, скажем

nm liblapack.a | grep cgels

Это позволит вам найти ответ на вопрос, есть ли такая фукнция в
библиотеке и как она точно там называется.

Далее, в С++ имена функций при формирования объектного файла меняются
(name mangling). Поэтому имеет смысл с помощью nm проверить, а как
называется функция cgels_ в вашем объектном файле. Если вы компилируете
в С++ и не используете extern "C", то она там называется совсем по
другому. Тогда сборщик может не найти ее в библиотеке, если она даже там
есть под названием cgels_.

Еще пара комментариев.

1) Разумнее всего компилировать LAPACK непосредственно, поскольку
CLAPACK получен с помощью f2c, а это может дать не самую лучшую
производительность.

2) LAPACK зависит от BLAS, поэтому библиотеки должны идти как -llapack
-lblas

3) Для оптимальной производительности рекомендуется использоваться
оптимизированный BLAS, см. например здесь

http://matrixprogramming.com/MatrixMultiply/

snnwolf

unread,
Feb 7, 2008, 5:23:59 PM2/7/08
to matrixprogramming_ru
Спасибо за наводки.
смена последовательности библиотек не помогла к сожалению
Вот некоторые результаты. Что с этим можно сделать???
$ nm liblapack.a |grep cgels
cgels.o:
00000000 T cgels_
cgelsd.o:
00000000 T cgelsd_
cgelss.o:
00000000 T cgelss_
cgelsx.o:
00000000 T cgelsx_
cgelsy.o:
00000000 T cgelsy_

// а это мой объектник
$ nm main.o | grep cge
U _Z6cgels_PcPlS0_S0_P7complexS0_S2_S0_S2_S0_S0_
Что с этим можно сделать

А вот собрал blas и lapack и мой файл проекта выглядит так
SOURCES += main.cpp
TEMPLATE = app
CONFIG += warn_on \
thread \
qt
TARGET = ../bin/vt
LIBS += -L./lib -llapack -lblas
QT -= gui
Но все равно вылетает ошибки вида:
$ make
g++ -Wl,-rpath,/opt/qt4/lib -o ../bin/vt main.o -L/opt/qt4/lib -L./
lib -llapack -lblas -lQtCore -L/opt/qt4/lib -lz -lm -pthread -
lgthread-2.0 -lrt -lglib-2.0 -ldl -lpthread
./lib/liblapack.a(cunmlq.o): In function `cunmlq_':
cunmlq.f:(.text+0x47b): undefined reference to
`_gfortran_concat_string'
cunmlq.f:(.text+0x52e): undefined reference to
`_gfortran_concat_string'
./lib/liblapack.a(cunmqr.o): In function `cunmqr_':
cunmqr.f:(.text+0x404): undefined reference to
`_gfortran_concat_string'
cunmqr.f:(.text+0x4c0): undefined reference to
`_gfortran_concat_string'
./lib/liblapack.a(slamch.o): In function `slamc2_':
slamch.f:(.text+0x790): undefined reference to `_gfortran_pow_r4_i4'
slamch.f:(.text+0x885): undefined reference to `_gfortran_pow_r4_i4'
slamch.f:(.text+0xaaf): undefined reference to `_gfortran_st_write'
slamch.f:(.text+0xabf): undefined reference to
`_gfortran_transfer_integer'
slamch.f:(.text+0xac7): undefined reference to
`_gfortran_st_write_done'
./lib/liblapack.a(slamch.o): In function `slamch_':
slamch.f:(.text+0x131b): undefined reference to `_gfortran_pow_r4_i4'
slamch.f:(.text+0x13dc): undefined reference to `_gfortran_pow_r4_i4'
./lib/liblapack.a(ilaenv.o): In function `ilaenv_':
ilaenv.f:(.text+0x4b): undefined reference to
`_gfortran_compare_string'
ilaenv.f:(.text+0x65): undefined reference to
`_gfortran_compare_string'
ilaenv.f:(.text+0x135): undefined reference to `_gfortran_copy_string'
ilaenv.f:(.text+0x1ec): undefined reference to `_gfortran_copy_string'
ilaenv.f:(.text+0x1fd): undefined reference to `_gfortran_copy_string'
ilaenv.f:(.text+0x211): undefined reference to `_gfortran_copy_string'
ilaenv.f:(.text+0x23a): undefined reference to
`_gfortran_compare_string'
ilaenv.f:(.text+0x254): undefined reference to
`_gfortran_compare_string'
ilaenv.f:(.text+0x26e): undefined reference to
`_gfortran_compare_string'
ilaenv.f:(.text+0x284): undefined reference to
`_gfortran_compare_string'
ilaenv.f:(.text+0x29a): undefined reference to
`_gfortran_compare_string'
./lib/liblapack.a(ilaenv.o):ilaenv.f:(.text+0x2b0): more undefined
references to `_gfortran_compare_string' follow
./lib/liblapack.a(xerbla.o): In function `xerbla_':
xerbla.f:(.text+0x4e): undefined reference to `_gfortran_st_write'
xerbla.f:(.text+0x5d): undefined reference to
`_gfortran_transfer_character'
xerbla.f:(.text+0x6c): undefined reference to
`_gfortran_transfer_integer'
xerbla.f:(.text+0x74): undefined reference to
`_gfortran_st_write_done'
xerbla.f:(.text+0x80): undefined reference to `_gfortran_stop_numeric'

Evgenii Rudnyi

unread,
Feb 8, 2008, 12:36:39 PM2/8/08
to matrixprog...@googlegroups.com
> $ nm liblapack.a |grep cgels
> cgels.o:
> 00000000 T cgels_

Это говорит, что в библиотеке присутствует объект cgels_. Буква T
показывает, что он есть, а не вызывается.

> $ nm main.o | grep cge
> U _Z6cgels_PcPlS0_S0_P7complexS0_S2_S0_S2_S0_S0_

А вот ваш файл вызывает (буква U) совсем другую функцию. Понятно, что
сборщик не находит такой фукнции в библиотеке. Надо сказать, чтобы С++
не менял название функции. Это достигается с помощью

extern "C" {
#include <lapack.h>
}

> g++ -Wl,-rpath,/opt/qt4/lib -o ../bin/vt main.o -L/opt/qt4/lib -L./
> lib -llapack -lblas -lQtCore -L/opt/qt4/lib -lz -lm -pthread -
> lgthread-2.0 -lrt -lglib-2.0 -ldl -lpthread
> ./lib/liblapack.a(cunmlq.o): In function `cunmlq_':
> cunmlq.f:(.text+0x47b): undefined reference to
> `_gfortran_concat_string'

g++ умолчанию не подключает стандартных библиотек Фортрана. Это надо
сделать вручную. Если бы вы использовали g77, то надо было бы добавить
-lg2c. Я не знаю, какие библиотеки использует gfortran. Это можно
посмотреть, если что-то скомпилировать им и задать ключ -v. В этом
случае все компиляторы gcc пишут полные команды, которые они подают. Там
все можно и найти. Также можно найти подходящую библиотеку с помощью nm.
Но проще, наверное, взглянуть на документацию gfortran.

snnwolf

unread,
Feb 9, 2008, 5:20:28 AM2/9/08
to matrixprogramming_ru
Спасибо помогло следующее:
1.
extern "C" {
#include <сlapack.h>
}

2. смена последовательности библиотек
LIBS += -L./lib -llapack -lblas -lF77 -lI77
Компиляция проходит.

Но теперь возникает другая ошибка при работе программы (когда
вызывается cgels_())
complex division by zero

Подскажите, плз. Как можно отследить когда когда именно происходит это
пресловутое деление на ноль?
Может ли это быть по причине выходы за пределы массива?
Спасибо

Evgenii Rudnyi

unread,
Feb 9, 2008, 3:26:43 PM2/9/08
to matrixprog...@googlegroups.com
> Но теперь возникает другая ошибка при работе программы (когда
> вызывается cgels_())
> complex division by zero
>
> Подскажите, плз. Как можно отследить когда когда именно происходит это
> пресловутое деление на ноль?
> Может ли это быть по причине выходы за пределы массива?

Скорее всего вы неправильно вызываете подпрограмму. Это наиболее частая
ошибка.

В LAPACK есть тесты. Может быть начать с них. Скажем для вашей
подрограммы это

http://www.netlib.org/lapack/testing/lin/cdrvls.f

Правда, я не знаю, есть ли это в СLAPACK.

С другой стороны, можно сделать простой пример с небольшими матрицами в
чем угодно, Matlab, Mathematica, SciPy или даже на бумаге. И затем
прогнать его. Чтобы проверить, правильно ли вы вызываете подрограмму,
вставьте в нее распечатку входных параметров.

snnwolf

unread,
Feb 10, 2008, 4:58:45 PM2/10/08
to matrixprogramming_ru
Попробовал на простых матрицах - получилось.
только вот при реальных расчетах не получается

Если интересно, вот исходник
#include <QCoreApplication>

// lapack

#include "f2c.h"
extern "C" {
#include "clapack.h"
}
// standart libraries
#include <math.h>
#include <iostream>

using std::cout;
using std::endl;

int main(/*int argc, char *argv[]*/)
{

integer M = 2, N = 3;
integer nrhs = 1;
integer lwork = 2*M*N;
integer info = 0;
complex* A = new complex [M*N];
complex* y = new complex [N];
complex* work = new complex [2*M*N];

A[0].r = 1; A[0].i = 0; A[1].r = 1; A[1].i = 0; A[2].r = 1; A[2].i =
0;
A[3].r = 1; A[3].i = 0; A[4].r = 1; A[4].i = 0; A[5].r = 1; A[3].i =
0;

y[0].r = 1; y[0].i = 0;
y[1].r = 0; y[1].i = 0;

for(int i = 0; i < N; i++) cout << y[i].r << " " << y[i].i << ";";
cout<<endl;

cgels_("N", &M, &N, &nrhs, A, &M, y, &N, work, &lwork, &info);

for(int i = 0; i < N; i++) cout << y[i].r << " " << y[i].i << ";";
cout<<endl;

delete []A;
delete []y;
delete []work;
return 0;

/*
// кол-во антенн
integer M = 16;
// нарезка по пространству = N_theta+N_alpha
integer N = 0;
// углы по азимуту
double aStart = 30;
double aEnd = 90;
double aStep = 2;

// углы по углу места
double eStart = 30;
double eEnd = 30;
double eStep = 3;

// углы расположения антенн
double* rAngle = new double [M];
for(int i = 0; i<M; i++)
{
rAngle[i] = i * 180./M;
}

integer nAlpha = (integer)ceil((aEnd - aStart) / aStep)+1;
integer nTheta = (integer)ceil((eEnd - eStart) / eStep)+1;

N = nAlpha + nTheta;

double freq = 10.0;

complex* A = new complex [M * nAlpha];
complex* y = new complex [nAlpha];
//complex* X = new complex [N];
for(int i = 0; i < M * nAlpha; i++) {
A[i].r = 0.;
A[i].i = 0.;
}
for(int i = 0; i < nAlpha; i++) {
y[i].r = 0.;
y[i].i = 0.;
}

y[0].r = -12.67677286; y[0].i = 0.00000000;
y[1].r = -13.65607090; y[1].i = 159.61839150;
y[2].r = -14.99760000; y[2].i = -61.99920079;
y[3].r = -15.16788303; y[3].i = -24.67102343;
y[4].r = -15.63444486; y[4].i = 50.78702498;
y[5].r = -14.22976523; y[5].i = -15.48327003;
y[6].r = -12.62596764; y[6].i = 88.83426657;
y[7].r = -13.03345763; y[7].i = -35.62312586;
y[8].r = -14.38472516; y[8].i = -169.00441603;
y[9].r = -15.70115086; y[9].i = 86.11276353;
y[10].r = -17.56768522; y[10].i = -22.49321424;
y[11].r = -18.69531465; y[11].i = -93.27394993;
y[12].r = -23.15060614; y[12].i = 85.57423254;
y[13].r = -23.73687465; y[13].i = 36.50388426;
y[14].r = -21.69560531; y[14].i = 94.64760697;
y[15].r = -16.20436997; y[15].i = -74.03038318;

// радиус-векторы антенн
//double R = new double R[M];
double R = 100; // m

double arg = .0;
double curTheta = 0.;
double curAlpha = 0.;
integer lwork = 2*M*nAlpha;
complex* work = new complex[lwork];
integer info = 0;
integer nrhs = 1;

for(int i = 0; i < lwork; i++) {
work[i].r = 0.;
work[i].i = 0.;
}

for(int t = 0; t < nTheta; t++) {
curTheta = eStart + t * eStep;
cout<<"theta = " << curTheta << endl;
for(int m = 0; m < M; m++) {
for(int j = 0; j < nAlpha; j++) {
//double tmp1 = eStart + j * eStep;
curAlpha = aStart + j * aStep;
arg = cos(curTheta)
* cos(curAlpha - rAngle[m]) * R;
A[j + m].r = -2 * 4*atan(1) * freq/300 * cos(arg);
A[j + m].i = -2 * 4*atan(1) * freq/300 * sin(arg);
if (A[j+m].r == 0 && A[j+m].i == 0)
cout << "alpha = " << curAlpha << ":" << A[j+m].r << ' ' << A[j
+m].i << "; ";
}
cout << endl;
}
cout<< endl;
// расчет
cout << "COUNTING"<<endl;
for(int dd = 0; dd < nAlpha; dd++)
cout << dd << ":" << y[dd].r << " " << y[dd].i << "; ";
cout << endl << endl;
//cgels_("N", &M, &nAlpha, &nrhs, A, &M, y, &nAlpha, work, &lwork,
&info);
}
//for (int i = 0; i < N; i++) cout << y[i].r << "," << y[i].i << ";
";
//cout << endl;

//cgels_("N", &M, &N, &nrhs, A, &M, y, &N, work, &lwork, &info);

//for (int i = 0; i < N; i++) cout << y[i].r << " " << y[i].i << ";";
//cout << endl;

delete []y;
delete []A;
delete []rAngle;
//delete []X;
delete []work;
return 0;
*/

snnwolf

unread,
Feb 10, 2008, 4:59:38 PM2/10/08
to matrixprogramming_ru
Аналогичная функция в clapack есть http://www.netlib.org/lapack/testing/lin/cdrvls.f
Только что ней делать? Не совсем понятно для меня

Evgenii Rudnyi

unread,
Feb 11, 2008, 3:44:59 PM2/11/08
to matrixprog...@googlegroups.com
> Попробовал на простых матрицах - получилось.
> только вот при реальных расчетах не получается

Сложно сказать. Я бы ожидал, что в LAPACK есть проверки, чтобы исключить
деление на нуль, но чего только не бывает. Я сам не работал с этой
подпрограммой.

Проверьте еще раз и попробуйте обратиться в поддержку

http://www.netlib.org/lapack/support.html

Но там как раз рекомендуют вначале запустить тесты LAPACK.

>Аналогичная функция в clapack есть
>http://www.netlib.org/lapack/testing/lin/cdrvls.f
>Только что ней делать? Не совсем понятно для меня

Это часть тестов LAPACK. Там при компиляции можно указать, чтобы
скомпилировать и прогнать все тесты. Я как-то раз это делал, но только
для версии double.

Недавно мне потребовалось решение системы линейных уравнений с
комплексной матрицей. У меня zgesv работает.

Evgenii Rudnyi

unread,
Feb 12, 2008, 3:52:09 PM2/12/08
to matrixprog...@googlegroups.com
Я только сейчас поглядел на документацию cgels. Мне кажется, что
использование SVD будет более надежным - посмотрите, может быть вам
лучше подойдет cgelss или cgelsd

http://www.netlib.org/lapack/lug/node27.html

Если вы запишите вашу матрицу и вектор, с котороми происходит деление на
нуль, в текстовой файл, то я мог бы попробовать решить эту задачу в
SciPy - там есть LAPACK интерфейс. Правда я боюсь, что смогу сделать это
только в конце следующей недели.

snnwolf

unread,
Feb 17, 2008, 1:52:53 PM2/17/08
to matrixprogramming_ru
Спасибо за помощь.
Проблема была в том, что не делал смещение на количество строк в
матрице (А - одномерный массив для лапака)
В результате получалась матрица с частично заполненными элементами.
Reply all
Reply to author
Forward
0 new messages