Skip to content

Instantly share code, notes, and snippets.

@grodtron
Created July 10, 2012 17:17
Show Gist options
  • Save grodtron/3084835 to your computer and use it in GitHub Desktop.
Save grodtron/3084835 to your computer and use it in GitHub Desktop.
Little assignment for a programming class
Debug/*
*.vcxproj*
*.o
*.swp
test
#include "factorial.h"
unsigned long factorial::iterative(int n){
unsigned long value = 1;
for(int i = 2; i <= n; ++i){
value *= i;
}
return value;
}
unsigned long factorial::recursive(int n){
if (!n) return 1;
return n * factorial::recursive(n - 1);
}
#ifndef factorial_h
#define factorial_h
namespace factorial{
unsigned long iterative(int n);
unsigned long recursive(int n);
/*
The constants below are used with the timer to calculate approximate costs
of basic operations. The number of basic operations is going to be based on
lines of assembly code generated by g++.
The entire assembly code generated is given below.
Calculation of the cost of basic operations using this method depends on the
terrible assumption that all instructions take the same amount of time to
execute, but it should still give a good general idea.
*/
const int numberOfIterativeOperations = 10;
/*
Stripping out all of the assembler directives, we get:
.LFB0:
pushl %ebp
movl %esp, %ebp
subl $16, %esp
movl $1, -8(%ebp)
movl $2, -4(%ebp)
jmp .L2
== for loop body starts here ==
.L3:
movl -4(%ebp), %eax
movl -8(%ebp), %edx
imull %edx, %eax
movl %eax, -8(%ebp)
addl $1, -4(%ebp)
.L2:
movl -4(%ebp), %eax
cmpl 8(%ebp), %eax
setle %al
testb %al, %al
jne .L3
== for loop body ends here ==
movl -8(%ebp), %eax
leave
ret
*/
const int numberOfRecursiveOperations = 11;
/*
Generated assembly minus directives:
_ZN9factorial9recursiveEi:
== Stuff that is repeated starts here... ==
.LFB1:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
cmpl $0, 8(%ebp)
jne .L6
== ...Until here ==
movl $1, %eax
jmp .L7
== Then from here.. ==
.L6:
movl 8(%ebp), %eax
subl $1, %eax
movl %eax, (%esp)
call _ZN9factorial9recursiveEi
movl 8(%ebp), %edx
imull %edx, %eax
== ...'til here ==
.L7:
leave
ret
*/
///////////////////////////////////////////////
// //
// Complete Generated GAS Code //
// //
///////////////////////////////////////////////
/*
.file "factorial.cpp"
.text
.align 2
.globl _ZN9factorial9iterativeEi
.type _ZN9factorial9iterativeEi, @function
_ZN9factorial9iterativeEi:
.LFB0:
.cfi_startproc
.cfi_personality 0x0,__gxx_personality_v0
pushl %ebp
.cfi_def_cfa_offset 8
movl %esp, %ebp
.cfi_offset 5, -8
.cfi_def_cfa_register 5
subl $16, %esp
movl $1, -8(%ebp)
movl $2, -4(%ebp)
jmp .L2
.L3:
movl -4(%ebp), %eax
movl -8(%ebp), %edx
imull %edx, %eax
movl %eax, -8(%ebp)
addl $1, -4(%ebp)
.L2:
movl -4(%ebp), %eax
cmpl 8(%ebp), %eax
setle %al
testb %al, %al
jne .L3
movl -8(%ebp), %eax
leave
ret
.cfi_endproc
.LFE0:
.size _ZN9factorial9iterativeEi, .-_ZN9factorial9iterativeEi
.align 2
.globl _ZN9factorial9recursiveEi
.type _ZN9factorial9recursiveEi, @function
_ZN9factorial9recursiveEi:
.LFB1:
.cfi_startproc
.cfi_personality 0x0,__gxx_personality_v0
pushl %ebp
.cfi_def_cfa_offset 8
movl %esp, %ebp
.cfi_offset 5, -8
.cfi_def_cfa_register 5
subl $24, %esp
cmpl $0, 8(%ebp)
jne .L6
movl $1, %eax
jmp .L7
.L6:
movl 8(%ebp), %eax
subl $1, %eax
movl %eax, (%esp)
call _ZN9factorial9recursiveEi
movl 8(%ebp), %edx
imull %edx, %eax
.L7:
leave
ret
.cfi_endproc
.LFE1:
.size _ZN9factorial9recursiveEi, .-_ZN9factorial9recursiveEi
.ident "GCC: (Debian 4.4.5-8) 4.4.5"
.section .note.GNU-stack,"",@progbits
*/
}
#endif
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
#include "timer.h"
#include "factorial.h"
int main()
{
timer i_timer;
timer r_timer;
int n;
unsigned long long i_value;
unsigned long long r_value;
cout << "Enter the value to calculate the factorial of: ";
cin >> n;
i_timer.start();
i_value = factorial::iterative(n);
i_timer.end();
r_timer.start();
r_value = factorial::recursive(n);
r_timer.end();
cout << endl << endl
<< "With n=" << n << ',' << endl
<< " Recursively:" << endl
<< " value: " << r_value << endl
<< " time : " << r_timer.duration() << endl
<< " calculated cost of operations: " << r_timer.duration()/(n * factorial::numberOfRecursiveOperations) << endl
<< " Iteratively:" << endl
<< " value: " << i_value << endl
<< " time : " << i_timer.duration() << endl
<< " calculated cost of operations: " << i_timer.duration()/(n * factorial::numberOfIterativeOperations) << endl;
#ifdef _WIN32
system("pause");
#endif
return 0;
}
exe=test
ldflags=-lrt
ccflags=-O3 -Wall -Wextra
cc=g++
.PHONY: all clean
all: $(exe)
clean:
@rm -f *.o
@rm -f $(exe)
test: main.cpp factorial.o timer.o
$(cc) $(ccflags) $(ldflags) $^ -o $@
%.o: %.cpp
$(cc) $(ccflags) -c $^ -o $@
/*
* A class that provides a simple timer
* Works in Windows and Linux, resolution is hardware dependant
*
*
* Copyleft Gordon Bailey 2012 - All wrongs reserved
*
* */
#include "timer.h"
#ifdef _WIN32
#include <cstdlib>
#include <iostream>
using std::endl;
using std::cerr;
timer::timer() : ready(false) {
bool success = QueryPerformanceFrequency(&counter_freq);
if(!success){
cerr << "Error, QueryPerformanceFrequency failed." << endl;
system("pause");
exit(EXIT_FAILURE);
}
}
void timer::start() {
ready = false;
bool success = QueryPerformanceCounter(&start_time);
if(!success){
cerr << "Error, QueryPerformanceCounter failed." << endl;
system("pause");
exit(EXIT_FAILURE);
}
}
void timer::end(){
ready = true;
bool success = QueryPerformanceCounter(&end_time);
if(!success){
cerr << "Error, QueryPerformanceCounter failed." << endl;
system("pause");
exit(EXIT_FAILURE);
}
}
// there is probably some unnecessary typecasting here, but better safe than sorry
double timer::duration(){
if (ready){
return 1e6 * (((double)(end_time.QuadPart - start_time.QuadPart)) / ((double)counter_freq.QuadPart));
}else{
return 0;
}
}
#else
timer::timer() : ready(false) {}
void timer::start() {
ready = false;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start_time);
}
void timer::end(){
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end_time);
ready = true;
}
double timer::duration(){
if (ready){
return 1e6 * (difftime(end_time.tv_sec, start_time.tv_sec) + (1e-9 * (double)(end_time.tv_nsec - start_time.tv_nsec)));
}else{
return 0;
}
}
#endif
#ifndef TIMER_H
#define TIMER_H
#ifdef _WIN32
#include <Windows.h>
#else
#include <time.h>
#endif
class timer{
#ifdef _WIN32
LARGE_INTEGER start_time;
LARGE_INTEGER end_time;
LARGE_INTEGER counter_freq;
#else
struct timespec start_time;
struct timespec end_time;
#endif
bool ready;
public:
void start();
void end();
double duration();
timer();
};
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment