分享一下最近的成果0.0
时间:2013-05-10
来源:互联网
不过其实都不算最近的了....算起上来都写了很多个月
先来一个mutiarray的DFT算法...这个是用来作正确性测试 (((效率很糟糕
这个其实是半完成品...因为Cooley Tukey algorithm只能使用在合数长度
对於质数的要另外再写个Rader's algorithm...但还是未能想出有效的解决primitive root的问题
先来一个mutiarray的DFT算法...这个是用来作正确性测试 (((效率很糟糕
复制内容到剪贴板
std::complex<type> DFT(const multiarraycase<type, Rank, Allocator> &buffer, size_t idx)
{
typedef multiarraycase<type, Rank, Allocator>::base_array base_array;
size_t d = idx / buffer.size(0, 2);
type factor = -(type)2 * (type)M_PI * (type)d / (type)buffer.size(0);
std::complex<type> result(0, 0);
__if_exists(base_array::type)
{
for(size_t i = 0; i < buffer.size(0); ++i)
result += DFT(buffer, idx % buffer.size(0, 2)) * polar<type>(1, (type)i * factor);
}
__if_not_exists(base_array::type)
{
for(size_t i = 0; i < buffer.size(0); ++i)
result += polar<type>(buffer, (type)i * factor);
}
return result;
}
FFT算法...使用了Cooley Tukey algorithm...代码:
template <typename type, size_t Rank, typename Allocator>std::complex<type> DFT(const multiarraycase<type, Rank, Allocator> &buffer, size_t idx)
{
typedef multiarraycase<type, Rank, Allocator>::base_array base_array;
size_t d = idx / buffer.size(0, 2);
type factor = -(type)2 * (type)M_PI * (type)d / (type)buffer.size(0);
std::complex<type> result(0, 0);
__if_exists(base_array::type)
{
for(size_t i = 0; i < buffer.size(0); ++i)
result += DFT(buffer, idx % buffer.size(0, 2)) * polar<type>(1, (type)i * factor);
}
__if_not_exists(base_array::type)
{
for(size_t i = 0; i < buffer.size(0); ++i)
result += polar<type>(buffer, (type)i * factor);
}
return result;
}
这个其实是半完成品...因为Cooley Tukey algorithm只能使用在合数长度
对於质数的要另外再写个Rader's algorithm...但还是未能想出有效的解决primitive root的问题
复制内容到剪贴板
multiarray<std::complex<type>, Rank> &_FourierTransform(const multiarray<arg_type, Rank> &buffer, const bool inverse,
multiarray<std::complex<type>, Rank> &result)
{
size_t size = buffer.size(0);
result._base::reshape(buffer.shape().begin(),
(multiarray<arg_type, Rank>::pointer)nullptr, (multiarray<arg_type, Rank>::pointer)nullptr);
parallel_for(size, [&, inverse](size_t idx) -> void
{
multiarray<std::complex<type>, Rank - 1> row;
FourierTransform<type, arg_type, Rank - 1>(buffer[idx], inverse, row);
std::copy(row.begin(), row.end(), result[idx].begin());
});
return result;
}
template <typename type, typename arg_type>
multiarray<std::complex<type>> &CooleyTukey(const multiarray<arg_type> &buffer, const size_t radix, const bool inverse,
multiarray<std::complex<type>> &result)
{
const size_t N = buffer.size(), index[2][2] = {{radix, N / radix}, {N / radix, radix}};
const std::complex<type> TwiddleFactor = std::polar<type>(1, (type)(inverse ? -1 : 1) * (type)2 * (type)M_PI / (type)N);
multiarray<arg_type, 2> temp(index[1], buffer.begin(), buffer.end());
Transpose(temp, temp)._base::reshape(index[0], (multiarray<arg_type, 2>::pointer)nullptr, (multiarray<arg_type, 2>::pointer)nullptr);
multiarray<std::complex<type>, 2> reorder;
Transpose(_FourierTransform<type, arg_type>(temp, inverse, reorder), reorder);
for(size_t i = 0; i < reorder.size(0); ++i)
for(size_t j = 0; j < reorder.size(1); ++j)
reorder[j] *= std::pow<type>(TwiddleFactor, (type)i * (type)j);
Transpose(_FourierTransform<type, std::complex<type>>(reorder, inverse, reorder), reorder);
result.reshape(N);
std::copy(reorder.begin(), reorder.end(), result.begin());
return result;
}
template <typename type, typename arg_type, size_t Rank>
multiarray<std::complex<type>, Rank> &FourierTransform(const multiarray<arg_type, Rank> &buffer, const bool inverse,
multiarray<std::complex<type>, Rank> &result)
{
typedef multiarray<type, Rank>::base_array base_array;
__if_exists(base_array::type)
{
const size_t index[2] = {buffer.size(0), buffer.size(0, 2)};
multiarray<std::complex<type>, 2> reorder(index[0], index[1]);
multiarray<std::complex<type>, Rank> rows;
_FourierTransform<type, arg_type, Rank>(buffer, inverse, rows);
std::copy(rows.begin(), rows.end(), reorder.begin());
Transpose(reorder, reorder);
_FourierTransform<type, std::complex<type>>(reorder, inverse, reorder);
Transpose(reorder, reorder);
for(size_t i = 0; i < Rank; ++i)
result.reshape(i + 1, buffer.size(i));
std::copy(reorder.begin(), reorder.end(), result.begin());
}
__if_not_exists(base_array::type)
{
const size_t N = buffer.size();
const std::complex<type> TwiddleFactor = std::polar<type>(1, (type)(inverse ? -1 : 1) * (type)2 * (type)M_PI / (type)N);
switch(N)
{
case 0:
break;
case 1:
result.reshape(N);
result[0] = buffer[0];
break;
case 2:
{
multiarray<arg_type> temp(buffer);
result.reshape(N);
result[0] = temp[0] + temp[1];
result[1] = temp[0] + temp[1] * TwiddleFactor;
}
break;
default:
CooleyTukey<type, arg_type>(buffer, 2, inverse, result); //这里只要把2给改了就可以变成mixed radix...至於合数分解这方面问题还未有时间处理
}
if(inverse)
{
for(auto &value : result)
value /= (type)N;
}
}
return result;
}
[ 本帖最后由 Susan﹏汪汪 於 2013-5-10 01:07 PM 编辑 ] 代码:
template <typename type, typename arg_type, size_t Rank>multiarray<std::complex<type>, Rank> &_FourierTransform(const multiarray<arg_type, Rank> &buffer, const bool inverse,
multiarray<std::complex<type>, Rank> &result)
{
size_t size = buffer.size(0);
result._base::reshape(buffer.shape().begin(),
(multiarray<arg_type, Rank>::pointer)nullptr, (multiarray<arg_type, Rank>::pointer)nullptr);
parallel_for(size, [&, inverse](size_t idx) -> void
{
multiarray<std::complex<type>, Rank - 1> row;
FourierTransform<type, arg_type, Rank - 1>(buffer[idx], inverse, row);
std::copy(row.begin(), row.end(), result[idx].begin());
});
return result;
}
template <typename type, typename arg_type>
multiarray<std::complex<type>> &CooleyTukey(const multiarray<arg_type> &buffer, const size_t radix, const bool inverse,
multiarray<std::complex<type>> &result)
{
const size_t N = buffer.size(), index[2][2] = {{radix, N / radix}, {N / radix, radix}};
const std::complex<type> TwiddleFactor = std::polar<type>(1, (type)(inverse ? -1 : 1) * (type)2 * (type)M_PI / (type)N);
multiarray<arg_type, 2> temp(index[1], buffer.begin(), buffer.end());
Transpose(temp, temp)._base::reshape(index[0], (multiarray<arg_type, 2>::pointer)nullptr, (multiarray<arg_type, 2>::pointer)nullptr);
multiarray<std::complex<type>, 2> reorder;
Transpose(_FourierTransform<type, arg_type>(temp, inverse, reorder), reorder);
for(size_t i = 0; i < reorder.size(0); ++i)
for(size_t j = 0; j < reorder.size(1); ++j)
reorder[j] *= std::pow<type>(TwiddleFactor, (type)i * (type)j);
Transpose(_FourierTransform<type, std::complex<type>>(reorder, inverse, reorder), reorder);
result.reshape(N);
std::copy(reorder.begin(), reorder.end(), result.begin());
return result;
}
template <typename type, typename arg_type, size_t Rank>
multiarray<std::complex<type>, Rank> &FourierTransform(const multiarray<arg_type, Rank> &buffer, const bool inverse,
multiarray<std::complex<type>, Rank> &result)
{
typedef multiarray<type, Rank>::base_array base_array;
__if_exists(base_array::type)
{
const size_t index[2] = {buffer.size(0), buffer.size(0, 2)};
multiarray<std::complex<type>, 2> reorder(index[0], index[1]);
multiarray<std::complex<type>, Rank> rows;
_FourierTransform<type, arg_type, Rank>(buffer, inverse, rows);
std::copy(rows.begin(), rows.end(), reorder.begin());
Transpose(reorder, reorder);
_FourierTransform<type, std::complex<type>>(reorder, inverse, reorder);
Transpose(reorder, reorder);
for(size_t i = 0; i < Rank; ++i)
result.reshape(i + 1, buffer.size(i));
std::copy(reorder.begin(), reorder.end(), result.begin());
}
__if_not_exists(base_array::type)
{
const size_t N = buffer.size();
const std::complex<type> TwiddleFactor = std::polar<type>(1, (type)(inverse ? -1 : 1) * (type)2 * (type)M_PI / (type)N);
switch(N)
{
case 0:
break;
case 1:
result.reshape(N);
result[0] = buffer[0];
break;
case 2:
{
multiarray<arg_type> temp(buffer);
result.reshape(N);
result[0] = temp[0] + temp[1];
result[1] = temp[0] + temp[1] * TwiddleFactor;
}
break;
default:
CooleyTukey<type, arg_type>(buffer, 2, inverse, result); //这里只要把2给改了就可以变成mixed radix...至於合数分解这方面问题还未有时间处理
}
if(inverse)
{
for(auto &value : result)
value /= (type)N;
}
}
return result;
}
作者: Susan﹏汪汪 发布时间: 2013-05-10
感觉上用C++11写threading的确很方便...喜欢了这玩意XD
复制内容到剪贴板
{
if(count > MAX_PARALLEL_NUM)
{
std::thread pThread[MAX_PARALLEL_NUM];
const size_t blocksize = count % MAX_PARALLEL_NUM ? count / MAX_PARALLEL_NUM + 1 : count / MAX_PARALLEL_NUM;
for(size_t i = 0; i < MAX_PARALLEL_NUM; ++i)
{
const size_t start = blocksize * i, end = count < start + blocksize ? count : start + blocksize;
pThread = std::thread([](const std::function<void(size_t)> &functor, const size_t start, const size_t end) -> void
{
for(size_t i = start; i < end; ++i)
functor(i);
}, std::ref(functor), start, end);
}
for(size_t i = 0; i < MAX_PARALLEL_NUM; ++i)
pThread.join();
} else
for(size_t i = 0; i < count; ++i)
functor(i);
}
[ 本帖最后由 Susan﹏汪汪 於 2013-5-10 01:26 PM 编辑 ] 代码:
void parallel_for(const size_t count, const std::function<void(size_t)> &functor){
if(count > MAX_PARALLEL_NUM)
{
std::thread pThread[MAX_PARALLEL_NUM];
const size_t blocksize = count % MAX_PARALLEL_NUM ? count / MAX_PARALLEL_NUM + 1 : count / MAX_PARALLEL_NUM;
for(size_t i = 0; i < MAX_PARALLEL_NUM; ++i)
{
const size_t start = blocksize * i, end = count < start + blocksize ? count : start + blocksize;
pThread = std::thread([](const std::function<void(size_t)> &functor, const size_t start, const size_t end) -> void
{
for(size_t i = start; i < end; ++i)
functor(i);
}, std::ref(functor), start, end);
}
for(size_t i = 0; i < MAX_PARALLEL_NUM; ++i)
pThread.join();
} else
for(size_t i = 0; i < count; ++i)
functor(i);
}
作者: Susan﹏汪汪 发布时间: 2013-05-10
相关阅读 更多
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28