C语言高效实现向量循环移位

2020-01-06 20:15:53于海丽

 


//#define __LINUX__
#define __WINDOWS__
 
#include <stdio.h>
#ifdef __WINDOWS__
#include <memory.h>
#include <Windows.h>
#endif
#ifdef __LINUX__
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
#endif
 
#define cntoffun          3
#define cntofi              80
#define start              20
 
#ifdef __WINDOWS__
#define mintomillsec        (60*1000)
#define sectomillsec        1000
#endif
#ifdef __LINUX__
#define sectomicrosec      (1e6)
#define microsectomillisec  (1e-3)
#define startp              0
#define endp              1
#endif
 
/*i from 21 to 100*/
#define v_length            10000000
char vec[v_length];
 
int gcd(int n, int i);
void swap(char *a,char *b);
void loopshift_gcd(char v[],int i,int high);
void recshift(char v[],int i,int low,int high);
void reverse(char v[],int low,int high);
void reverseshift(char v[],int i,int high);
typedef int DWORD;
 
int main()
{
#ifdef __WINDOWS__
 SYSTEMTIME tm;
#endif
#ifdef __LINUX__
 struct timeval tv[2];
#endif
 
 char colofline[]="yrb";
 DWORD s_millsec,e_millsec;
 FILE *fp;
 int i,j;
 size_t timearray[cntoffun][cntofi];
 memset(vec,0,sizeof(vec));
 memset(timearray,0,sizeof(timearray));
 
#ifdef __WINDOWS__
 fp=fopen("F:gettimeofrp.m","w");
#endif
#ifdef __LINUX__
 fp=fopen("/home/raine/Desktop/gettimeofrp.m","w");
#endif
 
 for(j=0;j<cntoffun;j++)
 {
 for(i=start+1;i<=(start+cntofi);i++)
 {
  printf("func[%d]tcount_of_shift[%d]t",j,i);
#ifdef __WINDOWS__
  GetLocalTime(&tm);
  s_millsec=tm.wMinute*mintomillsec+tm.wSecond*sectomillsec+ 
                    tm.wMilliseconds;
#endif
#ifdef __LINUX__
  gettimeofday(&tv[startp],NULL);
#endif
 
  if (j==0)
  loopshift_gcd(vec,i,v_length-1);
  else if (j==1)
  recshift(vec,i,0,v_length-1);
  else
  reverseshift(vec,i,v_length-1);
  
#ifdef __WINDOWS__
  GetLocalTime(&tm);
  e_millsec=tm.wMinute*mintomillsec+tm.wSecond*sectomillsec+ 
                    tm.wMilliseconds;
  timearray[j][i-start-1] = e_millsec - s_millsec;
#endif
#ifdef __LINUX__
  gettimeofday(&tv[endp],NULL);
  timearray[j][i-start-1] = ((tv[endp].tv_sec-tv[startp].tv_sec)*sectomicrosec+
                  (tv[endp].tv_usec-tv[startp].tv_usec))*microsectomillisec; 
#endif
  printf("use time %dn",timearray[j][i-start-1]);
 }
 }
 
 /*matlab code*/
 fprintf(fp,"clear;nclc;nord_x=[...n");
 for(i=start+1;i<=(start+cntofi);i++)
 {
 fprintf(fp,"%d ",i);
 if(i%10==0) fprintf(fp,"...n");
 }
 fprintf(fp,"];nn");
 for(i=0;i<cntoffun;i++)
 { 
 fprintf(fp,"ord_yfunc%d=[...n",i+1);
 for(j=0;j<cntofi;j++)
 {
  fprintf(fp,"%d ",timearray[i][j]);
  if ((j+1)%10 == 0) fprintf(fp,"...n");
 }
 fprintf(fp,"];nn");
 }
 fprintf(fp,"title('performance of three function');n");
 fprintf(fp,"xlabel('x=[21:100]');n");
 fprintf(fp,"ylabel('the time three function use(millisecond)');n");
 fprintf(fp,"hold on;n");
 for(i=0;i<cntoffun;i++)
 fprintf(fp,"plot(ord_x,ord_yfunc%d,'%c*-');n",i+1,colofline[i]);
 fprintf(fp,"legend('func1'");
 for(i=1;i<cntoffun;i++)
 fprintf(fp,",'func%d'",i+1);
 fprintf(fp,");");
 fclose(fp);
 
 printf("nhave been finished,press any key to quit ^ ^n");
#ifdef __WINDOWS__
 system("pause");
#endif
}
 
void swap(char *a,char *b)
{
 char temp=*a;*a=*b;*b=temp;
}
 
int gcd(int n,int i) /*n:length[v], i:shift times, n>=i*/
{
 int temp=i;
 while(n%i != 0)
 {
 temp = n%i;
 n=i; i=temp;
 }
 return temp;
}
 
void loopshift_gcd(char v[],int i,int high)
{
 size_t length = gcd(high+1,i);
 size_t cntofelem = ((high+1)/length)-1;
 int cnt, j, k;
 char temp;
 for(cnt=0;cnt<length;cnt++)
 {
 temp=v[cnt];
 k=i;
 for(j=1;j<=cntofelem;j++)
 {
  v[(k-i)%(high+1)] = v[k%(high+1)];
  k+=i;
 }
 v[(k-i)%(high+1)]=temp;
 }
}
 
void recshift(char v[],int i,int low,int high)
{
 int revcnt,j,temp=0;
 if(low == high || high<i) return;
 
 if (i-low>high-i+1)
 revcnt=high-i+1,temp=1;
 else
 revcnt=i-low;
 for(j=0;j<=revcnt-1;j++)
 swap(&v[low+j],&v[high+1+j-revcnt]);
 if(temp == 1)
 low+=revcnt;
 else
 high-=revcnt;
 recshift(v,i,low,high);
}
 
void reverse(char v[],int low,int high)
{
 int j;
 for(j=0;j<(high-low+1)/2;j++)
 swap(&v[low+j],&v[high-j]);
}
 
void reverseshift(char v[],int i,int high)
{
 reverse(v,0,i-1);
 reverse(v,i,high);
 reverse(v,0,high);
}