Degun
Участник-
Постов
84 -
Зарегистрирован
-
Посещение
Репутация
0 ОбычныйИнформация о Degun
-
Звание
Частый гость
Контакты
-
Сайт
Array
Информация
-
Город
Array
-
Ошибка STL в Code Composer Studio
Degun ответил Degun тема в Алгоритмы ЦОС (DSP)
С typedef-ом следующая история. Если сделать так: template <typename DataT> class TTreeObj { private: TTreeObj<DataT>* parent; list<TTreeObj<DataT>*> *childs; public: TTreeObj(DataT d=0, TTreeObj<DataT>* p=NULL) : info(d), parent(p), childs(NULL) {} DataT info; ..... }; typedef TTreeObj<DataT> TreeObjRefT; template <typename DataT> TTreeObj<DataT>* TTreeObj<DataT>::operator[](int Index) { ...... list<TreeObjRefT*>::iterator iterator_begin=childs->begin(); ..... return *iterator_begin; } то выводит такое сообщение об ошибке: "ap_common.h", line 817: error: identifier "DataT" is undefined Если сделать так: template <typename DataT> class TTreeObj { private: TTreeObj<DataT>* parent; list<TTreeObj<DataT>*> *childs; public: TTreeObj(DataT d=0, TTreeObj<DataT>* p=NULL) : info(d), parent(p), childs(NULL) {} DataT info; ..... typedef TTreeObj<DataT> TreeObjRefT; }; template <typename DataT> TTreeObj<DataT>* TTreeObj<DataT>::operator[](int Index) { ...... list<TreeObjRefT*>::iterator iterator_begin=childs->begin(); ..... return *iterator_begin; } то выводит такое сообщение об ошибке: "ap_common.h", line 827: error: identifier "iterator_begin" is undefined Как правильно нужно сделать? -
Ошибка STL в Code Composer Studio
Degun опубликовал тема в Алгоритмы ЦОС (DSP)
Для следующей строки, использующей контейнер list из STL и шаблоны, list< TTreeObj<DataT>* >::iterator iterator_begin=childs->begin(); в Code Composer Studio выдаётся такое сообщение об ошибке: "ap_common.h", line 851: error: expected a ";" Т. е. компилятору не нравится конструкция list< TTreeObj<DataT>* > Таже самая строка в Microsoft Visual Studio 2008 компилируется без проблем. Как это исправить? -
Я думаю здесь все в курсе того, что формат с фиксированной запятой является всего лишь приближенным представлением действительного числа. Подробнее об этом можно прочитать, например, по ссылке ниже: http://matlab.exponenta.ru/fixedpoint/book1/1.php
-
Да, т. е. для хранения целой и дробной частей числа отводятся разные биты одной и той же переменной длиной 64 бит.
-
А вы посмотрите по ссылкам: там плавающее число хранится в одной целочисленной переменной и запятая смещена относительно начала регистра на определённое кол-во бит.
-
Сейчас как раз думаю над этим вариантом. Возникает вопрос о его целесообразности, т. к. есть более простые и быстрые, но, соответственно, менее точные варианты реализации плавающей арифметики: http://www.koders.com/cpp/fid5E90955711BFB...1C652C383C.aspx http://electronix.ru/forum/index.php?showt...45865&st=26 Вообще же эти варианты работают значительно быстрее, чем эмуляция плавающей арифметики через компилятор. Для предлагаемого вами варианта необходима будет операция по суммированию двух чисел с учётом флага переноса, которой в C++ нет.
-
Операции с плавающей точкой без FPU
Degun ответил sigmaN тема в Алгоритмы ЦОС (DSP)
Как-то это некрасиво - лучше пойти другим путём. Я сделал класс на основе представления плавающего числа типа double в виде целочисленного типа long long (на основе класса fastfloat по ссылке http://www.koders.com/cpp/fid5E90955711BFB...1C652C383C.aspx). Такой подход предоставляет полный эквивалент числа с плавающей запятой без использования последнего. Моя тестовая функция билинейного масштабирования при этом сразу стала выполняться в полтора раза быстрее. И это при том, что я её ещё не оптимизировал насчёт применения DMA (тогда бы улучшение производительности было бы гораздо заметнее). Так что предлагаю к использованию (охотно принимаются замечания по улучшению производительности этого класса или замеченные ошибки). /*!\file fastfloat.h * \brief This class stores floating point numbers as integers, * \brief with BITS shift, i.e. value XYZ is stored as XYZ * RATIO * \version 1.0 * \date 25 april 2008 */ #ifndef __FAST_FLOAT_H #define __FAST_FLOAT_H class fastdouble { private: enum { BITS = 16, RATIO = 65536 }; long long value; inline fastdouble( long v, bool ) : value( v ) {} // for operator-() public: inline fastdouble() { value=0; } inline fastdouble( double v ) { value=static_cast<long long>(v * RATIO + 0.5); } inline fastdouble( float v ) { value=static_cast<long long>(v * RATIO + 0.5); } inline fastdouble( char v ) { value=static_cast<long long>(v) << BITS; } inline fastdouble( short v ) { value=static_cast<long long>(v) << BITS; } inline fastdouble( int v ) { value=static_cast<long long>(v) << BITS; } inline fastdouble( long v ) { value=static_cast<long long>(v) << BITS; } inline fastdouble( unsigned char v ) { value=static_cast<long long>(v) << BITS; } inline fastdouble( unsigned short v ) { value=static_cast<long long>(v) << BITS; } inline fastdouble( unsigned int v ) { value=static_cast<long long>(v) << BITS; } inline fastdouble( unsigned long v ) { value=static_cast<long long>(v) << BITS; } inline void operator =( fastdouble r ) { value=r.value; } inline void operator =( double v ) { value=static_cast<long long>(v * RATIO + 0.5); } inline void operator =( float v ) { value=static_cast<long long>(v * RATIO + 0.5); } inline void operator =( char v ) { value=static_cast<long long>(v) << BITS; } inline void operator =( short v ) { value=static_cast<long long>(v) << BITS; } inline void operator =( int v ) { value=static_cast<long long>(v) << BITS; } inline void operator =( long v ) { value=static_cast<long long>(v) << BITS; } inline void operator =( unsigned char v ) { value=static_cast<long long>(v) << BITS; } inline void operator =( unsigned short v ) { value=static_cast<long long>(v) << BITS; } inline void operator =( unsigned int v ) { value=static_cast<long long>(v) << BITS; } inline void operator =( unsigned long v ) { value=static_cast<long long>(v) << BITS; } inline double toDouble() const { return static_cast<double>( value ) / RATIO; } inline long toLong() const { return static_cast<long>(value >> BITS); } inline operator double() const { return toDouble(); } inline operator float() const { return (float)toDouble(); } inline operator char() const { return (char)toLong(); } inline operator short() const { return (short)toLong(); } inline operator int() const { return (int)toLong(); } inline operator long() const { return toLong(); } inline operator unsigned char() const { return (unsigned char)toLong(); } inline operator unsigned short() const { return (unsigned short)toLong(); } inline operator unsigned int() const { return (unsigned int)toLong(); } inline operator unsigned long() const { return (unsigned long)toLong(); } inline fastdouble operator - () const { return fastdouble( -value, false ); } inline fastdouble& operator += ( fastdouble r ) { value += r.value; return *this; } inline fastdouble& operator -= ( fastdouble r ) { value -= r.value; return *this; } inline fastdouble& operator *= ( fastdouble r ) { value = ( value * r.value ) >> BITS; return *this; } inline fastdouble& operator /= ( fastdouble r ) { value = ( value << BITS ) / r.value; return *this; } inline fastdouble& operator += ( double v ) { value += static_cast<long long>( v * RATIO + 0.5 ); return *this; } inline fastdouble& operator -= ( double v ) { value -= static_cast<long long>( v * RATIO + 0.5 ); return *this; } inline fastdouble& operator *= ( double v ) { value = static_cast<long long >( value * v + 0.5 ); return *this; } inline fastdouble& operator /= ( double v ) { value = static_cast<long long>( value / v + 0.5 ); return *this; } inline fastdouble& operator += ( float v ) { value += static_cast<long long>( v * RATIO + 0.5 ); return *this; } inline fastdouble& operator -= ( float v ) { value -= static_cast<long long>( v * RATIO + 0.5 ); return *this; } inline fastdouble& operator *= ( float v ) { value = static_cast<long long>( value * v + 0.5 ); return *this; } inline fastdouble& operator /= ( float v ) { value = static_cast<long long>( value / v + 0.5 ); return *this; } inline fastdouble& operator += ( char v ) { value += static_cast<long long>( v ) << BITS; return *this; } inline fastdouble& operator -= ( char v ) { value -= static_cast<long long>( v ) << BITS; return *this; } inline fastdouble& operator *= ( char v ) { value *= v; return *this; } inline fastdouble& operator /= ( char v ) { value /= v; return *this; } inline fastdouble& operator += ( short v ) { value += static_cast<long long>( v ) << BITS; return *this; } inline fastdouble& operator -= ( short v ) { value -= static_cast<long long>( v ) << BITS; return *this; } inline fastdouble& operator *= ( short v ) { value *= v; return *this; } inline fastdouble& operator /= ( short v ) { value /= v; return *this; } inline fastdouble& operator += ( int v ) { value += static_cast<long long>( v ) << BITS; return *this; } inline fastdouble& operator -= ( int v ) { value -= static_cast<long long>( v ) << BITS; return *this; } inline fastdouble& operator *= ( int v ) { value *= v; return *this; } inline fastdouble& operator /= ( int v ) { value /= v; return *this; } inline fastdouble& operator += ( long v ) { value += static_cast<long long>( v ) << BITS; return *this; } inline fastdouble& operator -= ( long v ) { value -= static_cast<long long>( v ) << BITS; return *this; } inline fastdouble& operator *= ( long v ) { value *= v; return *this; } inline fastdouble& operator /= ( long v ) { value /= v; return *this; } inline fastdouble& operator += ( unsigned char v ) { value += static_cast<long long>( v ) << BITS; return *this; } inline fastdouble& operator -= ( unsigned char v ) { value -= static_cast<long long>( v ) << BITS; return *this; } inline fastdouble& operator *= ( unsigned char v ) { value *= v; return *this; } inline fastdouble& operator /= ( unsigned char v ) { value /= v; return *this; } inline fastdouble& operator += ( unsigned short v ) { value += static_cast<long long>( v ) << BITS; return *this; } inline fastdouble& operator -= ( unsigned short v ) { value -= static_cast<long long>( v ) << BITS; return *this; } inline fastdouble& operator *= ( unsigned short v ) { value *= v; return *this; } inline fastdouble& operator /= ( unsigned short v ) { value /= v; return *this; } inline fastdouble& operator += ( unsigned int v ) { value += static_cast<long long>( v ) << BITS; return *this; } inline fastdouble& operator -= ( unsigned int v ) { value -= static_cast<long long>( v ) << BITS; return *this; } inline fastdouble& operator *= ( unsigned int v ) { value *= v; return *this; } inline fastdouble& operator /= ( unsigned int v ) { value /= v; return *this; } inline fastdouble& operator += ( unsigned long v ) { value += static_cast<long long>( v ) << BITS; return *this; } inline fastdouble& operator -= ( unsigned long v ) { value -= static_cast<long long>( v ) << BITS; return *this; } inline fastdouble& operator *= ( unsigned long v ) { value *= v; return *this; } inline fastdouble& operator /= ( unsigned long v ) { value /= v; return *this; } //Для типа fastdouble inline bool operator < ( fastdouble r ) const { return value < r.value; } inline bool operator <= ( fastdouble r ) const { return value <= r.value; } inline bool operator > ( fastdouble r ) const { return value > r.value; } inline bool operator >= ( fastdouble r ) const { return value >= r.value; } inline bool operator == ( fastdouble r ) const { return value == r.value; } inline bool operator != ( fastdouble r ) const { return value != r.value; } }; //Для типа fastdouble inline fastdouble operator+ ( fastdouble l, fastdouble r ) { return fastdouble( l ) += r; } inline fastdouble operator- ( fastdouble l, fastdouble r ) { return fastdouble( l ) -= r; } inline fastdouble operator* ( fastdouble l, fastdouble r ) { return fastdouble( l ) *= r; } inline fastdouble operator/ ( fastdouble l, fastdouble r ) { return fastdouble( l ) /= r; } //Для типа double inline fastdouble operator + ( double l, fastdouble r ) { return fastdouble( l ) += r; } inline fastdouble operator - ( double l, fastdouble r ) { return fastdouble( l ) -= r; } inline fastdouble operator * ( double l, fastdouble r ) { return fastdouble( l ) *= r; } inline fastdouble operator / ( double l, fastdouble r ) { return fastdouble( l ) /= r; } inline fastdouble operator + ( fastdouble l, double r ) { return fastdouble( l ) += r; } inline fastdouble operator - ( fastdouble l, double r ) { return fastdouble( l ) -= r; } inline fastdouble operator * ( fastdouble l, double r ) { return fastdouble( l ) *= r; } inline fastdouble operator / ( fastdouble l, double r ) { return fastdouble( l ) /= r; } //Для типа float inline fastdouble operator + ( float l, fastdouble r ) { return fastdouble( l ) += r; } inline fastdouble operator - ( float l, fastdouble r ) { return fastdouble( l ) -= r; } inline fastdouble operator * ( float l, fastdouble r ) { return fastdouble( l ) *= r; } inline fastdouble operator / ( float l, fastdouble r ) { return fastdouble( l ) /= r; } inline fastdouble operator + ( fastdouble l, float r ) { return fastdouble( l ) += r; } inline fastdouble operator - ( fastdouble l, float r ) { return fastdouble( l ) -= r; } inline fastdouble operator * ( fastdouble l, float r ) { return fastdouble( l ) *= r; } inline fastdouble operator / ( fastdouble l, float r ) { return fastdouble( l ) /= r; } //Для типа char inline fastdouble operator + ( char l, fastdouble r ) { return fastdouble( l ) += r; } inline fastdouble operator - ( char l, fastdouble r ) { return fastdouble( l ) -= r; } inline fastdouble operator * ( char l, fastdouble r ) { return fastdouble( l ) *= r; } inline fastdouble operator / ( char l, fastdouble r ) { return fastdouble( l ) /= r; } inline fastdouble operator + ( fastdouble l, char r ) { return fastdouble( l ) += r; } inline fastdouble operator - ( fastdouble l, char r ) { return fastdouble( l ) -= r; } inline fastdouble operator * ( fastdouble l, char r ) { return fastdouble( l ) *= r; } inline fastdouble operator / ( fastdouble l, char r ) { return fastdouble( l ) /= r; } //Для типа short inline fastdouble operator + ( short l, fastdouble r ) { return fastdouble( l ) += r; } inline fastdouble operator - ( short l, fastdouble r ) { return fastdouble( l ) -= r; } inline fastdouble operator * ( short l, fastdouble r ) { return fastdouble( l ) *= r; } inline fastdouble operator / ( short l, fastdouble r ) { return fastdouble( l ) /= r; } inline fastdouble operator + ( fastdouble l, short r ) { return fastdouble( l ) += r; } inline fastdouble operator - ( fastdouble l, short r ) { return fastdouble( l ) -= r; } inline fastdouble operator * ( fastdouble l, short r ) { return fastdouble( l ) *= r; } inline fastdouble operator / ( fastdouble l, short r ) { return fastdouble( l ) /= r; } //Для типа int inline fastdouble operator + ( int l, fastdouble r ) { return fastdouble( l ) += r; } inline fastdouble operator - ( int l, fastdouble r ) { return fastdouble( l ) -= r; } inline fastdouble operator * ( int l, fastdouble r ) { return fastdouble( l ) *= r; } inline fastdouble operator / ( int l, fastdouble r ) { return fastdouble( l ) /= r; } inline fastdouble operator + ( fastdouble l, int r ) { return fastdouble( l ) += r; } inline fastdouble operator - ( fastdouble l, int r ) { return fastdouble( l ) -= r; } inline fastdouble operator * ( fastdouble l, int r ) { return fastdouble( l ) *= r; } inline fastdouble operator / ( fastdouble l, int r ) { return fastdouble( l ) /= r; } //Для типа long inline fastdouble operator + ( long l, fastdouble r ) { return fastdouble( l ) += r; } inline fastdouble operator - ( long l, fastdouble r ) { return fastdouble( l ) -= r; } inline fastdouble operator * ( long l, fastdouble r ) { return fastdouble( l ) *= r; } inline fastdouble operator / ( long l, fastdouble r ) { return fastdouble( l ) /= r; } inline fastdouble operator + ( fastdouble l, long r ) { return fastdouble( l ) += r; } inline fastdouble operator - ( fastdouble l, long r ) { return fastdouble( l ) -= r; } inline fastdouble operator * ( fastdouble l, long r ) { return fastdouble( l ) *= r; } inline fastdouble operator / ( fastdouble l, long r ) { return fastdouble( l ) /= r; } //Для типа unsigned char inline fastdouble operator + ( unsigned char l, fastdouble r ) { return fastdouble( l ) += r; } inline fastdouble operator - ( unsigned char l, fastdouble r ) { return fastdouble( l ) -= r; } inline fastdouble operator * ( unsigned char l, fastdouble r ) { return fastdouble( l ) *= r; } inline fastdouble operator / ( unsigned char l, fastdouble r ) { return fastdouble( l ) /= r; } inline fastdouble operator + ( fastdouble l, unsigned char r ) { return fastdouble( l ) += r; } inline fastdouble operator - ( fastdouble l, unsigned char r ) { return fastdouble( l ) -= r; } inline fastdouble operator * ( fastdouble l, unsigned char r ) { return fastdouble( l ) *= r; } inline fastdouble operator / ( fastdouble l, unsigned char r ) { return fastdouble( l ) /= r; } //Для типа unsigned short inline fastdouble operator + ( unsigned short l, fastdouble r ) { return fastdouble( l ) += r; } inline fastdouble operator - ( unsigned short l, fastdouble r ) { return fastdouble( l ) -= r; } inline fastdouble operator * ( unsigned short l, fastdouble r ) { return fastdouble( l ) *= r; } inline fastdouble operator / ( unsigned short l, fastdouble r ) { return fastdouble( l ) /= r; } inline fastdouble operator + ( fastdouble l, unsigned short r ) { return fastdouble( l ) += r; } inline fastdouble operator - ( fastdouble l, unsigned short r ) { return fastdouble( l ) -= r; } inline fastdouble operator * ( fastdouble l, unsigned short r ) { return fastdouble( l ) *= r; } inline fastdouble operator / ( fastdouble l, unsigned short r ) { return fastdouble( l ) /= r; } //Для типа unsigned int inline fastdouble operator + ( unsigned int l, fastdouble r ) { return fastdouble( l ) += r; } inline fastdouble operator - ( unsigned int l, fastdouble r ) { return fastdouble( l ) -= r; } inline fastdouble operator * ( unsigned int l, fastdouble r ) { return fastdouble( l ) *= r; } inline fastdouble operator / ( unsigned int l, fastdouble r ) { return fastdouble( l ) /= r; } inline fastdouble operator + ( fastdouble l, unsigned int r ) { return fastdouble( l ) += r; } inline fastdouble operator - ( fastdouble l, unsigned int r ) { return fastdouble( l ) -= r; } inline fastdouble operator * ( fastdouble l, unsigned int r ) { return fastdouble( l ) *= r; } inline fastdouble operator / ( fastdouble l, unsigned int r ) { return fastdouble( l ) /= r; } //Для типа unsigned long inline fastdouble operator + ( unsigned long l, fastdouble r ) { return fastdouble( l ) += r; } inline fastdouble operator - ( unsigned long l, fastdouble r ) { return fastdouble( l ) -= r; } inline fastdouble operator * ( unsigned long l, fastdouble r ) { return fastdouble( l ) *= r; } inline fastdouble operator / ( unsigned long l, fastdouble r ) { return fastdouble( l ) /= r; } inline fastdouble operator + ( fastdouble l, unsigned long r ) { return fastdouble( l ) += r; } inline fastdouble operator - ( fastdouble l, unsigned long r ) { return fastdouble( l ) -= r; } inline fastdouble operator * ( fastdouble l, unsigned long r ) { return fastdouble( l ) *= r; } inline fastdouble operator / ( fastdouble l, unsigned long r ) { return fastdouble( l ) /= r; } //Для типа double inline bool operator < ( fastdouble l, double r ) { return l < fastdouble( r ); } inline bool operator <= ( fastdouble l, double r ) { return l <= fastdouble( r ); } inline bool operator > ( fastdouble l, double r ) { return l > fastdouble( r ); } inline bool operator >= ( fastdouble l, double r ) { return l >= fastdouble( r ); } inline bool operator == ( fastdouble l, double r ) { return l == fastdouble( r ); } inline bool operator != ( fastdouble l, double r ) { return l != fastdouble( r ); } inline bool operator < ( double l, fastdouble r ) { return fastdouble( l ) < r; } inline bool operator <= ( double l, fastdouble r ) { return fastdouble( l ) <= r; } inline bool operator > ( double l, fastdouble r ) { return fastdouble( l ) > r; } inline bool operator >= ( double l, fastdouble r ) { return fastdouble( l ) >= r; } inline bool operator == ( double l, fastdouble r ) { return fastdouble( l ) == r; } inline bool operator != ( double l, fastdouble r ) { return fastdouble( l ) != r; } //Для типа float inline bool operator < ( fastdouble l, float r ) { return l < fastdouble( r ); } inline bool operator <= ( fastdouble l, float r ) { return l <= fastdouble( r ); } inline bool operator > ( fastdouble l, float r ) { return l > fastdouble( r ); } inline bool operator >= ( fastdouble l, float r ) { return l >= fastdouble( r ); } inline bool operator == ( fastdouble l, float r ) { return l == fastdouble( r ); } inline bool operator != ( fastdouble l, float r ) { return l != fastdouble( r ); } inline bool operator < ( float l, fastdouble r ) { return fastdouble( l ) < r; } inline bool operator <= ( float l, fastdouble r ) { return fastdouble( l ) <= r; } inline bool operator > ( float l, fastdouble r ) { return fastdouble( l ) > r; } inline bool operator >= ( float l, fastdouble r ) { return fastdouble( l ) >= r; } inline bool operator == ( float l, fastdouble r ) { return fastdouble( l ) == r; } inline bool operator != ( float l, fastdouble r ) { return fastdouble( l ) != r; } //Для типа char inline bool operator < ( fastdouble l, char r ) { return l < fastdouble( r ); } inline bool operator <= ( fastdouble l, char r ) { return l <= fastdouble( r ); } inline bool operator > ( fastdouble l, char r ) { return l > fastdouble( r ); } inline bool operator >= ( fastdouble l, char r ) { return l >= fastdouble( r ); } inline bool operator == ( fastdouble l, char r ) { return l == fastdouble( r ); } inline bool operator != ( fastdouble l, char r ) { return l != fastdouble( r ); } inline bool operator < ( char l, fastdouble r ) { return fastdouble( l ) < r; } inline bool operator <= ( char l, fastdouble r ) { return fastdouble( l ) <= r; } inline bool operator > ( char l, fastdouble r ) { return fastdouble( l ) > r; } inline bool operator >= ( char l, fastdouble r ) { return fastdouble( l ) >= r; } inline bool operator == ( char l, fastdouble r ) { return fastdouble( l ) == r; } inline bool operator != ( char l, fastdouble r ) { return fastdouble( l ) != r; } //Для типа short inline bool operator < ( fastdouble l, short r ) { return l < fastdouble( r ); } inline bool operator <= ( fastdouble l, short r ) { return l <= fastdouble( r ); } inline bool operator > ( fastdouble l, short r ) { return l > fastdouble( r ); } inline bool operator >= ( fastdouble l, short r ) { return l >= fastdouble( r ); } inline bool operator == ( fastdouble l, short r ) { return l == fastdouble( r ); } inline bool operator != ( fastdouble l, short r ) { return l != fastdouble( r ); } inline bool operator < ( short l, fastdouble r ) { return fastdouble( l ) < r; } inline bool operator <= ( short l, fastdouble r ) { return fastdouble( l ) <= r; } inline bool operator > ( short l, fastdouble r ) { return fastdouble( l ) > r; } inline bool operator >= ( short l, fastdouble r ) { return fastdouble( l ) >= r; } inline bool operator == ( short l, fastdouble r ) { return fastdouble( l ) == r; } inline bool operator != ( short l, fastdouble r ) { return fastdouble( l ) != r; } //Для типа int inline bool operator < ( fastdouble l, int r ) { return l < fastdouble( r ); } inline bool operator <= ( fastdouble l, int r ) { return l <= fastdouble( r ); } inline bool operator > ( fastdouble l, int r ) { return l > fastdouble( r ); } inline bool operator >= ( fastdouble l, int r ) { return l >= fastdouble( r ); } inline bool operator == ( fastdouble l, int r ) { return l == fastdouble( r ); } inline bool operator != ( fastdouble l, int r ) { return l != fastdouble( r ); } inline bool operator < ( int l, fastdouble r ) { return fastdouble( l ) < r; } inline bool operator <= ( int l, fastdouble r ) { return fastdouble( l ) <= r; } inline bool operator > ( int l, fastdouble r ) { return fastdouble( l ) > r; } inline bool operator >= ( int l, fastdouble r ) { return fastdouble( l ) >= r; } inline bool operator == ( int l, fastdouble r ) { return fastdouble( l ) == r; } inline bool operator != ( int l, fastdouble r ) { return fastdouble( l ) != r; } //Для типа long inline bool operator < ( fastdouble l, long r ) { return l < fastdouble( r ); } inline bool operator <= ( fastdouble l, long r ) { return l <= fastdouble( r ); } inline bool operator > ( fastdouble l, long r ) { return l > fastdouble( r ); } inline bool operator >= ( fastdouble l, long r ) { return l >= fastdouble( r ); } inline bool operator == ( fastdouble l, long r ) { return l == fastdouble( r ); } inline bool operator != ( fastdouble l, long r ) { return l != fastdouble( r ); } inline bool operator < ( long l, fastdouble r ) { return fastdouble( l ) < r; } inline bool operator <= ( long l, fastdouble r ) { return fastdouble( l ) <= r; } inline bool operator > ( long l, fastdouble r ) { return fastdouble( l ) > r; } inline bool operator >= ( long l, fastdouble r ) { return fastdouble( l ) >= r; } inline bool operator == ( long l, fastdouble r ) { return fastdouble( l ) == r; } inline bool operator != ( long l, fastdouble r ) { return fastdouble( l ) != r; } //Для типа unsigned char inline bool operator < ( fastdouble l, unsigned char r ) { return l < fastdouble( r ); } inline bool operator <= ( fastdouble l, unsigned char r ) { return l <= fastdouble( r ); } inline bool operator > ( fastdouble l, unsigned char r ) { return l > fastdouble( r ); } inline bool operator >= ( fastdouble l, unsigned char r ) { return l >= fastdouble( r ); } inline bool operator == ( fastdouble l, unsigned char r ) { return l == fastdouble( r ); } inline bool operator != ( fastdouble l, unsigned char r ) { return l != fastdouble( r ); } inline bool operator < ( unsigned char l, fastdouble r ) { return fastdouble( l ) < r; } inline bool operator <= ( unsigned char l, fastdouble r ) { return fastdouble( l ) <= r; } inline bool operator > ( unsigned char l, fastdouble r ) { return fastdouble( l ) > r; } inline bool operator >= ( unsigned char l, fastdouble r ) { return fastdouble( l ) >= r; } inline bool operator == ( unsigned char l, fastdouble r ) { return fastdouble( l ) == r; } inline bool operator != ( unsigned char l, fastdouble r ) { return fastdouble( l ) != r; } //Для типа unsigned short inline bool operator < ( fastdouble l, unsigned short r ) { return l < fastdouble( r ); } inline bool operator <= ( fastdouble l, unsigned short r ) { return l <= fastdouble( r ); } inline bool operator > ( fastdouble l, unsigned short r ) { return l > fastdouble( r ); } inline bool operator >= ( fastdouble l, unsigned short r ) { return l >= fastdouble( r ); } inline bool operator == ( fastdouble l, unsigned short r ) { return l == fastdouble( r ); } inline bool operator != ( fastdouble l, unsigned short r ) { return l != fastdouble( r ); } inline bool operator < ( unsigned short l, fastdouble r ) { return fastdouble( l ) < r; } inline bool operator <= ( unsigned short l, fastdouble r ) { return fastdouble( l ) <= r; } inline bool operator > ( unsigned short l, fastdouble r ) { return fastdouble( l ) > r; } inline bool operator >= ( unsigned short l, fastdouble r ) { return fastdouble( l ) >= r; } inline bool operator == ( unsigned short l, fastdouble r ) { return fastdouble( l ) == r; } inline bool operator != ( unsigned short l, fastdouble r ) { return fastdouble( l ) != r; } //Для типа unsigned int inline bool operator < ( fastdouble l, unsigned int r ) { return l < fastdouble( r ); } inline bool operator <= ( fastdouble l, unsigned int r ) { return l <= fastdouble( r ); } inline bool operator > ( fastdouble l, unsigned int r ) { return l > fastdouble( r ); } inline bool operator >= ( fastdouble l, unsigned int r ) { return l >= fastdouble( r ); } inline bool operator == ( fastdouble l, unsigned int r ) { return l == fastdouble( r ); } inline bool operator != ( fastdouble l, unsigned int r ) { return l != fastdouble( r ); } inline bool operator < ( unsigned int l, fastdouble r ) { return fastdouble( l ) < r; } inline bool operator <= ( unsigned int l, fastdouble r ) { return fastdouble( l ) <= r; } inline bool operator > ( unsigned int l, fastdouble r ) { return fastdouble( l ) > r; } inline bool operator >= ( unsigned int l, fastdouble r ) { return fastdouble( l ) >= r; } inline bool operator == ( unsigned int l, fastdouble r ) { return fastdouble( l ) == r; } inline bool operator != ( unsigned int l, fastdouble r ) { return fastdouble( l ) != r; } //Для типа unsigned long inline bool operator < ( fastdouble l, unsigned long r ) { return l < fastdouble( r ); } inline bool operator <= ( fastdouble l, unsigned long r ) { return l <= fastdouble( r ); } inline bool operator > ( fastdouble l, unsigned long r ) { return l > fastdouble( r ); } inline bool operator >= ( fastdouble l, unsigned long r ) { return l >= fastdouble( r ); } inline bool operator == ( fastdouble l, unsigned long r ) { return l == fastdouble( r ); } inline bool operator != ( fastdouble l, unsigned long r ) { return l != fastdouble( r ); } inline bool operator < ( unsigned long l, fastdouble r ) { return fastdouble( l ) < r; } inline bool operator <= ( unsigned long l, fastdouble r ) { return fastdouble( l ) <= r; } inline bool operator > ( unsigned long l, fastdouble r ) { return fastdouble( l ) > r; } inline bool operator >= ( unsigned long l, fastdouble r ) { return fastdouble( l ) >= r; } inline bool operator == ( unsigned long l, fastdouble r ) { return fastdouble( l ) == r; } inline bool operator != ( unsigned long l, fastdouble r ) { return fastdouble( l ) != r; } #if 1 // change to 0 to turn fastdouble usage off #else #define fastdouble double #define fasttodouble( v ) double( v ) #define fasttolong( v ) long( v ) #endif #endif //__FAST_FLOAT_H -
Операции с плавающей точкой без FPU
Degun ответил sigmaN тема в Алгоритмы ЦОС (DSP)
А разве можно функции, собранные в файл-библиотеку fastrts62x64x.lib, объявить как inline. Вроде бы, т. к. они уже скомпилированны в библиотеку, то они не могут быть inline. -
Операции с плавающей точкой без FPU
Degun ответил sigmaN тема в Алгоритмы ЦОС (DSP)
Кто пробовал для DSP фирмы Texas Instruments серии 62x или 64x пользоваться библиотекой Fast Run Time Support Library fastrts64x.lib, которая вроде бы предоставляет быструю реализацию основных операций с типами double и float. Насколько она действительно быстрее тех же операций, но встроенных в компилятор? Будет ли выигрыш? Если нет, то зачем она нужна вообще? -
И как же, если не сложно объяснить
-
Лишние NOP в ассемблерном коде
Degun ответил Degun тема в Алгоритмы ЦОС (DSP)
Следующий вариант выполняется на 1 мсек быстрее, чем предыдущий. Возможно это ещё не предел оптимизации, но больше у меня идей нет. Если кто знает, то подскажите. /*!\brief Разбиение изображения на непересекающиеся области * \brief в соответствии с таблицей мод * \param Image - исходное изображение * \param Height - высота изображения * \param Width - ширина изображение * \param ModeNumb4Pix - таблица соответствия значений пикселов модам гистограммы * \param Areas - буфер результата, отражающий номера областей каждого из пикселов * \result Количество непересекающихся областей в изображении */ #include <stdlib.h> #include <csl_dat.h> //Максимальное кол-во областей в изображении #define MAX_AREAS 2000 //Ограниченный массив структур описателей областей!!! #pragma DATA_ALIGN(8); static short AreasMode[MAX_AREAS+1]; #pragma DATA_ALIGN(8); static short AreasNumber[MAX_AREAS+1]; #pragma DATA_ALIGN(8); static short AreasPixel[MAX_AREAS+1]; //Буферы для кэширования строк изображения #pragma DATA_ALIGN(8); static unsigned char ImageBuf[2][IMG_WIDTH_MAX]; #pragma DATA_ALIGN(8); static unsigned short AreasBuf[2][IMG_WIDTH_MAX]; int dsp_SplitImage2AreasFast( unsigned char ** restrict Image, int Height, int Width, unsigned char * restrict ModeNumb4Pix, unsigned short ** restrict Areas) { //Изображение последовательно просматривается по строкам //для отнесения каждого пиксела к определённой области //Вычисление площади, занимаемой каждой областью и модой register int iAreasCounter; //Счётчик количества областей в изображении register int iAreasInfoCounter;//Счётчик количества областей в контейнере //Временные переменные register int i, y, x, iSrcIndex, iDstIndex, iTmp; register int iCurrAreaNumb, iCurrModeNumb; register Uint32 id_LoadTransfer, id_SaveTransfer; register unsigned char * restrict pImageNextBuf; register unsigned char * restrict pImageCurrBuf; register unsigned short * restrict pAreasCurrBuf; register unsigned short * restrict pAreasPrevBuf; //Проверка корректности входных параметров if ((Image==0)||(ModeNumb4Pix==0)||(Areas==0)|| (Width<=0)||(Height<=0)||(Width>IMG_WIDTH_MAX)) return -1; //Установка указателя на следующую строку изображения pImageNextBuf=ImageBuf[0]; //Загрузка первой строки изображения id_LoadTransfer=DAT_copy(Image[0], pImageNextBuf, Width); //Начальная инициализация идентификатора канала сохранения id_SaveTransfer=DAT_XFRID_WAITNONE; //Обнуление счётчиков кол-ва областей iAreasCounter=iAreasInfoCounter=0; //Установка кол-ва областей максимально возможное для исключения //применения к первой строке ветви выявления связей с предыдущими строками iTmp=IMG_WIDTH_MAX; //Обнуление указателя на текущую строку pAreasCurrBuf=NULL; //Цикл по всем точкам изображения for (y=0; y<Height; y++) { //Сохранение указателя на текущую строку изображения pImageCurrBuf=pImageNextBuf; //Сохранение указателя на предыдущую строку результата pAreasPrevBuf=pAreasCurrBuf; //Указатель на следующую строку изображения pImageNextBuf=ImageBuf[(y+1)&1]; //Указатель на текущую строку результата pAreasCurrBuf=AreasBuf[y&1]; //Начальные значения номера моды iCurrModeNumb=-1; //Ожидание окончания загрузки текущей строки изображения DAT_wait(id_LoadTransfer); //Запуск загрузки следующей строки изображения id_LoadTransfer = DAT_copy(Image[y+1], pImageNextBuf, Width); //Обработка очередной строки изображения for (x=0; x<Width; x++) { //Номер моды текущей точки i=ModeNumb4Pix[pImageCurrBuf[x]]; //В зависимости от того принадлежит ли точка той же моде, //что и её левая точка, установка номера области if (iCurrModeNumb!=i) { //Добавление новой области // if (iAreasInfoCount>=MAX_AREAS) return -1; iCurrModeNumb=i; iCurrAreaNumb=iAreasInfoCounter; AreasMode[iAreasInfoCounter]=iCurrModeNumb; AreasNumber[iAreasInfoCounter]=iAreasInfoCounter; AreasPixel[iAreasInfoCounter]=x; //Инкремент счётчиков областей iAreasCounter++; iAreasInfoCounter++; } //Установка номера области текущей точки pAreasCurrBuf[x]=iCurrAreaNumb; } //Обработка всех областей в текущей строке для выявления их связей for (; iTmp<iAreasInfoCounter; iTmp++) { iSrcIndex=iTmp; iCurrModeNumb=AreasMode[iTmp]; i=AreasPixel[iTmp]; if (i>0) i--; if (iTmp==(iAreasInfoCounter-1)) iCurrAreaNumb=Width-1; else iCurrAreaNumb=AreasPixel[iTmp+1]; iCurrAreaNumb=pAreasPrevBuf[iCurrAreaNumb]; //Цикл по всем граничащим на предыдущей строке областям for (i=pAreasPrevBuf[i]; i<=iCurrAreaNumb; i++) { if (AreasMode[i]!=iCurrModeNumb) continue; //На предыдущей строке найдена область с совпадающей модой, //которая соседствует с исходной iDstIndex=i; while(AreasNumber[iDstIndex]!=iDstIndex) iDstIndex=AreasNumber[iDstIndex]; if (iSrcIndex!=iDstIndex) { //Объединение двух кластеров областей if (iSrcIndex<iDstIndex) { //Сохранение номера AreasNumber[iDstIndex]=iSrcIndex; } else { //Сохранение номера AreasNumber[iSrcIndex]=iDstIndex; //Для дальнейшего объединения берётся меньший индекс iSrcIndex=iDstIndex; } //Декремент кол-ва областей iAreasCounter--; } } } //Сохранение кол-ва областей iTmp=iAreasInfoCounter; //Ожидание окончания сохранения результата DAT_wait(id_SaveTransfer); //Сохранение строки результата id_SaveTransfer=DAT_copy(pAreasCurrBuf, Areas[y], sizeof(short)*Width); } //Обновление ссылок на области for (iSrcIndex=0; iSrcIndex<iAreasInfoCounter; iSrcIndex++) { //Поиск индекса назначения iDstIndex=iSrcIndex; while(AreasNumber[iDstIndex]!=iDstIndex) iDstIndex=AreasNumber[iDstIndex]; //Обновление номера области AreasNumber[iSrcIndex]=iDstIndex; } //Могут оставаться независимые области с индексами больше iAreasCount for (iDstIndex=-1, iSrcIndex=iAreasCounter; iSrcIndex<iAreasInfoCounter; iSrcIndex++) { //Если эта область уже переадресована - все нормально if (AreasNumber[iSrcIndex]!=iSrcIndex) continue; //Поиск индекса для переадресации for (iDstIndex++; iDstIndex<iAreasCounter; iDstIndex++) if (AreasNumber[iDstIndex]!=iDstIndex) break; //Сохранение указателя на моду AreasMode[iDstIndex]=AreasMode[iSrcIndex]; //Установка ссылки данной области на переадресованную AreasNumber[iSrcIndex]=iDstIndex; //Замена всех ссылок на эту область!!!!!!!! for (i=iSrcIndex; i<iAreasInfoCounter; i++) if (AreasNumber[i]==iSrcIndex) AreasNumber[i]=iDstIndex; } //Установка указателя на текущую загружаемую строку pAreasCurrBuf=AreasBuf[0]; //Загрузка первой строки номеров областей id_LoadTransfer=DAT_copy(Areas[0], pAreasCurrBuf, sizeof(short)*Width); //Начальная инициализация идентификатора канала сохранения id_SaveTransfer=DAT_XFRID_WAITNONE; //Обработка всех строк for (y=0; y<Height; y++) { //Сохранение указателя на предыдущую строку результата pAreasPrevBuf=pAreasCurrBuf; //Указатель на следующую строку результата pAreasCurrBuf=AreasBuf[(y+1)&1]; //Ожидание окончания загрузки текущей строки изображения DAT_wait(id_LoadTransfer); //Запуск загрузки следующей строки изображения id_LoadTransfer=DAT_copy(Areas[y+1], pAreasCurrBuf, sizeof(short)*Width); //Переписывание индексов удалённых областей на переназначенные for (x=0; x<Width; x++) pAreasPrevBuf[x]=AreasNumber[pAreasPrevBuf[x]]; //Ожидание окончания сохранения результата DAT_wait(id_SaveTransfer); //Сохранение строки результата id_SaveTransfer=DAT_copy(pAreasPrevBuf, Areas[y], sizeof(short)*Width); } //Ожидание окончания сохранения результата DAT_wait(id_SaveTransfer); return iAreasCounter; } -
А драйверы XDS560R установлены для CCStudio именно версии 3.2? Отсюда брали драйвер http://support.spectrumdigital.com/ccs3x_xds560r
-
Лишние NOP в ассемблерном коде
Degun ответил Degun тема в Алгоритмы ЦОС (DSP)
Значительно упростил вложенный цикл за счёт чуть большего расхода памяти. В результате для изображения с разрешением 640*480 процедура стала выполняться за 55 мсек. Но всё равно как-то много. Чтобы ещё такого оптимизировать? #include <stdlib.h> #include <limits.h> #include <csl_dat.h> //Максимальное кол-во областей в изображении #define MAX_AREAS 2000 //Ограниченный массив структур описателей областей!!! #pragma DATA_ALIGN(8); static short AreasMode[MAX_AREAS+1]; #pragma DATA_ALIGN(8); static short AreasNumber[MAX_AREAS+1]; #pragma DATA_ALIGN(8); static short AreasPixel[MAX_AREAS+1]; //Буферы для кэширования строк изображения #pragma DATA_ALIGN(8); static unsigned char ImageBuf[2][IMG_WIDTH_MAX]; #pragma DATA_ALIGN(8); static unsigned short AreasBuf[2][IMG_WIDTH_MAX]; int dsp_SplitImage2AreasFast( unsigned char ** restrict Image, int Height, int Width, unsigned char * restrict ModeNumb4Pix, unsigned short ** restrict Areas) { //Изображение последовательно просматривается по строкам //для отнесения каждого пиксела к определённой области //Вычисление площади, занимаемой каждой областью и модой register int iAreasCounter; //Счётчик количества областей в изображении register int iAreasInfoCounter;//Счётчик количества областей в контейнере register int iPrevAreaNumbL; //Номер области предыдущей левой точки register int iPrevModeNumbL; //Номер моды предыдущей левой точки //Временные переменные register int i, y, x, iSrcIndex, iDstIndex, iTmp; register int iCurrAreaNumb, iCurrModeNumb, iAreasInfoCountSav; register Uint32 id_LoadTransfer, id_SaveTransfer; register unsigned char * restrict pImageNextBuf; register unsigned char * restrict pImageCurrBuf; register unsigned short * restrict pAreasCurrBuf; register unsigned short * restrict pAreasPrevBuf; //Проверка корректности входных параметров if ((Image==0)||(ModeNumb4Pix==0)||(Areas==0)||(Width<=0)||(Height<=0)|| (Width>IMG_WIDTH_MAX)||(Height>IMG_HEIGHT_MAX)) return -1; //Установка указателя на следующую строку изображения pImageNextBuf=ImageBuf[0]; //Загрузка первой строки изображения id_LoadTransfer=DAT_copy(Image[0], pImageNextBuf, Width); //Начальная инициализация идентификатора канала сохранения id_SaveTransfer=DAT_XFRID_WAITNONE; //Обнуление счётчиков кол-ва областей iAreasCounter=iAreasInfoCounter=0; //Установка кол-ва областей максимально возможное для первой строки iAreasInfoCountSav=INT_MAX; //Обнуление указателя на текущую строку pAreasCurrBuf=NULL; //Цикл по всем точкам изображения for (y=0; y<Height; y++) { //Сохранение указателя на текущую строку изображения pImageCurrBuf=pImageNextBuf; //Сохранение указателя на предыдущую строку результата pAreasPrevBuf=pAreasCurrBuf; //Указатель на следующую строку изображения pImageNextBuf=ImageBuf[(y+1)&1]; //Указатель на текущую строку результата pAreasCurrBuf=AreasBuf[y&1]; //Начальные значения номера области и моды для левой точки iPrevModeNumbL=iPrevAreaNumbL=-1; //Ожидание окончания загрузки текущей строки изображения DAT_wait(id_LoadTransfer); //Запуск загрузки следующей строки изображения id_LoadTransfer = DAT_copy(Image[y+1], pImageNextBuf, Width); //Обработка очередной строки изображения for (x=0; x<Width; x++) { //Номер моды текущей точки iCurrModeNumb=ModeNumb4Pix[pImageCurrBuf[x]]; //В зависимости от того принадлежит ли точка той же моде, //что и её левая точка, установка номера области if (iCurrModeNumb==iPrevModeNumbL) iCurrAreaNumb=iPrevAreaNumbL; else { //Добавление новой области // if (iAreasInfoCount>=MAX_AREAS) return -1; iCurrAreaNumb=iAreasInfoCounter; AreasMode[iAreasInfoCounter]=iCurrModeNumb; AreasNumber[iAreasInfoCounter]=iAreasInfoCounter; AreasPixel[iAreasInfoCounter]=x; //Инкремент счётчиков областей iAreasCounter++; iAreasInfoCounter++; //Запоминание номера области и моды для левой точки iPrevAreaNumbL=iCurrAreaNumb; iPrevModeNumbL=iCurrModeNumb; } //Установка номера области текущей точки pAreasCurrBuf[x]=iCurrAreaNumb; } //Обработка всех областей в текущей строке для выявления их связей //с областями на предыдущей строке for (; iAreasInfoCountSav<iAreasInfoCounter; iAreasInfoCountSav++) { iSrcIndex=iAreasInfoCountSav; iCurrModeNumb=AreasMode[iAreasInfoCountSav]; iTmp=AreasPixel[iAreasInfoCountSav]; if (iTmp>0) iTmp--; if (iAreasInfoCountSav==(iAreasInfoCounter-1)) iCurrAreaNumb=Width-1; else iCurrAreaNumb=AreasPixel[iAreasInfoCountSav+1]; iCurrAreaNumb=pAreasPrevBuf[iCurrAreaNumb]; //Цикл по всем граничащим на предыдущей строке областям for (i=pAreasPrevBuf[iTmp]; i<=iCurrAreaNumb; i++) { if (AreasMode[i]!=iCurrModeNumb) continue; //На предыдущей строке найдена область с совпадающей модой, //которая соседствует с исходной iDstIndex=i; while(AreasNumber[iDstIndex]!=iDstIndex) iDstIndex=AreasNumber[iDstIndex]; if (iSrcIndex!=iDstIndex) { //Объединение двух кластеров областей if (iSrcIndex<iDstIndex) { //Сохранение номера AreasNumber[iDstIndex]=iSrcIndex; } else { //Сохранение номера AreasNumber[iSrcIndex]=iDstIndex; //Для дальнейшего объединения берётся меньший индекс iSrcIndex=iDstIndex; } //Декремент кол-ва областей iAreasCounter--; } } } //Сохранение кол-ва областей iAreasInfoCountSav=iAreasInfoCounter; //Ожидание окончания сохранения результата DAT_wait(id_SaveTransfer); //Сохранение строки результата id_SaveTransfer=DAT_copy(pAreasCurrBuf, Areas[y], sizeof(short)*Width); } //Обновление ссылок на области for (iSrcIndex=0; iSrcIndex<iAreasInfoCounter; iSrcIndex++) { //Поиск индекса назначения iDstIndex=iSrcIndex; while(AreasNumber[iDstIndex]!=iDstIndex) iDstIndex=AreasNumber[iDstIndex]; //Обновление номера области AreasNumber[iSrcIndex]=iDstIndex; } //Могут оставаться независимые области с индексами больше iAreasCount for (iDstIndex=-1, iSrcIndex=iAreasCounter; iSrcIndex<iAreasInfoCounter; iSrcIndex++) { //Если эта область уже переадресована - все нормально if (AreasNumber[iSrcIndex]!=iSrcIndex) continue; //Поиск индекса для переадресации for (iDstIndex++; iDstIndex<iAreasCounter; iDstIndex++) if (AreasNumber[iDstIndex]!=iDstIndex) break; //Сохранение указателя на моду AreasMode[iDstIndex]=AreasMode[iSrcIndex]; //Установка ссылки данной области на переадресованную AreasNumber[iSrcIndex]=iDstIndex; //Замена всех ссылок на эту область!!!!!!!! for (i=iSrcIndex; i<iAreasInfoCounter; i++) if (AreasNumber[i]==iSrcIndex) AreasNumber[i]=iDstIndex; } //Установка указателя на текущую загружаемую строку pAreasCurrBuf=AreasBuf[0]; //Загрузка первой строки номеров областей id_LoadTransfer=DAT_copy(Areas[0], pAreasCurrBuf, sizeof(short)*Width); //Начальная инициализация идентификатора канала сохранения id_SaveTransfer=DAT_XFRID_WAITNONE; //Обработка всех строк for (y=0; y<Height; y++) { //Сохранение указателя на предыдущую строку результата pAreasPrevBuf=pAreasCurrBuf; //Указатель на следующую строку результата pAreasCurrBuf=AreasBuf[(y+1)&1]; //Ожидание окончания загрузки текущей строки изображения DAT_wait(id_LoadTransfer); //Запуск загрузки следующей строки изображения id_LoadTransfer=DAT_copy(Areas[y+1], pAreasCurrBuf, sizeof(short)*Width); //Переписывание индексов удалённых областей на переназначенные for (x=0; x<Width; x++) pAreasPrevBuf[x]=AreasNumber[pAreasPrevBuf[x]]; //Ожидание окончания сохранения результата DAT_wait(id_SaveTransfer); //Сохранение строки результата id_SaveTransfer=DAT_copy(pAreasPrevBuf, Areas[y], sizeof(short)*Width); } //Ожидание окончания сохранения результата DAT_wait(id_SaveTransfer); return iAreasCounter; } -
Работает CCS 3.3 в Vista?
Degun ответил Alexey_Sev тема в Алгоритмы ЦОС (DSP)
У меня при прямом запуске CCStudio тоже виснет. Но если запускать через "CCStudio v3.3 Setup", то запускается нормально. -
Лишние NOP в ассемблерном коде
Degun ответил Degun тема в Алгоритмы ЦОС (DSP)
Вот такой у меня получился код для DSP. Но для изображения размером 640*480 пикселей он выполняется за 85 мсек, что много. Что здесь можно ещё оптимизировать? #include <stdlib.h> #include <string.h> #include <csl_dat.h> //Максимальное кол-во областей в изображении #define MAX_AREAS 1000 //Максимальная ширина изображения #define IMG_WIDTH_MAX 640 //Максимальная высота изображения #define IMG_HEIGHT_MAX 480 //Макросы минимума и максимума #define max(a, b) (((a) > (b)) ? (a) : (b)) #define min(a, b) (((a) < (b)) ? (a) : (b)) //Счётчики количества областей в изображении и в контейнере static int iAreasCount=0, iAreasInfoCount=0; //Ограниченные массивы структур описателей областей!!! static short AreasMode[MAX_AREAS+1]; static short AreasNumber[MAX_AREAS+1]; //Функция создания новой области static inline int AddNewAreaInfo(const int iModeNumb) { // if (iAreasInfoCount>=MAX_AREAS) return -1; iAreasCount++; AreasMode[iAreasInfoCount]=iModeNumb; AreasNumber[iAreasInfoCount]=-1; return iAreasInfoCount++; } // Буферы для кэширования строк изображения static unsigned char ImageBuf[3][IMG_WIDTH_MAX]; static int AreasBuf[2][IMG_WIDTH_MAX]; int test_SplitImage2Areas( register unsigned char ** restrict Image, register int Height, register int Width, register short * restrict ModeNumb4Pix, register int ** restrict Areas) { //Изображение последовательно просматривается по строкам //для отнесения каждого пиксела к определённой области //Вычисление площади, занимаемой каждой областью и модой register int iPrevAreaNumbL=-1; //Номер области предыдущей левой точки register int iPrevModeNumbL=-1; //Номер моды предыдущей левой точки register int iPrevAreaNumbU=-1; //Номер области предыдущей верхней точки register int iPrevModeNumbU=-1; //Номер моды предыдущей верхней точки register int iPrevAreaNumbUL=-1; //Номер области предыдущей верхней левой точки register int iPrevModeNumbUL=-1; //Номер моды предыдущей верхней левой точки register int iPrevAreaNumbUR=-1; //Номер области предыдущей верхней правой точки register int iPrevModeNumbUR=-1; //Номер моды предыдущей верхней правой точки //Временные переменные register int i, y, x, iSrcIndex, iDstIndex, iDelta, iTmp; register int iCurrPixel, iCurrAreaNumb, iCurrModeNumb; register Uint32 id_LoadTransfer, id_SaveTransfer; register int iImageBufIndex, iAreasBufIndex; register unsigned char * restrict pImageCurrBuf; register unsigned char * restrict pImagePrevBuf; register int * restrict pAreasCurrBuf; register int * restrict pAreasPrevBuf; //Проверка корректности входных параметров if ((Image==0)||(ModeNumb4Pix==0)||(Areas==0)) return -1; if ((Width<=0)||(Height<=0)||(Width>IMG_WIDTH_MAX)||(Height>IMG_HEIGHT_MAX)) return -1; //Загрузка первой строки изображения id_LoadTransfer=DAT_copy(Image[0], ImageBuf[0], Width); //Обнуление счётчиков кол-ва областей iAreasCount=iAreasInfoCount=0; //Обработка верхней левой точки изображения iCurrPixel=Image[0][0]; iCurrModeNumb=ModeNumb4Pix[iCurrPixel]; if (iCurrModeNumb<0) { //Сканирование зигзагом окрестных точек для //выявления ближайшей с установленной модой iDelta=min(Width,Height); for (i=1; i<iDelta; i++) { iSrcIndex=-1; for (y=i, x=0; y>=0; y--, x++) { iDstIndex=Image[y][x]; iTmp=ModeNumb4Pix[iDstIndex]; if (iTmp<0) continue; iDstIndex=abs(iDstIndex-iCurrPixel); if ((iSrcIndex<0)||(iSrcIndex>iDstIndex)) { iSrcIndex=iDstIndex; iCurrModeNumb=iTmp; } } //Нашли подходящую точку - выход из поиска if (iCurrModeNumb>=0) break; } //Если точек нет, то нулевая мода if (iCurrModeNumb<0) iCurrModeNumb=0; } iCurrAreaNumb=AddNewAreaInfo(iCurrModeNumb); AreasBuf[0][0]=iCurrAreaNumb; //Указатель на текущую обрабатываемую строку изображения pImageCurrBuf=ImageBuf[0]; //Указатель на текущую результирующую строку номеров областей pAreasCurrBuf=AreasBuf[0]; //Ожидание окончания загрузки первой строки изображения while(DAT_busy(id_LoadTransfer)); //Запуск загрузки второй строки изображения id_LoadTransfer=DAT_copy(Image[1], ImageBuf[1], Width); //Обработка первой верхней строки изображения, //начиная со второго пиксела строки for (x=1; x<Width; x++) { //Запоминание номера области и моды для левой точки iPrevAreaNumbL=iCurrAreaNumb; iPrevModeNumbL=iCurrModeNumb; //Номер моды текущей точки iCurrModeNumb=ModeNumb4Pix[pImageCurrBuf[x]]; //В зависимости от наличия моды if (iCurrModeNumb<0) { iCurrModeNumb=iPrevModeNumbL; iCurrAreaNumb=iPrevAreaNumbL; } else if (iCurrModeNumb==iPrevModeNumbL) { iCurrAreaNumb=iPrevAreaNumbL; } else { //Добавление новой области iCurrAreaNumb=AddNewAreaInfo(iCurrModeNumb); } //Установка номера области текущей точки pAreasCurrBuf[x]=iCurrAreaNumb; } //Сохранение первой строки результата id_SaveTransfer=DAT_copy(AreasBuf[0], Areas[0], Width); //установка кольцевого указателя на буфер текущей строки iImageBufIndex=iAreasBufIndex=1; //Декремент ширины изображения для увеличения скорости обработки Width--; //Цикл по всем точкам изображения for (y=1; y<Height; y++) { //Сохранение указателя на предыдущую строку изображения pImagePrevBuf=pImageCurrBuf; //Сохранение указателя на предыдущую строку результата pAreasPrevBuf=pAreasCurrBuf; //Указатель на текущую строку изображения pImageCurrBuf=ImageBuf[iImageBufIndex]; //Указатель на текущую строку результата pAreasCurrBuf=AreasBuf[iAreasBufIndex]; //Продвижение индекса на следующую строку iImageBufIndex++; iImageBufIndex%=3; iAreasBufIndex++; iAreasBufIndex%=2; //Ожидание окончания загрузки текущей строки изображения while(DAT_busy(id_LoadTransfer)); //Запуск загрузки следующей строки изображения id_LoadTransfer = DAT_copy(Image[y+1], ImageBuf[iImageBufIndex], Width); //Установка начального значения для верхней левой точки iPrevAreaNumbUL=pAreasPrevBuf[0]; iPrevModeNumbUL=AreasMode[iPrevAreaNumbUL]; //Установка начального значения для верхней точки iPrevAreaNumbU=pAreasPrevBuf[1]; iPrevModeNumbU=AreasMode[iPrevAreaNumbU]; //Значение яркости первого пикселя строки iCurrPixel=pImageCurrBuf[0]; //Значение моды первого пикселя строки iPrevModeNumbL=ModeNumb4Pix[iCurrPixel]; //В зависимости от признака переходности пиксела if (iPrevModeNumbL<0) { if (abs(iCurrPixel-pImagePrevBuf[0])<abs(iCurrPixel-pImagePrevBuf[1])) { iPrevModeNumbL=iPrevModeNumbUL; iPrevAreaNumbL=iPrevAreaNumbUL; } else { iPrevModeNumbL=iPrevModeNumbU; iPrevAreaNumbL=iPrevAreaNumbU; } } else if (iPrevModeNumbL==iPrevModeNumbUL) iPrevAreaNumbL=iPrevAreaNumbUL; //Верхняя левая точка else if (iPrevModeNumbL==iPrevModeNumbU) iPrevAreaNumbL=iPrevAreaNumbU; //Верхняя точка else { //Добавление новой области iPrevAreaNumbL=AddNewAreaInfo(iPrevModeNumbL); } //Установка номера области первого пиксела строки pAreasCurrBuf[0] = iPrevAreaNumbL; //Обработка очередной строки изображения for (x=1; x<Width; x++) { //Определение параметров верхней правой точки iPrevAreaNumbUR=pAreasPrevBuf[x+1]; iPrevModeNumbUR=AreasMode[iPrevAreaNumbUR]; //Значение яркости текущего пикселя iCurrPixel=pImageCurrBuf[x]; //Номер моды текущей точки iCurrModeNumb=ModeNumb4Pix[iCurrPixel]; //В зависимости от того является ли точка переходной if (iCurrModeNumb<0) { //Текущая точка является переходной к любой области //Перебор всех точек окрестности и выбор наиболее близкой области //Левая точка iDelta=abs(pImageCurrBuf[x-1]-iCurrPixel); iCurrAreaNumb=iPrevAreaNumbL; iCurrModeNumb=iPrevModeNumbL; //Верхняя точка iTmp=abs(pImagePrevBuf[x]-iCurrPixel); if (iDelta>iTmp) { iDelta=iTmp; iCurrAreaNumb=iPrevAreaNumbU; iCurrModeNumb=iPrevModeNumbU; } //Верхняя левая точка iTmp=abs(pImagePrevBuf[x-1]-iCurrPixel); if (iDelta>iTmp) { iDelta=iTmp; iCurrAreaNumb=iPrevAreaNumbUL; iCurrModeNumb=iPrevModeNumbUL; } //Верхняя правая точка iTmp=abs(pImagePrevBuf[x+1]-iCurrPixel); if (iDelta>iTmp) { iDelta=iTmp; iCurrAreaNumb=iPrevAreaNumbUR; iCurrModeNumb=iPrevModeNumbUR; } } //Эта точка не является переходной ни к одной из мод //Просмотр всех соседних уже размеченных ранее точек //для возможного определения номера области текущей точки else if (iCurrModeNumb==iPrevModeNumbL) iCurrAreaNumb=iPrevAreaNumbL; //Левая точка else if (iCurrModeNumb==iPrevModeNumbUL) iCurrAreaNumb=iPrevAreaNumbUL; //Верхняя левая точка else if (iCurrModeNumb==iPrevModeNumbU) iCurrAreaNumb=iPrevAreaNumbU; //Верхняя точка else if (iCurrModeNumb==iPrevModeNumbUR) iCurrAreaNumb=iPrevAreaNumbUR; //Верхняя правая точка else { //Добавление новой области iCurrAreaNumb=AddNewAreaInfo(iCurrModeNumb); } //Установка номера области текущей точки pAreasCurrBuf[x] = iCurrAreaNumb; //Сканирование верхней правой точки для добавления её в список соседних областей if ((iCurrModeNumb==iPrevModeNumbUR)&&(iCurrAreaNumb!=iPrevAreaNumbUR)) { //Всего четыре возможных варианта if (AreasNumber[iCurrAreaNumb]<0) { if (AreasNumber[iPrevAreaNumbUR]>=0) { //Только добавляется ссылка на ссылочную область AreasNumber[iCurrAreaNumb]=AreasNumber[iPrevAreaNumbUR]; //Декремент кол-ва областей iAreasCount--; } else { //Обе области являются доменными iTmp=min(iCurrAreaNumb,iPrevAreaNumbUR); AreasNumber[iCurrAreaNumb]=iTmp; AreasNumber[iPrevAreaNumbUR]=iTmp; //Декремент кол-ва областей iAreasCount--; } } else //if (AreasNumber[iCurrAreaNumb]>=0) { if (AreasNumber[iPrevAreaNumbUR]<0) { //Только добавляется ссылка на ссылочную область AreasNumber[iPrevAreaNumbUR]=AreasNumber[iCurrAreaNumb]; //Декремент кол-ва областей iAreasCount--; } else { iSrcIndex=AreasNumber[iCurrAreaNumb]; iDstIndex=AreasNumber[iPrevAreaNumbUR]; if (iSrcIndex!=iDstIndex) { //Это самый трудоёмкий случай. //Но, к счастью, самый редкий! //Необходимо объединить две области if (iSrcIndex<iDstIndex) { //Обмен значениями iTmp=iSrcIndex; iSrcIndex=iDstIndex; iDstIndex=iTmp; } for (i=0; i<iAreasInfoCount; i++) { if (AreasNumber[i]==iSrcIndex) AreasNumber[i]=iDstIndex; } //Декремент кол-ва областей iAreasCount--; } } } } //Запоминание номера области и моды для левой точки iPrevAreaNumbL=iCurrAreaNumb; iPrevModeNumbL=iCurrModeNumb; //Запоминание номера области и моды для верхней левой точки iPrevAreaNumbUL=iPrevAreaNumbU; iPrevModeNumbUL=iPrevModeNumbU; //Запоминание номера области и моды для верхней точки iPrevAreaNumbU=iPrevAreaNumbUR; iPrevModeNumbU=iPrevModeNumbUR; } //Значение яркости последнего пикселя строки iCurrPixel=pImageCurrBuf[Width]; //Значение моды последнего пикселя строки iCurrModeNumb=ModeNumb4Pix[iCurrPixel]; //В зависимости от наличия моды if (iCurrModeNumb<0) { //Левая точка iDelta=abs(pImageCurrBuf[x-1]-iCurrPixel); iCurrAreaNumb=iPrevAreaNumbL; iCurrModeNumb=iPrevModeNumbL; //Верхняя левая точка iTmp=abs(pImagePrevBuf[x-1]-iCurrPixel); if (iDelta>iTmp) { iDelta=iTmp; iCurrAreaNumb=iPrevAreaNumbUL; iCurrModeNumb=iPrevModeNumbUL; } //Верхняя точка iTmp=abs(pImagePrevBuf[x]-iCurrPixel); if (iDelta>iTmp) { iDelta=iTmp; iCurrAreaNumb=iPrevAreaNumbU; iCurrModeNumb=iPrevModeNumbU; } } else if (iCurrModeNumb==iPrevModeNumbL) iCurrAreaNumb=iPrevAreaNumbL; //Левая точка else if (iCurrModeNumb==iPrevModeNumbUL) iCurrAreaNumb=iPrevAreaNumbUL; //Верхняя левая точка else if (iCurrModeNumb==iPrevModeNumbU) iCurrAreaNumb=iPrevAreaNumbU; //Верхняя правая точка else { //Добавление новой области iCurrAreaNumb=AddNewAreaInfo(iCurrModeNumb); } //Установка номера области последнего пикселя строки pAreasCurrBuf[Width]=iCurrAreaNumb; //Ожидание окончания сохранения результата while(DAT_busy(id_SaveTransfer)); //Сохранение строки результата id_SaveTransfer=DAT_copy(pAreasCurrBuf, Areas[y], Width); } //Восстановление исходной ширины изображения Width++; //Упорядочивание переадресации областей (именно здесь)!!!!! for (i=0; i<iAreasInfoCount; i++) { //Номер кластера для текущей области iTmp=AreasNumber[i]; //Пропуск кластерных областей if (iTmp<0) //Установка номера области AreasNumber[i]=i; else //Выключение области AreasMode[i]=-1; } //Могут оставаться независимые области с индексами больше iAreasCount for (iDstIndex=0, iSrcIndex=iAreasCount; iSrcIndex<iAreasInfoCount; iSrcIndex++) { //Если эта область уже переадресована - все нормально if (AreasMode[iSrcIndex]<0) continue; //Поиск индекса для переадресации for (/*задаётся вовне*/; iDstIndex<iAreasCount; iDstIndex++) if (AreasMode[iDstIndex]<0) break; //Сохранение указателя на моду AreasMode[iDstIndex]=AreasMode[iSrcIndex]; //Выключение переадресуемой области AreasMode[iSrcIndex]=-1; //Установка ссылки данной области на переадресованную AreasNumber[iSrcIndex]=iDstIndex; //Замена всех ссылок на эту область!!!!!!!! for (i=0; i<iAreasInfoCount; i++) if (AreasNumber[i]==iSrcIndex) AreasNumber[i]=iDstIndex; } //Загрузка первой строки номеров областей id_LoadTransfer=DAT_copy(Areas[0], AreasBuf[0], Width); //Установка кольцевого указателя iAreasBufIndex=0; //Начальная инициализация идентификатора канала сохранения id_SaveTransfer=DAT_XFRID_WAITNONE; //Обработка всех строк for (y=0; y<Height; y++) { //Указатель на текущую строку результата pAreasCurrBuf=AreasBuf[iAreasBufIndex]; //Продвижение индекса на следующую строку iAreasBufIndex^=1; //Ожидание окончания загрузки текущей строки изображения while(DAT_busy(id_LoadTransfer)); //Запуск загрузки следующей строки изображения id_LoadTransfer=DAT_copy(Areas[y+1], AreasBuf[iAreasBufIndex], Width); //Переписывание индексов удалённых областей на переназначенные for (x=0; x<Width; x++) pAreasCurrBuf[x]=AreasNumber[pAreasCurrBuf[x]]; //Ожидание окончания сохранения результата while(DAT_busy(id_SaveTransfer)); //Сохранение строки результата id_SaveTransfer=DAT_copy(pAreasCurrBuf, Areas[y], Width); } //Ожидание окончания сохранения результата while(DAT_busy(id_SaveTransfer)); return iAreasCount; }