IF OR NO IF?:-)

Conditional branches in the code have been very instrument to provide control flow safely. For theory's sake & (at some cases) to gain practical benefits, it'd be useful to know how to avoid IF-structures. Such a goal can be achieved with Pointer Arithmetic, Boolean Arithmetic + Comparison Operators. Let's take a look into classical IF-structure for sorting algo:

if(a[root]<a[child]){
swap(a, root, child);
root=child;
}

Our very method to escape if-structure at given case is to realize a linear code which could have null-swap operation. Well, let's go further.

int *p0, *p1, a[], i1, i2, empty, *pEmpty, root, child;
…..

p0=&a[root];
p1=&a[child];
i2=(*p0<*p1); // gets comparison flag
i1=(i2+1) AND 1; // forms another comparison flag (flags take boolean values)
p0=i2*p0 + pEmpty*i1;
p1=i2*p1 + pEmpty*i1;// So, if i1==1, then i2==0, then either of pointers (*p0 & *p1) get address
 //////////////////////////////////// of empty variable & swap operation changes nothing.

Another curious moment has been to run recursive functions w/ IF-free ideology. To calculate factorials is classical example to describe such techniques for that. Well let's smash into code:
typedef   __int64  (*TIMES)( __int64 *) ;
#define  adr  unsigned   long   long
__int64  ret( __int64  *n){
return  (*n>-1);}

__int64  factorial( __int64  *n){
TIMES p[2];
int  dv=(*n>1);
// --------------------------------------------
p[0]=&ret; // deadend
p[1]=&factorial; // new recursion
// --------------------------------------------
*n-=(*n>0);
return  (*n+1)*(p[dv])(n);
}

Actually, IF-free code ain't panacea to speed-up, but it may be extremely useful for many small pieces of code to branch, like this:
for( int i=0; i<N; i++) {
if(A[i])a[i]++;
}
Here dead turns become faster than branching.

P.S.

To add a yet another dab of paint to the picture :-), I must mention Pointer – free variant at 1st example.
empty=a[root];
a[root]=i2*a[child]+i1*a[root];
a[child]=i2*empty+i1*a[child];

Living example & source are reachable here.


// IF-free sorting.cpp : Defines the entry point for the console application.
// (C) 2013 Evgeney Knyazhev
// app name: IF-free Alg0Z
// ver: I.0

#include "stdafx.h"
//#include "api.h"
#include "stdafx.h"
#include <windows.h>
#include <process.h>
//#include<WinBase.h>
//#include <stdio.h>
#include "conio.h"
#include <wchar.h>
#include <shellapi.h>
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#define _OPEN_SYS_ITOA_EXT
#include <stdlib.h>
template <class T>
void modExp(T &mod, T &seed, T &exp){
	int root=1;
	for(int i=0; exp>>i+1>0; i++){
		if((exp>>i)&1==1){
			root*=seed;
			root%=mod;
		}
		seed=(seed*seed)%mod;
	}
	seed=root;
	return; 
} 
template <class T, class T1>
void pseudoRND(T *arr, int &num0fItems, T1 &mod, T1 &seed, T1 &exp){
	int size0fT1=sizeof(T1)*8-1;
	char binary[65];
	T1 sign=0;
	__int64 tst=-3;
	for(int i=0; i<num0fItems; i++){
		modExp<T1>(mod, seed, exp);
		sign=(seed>>size0fT1);
		arr[i]=-1*seed*sign+seed*((sign+1)&1);
	}
}
template <class T>
void IsArrSorted(T *arr, T I){
	bool bOrder, bWellOrdered;
	bWellOrdered=true;
	int i=1;
	while(arr[i]==arr[i-1])i++;
	if(arr[i]>arr[i-1]){
		for(; i<I; i++){
			if(arr[i]==arr[i-1])continue;
			if(arr[i]<arr[i-1]){
				bWellOrdered=false;
				goto ret;
			}
		}
			bOrder=false;
			goto ret;
	}
	bWellOrdered=true;
	for(; i<I; i++){
		if(arr[i]==arr[i-1])continue;
		if(arr[i]>arr[i-1]){
			bWellOrdered=false;
			break;
		}
	}
	if(bWellOrdered)bOrder=true;
ret: if(bWellOrdered){
		if(!bOrder)printf("\n\nAscending Order\n\n");
		else printf("\n\nDescending Order\n\n");
	 }  else printf("\n\nNot Ordered at %d\n\n", i);
	 return;
}
template <class T>
void compareArrays(T *arr1, T *arr2, T num){
	int number0fwrongNested=0;
	for(int i=0; i<num; i++){
		if(arr1[i]!=arr2[i])number0fwrongNested++;
	}
	printf("\n\n%d numbers were nested wrong.\n\n", number0fwrongNested);
	return;
}
#define chosenT unsigned  __int64

/*********************** HeapSort ********************************/
template <class T>
inline void swp(T *p0, T *p1)
{
	T empty;
	empty=*p0;
	*p0=*p1;
	*p1=empty;
	return;
}
template <class T, class adr>
inline int le(T *p0, T *p1)
{
	T i1, i2, empty, *pEmpty;
	pEmpty=&empty;
	i2=(*p0<*p1);
	i1=(i2+1)&1;
	p1=(T*)(i2*(adr)p1+i1*(adr)pEmpty);
	p0=(T*)(i2*(adr)p0+i1*(adr)pEmpty);
	empty=*p0;
	*p0=*p1;
	*p1=empty;
	return i2;
}
template <class T, class adr>
inline int siftDown(T *a, int root, int end){
	int child, count=0, dv;
	child=root<<1;//
	child++;
	while(child<end){
		dv=(child+1<end);          
		dv=(a[child]<a[child+1])*dv;
		child+=dv;
		dv=le<T, adr>(&a[root], &a[child]);
		root=child;
		end*=dv;
		child=root<<1;
	    child++;
		count++;
	}
	return count;
}
template <class T, class adr>
inline int Heapify(T *a, int end)
{
	int root=(end-1)>>1, cnt=0;
	while(root>-1){
		cnt+=siftDown<T, adr>(a, root--, end);
	}
	return cnt;
}
template <class T, class adr>
inline int heapSort(T *arr, int end){
 int count=Heapify<T, adr>(arr, end);
 while(end>0)
 {
	 swp<T>(&arr[0], &arr[end-1]);
	count+=siftDown<T, adr>(arr, 0, end-1);
	 end--;
 }
 return count;
}
/*********************** HeapSort ********************************/
/****************** factorial ***********************************/
#define I64 long long
typedef I64 (*TIMES)(I64*) ;
#define adr unsigned long long
//template <class T>
I64 ret(I64 *n){
	return (*n>-1);}
//template<class T, class adr>
I64 factorial(I64 *n){
//	__int64 (*times)(__int64*);
   //T (*times)(T*);
   //T (*unit)(T*);
	TIMES /*times, unit,*/ p[2];
  // TIMES times;
   int dv=(*n>1);//, ndv;
   //ndv=(dv+1) & 1;
  // times=&factorial;
   //unit=&ret;
   // --------------------------------------------
   p[0]=&ret;
   p[1]=&factorial;
   //times=p[dv];
   // --------------------------------------------
  // times=reinterpret_cast<TIMES>(((adr)times)*dv+ndv*((adr)unit));
 //  times=times*dv+ndv*unit;
   *n-=(*n>0);
   return (*n+1)*(p[dv])(n);
}
/****************** factorial ***********************************/
int _tmain(int argc, _TCHAR* argv[])
{
	SetConsoleTitleA("IF-free Alg0Z (ver I.0).");
	printf("(C) 2013 Evgeney Knyazhev.\n\n");
	int size0fInt=sizeof(__int64)*8-1, N0fItems=100000, N0I, bottom=0, DownThe, UpThe=1, i1, i2;
	__int64 deltaV, *array2sort, *unsortedArr, *p0, *p1, *pEmpty, empty;
	char StopThe=0, GV/*greater value*/, unit=0;
	pEmpty=&empty;
	chosenT seed=613, exp=259, mod=91477361, countIteration;
	bool onceRun=false;
main: printf("\n\nPlease, choose tasks:\n\n>>Sorting algos -- s.\n>>Compute factorial -- press f.\n\n");
	int gch=getch();
	switch(gch){
	case 'f':
		long long *n, t;
		n=&t;
		printf("\nN: ");
		scanf("%I64d", n);
		*n=factorial(n);
		char msg[2048];
		strcpy(msg, "Value is undefined");
		int len=strlen(msg)+1;
		sprintf(msg+len, "n!==%I64d\n\n", *n);
		*n=(*n>0)*len;
		printf("%s", &msg[*n]);
		goto main;

	}
Enter:	printf("Generate the array of pseudorandom numbers ((seed^exp)modN)");
		printf("\nDo ye want the default values? (y/n)");
		if(getch()=='y'){
			printf("\nPlease, enter a seed: ");
			scanf("%d", &seed);
			printf("\nPlease, enter an exp: ");
			scanf("%d", &exp);
			printf("\nPlease, enter a N: ");
			scanf("%d", &mod);
			printf("\nPlease, enter a number of items of array to generate: ");
			scanf("%d", &N0fItems);
			onceRun=false;
		}
		if(!onceRun){
gen:		array2sort=(__int64*)malloc(N0fItems*size0fInt);
			unsortedArr=(__int64*)malloc(N0fItems*size0fInt);
			if(array2sort==NULL || unsortedArr==NULL){
					printf("Not enough memory for array\n");
					return 0;
				}
			pseudoRND<__int64, chosenT>(array2sort, N0fItems, mod, seed, exp);
			for(unsigned int p=0; p<N0fItems; p++)unsortedArr[p]=array2sort[p];
		}
		DownThe=N0fItems-1;
		countIteration=0;
		bottom=0;
		N0I=N0fItems;
		StopThe=0;
		if(onceRun){
			printf("\nWould ye like to generate new array? (y/n)\n");
			if(getch()=='y'){
				free(array2sort);
				free(unsortedArr);
				goto Enter;
			}
		}
		printf("\n\nPlease, choose a method to sort\nBinary Heap -- press b.\nTwo-way Tides -- press t.\n\n");
		gch=getch();
switch(gch){
case 'b':
	countIteration=heapSort<__int64, chosenT>(array2sort, N0fItems);
	break;
case 't':
/*************88888888888********** IF-free Sorting two-way tides ***************88888888888888888**************************/
	while(StopThe!=1){
		p1=&array2sort[DownThe];
		p0=&array2sort[DownThe-1];
		deltaV=*p1-*p0;
		GV=((unsigned __int64)deltaV)>>size0fInt;
		if(*p0>*p1)
			i2=1;
		i1=(GV+1)&1;
		i2=GV&1;
		p1=(__int64*)(i2*(chosenT)p1+i1*(chosenT)pEmpty);
		p0=(__int64*)(i2*(chosenT)p0+i1*(chosenT)pEmpty);
		empty=*p1;
		*p1=*p0;
		*p0=empty;
		unit=i2+i1*unit;
		p1=&array2sort[UpThe];
		p0=&array2sort[UpThe-1];
		deltaV=*p1-*p0;
		GV=((unsigned __int64)deltaV)>>size0fInt;
		i1=(GV+1)&1;
		i2=GV&1;
		p1=(__int64*)(i2*(chosenT)p1+i1*(chosenT)pEmpty);
		p0=(__int64*)(i2*(chosenT)p0+i1*(chosenT)pEmpty);
		empty=*p1;
		*p1=*p0;
		*p0=empty;
		unit=i2+unit*i1;
		UpThe++;
		deltaV=UpThe-N0fItems;
		GV=((unsigned __int64)deltaV)>>size0fInt;
		i1=(GV+1)&1;
		i2=GV&1;
		bottom+=i1;
		UpThe=i2*UpThe+i1*bottom;
		DownThe--;
		/*deltaV=bottom-DownThe;
		GV=((unsigned int)deltaV)>>size0fInt;
		i1=(GV+1)&1;
		i2=GV&1;*/
		N0fItems-=i1;
		DownThe=i2*DownThe+i1*(N0fItems-1);
		StopThe=i1&(unit+1);
		unit&=i2;
		countIteration++;
	}
/*************88888888888********** IF-free Sorting two-way tides ***************88888888888888888**************************/
	break;
}
	countIteration/=N0I;
	N0fItems=N0I;
	onceRun=true;
	printf("\n\n%d iterations were gotten.\nP.S.\nNumber of iterations was taken by formula: \n(total number of loops)/(length of array)\n\n", countIteration);
menu:	printf("To test the order of array, please, press a.\nTo compare sorted & unsorted arrays, please, press c.\nTo swap items of sorted arrays, please, press s.\nTo repeat sorting, please, press r.\n");
	gch=getch();
	switch(gch){
	case 'a':
			  IsArrSorted<__int64>(array2sort, N0I);
		      goto menu;
	case 'c':
			  compareArrays<__int64>(array2sort, unsortedArr, N0fItems);
			  goto menu;
	case 's':
		__int64 item1, item2, tmp;
		printf("\nPlease, say me an item:");
		scanf("%d", &item1);
		printf("\nNow, please, 2nd one:");
		scanf("%d", &item2);
		tmp=array2sort[item1];
		array2sort[item1]=array2sort[item2];
		array2sort[item2]=tmp;
		goto menu;
	case 'r':
		goto main;
	}

	return 0;
}

你可能感兴趣的:(IF OR NO IF?:-))