#ifdef _MSC_VER
    #define _SECURE_SCL 0
    #define _CRT_SECURE_NO_DEPRECATE 1
    #define WIN32_LEAN_AND_MEAN
    #define VC_EXTRALEAN
    #define NOMINMAX
#endif

#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <cmath>
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <limits>
#include <vector>
#include <iomanip>
#include <stdint.h>
#include "cycle.h"

static const size_t N = 1000000;
static const size_t R = 7;



inline bool naive_char(const char *a, const char *b) {
	while (*a || *b) {
		if (*a != *b) {
			return false;
		}
		++a;
		++b;
	}
	return true;
}

inline bool naive_string(const std::string& a, const std::string& b) {
	if (a.length() == b.length()) {
		return naive_char(a.c_str(), b.c_str());
	}
	return false;
}

int main() {
    std::vector<const char*> chars;
    std::vector<std::string> strings;
    chars.reserve(N);
    strings.reserve(N);
    for (size_t i=0 ; i<N ; ++i) {
        char *s = new char[12];
        sprintf(s, "%u", uint32_t(i));
        chars.push_back(s);
        strings.push_back(s);
        strings.back().c_str();
    }

//*
    {
        size_t tlen = 0;
        std::vector<double> timings;
        timings.reserve(R);
        for (size_t r=0 ; r<R ; ++r) {
            ticks start = getticks();
            for (size_t i=1 ; i<N ; ++i) {
                if (naive_char(chars[i], chars[i-1])) {
                    ++tlen;
                }
            }
            ticks end = getticks();
            double timed = elapsed(end, start);
            timings.push_back(timed);
        }

        std::cout << "naive(char*,char*): ";
        PrintStats(timings);
        std::cout << std::endl;
        std::cout << tlen << std::endl;
    }
//*/

//*
    {
		size_t tlen = 0;
		std::vector<double> timings;
		timings.reserve(R);
		for (size_t r=0 ; r<R ; ++r) {
			ticks start = getticks();
			for (size_t i=1 ; i<N ; ++i) {
				if (naive_string(strings[i], strings[i-1])) {
					++tlen;
				}
			}
            ticks end = getticks();
            double timed = elapsed(end, start);
            timings.push_back(timed);
        }

        std::cout << "naive(string,string): ";
        PrintStats(timings);
        std::cout << std::endl;
        std::cout << tlen << std::endl;
    }
//*/

//*
    {
        size_t tlen = 0;
        std::vector<double> timings;
        timings.reserve(R);
        for (size_t r=0 ; r<R ; ++r) {
            ticks start = getticks();
            for (size_t i=1 ; i<N ; ++i) {
                if (strings[i] == strings[i-1]) {
                    ++tlen;
                }
            }
            ticks end = getticks();
            double timed = elapsed(end, start);
            timings.push_back(timed);
        }

        std::cout << "string == string: ";
        PrintStats(timings);
        std::cout << std::endl;
        std::cout << tlen << std::endl;
    }
//*/

//*
    {
        size_t tlen = 0;
        std::vector<double> timings;
        timings.reserve(R);
        for (size_t r=0 ; r<R ; ++r) {
            ticks start = getticks();
            for (size_t i=1 ; i<N ; ++i) {
                if (strings[i] == chars[i-1]) {
                    ++tlen;
                }
            }
            ticks end = getticks();
            double timed = elapsed(end, start);
            timings.push_back(timed);
        }

        std::cout << "string == char*: ";
        PrintStats(timings);
        std::cout << std::endl;
        std::cout << tlen << std::endl;
    }
//*/

//*
    {
        size_t tlen = 0;
        std::vector<double> timings;
        timings.reserve(R);
        for (size_t r=0 ; r<R ; ++r) {
            ticks start = getticks();
            for (size_t i=1 ; i<N ; ++i) {
                if (strcmp(chars[i], chars[i-1]) == 0) {
                    ++tlen;
                }
            }
            ticks end = getticks();
            double timed = elapsed(end, start);
            timings.push_back(timed);
        }

        std::cout << "strcmp(char*,char*) == 0: ";
        PrintStats(timings);
        std::cout << std::endl;
        std::cout << tlen << std::endl;
    }
//*/

//*
    {
        size_t tlen = 0;
        std::vector<double> timings;
        timings.reserve(R);
        for (size_t r=0 ; r<R ; ++r) {
            ticks start = getticks();
            for (size_t i=1 ; i<N ; ++i) {
                if (strcmp(chars[i], strings[i-1].c_str()) == 0) {
                    ++tlen;
                }
            }
            ticks end = getticks();
            double timed = elapsed(end, start);
            timings.push_back(timed);
        }

        std::cout << "strcmp(char*,string.c_str()) == 0: ";
        PrintStats(timings);
        std::cout << std::endl;
        std::cout << tlen << std::endl;
    }
//*/

//*
    {
        size_t tlen = 0;
        std::vector<double> timings;
        timings.reserve(R);
        for (size_t r=0 ; r<R ; ++r) {
            ticks start = getticks();
            for (size_t i=1 ; i<N ; ++i) {
                if (strcmp(strings[i].c_str(), strings[i-1].c_str()) == 0) {
                    ++tlen;
                }
            }
            ticks end = getticks();
            double timed = elapsed(end, start);
            timings.push_back(timed);
        }

        std::cout << "strcmp(string.c_str(),string.c_str()) == 0: ";
        PrintStats(timings);
        std::cout << std::endl;
        std::cout << tlen << std::endl;
    }
//*/

//*
    {
        size_t tlen = 0;
        std::vector<double> timings;
        timings.reserve(R);
        for (size_t r=0 ; r<R ; ++r) {
            ticks start = getticks();
            for (size_t i=1 ; i<N ; ++i) {
                if (strings[i].compare(strings[i-1]) == 0) {
                    ++tlen;
                }
            }
            ticks end = getticks();
            double timed = elapsed(end, start);
            timings.push_back(timed);
        }

        std::cout << "string.compare(string) == 0: ";
        PrintStats(timings);
        std::cout << std::endl;
        std::cout << tlen << std::endl;
    }
//*/

//*
    {
        size_t tlen = 0;
        std::vector<double> timings;
        timings.reserve(R);
        for (size_t r=0 ; r<R ; ++r) {
            ticks start = getticks();
            for (size_t i=1 ; i<N ; ++i) {
                if (strings[i].compare(chars[i-1]) == 0) {
                    ++tlen;
                }
            }
            ticks end = getticks();
            double timed = elapsed(end, start);
            timings.push_back(timed);
        }

        std::cout << "string.compare(char*) == 0: ";
        PrintStats(timings);
        std::cout << std::endl;
        std::cout << tlen << std::endl;
    }
//*/

	for (size_t i=0 ; i<N ; ++i) {
    	delete[] chars[i];
    }
}
