diff options
author | Tuowen Zhao <ztuowen@gmail.com> | 2017-01-14 14:32:40 -0700 |
---|---|---|
committer | Tuowen Zhao <ztuowen@gmail.com> | 2017-01-14 14:32:40 -0700 |
commit | 18607258a9516a6e809f9b996902759f5c6df263 (patch) | |
tree | 1f31397d611a15b106a9ea32d82f3f4d91708bd3 /main.cpp | |
parent | 0bf5200abc17824f4e7142254d1c43a1d5d47025 (diff) | |
download | qsort-18607258a9516a6e809f9b996902759f5c6df263.tar.gz qsort-18607258a9516a6e809f9b996902759f5c6df263.tar.bz2 qsort-18607258a9516a6e809f9b996902759f5c6df263.zip |
Diffstat (limited to 'main.cpp')
-rw-r--r-- | main.cpp | 285 |
1 files changed, 106 insertions, 179 deletions
@@ -1,126 +1,14 @@ #include <iostream> -#include <cstdlib> #include <random> #include <cstring> #include <ctime> +#include <algorithm> +#include "mqsort.h" template<typename T> -inline void swap(T &a, T &b) { - T t = a; - a = b; - b = t; -} - -template<typename T> -inline void insert(T *l, T *r, int (*compar)(const void*, const void*)) { - T* s = l; - while (s<r) { - T* k = s+1; - while (k > l && compar(k,k-1) < 0) { - swap(*k, *(k-1)); - --k; - } - ++s; - } -} - -#define INS 12 - -template<typename T> -void secret1(T *l, T *r, int (*compar)(const void*, const void*)) { - T *j = r; - T *i = l+1; - { - int a = compar(l, l+1), b= compar(l,l+2), c = compar(l+1,l+2); - if (a > 0) { - if (b > 0) - if (c<0) swap(*l,l[2]); - else swap(*l,l[1]); - } else if (a < 0) { - if (b < 0) - if (c<0) swap(*l,l[1]); - else swap(*l,l[2]); - } - } - while (i <= j) { - int a = compar(l,i); - if (a <= 0) { - int b = 0; - while (j > l && (b = compar(l,j)) < 0) - --j; - if (j > i) { - if (a != b) { - swap(*j, *i); - --j; - } else { - --i; --j; - } - } else break; - } else { - ++i; - } - } - swap(*l, *j); - --j; - //std::cout<< j-l <<" " << r-i << std::endl; - if (l+INS < j) - secret1(l,j, compar); - else - insert(l,j,compar); - if (i+INS < r) - secret1(i,r, compar); - else - insert(i,r,compar); -} - -inline void swapsize(char *a,char *b, size_t size) { - for (int cnt = 0; cnt < size; ++cnt) - swap<char>(a[cnt],b[cnt]); -} - -void secret(char *l, char *r, size_t size,int (*compar)(const void*, const void*)) { - char *j = r; - char *i = l+size; - while (i <= j) { - if (compar(l,i) < 0) { - swapsize(j, i, size); - j -= size; - } else { - i += size; - } - } - swapsize(l, j, size); - j -= size; - if (l < j) - secret1(l, j, compar); - if (i < r) - secret1(i, r, compar); - -} - -void mqsort(void* base, size_t num, size_t size, int (*compar)(const void*, const void*)) { - switch (size) { - case 1: - secret1((uint8_t*)base, (uint8_t*)base+(num-1), compar); - break; - case 2: - secret1((uint16_t *)base, (uint16_t *)base+(num-1), compar); - break; - case 4: - secret1((uint32_t *)base, (uint32_t*)base+(num-1), compar); - break; - case 8: - secret1((uint64_t *)base, (uint64_t *)base+(num-1), compar); - break; - default: - secret((char*)base, (char*)base+(num-1)*size, size, compar); - } -} - -template<typename T> -int compr(const void * a, const void * b){ - T aa = *(T*)a; - T bb = *(T*)b; +int compr(const void *a, const void *b) { + T aa = *(T *) a; + T bb = *(T *) b; if (aa > bb) return 1; if (aa < bb) @@ -129,118 +17,157 @@ int compr(const void * a, const void * b){ } template<typename T> -void* genInt(size_t num) { +void genInt(void *base, size_t num) { std::random_device r; std::mt19937_64 e(r()); - std::uniform_int_distribution<T> unifrom_dist(0, 1 << (sizeof(T)*8 -2)); - T * res = (T*)malloc(num * sizeof(T)); - for (size_t i = 0; i<num; ++i) + std::uniform_int_distribution<T> unifrom_dist(0, (T) 1 << (sizeof(T) * 8 - 2)); + T *res = (T *) base; + for (size_t i = 0; i < num; ++i) res[i] = unifrom_dist(e); - return res; } template<typename T> -void* genFloat(size_t num) { +void genFloat(void *base, size_t num) { std::random_device r; std::mt19937_64 e(r()); std::uniform_real_distribution<T> unifrom_dist(0, 1); - T * res = (T*)malloc(num * sizeof(T)); - for (size_t i = 0; i<num; ++i) + T *res = (T *) base; + for (size_t i = 0; i < num; ++i) res[i] = unifrom_dist(e); - return res; } template<typename T> -void* gen(size_t num) { - return genInt<T>(num); +void gen(void *base, size_t num) { + genInt<T>(base, num); } -template <> -void* gen<float>(size_t num) { - return genFloat<float>(num); +template<> +void gen<float>(void *base, size_t num) { + genFloat<float>(base, num); } -template <> -void* gen<double>(size_t num) { - return genFloat<double>(num); +template<> +void gen<double>(void *base, size_t num) { + genFloat<double>(base, num); } -int compeq(uint32_t *a,uint32_t *b, size_t size) { - for (size_t i = 0; i< size; ++i) +int compeq(uint32_t *a, uint32_t *b, size_t size) { + for (size_t i = 0; i < size; ++i) if (a[i] != b[i]) return 1; return 0; } template<typename T> -void print(void *v, size_t num) { - T * k = (T*) v; - for (int i = 0; i<num; ++i) - std::cout<< k[i] << " "; - std::cout<<std::endl; -} - -template<typename T> -void runAndTest(size_t num) { +void runAndTest(size_t num, size_t it) { clock_t tst; clock_t tmd; clock_t ted; + std::vector<clock_t> mine, stnd; size_t size = sizeof(T); - void *base = gen<T>(num); - void *base2 = malloc(num*size); - memcpy(base2,base,num*size); - tst = clock(); - mqsort(base,num,size,compr<T>); - tmd = clock(); - qsort(base2,num,size,compr<T>); - ted = clock(); - if (compeq((uint32_t*)base,(uint32_t*)base2,num*size/4)) { - std::cout << "Not equal" << std::endl; - print<T>(base, num); - print<T>(base2,num); + void *base = malloc(num * size); + void *base2 = malloc(num * size); + for (size_t t = 0; t < it; ++t) { + gen<T>(base, num); + memcpy(base2, base, num * size); + tst = clock(); + mqsort(base, num, size, compr<T>); + tmd = clock(); + qsort(base2, num, size, compr<T>); + ted = clock(); + if (compeq((uint32_t *) base, (uint32_t *) base2, num * size / 4)) { + std::cout << "Not equal" << std::endl; + return; + } + mine.push_back(tmd - tst); + stnd.push_back(ted - tmd); } - else - std::cout<<"Equal"<<std::endl; - std::cout<<"Time taken for me : " << float(tmd - tst) / CLOCKS_PER_SEC<<std::endl; - std::cout<<"Time taken for std : " << float(ted - tmd) / CLOCKS_PER_SEC<<std::endl; + free(base); + free(base2); + std::sort(mine.begin(), mine.end()); + std::sort(stnd.begin(), stnd.end()); + double m = 0, s = 0; + for (auto itt = mine.begin(); itt < mine.end(); ++itt) + m += *itt; + for (auto itt = stnd.begin(); itt < stnd.end(); ++itt) + s += *itt; + std::cout << "Average time taken for me (s): " << m / CLOCKS_PER_SEC / it << std::endl; + std::cout << "Average time taken for std (s): " << s / CLOCKS_PER_SEC / it << std::endl; + std::cout << "Speedup over std : " << s / m << std::endl; + if (it & 1) { + m = mine[it >> 1]; + s = stnd[it >> 1]; + } else { + m = mine[it >> 1]; + m += mine[(it >> 1) - 1]; + m /= 2; + s = stnd[it >> 1]; + s += stnd[(it >> 1) - 1]; + s /= 2; + } + std::cout << "Median time taken for me (s): " << m / CLOCKS_PER_SEC << std::endl; + std::cout << "Median time taken for std (s): " << s / CLOCKS_PER_SEC << std::endl; + std::cout << "Speedup over std : " << s / m << std::endl; } void usage() { - std::cout << "Usage: <this> [TYPE] [LENGTH]" <<std::endl; - std::cout << " [TYPE]" <<std::endl; - std::cout << " i : int" <<std::endl; - std::cout << " l : long" <<std::endl; - std::cout << " f : float" <<std::endl; - std::cout << " d : double" <<std::endl; - std::cout << " [LENGTH]" <<std::endl; - std::cout << " An int specify the number of elements in the list to be sorted" <<std::endl; -} - -int main(int argc,char** argv) { - if (argc < 3) { + std::cout << "Usage: <this> [TYPE] [LENGTH]" << std::endl; + std::cout << " [TYPE]" << std::endl; + std::cout << " c : char(int8)" << std::endl; + std::cout << " s : short(int16)" << std::endl; + std::cout << " i : int" << std::endl; + std::cout << " l : long" << std::endl; + std::cout << " f : float" << std::endl; + std::cout << " d : double" << std::endl; + std::cout << " [LENGTH]" << std::endl; + std::cout << " An int specify the number of elements in the list to be sorted" << std::endl; + std::cout << " [ITERATIONS]" << std::endl; + std::cout << " An int specify the number of iterations of test" << std::endl; +} + +int main(int argc, char **argv) { + if (argc < 4) { usage(); return -1; } size_t num; + size_t it; try { - num = (size_t)std::stoi(argv[2]); + num = (size_t) std::stoi(argv[2]); + if (num > 10000000) + std::cout << "The [LENGTH] seems to be too large" << std::endl; + it = (size_t) std::stoi(argv[3]); + if (it > 10000000) + std::cout << "The [ITERATIONS] seems to be too large" << std::endl; } catch (std::exception &e) { std::cout << e.what() << std::endl; usage(); return -1; } - switch(argv[1][0]) { + switch (argv[1][0]) { + case 'c': + std::cout<<num<<" Char for "<<it<<" Iterations"<<std::endl; + runAndTest<int8_t>(num, it); + break; + case 's': + std::cout<<num<<" Short for "<<it<<" Iterations"<<std::endl; + runAndTest<int16_t>(num, it); + break; case 'i': - runAndTest<int>(num); + std::cout<<num<<" Int for "<<it<<" Iterations"<<std::endl; + runAndTest<int>(num, it); break; case 'l': - runAndTest<long>(num); + std::cout<<num<<" Long for "<<it<<" Iterations"<<std::endl; + runAndTest<long>(num, it); break; case 'f': - runAndTest<float>(num); + std::cout<<num<<" Float for "<<it<<" Iterations"<<std::endl; + runAndTest<float>(num, it); break; case 'd': - runAndTest<double>(num); + std::cout<<num<<" Double for "<<it<<" Iterations"<<std::endl; + runAndTest<double>(num, it); break; default: usage(); |