提交 b1e4c90a 编写于 作者: 丁劲犇's avatar 丁劲犇 😸

Add nmcalc

上级 b5f18a03
...@@ -8,3 +8,6 @@ Release ...@@ -8,3 +8,6 @@ Release
debug debug
release release
*.pdb *.pdb
build-*
*.user
*.exe
\ No newline at end of file
...@@ -12,6 +12,10 @@ cpp_threadpool ...@@ -12,6 +12,10 @@ cpp_threadpool
functional助力C++11实现高度可重用接口-线程池例子 functional助力C++11实现高度可重用接口-线程池例子
https://goldenhawking.blog.csdn.net/article/details/51981905 https://goldenhawking.blog.csdn.net/article/details/51981905
nmcalc
一种基于C++STL库的回溯排列组合枚举器
https://goldenhawking.blog.csdn.net/article/details/80037669
omp_threadpool omp_threadpool
C++与OMP配合的最简线程池 C++与OMP配合的最简线程池
https://goldenhawking.blog.csdn.net/article/details/51824243 https://goldenhawking.blog.csdn.net/article/details/51824243
...@@ -36,7 +40,9 @@ string_split ...@@ -36,7 +40,9 @@ string_split
C++11分解字符串 C++11分解字符串
https://goldenhawking.blog.csdn.net/article/details/80833565 https://goldenhawking.blog.csdn.net/article/details/80833565
udp_loss_test
(Win32) QUdpSocket 丢包测试与解决
https://goldenhawking.blog.csdn.net/article/details/105622237
#!/bin/bash
g++ -o nmcalc nmcalc.cpp main.cpp -fopenmp -lgomp -O3
#include <iostream>
#include <vector>
#include <string>
#include <time.h>
#include <stdlib.h>
///包含这个工具文件以使用分组排列组合算法
#include "nmcalc.h"
using namespace NM_CALC; //使用命名空间
using namespace std;
void prepare_task(nmserial<string> * task);
void serial_deal(nmserial<string> * task);
//演示
int main()
{
srand(time(0));
///测试10次
for (int test = 0; test < 10; ++ test)
{
printf ("Test %d:\n",test);
/// 0. 一次联合排列组合由一个状态机完成,状态机可以批量的返回结果,速度非常快。
nmserial<string> state_machine;
/// 设置状态机每次返回的规模
state_machine.set_batch_deal(1024*1024); //每次返回1M个排列组合
state_machine.set_group_deal(65536); //每组内,以该参数为单位记忆缓存提高速度
/// 1. 随机产生排列需求,实际过程中应使用真实数据填写,
/// 元素类型也不一定是string。这里使用string是为了打印美观。
prepare_task(&state_machine);
/// 2. 开始处理,不断获取批量数据
serial_deal(&state_machine);
printf ("\n");
}
printf ("\n Finished.");
return 0;
}
void serial_deal(nmserial<string> * state)
{
///1.准备一个矩阵用来存放结果窗口
std::vector<std::vector<string> > vec_results;
///2.调用开始方法,产生首组结果,返回总共的规模。
unsigned long long totalAmounts = state->serial_nm_begin(vec_results);
printf (" = %lld\n" ,totalAmounts);
///3.不断获取一组排列组合并处理
int currGpsz = vec_results.size();
unsigned long long currDeal = 0;
//最终结果
while (currGpsz)
{
//此处可以并行化
/*
#pragma omp parallel for
for (int gi = 0;gi<currGpsz;++gi)
{
const vector<string> &vec_result = vec_results[gi];
//开始干活,这里只是打印出顺序
}
*/
currDeal += currGpsz;
//打印本组完成时的进度
for (int j = 0; j < state->total_out(); ++j)
printf("%s ",vec_results[currGpsz-1][j].c_str());
printf (",%6.2lf%%\n",double(100.0*currDeal / totalAmounts));
///3.1 获取下一组数据。注意,vec_results 已经分配好内存,不会重复分配
currGpsz = state->serial_nm_next(vec_results);
fflush(stdout);
}//end while (currGpsz)
}
void prepare_task(nmserial<string> * state)
{
//分 serial_count 组
const int serial_count = rand()%2+3;
printf ("serial_count = %d\n",serial_count);
//插入若干字符,准备数据
for (int i=0;i<serial_count;++i)
{
state->vec_groups.push_back(vector<string>());
//为本组追加插入随机个数
int n = rand() % 3 + 3;
int m = n - rand()%2 - 1;
if (i==serial_count-1)
{
m = 6;
n = 10;
}
//通过向量 state.group_m 指定各组的 m
state->group_m.push_back(m);
//插入各组元素
for (int j = 0; j < n; j++)
{
string name;
name.push_back('A' + i);
int ch = j;
string tail;
do
{
string dec;
dec.push_back('0'+ ch % 10);
tail = dec + tail;
ch /= 10;
}while (ch);
name += tail;
state->vec_groups[i].push_back(name);
}
//随机决定本组是 PNM 还是 CNM
if (rand()%2)
{
//通过向量 state.group_type 指定各组的策略是PNM还是CNM
state->group_type.push_back(nmserial<string>::func_CNM);
printf ("C(%d,%d) ",n,m);
}
else
{
//通过向量 state.group_type 指定各组的策略是PNM还是CNM
state->group_type.push_back(nmserial<string>::func_PNM);
printf ("P(%d,%d) ",n,m);
}
}
}
#include "nmcalc.h"
#include <memory.h>
namespace NM_CALC{
/*!
* \brief fnm 产生m组for循环等效的下标组合,初始化状态机
* \param n 每组中for 的规模。 等效 for (int j=0;j<n[i];++j),其中 i 范围 [0~m-1]
* \param m 组数
* \param vec_output 用于存储输出的向量
* \param state 状态机
* \param limit 一次最多返回多少结果
* \return 实际返回的结果数
*/
int fnm(const unsigned long long n[/*m*/], int m, std::vector<std::vector <unsigned long long> > & vec_output,tag_FOR_State * state, int limit/* = 0*/)
{
std::vector<unsigned long long> & vec_buf = state->vec_buf,
& vec_bz = state->vec_bz;
int &swim = state->swim;
bool &finished = state->finished;
if (vec_bz.size()==0)
{
for (int i=0;i<m;++i) vec_buf.push_back(0);
vec_bz.push_back(0);
swim = 0;
finished = false;
}
if (finished==true)
return 0;
int group = 0;
do
{
unsigned long long ch = 0;
if (swim<m)
{
vec_buf[swim] = ch;
++swim;
}
if (swim==m)
{
vec_output.push_back(vec_buf);
++group;
bool hit = false;
do
{
--swim;
if (swim>=0)
{
unsigned long long nextv = vec_buf[swim];
do
{
++nextv;
if (nextv >=n[swim])
break;
hit = true;
} while (hit == false);
if (hit==true)
{
vec_buf[swim] = nextv;
++swim;
}
}
else
finished = true;
} while (finished == false && hit == false);
if (group>=limit && limit>0)
break;
}
}while(finished == false);
return group;
}
/*!
* \brief fnm_next 继续产生m组for循环等效的下标组合
* \param n 每组中for 的规模。 等效 for (int j=0;j<n[i];++j),其中 i 范围 [0~m-1]
* \param m 组数
* \param vec_output 用于存储输出的向量
* \param state 状态机
* \param limit 一次最多返回多少结果
* \return 实际返回的结果数
*/
int fnm_next(const unsigned long long n[/*m*/], int m, std::vector<std::vector <unsigned long long> > & vec_output,tag_FOR_State * state, int limit/* = 0*/)
{
std::vector<unsigned long long> & vec_buf = state->vec_buf,
& vec_bz = state->vec_bz;
int &swim = state->swim;
bool &finished = state->finished;
if (vec_bz.size()==0)
{
for (int i=0;i<m;++i) vec_buf.push_back(0);
vec_bz.push_back(0);
swim = 0;
finished = false;
}
if (finished==true)
return 0;
int group = 0;
do
{
unsigned long long ch = 0;
if (swim<m)
{
vec_buf[swim] = ch;
++swim;
}
if (swim==m)
{
memcpy(vec_output[group].data(),vec_buf.data(),m*sizeof(unsigned long long));
++group;
bool hit = false;
do
{
--swim;
if (swim>=0)
{
unsigned long long nextv = vec_buf[swim];
do
{
++nextv;
if (nextv >=n[swim])
break;
hit = true;
} while (hit == false);
if (hit==true)
{
vec_buf[swim] = nextv;
++swim;
}
}
else
finished = true;
} while (finished == false && hit == false);
if (group>=limit && limit>0)
break;
}
}while(finished == false);
return group;
}
unsigned long long fnm_total(const int n[/*m*/], int m)
{
unsigned long long totalTestsCur = 1;
for (int j = 0;j<m;++j)
totalTestsCur *= n[j];
return totalTestsCur;
}
/*!
\brief pnm 快速算法,使用带有记忆效应的 tag_NM_State 记录穷尽进度很好的避免了重新计算的耗时
\fn pnm
\param n N,集合数
\param m M, 子集
\param vec_output 存储结果的集合,本集合会自动增长
\param state 状态存储
\param limit 本次最多样本数
\return int 本次给出的样本数
*/
int pnm(int n, int m, std::vector<std::vector <unsigned short> > & vec_output,tag_NM_State * state, int limit/* = 0*/)
{
std::vector<unsigned short> & vec_buf = state->vec_buf,
& vec_bz = state->vec_bz;
int &swim = state->swim;
bool &finished = state->finished;
if (vec_bz.size()==0)
{
for (int i=0;i<m;++i) vec_buf.push_back(0);
for (int i=0;i<n;++i) vec_bz.push_back(0);
swim = 0;
finished = false;
}
if (finished==true)
return 0;
int group = 0;
do
{
int ch = 0;
if (swim<m)
{
while (vec_bz[ch])
++ch;
vec_buf[swim] = ch;
vec_bz[ch] = 1;
++swim;
}
if (swim==m)
{
vec_output.push_back(vec_buf);
++group;
bool hit = false;
do
{
if (swim<m && swim >=0) vec_bz[vec_buf[swim]] = 0;
--swim;
if (swim>=0)
{
int nextv = vec_buf[swim];
do
{
++nextv;
if (nextv >=n)
break;
if (vec_bz[nextv]==0)
hit = true;
} while (hit == false);
if (hit==true)
{
vec_bz[vec_buf[swim]] = 0;
vec_buf[swim] = nextv;
vec_bz[nextv] = 1;
++swim;
}
}
else
finished = true;
} while (finished == false && hit == false);
if (group>=limit && limit>0)
break;
}
}while(finished == false);
return group;
}
/*!
\brief pnm_next 使用带有记忆效应的 tag_NM_State 记录穷尽进度很好的避免了重新计算的耗时
\fn pnm_next
\param n N,集合数
\param m M, 子集
\param vec_output 存储结果的集合,本集合必须已经存在!!
\param state 状态存储
\param limit 本次最多样本数
\return int 本次给出的样本数
*/
int pnm_next(int n, int m, std::vector<std::vector <unsigned short> > & vec_output,tag_NM_State * state, int limit/* = 0*/)
{
std::vector<unsigned short> & vec_buf = state->vec_buf,
& vec_bz = state->vec_bz;
int &swim = state->swim;
bool &finished = state->finished;
if (vec_bz.size()==0)
{
for (int i=0;i<m;++i) vec_buf.push_back(0);
for (int i=0;i<n;++i) vec_bz.push_back(0);
swim = 0;
finished = false;
}
if (finished==true)
return 0;
int group = 0;
do
{
int ch = 0;
if (swim<m)
{
while (vec_bz[ch])
++ch;
vec_buf[swim] = ch;
vec_bz[ch] = 1;
++swim;
}
if (swim==m)
{
memcpy(vec_output[group].data(),vec_buf.data(),m*sizeof(unsigned short));
++group;
bool hit = false;
do
{
if (swim<m && swim >=0) vec_bz[vec_buf[swim]] = 0;
--swim;
if (swim>=0)
{
int nextv = vec_buf[swim];
do
{
++nextv;
if (nextv >=n)
break;
if (vec_bz[nextv]==0)
hit = true;
} while (hit == false);
if (hit==true)
{
vec_bz[vec_buf[swim]] = 0;
vec_buf[swim] = nextv;
vec_bz[nextv] = 1;
++swim;
}
}
else
finished = true;
} while (finished == false && hit == false);
if (group>=limit && limit>0)
break;
}
}while(finished == false);
return group;
}
unsigned long long pnm_total(int n, int m)
{
unsigned long long totalTestsCur = 1;
for (int j = 0;j<m;++j)
totalTestsCur *= (n-j);
return totalTestsCur;
}
/*!
\brief cnm 快速算法,使用带有记忆效应的 tag_NM_State 记录穷尽进度很好的避免了重新计算的耗时
\fn cnm
\param n N,集合数
\param m M, 子集
\param vec_output 存储结果的集合,本集合会自动增长
\param state 状态存储
\param limit 本次最多样本数
\return int 本次给出的样本数
*/
int cnm(int n, int m, std::vector<std::vector <unsigned short> > & vec_output,tag_NM_State * state, int limit)
{
std::vector<unsigned short> & vec_buf = state->vec_buf,
& vec_bz = state->vec_bz;
int &swim = state->swim;
bool &finished = state->finished;
if (vec_bz.size()==0)
{
for (int i=0;i<m;++i) vec_buf.push_back(0);
for (int i=0;i<n;++i) vec_bz.push_back(0);
swim = 0;
finished = false;
}
if (finished==true)
return 0;
int group = 0;
do
{
int ch = 0;
if (swim>0 && swim < m)
ch = vec_buf[swim-1];
if (swim<m)
{
bool hit = false;
while (ch < n && !hit)
{
if (vec_bz[ch]==0) hit = true;
else
++ch;
}
if (hit)
{
vec_buf[swim] = ch;
vec_bz[ch] = 1;
++swim;
}
else
while (!hit && finished==false)
{
//回溯
if (swim<m && swim >=0) vec_bz[vec_buf[swim]] = 0;
--swim;
if (swim>=0)
{
int nextv = vec_buf[swim];
do
{
++nextv;
if (nextv >=n)
break;
if (vec_bz[nextv]==0)
hit = true;
} while (hit == false);
if (hit==true)
{
vec_bz[vec_buf[swim]] = 0;
vec_buf[swim] = nextv;
vec_bz[nextv] = 1;
++swim;
}
}
else
finished = true;
}
}
if (swim==m && finished==false)
{
vec_output.push_back(vec_buf);
if (group>=limit && limit>0)
break;
++group;
bool hit = false;
do
{
if (swim<m && swim >=0) vec_bz[vec_buf[swim]] = 0;
--swim;
if (swim>=0)
{
int nextv = vec_buf[swim];
do
{
++nextv;
if (nextv >=n)
break;
if (vec_bz[nextv]==0)
hit = true;
} while (hit == false);
if (hit==true)
{
vec_bz[vec_buf[swim]] = 0;
vec_buf[swim] = nextv;
vec_bz[nextv] = 1;
++swim;
}
}
else
finished = true;
} while (finished == false && hit == false);
}
}while(finished == false);
return group;
}
/*!
\brief cnm 快速算法,使用带有记忆效应的 tag_NM_State 记录穷尽进度很好的避免了重新计算的耗时
\fn cnm_next
\param n N,集合数
\param m M, 子集
\param vec_output 存储结果的集合,本集合必须已经存在!!
\param state 状态存储
\param limit 本次最多样本数
\return int 本次给出的样本数
*/
int cnm_next(int n, int m, std::vector<std::vector <unsigned short> > & vec_output,tag_NM_State * state, int limit)
{
std::vector<unsigned short> & vec_buf = state->vec_buf,
& vec_bz = state->vec_bz;
int &swim = state->swim;
bool &finished = state->finished;
if (vec_bz.size()==0)
{
for (int i=0;i<m;++i) vec_buf.push_back(0);
for (int i=0;i<n;++i) vec_bz.push_back(0);
swim = 0;
finished = false;
}
if (finished==true)
return 0;
int group = 0;
do
{
int ch = 0;
if (swim>0 && swim < m)
ch = vec_buf[swim-1];
if (swim<m)
{
bool hit = false;
while (ch < n && !hit)
{
if (vec_bz[ch]==0) hit = true;
else
++ch;
}
if (hit)
{
vec_buf[swim] = ch;
vec_bz[ch] = 1;
++swim;
}
else
while (!hit && finished==false)
{
//回溯
if (swim<m && swim >=0) vec_bz[vec_buf[swim]] = 0;
--swim;
if (swim>=0)
{
int nextv = vec_buf[swim];
do
{
++nextv;
if (nextv >=n)
break;
if (vec_bz[nextv]==0)
hit = true;
} while (hit == false);
if (hit==true)
{
vec_bz[vec_buf[swim]] = 0;
vec_buf[swim] = nextv;
vec_bz[nextv] = 1;
++swim;
}
}
else
finished = true;
}
}
if (swim==m && finished==false)
{
memcpy(vec_output[group].data(),vec_buf.data(),m*sizeof(unsigned short));
if (group>=limit && limit>0)
break;
++group;
bool hit = false;
do
{
if (swim<m && swim >=0) vec_bz[vec_buf[swim]] = 0;
--swim;
if (swim>=0)
{
int nextv = vec_buf[swim];
do
{
++nextv;
if (nextv >=n)
break;
if (vec_bz[nextv]==0)
hit = true;
} while (hit == false);
if (hit==true)
{
vec_bz[vec_buf[swim]] = 0;
vec_buf[swim] = nextv;
vec_bz[nextv] = 1;
++swim;
}
}
else
finished = true;
} while (finished == false && hit == false);
}
}while(finished == false);
return group;
}
unsigned long long cnm_total(int n, int m)
{
unsigned long long totalTestsCur = 1;
for (int j = 0;j<m;++j)
totalTestsCur *= (n-j);
for (int j = 0;j<m;++j)
totalTestsCur /= (j+1);
return totalTestsCur;
}
}
#pragma once
#include <vector>
#include <assert.h>
#include <functional>
namespace NM_CALC{
struct tag_NM_State
{
std::vector<unsigned short> vec_buf;
std::vector<unsigned short> vec_bz;
int swim;
bool finished;
};
struct tag_FOR_State
{
std::vector<unsigned long long> vec_buf;
std::vector<unsigned long long> vec_bz;
int swim;
bool finished;
};
//快速for算法,m组,每组for规模为n
int fnm(const unsigned long long n[/*m*/], int m, std::vector<std::vector <unsigned long long> > & vec_output,tag_FOR_State * state, int limit = 0);
//预分配vec_output排列算法
int fnm_next(const unsigned long long n[/*m*/], int m, std::vector<std::vector <unsigned long long> > & vec_output,tag_FOR_State * state, int limit = 0);
unsigned long long fnm_total(const int n[/*m*/], int m);
//快速排列算法
int pnm(int n, int m, std::vector<std::vector <unsigned short> > & vec_output,tag_NM_State * state, int limit = 0);
//预分配vec_output排列算法
int pnm_next(int n, int m, std::vector<std::vector <unsigned short> > & vec_output,tag_NM_State * state, int limit = 0);
//规模
unsigned long long pnm_total(int n, int m);
//快速组合算法
int cnm(int n, int m, std::vector<std::vector <unsigned short> > & vec_output,tag_NM_State * state, int limit = 0);
//预分配vec_output组合算法
int cnm_next(int n, int m, std::vector<std::vector <unsigned short> > & vec_output,tag_NM_State * state, int limit = 0);
//规模
unsigned long long cnm_total(int n, int m);
//多组串联排列组合类,可选择每组采用的策略
/*! 联合排列组合类
* 可任意指定分组个数、每组策略(P,C)和规模
*/
template <class T>
class nmserial
{
public:
enum enum_function{
func_PNM = 0,
func_CNM = 1
};
public:
std::vector<std::vector< T > > vec_groups;
std::vector<int> group_m;
std::vector<enum_function> group_type;//0:PNM, 1:CNM, 2: FNM
public:
nmserial()
:batch_deal(65536),group_deal(4096),
serial_count(0),totaltask(1),m_totalout(0),
nFNm(0)
{}
void set_batch_deal(int d){batch_deal = d;} //设置每波数据最多返回多少
void set_group_deal(int d){group_deal = d;} //设置每组排列组合中,窗口记忆多少结果。
int get_batch_deal() const {return batch_deal;}
int get_group_deal() const {return group_deal;}
//取得总的计算规模
unsigned long long total_task() const { return totaltask;}
//输出有多少元素,即每组m的和
int total_out() const { return m_totalout;}
private:
std::vector<std::function<unsigned long long (const int n, int m)> > vec_nmfunc_total;
std::vector<std::function<int (int n, int m, std::vector<std::vector <unsigned short> > & vec_output,tag_NM_State * state, int limit)> > vec_nmfunc_initial;
std::vector<std::function<int (int n, int m, std::vector<std::vector <unsigned short> > & vec_output,tag_NM_State * state, int limit)> > vec_nmfunc_next;
int batch_deal;
int group_deal;
int serial_count;
std::vector<int> vec_chars_n;
std::vector<unsigned long long> vec_chars_pnm;
std::vector<int> vec_char_out_group;
std::vector<int> vec_char_out_offset;
unsigned long long totaltask;
int m_totalout;
//fnm
tag_FOR_State g_state;
std::vector<std::vector < unsigned long long> > vec_fnm;
int nFNm;
//各组
std::vector<std::vector<std::vector <unsigned short> > > vec_states_pnm;
std::vector<tag_NM_State> vec_states;
std::vector<unsigned long long> vec_states_gp;
std::vector<int> vec_states_size;
public:
/*!
* \brief serial_nm_begin 初始化一次任务
* \param vec_results 用于存放任务结果的矩阵
* \return 总规模
*/
unsigned long long serial_nm_begin(
std::vector<std::vector<T> > & vec_results);
/*!
* \brief serial_nm_next 获得下一组结果集合
* \param vec_results 用于存放任务结果的矩阵
* \return 本次有效的结果个数
*/
int serial_nm_next(
std::vector<std::vector<T> > & vec_results);
};
template <class T>
unsigned long long nmserial<T>::serial_nm_begin(
std::vector<std::vector<T> > & vec_results)
{
assert(this->serial_count==0);
assert(group_m.size()==vec_groups.size() && group_type.size() == group_m.size());
assert(group_m.size()>0);
//分组
this->serial_count = this->vec_groups.size();
for (int i=0;i<this->serial_count;++i)
{
const int n = this->vec_groups[i].size();
const int m = this->group_m[i];
assert(m<=n);
switch (group_type[i])
{
case func_PNM:
vec_nmfunc_total.push_back(pnm_total);
vec_nmfunc_initial.push_back(pnm);
vec_nmfunc_next.push_back(pnm_next);
break;
case func_CNM:
vec_nmfunc_total.push_back(cnm_total);
vec_nmfunc_initial.push_back(cnm);
vec_nmfunc_next.push_back(cnm_next);
break;
default:
assert(false);
}
this->vec_chars_n.push_back(n);
this->vec_chars_pnm.push_back(vec_nmfunc_total[i](n,m));
this->totaltask *= this->vec_chars_pnm[i];
for (int j = 0; j < m; j++)
{
this->vec_char_out_group.push_back(i);
this->vec_char_out_offset.push_back(j);
}
this->m_totalout += m;
}
//开始进行串联排列
const int * pFNs = this->vec_chars_n.data();
const int * pFMs = this->group_m.data();
const unsigned long long * pPNMs = this->vec_chars_pnm.data();
//fnm
fnm(pPNMs,this->serial_count,this->vec_fnm,&this->g_state,this->batch_deal);
this->nFNm = this->vec_fnm.size();
//各组
for (int i=0;i<this->serial_count;++i)
{
this->vec_states_pnm.push_back(std::vector<std::vector <unsigned short> >());
this->vec_states.push_back(tag_NM_State());
this->vec_states_gp.push_back(0);
vec_nmfunc_initial[i](pFNs[i],pFMs[i],this->vec_states_pnm[i],&this->vec_states[i],this->group_deal);
this->vec_states_size.push_back(this->vec_states_pnm[i].size());
}
//最终结果
if (this->nFNm)
{
for (int group = 0; group < this->nFNm; ++group)
{
std::vector<T> vec_result;
vec_result.resize(this->m_totalout);
//按照顺序填写vec_result
bool bad = false;
for (int ci=0;ci<this->m_totalout && bad==false;++ci)
{
//第几组,即 vec_states_pnm的第几行
const int serial_group = this->vec_char_out_group[ci];
//判断本组是不是需要进行下一轮生成
const unsigned long long npnmCt = this->vec_fnm[group][serial_group];
const unsigned long long npnmGp = npnmCt / this->group_deal;
//如果要访问当前状态机之前的组合,则重新PNM
if (npnmGp < this->vec_states_gp[serial_group])
{
this->vec_states_pnm[serial_group] = (std::vector<std::vector <unsigned short> >());
this->vec_states[serial_group] = tag_NM_State();
this->vec_states_gp[serial_group] = 0;
vec_nmfunc_initial[serial_group](pFNs[serial_group],pFMs[serial_group],
this->vec_states_pnm[serial_group],&this->vec_states[serial_group],this->group_deal);
this->vec_states_size[serial_group]= this->vec_states_pnm[serial_group].size();
}//end if (npnmGp < vec_states_gp[serial_group])
//追赶进度
while (npnmGp > this->vec_states_gp[serial_group]&&bad==false)
{
++this->vec_states_gp[serial_group];
this->vec_states_size[serial_group] = vec_nmfunc_next[serial_group](
pFNs[serial_group],
pFMs[serial_group],
this->vec_states_pnm[serial_group],
&this->vec_states[serial_group],this->group_deal);
if (this->vec_states_size[serial_group]==0)
bad = true;
}//end while (npnmGp > vec_states_gp[serial_group]&&bad==false)
if (bad)
continue;
//计算本组排列组合里的下标
const int curPNMIdx = npnmCt % this->group_deal;
if (curPNMIdx>=this->vec_states_size[serial_group])
{
bad = true;
continue;
}
//取得索引位置
const int sfidx = this->vec_states_pnm[serial_group][curPNMIdx][this->vec_char_out_offset[ci]];
vec_result[ci] = this->vec_groups[serial_group][sfidx];
}//end for (int ci=0;ci<total_out && bad==false;++ci)
if (bad)
continue;
//生成了一组PNM
vec_results.push_back(std::move(vec_result));
}//end for (int group = 0; group < nFNm; ++group)
}//end while (nFNm)
return this->totaltask;
}
template <class T>
int nmserial<T>::serial_nm_next(
std::vector<std::vector<T> > & vec_results)
{
if (this->serial_count==0)
return 0;
//开始进行串联排列
const int * pFNs = this->vec_chars_n.data();
const int * pFMs = this->group_m.data();
const unsigned long long * pPNMs = this->vec_chars_pnm.data();
//最终结果
//下一组
this->nFNm = fnm_next(pPNMs,this->serial_count,this->vec_fnm,&this->g_state,this->batch_deal);
if (this->nFNm)
{
for (int group = 0; group < this->nFNm; ++group)
{
std::vector<T> vec_result;
vec_result.resize(this->m_totalout);
//按照顺序填写vec_result
bool bad = false;
for (int ci=0;ci<this->m_totalout && bad==false;++ci)
{
//第几组,即 vec_states_pnm的第几行
const int serial_group = this->vec_char_out_group[ci];
//判断本组是不是需要进行下一轮生成
const unsigned long long npnmCt = this->vec_fnm[group][serial_group];
const unsigned long long npnmGp = npnmCt / this->group_deal;
//如果要访问当前状态机之前的组合,则重新PNM
if (npnmGp < this->vec_states_gp[serial_group])
{
this->vec_states_pnm[serial_group] = (std::vector<std::vector <unsigned short> >());
this->vec_states[serial_group] = tag_NM_State();
this->vec_states_gp[serial_group] = 0;
vec_nmfunc_initial[serial_group](pFNs[serial_group],pFMs[serial_group],
this->vec_states_pnm[serial_group],&this->vec_states[serial_group],this->group_deal);
this->vec_states_size[serial_group]= this->vec_states_pnm[serial_group].size();
}//end if (npnmGp < vec_states_gp[serial_group])
//追赶进度
while (npnmGp > this->vec_states_gp[serial_group]&&bad==false)
{
++this->vec_states_gp[serial_group];
this->vec_states_size[serial_group] = vec_nmfunc_next[serial_group](
pFNs[serial_group],
pFMs[serial_group],
this->vec_states_pnm[serial_group],
&this->vec_states[serial_group],this->group_deal);
if (this->vec_states_size[serial_group]==0)
bad = true;
}//end while (npnmGp > vec_states_gp[serial_group]&&bad==false)
if (bad)
continue;
//计算本组排列组合里的下标
const int curPNMIdx = npnmCt % this->group_deal;
if (curPNMIdx>=this->vec_states_size[serial_group])
{
bad = true;
continue;
}
//取得索引位置
const int sfidx = this->vec_states_pnm[serial_group][curPNMIdx][this->vec_char_out_offset[ci]];
vec_result[ci] = this->vec_groups[serial_group][sfidx];
}//end for (int ci=0;ci<total_out && bad==false;++ci)
if (bad)
continue;
//生成了一组PNM
vec_results[group] = std::move(vec_result);
}//end for (int group = 0; group < nFNm; ++group)
}//end if (nFNm)
return this->nFNm;
}
}
QT += core
QT -= gui
CONFIG += c++11
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
QMAKE_CXXFLAGS += -fopenmp
QMAKE_LIBS += -lgomp
# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
HEADERS += \
nmcalc.h
SOURCES += \
main.cpp \
nmcalc.cpp
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册