21#define blas_unused( var ) ((void)var)
26using llong =
long long;
30class Error:
public std::exception {
38 Error( std::string
const& msg ):
44 Error(
const char* msg,
const char* func ):
46 msg_( std::string(msg) +
", in function " + func )
50 virtual const char*
what() const noexcept
override
51 {
return msg_.c_str(); }
58enum class Layout :
char { ColMajor =
'C', RowMajor =
'R' };
59enum class Op :
char { NoTrans =
'N', Trans =
'T', ConjTrans =
'C' };
60enum class Uplo :
char { Upper =
'U', Lower =
'L', General =
'G' };
61enum class Diag :
char { NonUnit =
'N', Unit =
'U' };
62enum class Side :
char { Left =
'L', Right =
'R' };
64extern const char* Layout_help;
65extern const char* Op_help;
66extern const char* Uplo_help;
67extern const char* Diag_help;
68extern const char* Side_help;
73inline char to_char( Layout value ) {
return char( value ); }
74inline char to_char( Op value ) {
return char( value ); }
75inline char to_char( Uplo value ) {
return char( value ); }
76inline char to_char( Diag value ) {
return char( value ); }
77inline char to_char( Side value ) {
return char( value ); }
79[[deprecated(
"use to_char. To be removed 2025-05.")]]
80inline char layout2char( Layout value ) {
return char( value ); }
82[[deprecated(
"use to_char. To be removed 2025-05.")]]
83inline char op2char( Op value ) {
return char( value ); }
85[[deprecated(
"use to_char. To be removed 2025-05.")]]
86inline char uplo2char( Uplo value ) {
return char( value ); }
88[[deprecated(
"use to_char. To be removed 2025-05.")]]
89inline char diag2char( Diag value ) {
return char( value ); }
91[[deprecated(
"use to_char. To be removed 2025-05.")]]
92inline char side2char( Side value ) {
return char( value ); }
97inline const char* to_c_string( Layout value )
100 case Layout::ColMajor:
return "col";
101 case Layout::RowMajor:
return "row";
106inline const char* to_c_string( Op value )
109 case Op::NoTrans:
return "notrans";
110 case Op::Trans:
return "trans";
111 case Op::ConjTrans:
return "conj";
116inline const char* to_c_string( Uplo value )
119 case Uplo::Lower:
return "lower";
120 case Uplo::Upper:
return "upper";
121 case Uplo::General:
return "general";
126inline const char* to_c_string( Diag value )
129 case Diag::NonUnit:
return "nonunit";
130 case Diag::Unit:
return "unit";
135inline const char* to_c_string( Side value )
138 case Side::Left:
return "left";
139 case Side::Right:
return "right";
147inline std::string to_string( Layout value )
149 return to_c_string( value );
152inline std::string to_string( Op value )
154 return to_c_string( value );
157inline std::string to_string( Uplo value )
159 return to_c_string( value );
162inline std::string to_string( Diag value )
164 return to_c_string( value );
167inline std::string to_string( Side value )
169 return to_c_string( value );
175[[deprecated(
"use to_string or to_c_string. To be removed 2025-05.")]]
176inline const char* layout2str( Layout value )
178 return to_c_string( value );
181[[deprecated(
"use to_string or to_c_string. To be removed 2025-05.")]]
182inline const char* op2str( Op value )
184 return to_c_string( value );
187[[deprecated(
"use to_string or to_c_string. To be removed 2025-05.")]]
188inline const char* uplo2str( Uplo value )
190 return to_c_string( value );
193[[deprecated(
"use to_string or to_c_string. To be removed 2025-05.")]]
194inline const char* diag2str( Diag value )
196 return to_c_string( value );
199[[deprecated(
"use to_string or to_c_string. To be removed 2025-05.")]]
200inline const char* side2str( Side value )
202 return to_c_string( value );
208inline void from_string( std::string
const& str, Layout* val )
210 std::string str_ = str;
211 std::transform( str_.begin(), str_.end(), str_.begin(), ::tolower );
212 if (str_ ==
"c" || str_ ==
"colmajor")
213 *val = Layout::ColMajor;
214 else if (str_ ==
"r" || str_ ==
"rowmajor")
215 *val = Layout::RowMajor;
217 throw Error(
"unknown Layout: " + str );
220inline void from_string( std::string
const& str, Op* val )
222 std::string str_ = str;
223 std::transform( str_.begin(), str_.end(), str_.begin(), ::tolower );
224 if (str_ ==
"n" || str_ ==
"notrans")
226 else if (str_ ==
"t" || str_ ==
"trans")
228 else if (str_ ==
"c" || str_ ==
"conjtrans")
229 *val = Op::ConjTrans;
231 throw Error(
"unknown Op: " + str );
234inline void from_string( std::string
const& str, Uplo* val )
236 std::string str_ = str;
237 std::transform( str_.begin(), str_.end(), str_.begin(), ::tolower );
238 if (str_ ==
"l" || str_ ==
"lower")
240 else if (str_ ==
"u" || str_ ==
"upper")
242 else if (str_ ==
"g" || str_ ==
"general")
243 *val = Uplo::General;
245 throw Error(
"unknown Uplo: " + str );
248inline void from_string( std::string
const& str, Diag* val )
250 std::string str_ = str;
251 std::transform( str_.begin(), str_.end(), str_.begin(), ::tolower );
252 if (str_ ==
"n" || str_ ==
"nonunit")
253 *val = Diag::NonUnit;
254 else if (str_ ==
"u" || str_ ==
"unit")
257 throw Error(
"unknown Diag: " + str );
260inline void from_string( std::string
const& str, Side* val )
262 std::string str_ = str;
263 std::transform( str_.begin(), str_.end(), str_.begin(), ::tolower );
264 if (str_ ==
"l" || str_ ==
"left")
266 else if (str_ ==
"r" || str_ ==
"right")
269 throw Error(
"unknown Side: " + str );
275[[deprecated(
"use from_string. To be removed 2025-05.")]]
276inline Layout char2layout(
char layout )
278 layout = (char) toupper( layout );
279 assert( layout ==
'C' || layout ==
'R' );
280 return Layout( layout );
283[[deprecated(
"use from_string. To be removed 2025-05.")]]
284inline Op char2op(
char op )
286 op = (char) toupper( op );
287 assert( op ==
'N' || op ==
'T' || op ==
'C' );
291[[deprecated(
"use from_string. To be removed 2025-05.")]]
292inline Uplo char2uplo(
char uplo )
294 uplo = (char) toupper( uplo );
295 assert( uplo ==
'L' || uplo ==
'U' || uplo ==
'G' );
299[[deprecated(
"use from_string. To be removed 2025-05.")]]
300inline Diag char2diag(
char diag )
302 diag = (char) toupper( diag );
303 assert( diag ==
'N' || diag ==
'U' );
307[[deprecated(
"use from_string. To be removed 2025-05.")]]
308inline Side char2side(
char side )
310 side = (char) toupper( side );
311 assert( side ==
'L' || side ==
'R' );
325T abs1( std::complex<T> x )
328 return abs( real( x ) ) + abs( imag( x ) );
333#if __cplusplus >= 201402L
334 using std::common_type_t;
337 template <
typename... Ts>
338 using common_type_t =
typename std::common_type< Ts... >::type;
340 template <
typename... Ts>
341 using decay_t =
typename std::decay< Ts... >::type;
348 std::integral_constant<bool, false>
354 std::integral_constant<bool, true>
377 ! is_complex<T>::value,
378 "Usage: using blas::conj; y = conj(x); NOT: y = blas::conj(x);" );
395template <
typename... Types>
396struct scalar_type_traits;
399template <
typename... Types>
400using scalar_type =
typename scalar_type_traits< Types... >::type;
404struct scalar_type_traits< T >
406 using type = decay_t<T>;
411template <
typename T1,
typename T2>
412struct scalar_type_traits< T1, T2 >
414 using type = decay_t< decltype( true ? std::declval<T1>() : std::declval<T2>() ) >;
419template <
typename T1,
typename T2>
420struct scalar_type_traits< std::complex<T1>, T2 >
422 using type = std::complex< common_type_t< T1, T2 > >;
425template <
typename T1,
typename T2>
426struct scalar_type_traits< T1, std::complex<T2> >
428 using type = std::complex< common_type_t< T1, T2 > >;
431template <
typename T1,
typename T2>
432struct scalar_type_traits< std::complex<T1>, std::complex<T2> >
434 using type = std::complex< common_type_t< T1, T2 > >;
438template <
typename T1,
typename T2,
typename... Types>
439struct scalar_type_traits< T1, T2, Types... >
441 using type = scalar_type< scalar_type< T1, T2 >, Types... >;
460template <
typename... Types>
461struct real_type_traits;
464template <
typename... Types>
465using real_type =
typename real_type_traits< Types... >::real_t;
468template <
typename... Types>
469using complex_type = std::complex< real_type< Types... > >;
473struct real_type_traits<T>
480struct real_type_traits< std::complex<T> >
486template <
typename T1,
typename... Types>
487struct real_type_traits< T1, Types... >
489 using real_t = scalar_type< real_type<T1>, real_type< Types... > >;
504template <
typename T1,
typename T2>
508 return (x >= y ? x : y);
512template <
typename T1,
typename... Types>
513scalar_type< T1, Types... >
514 max( T1 first, Types... args )
516 return max( first, max( args... ) );
531template <
typename T1,
typename T2>
535 return (x <= y ? x : y);
539template <
typename T1,
typename... Types>
540scalar_type< T1, Types... >
541 min( T1 first, Types... args )
543 return min( first, min( args... ) );
551template <
typename real_t>
552struct MakeScalarTraits {
553 static real_t make( real_t re, real_t im )
558template <
typename real_t>
559struct MakeScalarTraits< std::complex<real_t> > {
560 static std::complex<real_t> make( real_t re, real_t im )
561 {
return std::complex<real_t>( re, im ); }
564template <
typename scalar_t>
565scalar_t make_scalar( blas::real_type<scalar_t> re,
566 blas::real_type<scalar_t> im=0 )
568 return MakeScalarTraits<scalar_t>::make( re, im );
575template <
typename real_t>
578 return (real_t(0) < val) - (val < real_t(0));
590template <
typename real_t>
591inline const real_t ulp()
593 return std::numeric_limits< real_t >::epsilon();
597template <
typename real_t>
598inline const real_t safe_min()
600 const int fradix = std::numeric_limits<real_t>::radix;
601 const int expm = std::numeric_limits<real_t>::min_exponent;
602 const int expM = std::numeric_limits<real_t>::max_exponent;
604 return max( pow(fradix, expm-1), pow(fradix, 1-expM) );
608template <
typename real_t>
609inline const real_t safe_max()
611 const int fradix = std::numeric_limits<real_t>::radix;
612 const int expm = std::numeric_limits<real_t>::min_exponent;
613 const int expM = std::numeric_limits<real_t>::max_exponent;
615 return min( pow(fradix, 1-expm), pow(fradix, expM-1) );
619template <
typename real_t>
620inline const real_t root_min()
622 return sqrt( safe_min<real_t>() / ulp<real_t>() );
626template <
typename real_t>
627inline const real_t root_max()
629 return sqrt( safe_max<real_t>() * ulp<real_t>() );
638inline void throw_if(
bool cond,
const char* condstr,
const char* func )
641 throw Error( condstr, func );
646 #define BLASPP_ATTR_FORMAT(I, F)
648 #define BLASPP_ATTR_FORMAT(I, F) __attribute__((format( printf, I, F )))
656inline void throw_if(
bool cond,
const char* condstr,
const char* func,
const char* format, ... )
657 BLASPP_ATTR_FORMAT(4, 5);
659inline
void throw_if(
bool cond, const
char* condstr, const
char* func, const
char* format, ... )
664 va_start( va, format );
665 vsnprintf( buf,
sizeof(buf), format, va );
666 throw Error( buf, func );
674inline void abort_if(
bool cond,
const char* func,
const char* format, ... )
675 BLASPP_ATTR_FORMAT(3, 4);
677inline
void abort_if(
bool cond, const
char* func, const
char* format, ... )
682 va_start( va, format );
683 vsnprintf( buf,
sizeof(buf), format, va );
685 fprintf( stderr,
"Error: %s, in function %s\n", buf, func );
690#undef BLASPP_ATTR_FORMAT
696#if defined(BLAS_ERROR_NDEBUG) || (defined(BLAS_ERROR_ASSERT) && defined(NDEBUG))
700 #define blas_error_if( cond ) \
703 #define blas_error_if_msg( cond, ... ) \
706#elif defined(BLAS_ERROR_ASSERT)
709 #define blas_error_if( cond ) \
710 blas::internal::abort_if( cond, __func__, "%s", #cond )
712 #define blas_error_if_msg( cond, ... ) \
713 blas::internal::abort_if( cond, __func__, __VA_ARGS__ )
720 #define blas_error_if( cond ) \
721 blas::internal::throw_if( cond, #cond, __func__ )
726 #define blas_error_if_msg( cond, ... ) \
727 blas::internal::throw_if( cond, #cond, __func__, __VA_ARGS__ )
Exception class for BLAS errors.
Definition util.hh:30
Error(std::string const &msg)
Constructs BLAS error with message.
Definition util.hh:38
Error(const char *msg, const char *func)
Constructs BLAS error with message: "msg, in function func".
Definition util.hh:44
virtual const char * what() const noexcept override
Returns BLAS error message.
Definition util.hh:50
Error()
Constructs BLAS error.
Definition util.hh:33
True if T is std::complex<T2> for some type T2.
Definition util.hh:349