带选择算法的编译时递归排序 P>可以使用C++选择算法< < /P>编写C++中的编译时递归排序函数吗?
我想按升序将数组带选择算法的编译时递归排序 P>可以使用C++选择算法< < /P>编写C++中的编译时递归排序函数吗?,c++,c++11,C++,C++11,我想按升序将数组x从元素istart排序到元素iend。数组x具有N元素。输入数组x中的数据仅在运行时已知,因此只能在运行时对数据进行排序。但是,我想在编译时生成C++代码,即所有的递归函数调用 SoToSyCase](< /代码>)。此外,我想在CUDA设备函数中使用此代码。由于CUDA是C++的一个子集,有少量扩展,我认为这是正确的地方。不幸的是,我认为CUDA不支持constexpr关键字,也不支持Boost和STL 我提出了以下代码,用于按升序排序 // sort in ascendin
x
从元素istart
排序到元素iend
。数组x
具有N
元素。输入数组x
中的数据仅在运行时已知,因此只能在运行时对数据进行排序。但是,我想在编译时生成C++代码,即所有的递归函数调用<代码> SoToSyCase](< /代码>)。此外,我想在CUDA设备函数中使用此代码。由于CUDA是C++的一个子集,有少量扩展,我认为这是正确的地方。不幸的是,我认为CUDA不支持constexpr
关键字,也不支持Boost和STL
我提出了以下代码,用于按升序排序
// sort in ascending order.
template< int istart, int N, int iend, int iend_min_istart >
inline void sort_asc
(
float *x
)
{
int min_idx = istart;
float min_val = x[ min_idx ];
#pragma unroll
for( int i=istart+1; i<N; i++ ){
if( x[ i ] < min_val ){
min_idx = i;
min_val = x[ i ];
}
}
swap( x[ istart ], x[ min_idx ] );
sort_asc< istart+1, N, iend, iend-(istart+1) >( x );
}
交换功能定义为:
void d_swap
(
float &a,
float &b
)
{
float c = a;
a = b;
b = c;
}
然后我将调用排序函数,如下所示:
void main( int argc, char *argv[] )
{
float x[] = { 3, 4, 9, 2, 7 }; // 5 element array.
sort_asc< 0, 5, 2, 2-0 >( x ); // sort from the 1st till the 3th element.
float x_median = cost[ 2 ]; // the 3th element is the median
}
void main(int-argc,char*argv[])
{
浮点x[]={3,4,9,2,7};//5元素数组。
sort_asc<0,5,2,2-0>(x);//从第一个元素到第三个元素进行排序。
浮动x_中位数=成本[2];//第三个元素是中位数
}
但是,由于C++不支持函数的部分模板特化,所以此代码不编译。此外,我不知道如何在C++元编程中编写这个。有什么方法可以让这段代码工作吗?
这次使用选择排序。(.) 没有任何保证,但通过了一个简单的测试:// generate a sequence of integers as non-type template arguments
// (a basic meta-programming tool)
template<int... Is> struct seq {};
template<int N, int... Is> struct gen_seq : gen_seq<N-1, N-1, Is...> {};
template<int... Is> struct gen_seq<0, Is...> : seq<Is...> {};
// an array type that can be returned from a function
// and has `constexpr` accessors (as opposed to C++11's `std::array`)
template<class T, int N>
struct c_array
{
T m[N];
constexpr T const& operator[](int p) const
{ return m[p]; }
constexpr T const* begin() const { return m+0; }
constexpr T const* end() const { return m+N; }
};
// return the index of the smallest element
template<class T, int Size>
constexpr int c_min_index(c_array<T, Size> const& arr, int offset, int cur)
{
return Size == offset ? cur :
c_min_index(arr, offset+1, arr[cur] < arr[offset] ? cur : offset);
}
由于constexpr
函数限制,我们无法修改参数,因此我们需要返回整个数组的一个副本来交换两个元素
函数期望是…
是一个整数序列0,1,2。。大小-1,由gen_seq{}
生成(在其基类中)。这些整数用于访问数组的元素arr
。一些表达式,如arr[Is]…
将生成arr[0]、arr[1]、arr[2]。。arr[Size-1]
。这里,我们通过对当前整数应用一个条件来交换索引:a[0==index0?index1:0==index1?index0:0],…
// the selection sort algorithm
template<class T, int Size>
constexpr c_array<T, Size> c_sel_sort(c_array<T, Size> const& arr, int cur = 0)
{
return cur == Size ? arr :
c_sel_sort( c_swap(arr, cur, c_min_index(arr, cur, cur),
gen_seq<Size>{}),
cur+1 );
}
我想出了下面的元代码,它是有效的
template < class T >
__forceinline void swap
(
T &a,
T &b
)
{
T c = a;
a = b;
b = c;
}
template< int istart, int N, int iend, int iend_min_istart >
class SORT
{
public:
static __forceinline void sort( float *x, int *idx )
{
// sort code.
int min_idx = istart;
float min_val = x[ min_idx ];
for( int i=istart+1; i<N; i++ ){
if( x[ i ] < min_val ){
min_idx = i;
min_val = x[ i ];
}
}
swap( x[ istart ], x[ min_idx ] );
swap( idx[ istart ], idx[ min_idx ] );
SORT<istart+1, N, iend, iend-(istart+1)>::sort( x, idx );
}
};
template< int istart, int N, int iend >
class SORT<istart,N,iend,-1>
{
public:
static __forceinline void sort( float *x, int *idx )
{
}
};
void main( int argc, char *argv[] )
{
float arr[] = {1,4,2,7,5};
int idx[] = {0,1,2,3,4};
SORT<0,5,3,2-0>::sort( arr, idx );
}
模板
__强制无效交换
(
T&a,
T&b酒店
)
{
tc=a;
a=b;
b=c;
}
模板
类排序
{
公众:
静态强制内联无效排序(float*x,int*idx)
{
//排序代码。
int min_idx=istart;
浮动最小值=x[min_idx];
对于(int i=istart+1;i
类排序
{
公众:
静态强制内联无效排序(float*x,int*idx)
{
}
};
void main(int argc,char*argv[])
{
浮点arr[]={1,4,2,7,5};
int idx[]={0,1,2,3,4};
SORT::SORT(arr,idx);
}
Related:通常可以使用重载代替部分专门化。使用std::integral_常量
,让编译器推断N
;另一个重载使用固定的N
,因此在重载解析方面更专业,更受欢迎。Boost解决方案(看起来像一个快速排序)此外,为了使我的问题更具体:输入数组<代码> x>代码>的数据只在运行时才知道,因此数据只能在运行时排序。但是,我想生成C++代码,即所有递归函数调用排序::此外,我想在CUDA设备函数中使用这个代码。因为CUDA是C++的一个子集,有少量扩展,我认为这是正确的地方。不幸的是,我认为CUDA不支持<代码> CONTXPRP<代码>关键字,既不支持Boost也不支持STL。我认为您应该将这部分添加到您的问题中。(作为编辑,而不仅仅是评论),因为这是非常重要的。我很惊讶c_swap
可以如此轻松地实现。我曾预料到会有更多的麻烦。有趣的是,这是用铿锵编译的,而不是g++。@remyabel是的,我在实现合并排序时就已经遇到了这个问题。我认为可以通过传递c_数组来避免这个问题e> 它本身不是指针。@remyabel Voilá,到处使用c_数组
,现在g++4.8.1也很高兴。虽然我不太清楚这是一个铿锵的扩展还是g++错误(倾向于认为是前者)我想它现在也变得更简单了,但不幸的是,它与 CyLaule >非常不同。非常感谢你的详细代码和解释。我很感激。我将深入研究C++的元编程,了解这个代码是如何在引擎盖下工作的。但是如果编译器解决了这个问题,这只是编译时间。作为一种优化,这意味着您得不到可以在需要常量表达式的上下文中使用的结果。@DyP,我有以下情况:输入数组x
中的数据仅在运行时已知,其长度N
,istart
和iend
在编译时已知。(main函数中的代码< >代码> AR/<代码>只是作为示例,但是它的内容在我的应用程序中不在编译时知道),因此,我必须在运行时对数据进行排序。但是,我想生成C++代码,即递归函数调用到<代码>排序::
,用于在编译时将长度为N
的数组从元素istart
排序到元素iend
。编译器会为我这样做吗?这取决于编译器是否实际内联。\u forceinline
,尽管它的名称不同,但并不强制内联(至少对于MSVC++)。但现在您的算法对我来说更有意义;)我建议不要使用我的(constexpr
)进行运行时排序。也许我稍后会添加另一个答案,演示我在对您的问题的评论中提到的重载技巧。它
// the selection sort algorithm
template<class T, int Size>
constexpr c_array<T, Size> c_sel_sort(c_array<T, Size> const& arr, int cur = 0)
{
return cur == Size ? arr :
c_sel_sort( c_swap(arr, cur, c_min_index(arr, cur, cur),
gen_seq<Size>{}),
cur+1 );
}
#include <iostream>
#include <iterator>
int main()
{
// homework: write a wrapper so that C-style arrays can be passed
// to an overload of `c_sel_sort` ;)
constexpr c_array<float,10> f = {{4, 7, 9, 0, 6, 2, 3, 8, 1, 5}};
constexpr auto sorted = c_sel_sort(f);
for(auto const& e : sorted) std::cout << e << ", ";
}
template < class T >
__forceinline void swap
(
T &a,
T &b
)
{
T c = a;
a = b;
b = c;
}
template< int istart, int N, int iend, int iend_min_istart >
class SORT
{
public:
static __forceinline void sort( float *x, int *idx )
{
// sort code.
int min_idx = istart;
float min_val = x[ min_idx ];
for( int i=istart+1; i<N; i++ ){
if( x[ i ] < min_val ){
min_idx = i;
min_val = x[ i ];
}
}
swap( x[ istart ], x[ min_idx ] );
swap( idx[ istart ], idx[ min_idx ] );
SORT<istart+1, N, iend, iend-(istart+1)>::sort( x, idx );
}
};
template< int istart, int N, int iend >
class SORT<istart,N,iend,-1>
{
public:
static __forceinline void sort( float *x, int *idx )
{
}
};
void main( int argc, char *argv[] )
{
float arr[] = {1,4,2,7,5};
int idx[] = {0,1,2,3,4};
SORT<0,5,3,2-0>::sort( arr, idx );
}